summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/camera_2d.cpp2
-rw-r--r--scene/2d/cpu_particles_2d.cpp2
-rw-r--r--scene/2d/gpu_particles_2d.cpp12
-rw-r--r--scene/2d/gpu_particles_2d.h9
-rw-r--r--scene/2d/path_2d.cpp14
-rw-r--r--scene/2d/path_2d.h1
-rw-r--r--scene/3d/audio_stream_player_3d.cpp6
-rw-r--r--scene/3d/cpu_particles_3d.cpp22
-rw-r--r--scene/3d/proximity_group_3d.cpp182
-rw-r--r--scene/3d/proximity_group_3d.h85
-rw-r--r--scene/3d/soft_dynamic_body_3d.cpp3
-rw-r--r--scene/3d/soft_dynamic_body_3d.h2
-rw-r--r--scene/3d/sprite_3d.cpp2
-rw-r--r--scene/3d/world_environment.cpp4
-rw-r--r--scene/animation/animation_player.cpp8
-rw-r--r--scene/animation/animation_player.h2
-rw-r--r--scene/debugger/scene_debugger.cpp2
-rw-r--r--scene/gui/box_container.cpp2
-rw-r--r--scene/gui/button.cpp14
-rw-r--r--scene/gui/center_container.cpp2
-rw-r--r--scene/gui/container.cpp8
-rw-r--r--scene/gui/control.cpp14
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/file_dialog.cpp20
-rw-r--r--scene/gui/graph_edit.cpp2
-rw-r--r--scene/gui/graph_node.cpp4
-rw-r--r--scene/gui/grid_container.cpp4
-rw-r--r--scene/gui/item_list.cpp4
-rw-r--r--scene/gui/label.cpp10
-rw-r--r--scene/gui/line_edit.cpp32
-rw-r--r--scene/gui/link_button.cpp6
-rw-r--r--scene/gui/margin_container.cpp2
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/nine_patch_rect.cpp4
-rw-r--r--scene/gui/popup_menu.cpp4
-rw-r--r--scene/gui/rich_text_label.cpp12
-rw-r--r--scene/gui/scroll_container.cpp4
-rw-r--r--scene/gui/scroll_container.h3
-rw-r--r--scene/gui/slider.cpp2
-rw-r--r--scene/gui/spin_box.cpp4
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/tab_bar.cpp30
-rw-r--r--scene/gui/tab_container.cpp4
-rw-r--r--scene/gui/text_edit.cpp145
-rw-r--r--scene/gui/text_edit.h8
-rw-r--r--scene/gui/texture_button.cpp10
-rw-r--r--scene/gui/texture_progress_bar.cpp11
-rw-r--r--scene/gui/texture_rect.cpp6
-rw-r--r--scene/gui/tree.cpp9
-rw-r--r--scene/gui/video_stream_player.cpp (renamed from scene/gui/video_player.cpp)134
-rw-r--r--scene/gui/video_stream_player.h (renamed from scene/gui/video_player.h)16
-rw-r--r--scene/main/canvas_item.cpp7
-rw-r--r--scene/main/viewport.cpp28
-rw-r--r--scene/register_scene_types.cpp31
-rw-r--r--scene/register_scene_types.h2
-rw-r--r--scene/resources/curve.cpp484
-rw-r--r--scene/resources/curve.h120
-rw-r--r--scene/resources/immediate_mesh.cpp3
-rw-r--r--scene/resources/immediate_mesh.h2
-rw-r--r--scene/resources/material.cpp17
-rw-r--r--scene/resources/mesh.cpp4
-rw-r--r--scene/resources/particles_material.cpp2
-rw-r--r--scene/resources/visual_shader_nodes.cpp28
-rw-r--r--scene/resources/visual_shader_nodes.h6
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp157
-rw-r--r--scene/resources/visual_shader_particle_nodes.h1
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
68 files changed, 888 insertions, 900 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index bf5671be19..b6902686fe 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -176,7 +176,7 @@ Transform2D Camera2D::get_camera_transform() {
Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom);
- if (!limit_smoothing_enabled) {
+ if (!smoothing_enabled || !limit_smoothing_enabled) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
screen_rect.position.x = limit[SIDE_LEFT];
}
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 80c17b6e88..8d997bb1f5 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -890,7 +890,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed));
p.rotation = Math::deg2rad(base_angle); //angle
- p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + p.custom[1] * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed));
+ p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed));
}
//apply color
//apply hue rotation
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index f1f4d1b769..4384ec8141 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -170,6 +170,13 @@ void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) {
update();
}
+#ifdef TOOLS_ENABLED
+void GPUParticles2D::set_show_visibility_rect(bool p_show_visibility_rect) {
+ show_visibility_rect = p_show_visibility_rect;
+ update();
+}
+#endif
+
bool GPUParticles2D::is_trail_enabled() const {
return trail_enabled;
}
@@ -452,7 +459,7 @@ void GPUParticles2D::_notification(int p_what) {
RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid);
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
+ if (show_visibility_rect) {
draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false);
}
#endif
@@ -588,6 +595,9 @@ GPUParticles2D::GPUParticles2D() {
set_speed_scale(1);
set_fixed_fps(30);
set_collision_base_size(collision_base_size);
+#ifdef TOOLS_ENABLED
+ show_visibility_rect = false;
+#endif
}
GPUParticles2D::~GPUParticles2D() {
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index d7eee461b4..a9e66b3051 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -58,7 +58,9 @@ private:
bool local_coords;
int fixed_fps;
bool fractional_delta;
-
+#ifdef TOOLS_ENABLED
+ bool show_visibility_rect;
+#endif
Ref<Material> process_material;
DrawOrder draw_order;
@@ -81,7 +83,6 @@ protected:
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const override;
void _notification(int p_what);
-
void _update_collision_size();
public:
@@ -102,6 +103,10 @@ public:
void set_trail_sections(int p_sections);
void set_trail_section_subdivisions(int p_subdivisions);
+#ifdef TOOLS_ENABLED
+ void set_show_visibility_rect(bool p_show_visibility_rect);
+#endif
+
bool is_emitting() const;
int get_amount() const;
double get_lifetime() const;
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index ed30e871d7..40211f2a9b 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -100,16 +100,18 @@ void Path2D::_notification(int p_what) {
#endif
const Color color = Color(0.5, 0.6, 1.0, 0.7);
- for (int i = 0; i < curve->get_point_count(); i++) {
- Vector2 prev_p = curve->get_point_position(i);
+ _cached_draw_pts.resize(curve->get_point_count() * 8);
+ int count = 0;
- for (int j = 1; j <= 8; j++) {
- real_t frac = j / 8.0;
+ for (int i = 0; i < curve->get_point_count(); i++) {
+ for (int j = 0; j < 8; j++) {
+ real_t frac = j * (1.0 / 8.0);
Vector2 p = curve->interpolate(i, frac);
- draw_line(prev_p, p, color, line_width);
- prev_p = p;
+ _cached_draw_pts.set(count++, p);
}
}
+
+ draw_polyline(_cached_draw_pts, color, line_width, true);
}
}
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 3b12f025fc..7e8478283f 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -38,6 +38,7 @@ class Path2D : public Node2D {
GDCLASS(Path2D, Node2D);
Ref<Curve2D> curve;
+ Vector<Vector2> _cached_draw_pts;
void _curve_changed();
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index efe23c6102..bdcab49e4e 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -391,7 +391,13 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());
for (Camera3D *camera : cameras) {
+ if (!camera) {
+ continue;
+ }
Viewport *vp = camera->get_viewport();
+ if (!vp) {
+ continue;
+ }
if (!vp->is_audio_listener_3d()) {
continue;
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index d347d24c2c..b081142fbf 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -881,53 +881,53 @@ void CPUParticles3D::_particles_process(double p_delta) {
p.custom[1] = p.time / lifetime;
tv = p.time / p.lifetime;
- real_t tex_linear_velocity = 0.0;
+ real_t tex_linear_velocity = 1.0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
}
- real_t tex_orbit_velocity = 0.0;
+ real_t tex_orbit_velocity = 1.0;
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
}
}
- real_t tex_angular_velocity = 0.0;
+ real_t tex_angular_velocity = 1.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
}
- real_t tex_linear_accel = 0.0;
+ real_t tex_linear_accel = 1.0;
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
}
- real_t tex_tangential_accel = 0.0;
+ real_t tex_tangential_accel = 1.0;
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
}
- real_t tex_radial_accel = 0.0;
+ real_t tex_radial_accel = 1.0;
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
}
- real_t tex_damping = 0.0;
+ real_t tex_damping = 1.0;
if (curve_parameters[PARAM_DAMPING].is_valid()) {
tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
}
- real_t tex_angle = 0.0;
+ real_t tex_angle = 1.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
- real_t tex_anim_speed = 0.0;
+ real_t tex_anim_speed = 1.0;
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
}
- real_t tex_anim_offset = 0.0;
+ real_t tex_anim_offset = 1.0;
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
}
@@ -984,7 +984,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed));
p.custom[0] = Math::deg2rad(base_angle); //angle
- p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + p.custom[1] * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); //angle
+ p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); //angle
}
//apply color
//apply hue rotation
diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp
deleted file mode 100644
index 23df00c1f6..0000000000
--- a/scene/3d/proximity_group_3d.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*************************************************************************/
-/* proximity_group_3d.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "proximity_group_3d.h"
-
-#include "core/math/math_funcs.h"
-
-void ProximityGroup3D::_clear_groups() {
- Map<StringName, uint32_t>::Element *E;
- const int size = 16;
-
- do {
- StringName remove_list[size];
- E = groups.front();
- int num = 0;
- while (E && num < size) {
- if (E->get() != group_version) {
- remove_list[num++] = E->key();
- }
-
- E = E->next();
- }
- for (int i = 0; i < num; i++) {
- groups.erase(remove_list[i]);
- }
- } while (E);
-}
-
-void ProximityGroup3D::_update_groups() {
- if (grid_radius == Vector3(0, 0, 0)) {
- return;
- }
-
- ++group_version;
-
- Vector3 pos = get_global_transform().get_origin();
- Vector3 vcell = pos / cell_size;
- int cell[3] = { Math::fast_ftoi(vcell.x), Math::fast_ftoi(vcell.y), Math::fast_ftoi(vcell.z) };
-
- _add_groups(cell, group_name, 0);
-
- _clear_groups();
-}
-
-void ProximityGroup3D::_add_groups(int *p_cell, String p_base, int p_depth) {
- p_base = p_base + "|";
- if (grid_radius[p_depth] == 0) {
- if (p_depth == 2) {
- _new_group(p_base);
- } else {
- _add_groups(p_cell, p_base, p_depth + 1);
- }
- }
-
- int start = p_cell[p_depth] - grid_radius[p_depth];
- int end = p_cell[p_depth] + grid_radius[p_depth];
-
- for (int i = start; i <= end; i++) {
- String gname = p_base + itos(i);
- if (p_depth == 2) {
- _new_group(gname);
- } else {
- _add_groups(p_cell, gname, p_depth + 1);
- }
- }
-}
-
-void ProximityGroup3D::_new_group(StringName p_name) {
- const Map<StringName, uint32_t>::Element *E = groups.find(p_name);
- if (!E) {
- add_to_group(p_name);
- }
-
- groups[p_name] = group_version;
-}
-
-void ProximityGroup3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_EXIT_TREE:
- ++group_version;
- _clear_groups();
- break;
- case NOTIFICATION_TRANSFORM_CHANGED:
- _update_groups();
- break;
- }
-}
-
-void ProximityGroup3D::broadcast(String p_method, Variant p_parameters) {
- Map<StringName, uint32_t>::Element *E;
- E = groups.front();
- while (E) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_method, p_parameters);
- E = E->next();
- }
-}
-
-void ProximityGroup3D::_proximity_group_broadcast(String p_method, Variant p_parameters) {
- if (dispatch_mode == MODE_PROXY) {
- ERR_FAIL_COND(!is_inside_tree());
- get_parent()->call(p_method, p_parameters);
- } else {
- emit_signal(SNAME("broadcast"), p_method, p_parameters);
- }
-}
-
-void ProximityGroup3D::set_group_name(const String &p_group_name) {
- group_name = p_group_name;
-}
-
-String ProximityGroup3D::get_group_name() const {
- return group_name;
-}
-
-void ProximityGroup3D::set_dispatch_mode(DispatchMode p_mode) {
- dispatch_mode = p_mode;
-}
-
-ProximityGroup3D::DispatchMode ProximityGroup3D::get_dispatch_mode() const {
- return dispatch_mode;
-}
-
-void ProximityGroup3D::set_grid_radius(const Vector3 &p_radius) {
- grid_radius = p_radius;
-}
-
-Vector3 ProximityGroup3D::get_grid_radius() const {
- return grid_radius;
-}
-
-void ProximityGroup3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_group_name", "name"), &ProximityGroup3D::set_group_name);
- ClassDB::bind_method(D_METHOD("get_group_name"), &ProximityGroup3D::get_group_name);
- ClassDB::bind_method(D_METHOD("set_dispatch_mode", "mode"), &ProximityGroup3D::set_dispatch_mode);
- ClassDB::bind_method(D_METHOD("get_dispatch_mode"), &ProximityGroup3D::get_dispatch_mode);
- ClassDB::bind_method(D_METHOD("set_grid_radius", "radius"), &ProximityGroup3D::set_grid_radius);
- ClassDB::bind_method(D_METHOD("get_grid_radius"), &ProximityGroup3D::get_grid_radius);
-
- ClassDB::bind_method(D_METHOD("broadcast", "method", "parameters"), &ProximityGroup3D::broadcast);
-
- ClassDB::bind_method(D_METHOD("_proximity_group_broadcast", "method", "parameters"), &ProximityGroup3D::_proximity_group_broadcast);
-
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "group_name"), "set_group_name", "get_group_name");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dispatch_mode", PROPERTY_HINT_ENUM, "Proxy,Signal"), "set_dispatch_mode", "get_dispatch_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "grid_radius"), "set_grid_radius", "get_grid_radius");
-
- ADD_SIGNAL(MethodInfo("broadcast", PropertyInfo(Variant::STRING, "method"), PropertyInfo(Variant::ARRAY, "parameters")));
-
- BIND_ENUM_CONSTANT(MODE_PROXY);
- BIND_ENUM_CONSTANT(MODE_SIGNAL);
-}
-
-ProximityGroup3D::ProximityGroup3D() {
- set_notify_transform(true);
-}
diff --git a/scene/3d/proximity_group_3d.h b/scene/3d/proximity_group_3d.h
deleted file mode 100644
index e45adc3040..0000000000
--- a/scene/3d/proximity_group_3d.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/
-/* proximity_group_3d.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef PROXIMITY_GROUP_H
-#define PROXIMITY_GROUP_H
-
-#include "node_3d.h"
-
-class ProximityGroup3D : public Node3D {
- GDCLASS(ProximityGroup3D, Node3D);
-
-public:
- enum DispatchMode {
- MODE_PROXY,
- MODE_SIGNAL,
- };
-
-private:
- Map<StringName, uint32_t> groups;
-
- String group_name;
- DispatchMode dispatch_mode = MODE_PROXY;
- Vector3 grid_radius = Vector3(1, 1, 1);
-
- real_t cell_size = 1.0;
- uint32_t group_version = 0;
-
- void _clear_groups();
- void _update_groups();
- void _add_groups(int *p_cell, String p_base, int p_depth);
- void _new_group(StringName p_name);
-
- void _proximity_group_broadcast(String p_method, Variant p_parameters);
-
-protected:
- void _notification(int p_what);
-
- static void _bind_methods();
-
-public:
- void set_group_name(const String &p_group_name);
- String get_group_name() const;
-
- void set_dispatch_mode(DispatchMode p_mode);
- DispatchMode get_dispatch_mode() const;
-
- void set_grid_radius(const Vector3 &p_radius);
- Vector3 get_grid_radius() const;
-
- void broadcast(String p_method, Variant p_parameters);
-
- ProximityGroup3D();
- ~ProximityGroup3D() {}
-};
-
-VARIANT_ENUM_CAST(ProximityGroup3D::DispatchMode);
-
-#endif // PROXIMITY_GROUP_H
diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp
index 5546b88fb1..d9907430fc 100644
--- a/scene/3d/soft_dynamic_body_3d.cpp
+++ b/scene/3d/soft_dynamic_body_3d.cpp
@@ -100,12 +100,11 @@ SoftDynamicBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
offset = obj_tocopy.offset;
}
-SoftDynamicBody3D::PinnedPoint &SoftDynamicBody3D::PinnedPoint::operator=(const PinnedPoint &obj) {
+void SoftDynamicBody3D::PinnedPoint::operator=(const PinnedPoint &obj) {
point_index = obj.point_index;
spatial_attachment_path = obj.spatial_attachment_path;
spatial_attachment = obj.spatial_attachment;
offset = obj.offset;
- return *this;
}
void SoftDynamicBody3D::_update_pickable() {
diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h
index 57e116aa05..daef9acac0 100644
--- a/scene/3d/soft_dynamic_body_3d.h
+++ b/scene/3d/soft_dynamic_body_3d.h
@@ -80,7 +80,7 @@ public:
PinnedPoint();
PinnedPoint(const PinnedPoint &obj_tocopy);
- PinnedPoint &operator=(const PinnedPoint &obj);
+ void operator=(const PinnedPoint &obj);
};
private:
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 90af70e7c2..197a5c0f27 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -625,6 +625,7 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
texture->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update"));
}
_queue_update();
+ emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> Sprite3D::get_texture() const {
@@ -780,6 +781,7 @@ void Sprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
+ ADD_SIGNAL(MethodInfo("texture_changed"));
}
Sprite3D::Sprite3D() {
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index 26fa43b969..4eeb987dde 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -133,8 +133,8 @@ Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
- if (!environment.is_valid()) {
- warnings.push_back(TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."));
+ if (!environment.is_valid() && !camera_effects.is_valid()) {
+ warnings.push_back(TTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Effects\" property to contain a CameraEffects resource, or both."));
}
if (!is_inside_tree()) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 93339711bd..b9435b6692 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1754,7 +1754,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_o
Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
ERR_FAIL_COND_V(!can_apply_reset(), Ref<AnimatedValuesBackup>());
- Ref<Animation> reset_anim = animation_set["RESET"].animation;
+ Ref<Animation> reset_anim = animation_set[SceneStringNames::get_singleton()->RESET].animation;
ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>());
Node *root_node = get_node_or_null(root);
@@ -1762,8 +1762,8 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
AnimationPlayer *aux_player = memnew(AnimationPlayer);
EditorNode::get_singleton()->add_child(aux_player);
- aux_player->add_animation("RESET", reset_anim);
- aux_player->set_assigned_animation("RESET");
+ aux_player->add_animation(SceneStringNames::get_singleton()->RESET, reset_anim);
+ aux_player->set_assigned_animation(SceneStringNames::get_singleton()->RESET);
// Forcing the use of the original root because the scene where original player belongs may be not the active one
Node *root = get_node(get_root());
Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(root);
@@ -1785,7 +1785,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
}
bool AnimationPlayer::can_apply_reset() const {
- return has_animation("RESET") && playback.assigned != StringName("RESET");
+ return has_animation(SceneStringNames::get_singleton()->RESET) && playback.assigned != SceneStringNames::get_singleton()->RESET;
}
#endif
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index ea04918988..1b07c086c0 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -198,7 +198,7 @@ private:
struct PlaybackData {
AnimationData *from = nullptr;
- float pos = 0.0;
+ double pos = 0.0;
float speed_scale = 1.0;
};
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index 3c8949ddfb..56c04b32e3 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -367,7 +367,7 @@ void SceneDebuggerObject::serialize(Array &r_arr, int p_max_size) {
PropertyHint hint = pi.hint;
String hint_string = pi.hint_string;
- if (!res.is_null()) {
+ if (!res.is_null() && !res->get_path().is_empty()) {
var = res->get_path();
} else { //only send information that can be sent..
int len = 0; //test how big is this to encode
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index cb9f13e970..83c392614b 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -295,7 +295,7 @@ void BoxContainer::_notification(int p_what) {
_resort();
} break;
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 9818c8f0cc..2932707401 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -82,13 +82,13 @@ void Button::_notification(int p_what) {
xl_text = atr(text);
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_THEME_CHANGED: {
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_DRAW: {
@@ -368,7 +368,7 @@ void Button::set_text(const String &p_text) {
_shape();
update();
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -428,7 +428,7 @@ void Button::set_icon(const Ref<Texture2D> &p_icon) {
if (icon != p_icon) {
icon = p_icon;
update();
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -440,7 +440,7 @@ void Button::set_expand_icon(bool p_enabled) {
if (expand_icon != p_enabled) {
expand_icon = p_enabled;
update();
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -463,7 +463,7 @@ void Button::set_clip_text(bool p_enabled) {
if (clip_text != p_enabled) {
clip_text = p_enabled;
update();
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -484,7 +484,7 @@ Button::TextAlign Button::get_text_align() const {
void Button::set_icon_align(TextAlign p_align) {
icon_align = p_align;
- minimum_size_changed();
+ update_minimum_size();
update();
}
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index 909516e7ef..e17552006f 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -61,7 +61,7 @@ void CenterContainer::set_use_top_left(bool p_enable) {
use_top_left = p_enable;
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index a1bd82f6f7..81afa53d85 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -35,7 +35,7 @@
void Container::_child_minsize_changed() {
//Size2 ms = get_combined_minimum_size();
//if (ms.width > get_size().width || ms.height > get_size().height) {
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
@@ -51,7 +51,7 @@ void Container::add_child_notify(Node *p_child) {
control->connect(SNAME("minimum_size_changed"), callable_mp(this, &Container::_child_minsize_changed));
control->connect(SNAME("visibility_changed"), callable_mp(this, &Container::_child_minsize_changed));
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
@@ -62,7 +62,7 @@ void Container::move_child_notify(Node *p_child) {
return;
}
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
@@ -78,7 +78,7 @@ void Container::remove_child_notify(Node *p_child) {
control->disconnect("minimum_size_changed", callable_mp(this, &Container::_child_minsize_changed));
control->disconnect("visibility_changed", callable_mp(this, &Container::_child_minsize_changed));
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 9f715be155..fd6fb48412 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -192,7 +192,7 @@ void Control::set_custom_minimum_size(const Size2 &p_custom) {
return;
}
data.custom_minimum_size = p_custom;
- minimum_size_changed();
+ update_minimum_size();
}
Size2 Control::get_custom_minimum_size() const {
@@ -213,7 +213,7 @@ void Control::_update_minimum_size_cache() {
data.minimum_size_valid = true;
if (size_changed) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -713,7 +713,7 @@ void Control::_notification(int p_notification) {
update();
} break;
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -2534,7 +2534,7 @@ void Control::grab_click_focus() {
get_viewport()->_gui_grab_click_focus(this);
}
-void Control::minimum_size_changed() {
+void Control::update_minimum_size() {
if (!is_inside_tree() || data.block_minimum_size_adjust) {
return;
}
@@ -2590,7 +2590,7 @@ Control *Control::get_focus_owner() const {
void Control::warp_mouse(const Point2 &p_to_pos) {
ERR_FAIL_COND(!is_inside_tree());
- get_viewport()->warp_mouse(get_global_transform().xform(p_to_pos));
+ get_viewport()->warp_mouse(get_screen_transform().xform(p_to_pos));
}
bool Control::is_text_field() const {
@@ -2696,7 +2696,7 @@ real_t Control::get_rotation() const {
void Control::_override_changed() {
notification(NOTIFICATION_THEME_CHANGED);
emit_signal(SceneStringNames::get_singleton()->theme_changed);
- minimum_size_changed(); // overrides are likely to affect minimum size
+ update_minimum_size(); // Overrides are likely to affect minimum size.
}
void Control::set_pivot_offset(const Vector2 &p_pivot) {
@@ -2977,7 +2977,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Control::warp_mouse);
- ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
+ ClassDB::bind_method(D_METHOD("update_minimum_size"), &Control::update_minimum_size);
ClassDB::bind_method(D_METHOD("set_layout_direction", "direction"), &Control::set_layout_direction);
ClassDB::bind_method(D_METHOD("get_layout_direction"), &Control::get_layout_direction);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 1a94cc68a6..4cc949d0a8 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -441,7 +441,7 @@ public:
void set_stretch_ratio(real_t p_ratio);
real_t get_stretch_ratio() const;
- void minimum_size_changed();
+ void update_minimum_size();
/* FOCUS */
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 44853fc006..e3754c4d38 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -473,6 +473,13 @@ void FileDialog::update_file_list() {
dir_access->list_dir_begin();
+ if (dir_access->is_readable(dir_access->get_current_dir().utf8().get_data())) {
+ message->hide();
+ } else {
+ message->set_text(TTRC("You don't have permission to access contents of this folder."));
+ message->show();
+ }
+
TreeItem *root = tree->create_item();
Ref<Texture2D> folder = vbox->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
Ref<Texture2D> file_icon = vbox->get_theme_icon(SNAME("file"), SNAME("FileDialog"));
@@ -482,17 +489,11 @@ void FileDialog::update_file_list() {
List<String> dirs;
bool is_hidden;
- String item;
-
- if (dir_access->is_readable(dir_access->get_current_dir().utf8().get_data())) {
- message->hide();
- } else {
- message->set_text(TTRC("You don't have permission to access contents of this folder."));
- message->show();
- }
+ String item = dir_access->get_next();
- while ((item = dir_access->get_next()) != "") {
+ while (!item.is_empty()) {
if (item == "." || item == "..") {
+ item = dir_access->get_next();
continue;
}
@@ -505,6 +506,7 @@ void FileDialog::update_file_list() {
dirs.push_back(item);
}
}
+ item = dir_access->get_next();
}
dirs.sort_custom<NaturalNoCaseComparator>();
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index e7d98a686f..b0050f028b 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1166,7 +1166,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
top_layer->update();
minimap->update();
} else {
- emit_signal(SNAME("popup_request"), b->get_global_position());
+ emit_signal(SNAME("popup_request"), get_screen_position() + b->get_position());
}
}
}
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index e7094c89b1..3177911a70 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -442,7 +442,7 @@ void GraphNode::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
}
@@ -666,7 +666,7 @@ void GraphNode::set_title(const String &p_title) {
_shape();
update();
- minimum_size_changed();
+ update_minimum_size();
}
String GraphNode::get_title() const {
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 2beb2624d2..624330cdf6 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -182,7 +182,7 @@ void GridContainer::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
@@ -195,7 +195,7 @@ void GridContainer::set_columns(int p_columns) {
ERR_FAIL_COND(p_columns < 1);
columns = p_columns;
queue_sort();
- minimum_size_changed();
+ update_minimum_size();
}
int GridContainer::get_columns() const {
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 408ef53e89..857058f94e 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1037,7 +1037,7 @@ void ItemList::_notification(int p_what) {
}
}
- minimum_size_changed();
+ update_minimum_size();
shape_changed = false;
}
@@ -1663,7 +1663,7 @@ void ItemList::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines", PROPERTY_HINT_RANGE, "1,10,1,or_greater"), "set_max_text_lines", "get_max_text_lines");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
- ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "item_");
+ ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_");
ADD_GROUP("Columns", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 50908f6a77..3e1b9c9ceb 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -44,7 +44,7 @@ void Label::set_autowrap_mode(Label::AutowrapMode p_mode) {
update();
if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -207,7 +207,7 @@ void Label::_shape() {
_update_visible();
if (autowrap_mode == AUTOWRAP_OFF || !clip || overrun_behavior == OVERRUN_NO_TRIMMING) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -592,7 +592,7 @@ void Label::set_text(const String &p_string) {
visible_chars = get_total_character_count() * percent_visible;
}
update();
- minimum_size_changed();
+ update_minimum_size();
}
void Label::set_text_direction(Control::TextDirection p_text_direction) {
@@ -668,7 +668,7 @@ String Label::get_language() const {
void Label::set_clip_text(bool p_clip) {
clip = p_clip;
update();
- minimum_size_changed();
+ update_minimum_size();
}
bool Label::is_clipping_text() const {
@@ -682,7 +682,7 @@ void Label::set_text_overrun_behavior(Label::OverrunBehavior p_behavior) {
}
update();
if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
- minimum_size_changed();
+ update_minimum_size();
}
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 69b08fda3c..80f723de62 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -227,7 +227,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
if (b->is_pressed() && b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) {
_ensure_menu();
- menu->set_position(get_screen_transform().xform(get_local_mouse_position()));
+ menu->set_position(get_screen_position() + get_local_mouse_position());
menu->reset_size();
menu->popup();
grab_focus();
@@ -322,7 +322,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
deselect();
selection.start_column = caret_column;
selection.creating = true;
- } else if (selection.enabled) {
+ } else if (selection.enabled && !selection.double_click) {
selection.drag_attempt = true;
}
}
@@ -392,7 +392,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
if (k->is_action("ui_menu", true)) {
_ensure_menu();
Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2);
- menu->set_position(get_global_transform().xform(pos));
+ menu->set_position(get_screen_position() + pos);
menu->reset_size();
menu->popup();
menu->grab_focus();
@@ -588,13 +588,19 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
if (p_data.get_type() == Variant::STRING && is_editable()) {
set_caret_at_pixel_pos(p_point.x);
int caret_column_tmp = caret_column;
+ bool is_inside_sel = selection.enabled && caret_column >= selection.begin && caret_column <= selection.end;
+ if (Input::get_singleton()->is_key_pressed(Key::CTRL)) {
+ is_inside_sel = selection.enabled && caret_column > selection.begin && caret_column < selection.end;
+ }
if (selection.drag_attempt) {
selection.drag_attempt = false;
- if (caret_column < selection.begin || caret_column > selection.end) {
- if (caret_column_tmp > selection.end) {
- caret_column_tmp = caret_column_tmp - (selection.end - selection.begin);
+ if (!is_inside_sel) {
+ if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) {
+ if (caret_column_tmp > selection.end) {
+ caret_column_tmp = caret_column_tmp - (selection.end - selection.begin);
+ }
+ selection_delete();
}
- selection_delete();
set_caret_column(caret_column_tmp);
insert_text_at_caret(p_data);
@@ -975,7 +981,7 @@ void LineEdit::_notification(int p_what) {
if (is_drag_successful()) {
if (selection.drag_attempt) {
selection.drag_attempt = false;
- if (is_editable()) {
+ if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) {
selection_delete();
} else if (deselect_on_focus_loss_enabled) {
deselect();
@@ -1712,7 +1718,7 @@ void LineEdit::set_editable(bool p_editable) {
editable = p_editable;
- minimum_size_changed();
+ update_minimum_size();
update();
}
@@ -1942,7 +1948,7 @@ void LineEdit::_editor_settings_changed() {
void LineEdit::set_expand_to_text_length_enabled(bool p_enabled) {
expand_to_text_length = p_enabled;
- minimum_size_changed();
+ update_minimum_size();
set_caret_column(caret_column);
}
@@ -1956,7 +1962,7 @@ void LineEdit::set_clear_button_enabled(bool p_enabled) {
}
clear_button_enabled = p_enabled;
_fit_to_width();
- minimum_size_changed();
+ update_minimum_size();
update();
}
@@ -2017,7 +2023,7 @@ void LineEdit::set_right_icon(const Ref<Texture2D> &p_icon) {
}
right_icon = p_icon;
_fit_to_width();
- minimum_size_changed();
+ update_minimum_size();
update();
}
@@ -2081,7 +2087,7 @@ void LineEdit::_shape() {
Size2 size = TS->shaped_text_get_size(text_rid);
if ((expand_to_text_length && old_size.x != size.x) || (old_size.y != size.y)) {
- minimum_size_changed();
+ update_minimum_size();
}
}
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index c3201186ea..9856247b7c 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -52,7 +52,7 @@ void LinkButton::set_text(const String &p_text) {
text = p_text;
xl_text = atr(text);
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
}
@@ -149,7 +149,7 @@ void LinkButton::_notification(int p_what) {
xl_text = atr(text);
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
@@ -157,7 +157,7 @@ void LinkButton::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
_shape();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_DRAW: {
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index 50b4d192a9..af239d67ae 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -90,7 +90,7 @@ void MarginContainer::_notification(int p_what) {
}
} break;
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
} break;
}
}
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 39c7b04955..32501b65a0 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -207,7 +207,7 @@ void MenuButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_count"), &MenuButton::get_item_count);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover");
- ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "popup/item_");
+ ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
ADD_SIGNAL(MethodInfo("about_to_popup"));
}
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 8bf25ac915..ea5c82306d 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -97,7 +97,7 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
if (texture.is_valid())
texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
*/
- minimum_size_changed();
+ update_minimum_size();
emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
@@ -109,7 +109,7 @@ void NinePatchRect::set_patch_margin(Side p_side, int p_size) {
ERR_FAIL_INDEX((int)p_side, 4);
margin[p_side] = p_size;
update();
- minimum_size_changed();
+ update_minimum_size();
}
int NinePatchRect::get_patch_margin(Side p_side) const {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 2e854abb76..d2062a66f9 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -216,7 +216,7 @@ void PopupMenu::_activate_submenu(int p_over) {
submenu_pos.x = this_pos.x + submenu_size.width;
}
- if (submenu_pos.x + submenu_size.width > get_parent_rect().size.width) {
+ if (submenu_pos.x + submenu_size.width > get_parent_rect().position.x + get_parent_rect().size.width) {
submenu_pos.x = this_pos.x - submenu_size.width;
}
@@ -1762,7 +1762,7 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
- ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "item_");
+ ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_");
ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id")));
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index fd19fad667..2cb6ef91b5 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2190,7 +2190,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
updating_scroll = false;
if (fit_content_height) {
- minimum_size_changed();
+ update_minimum_size();
}
return;
}
@@ -2227,7 +2227,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
updating_scroll = false;
if (fit_content_height) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -2324,7 +2324,7 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline)
_invalidate_current_line(current_frame);
if (fixed_width != -1) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -2755,7 +2755,7 @@ void RichTextLabel::clear() {
}
if (fixed_width != -1) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -2772,7 +2772,7 @@ int RichTextLabel::get_tab_size() const {
void RichTextLabel::set_fit_content_height(bool p_enabled) {
if (p_enabled != fit_content_height) {
fit_content_height = p_enabled;
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -4268,7 +4268,7 @@ int RichTextLabel::get_total_character_count() const {
void RichTextLabel::set_fixed_size_to_width(int p_width) {
fixed_width = p_width;
- minimum_size_changed();
+ update_minimum_size();
}
Size2 RichTextLabel::get_minimum_size() const {
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 7b2ea46e17..f89623630d 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -467,7 +467,7 @@ void ScrollContainer::set_enable_h_scroll(bool p_enable) {
}
scroll_h = p_enable;
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
@@ -481,7 +481,7 @@ void ScrollContainer::set_enable_v_scroll(bool p_enable) {
}
scroll_v = p_enable;
- minimum_size_changed();
+ update_minimum_size();
queue_sort();
}
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index 9f4ec558dc..9c87d07f66 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -68,7 +68,6 @@ class ScrollContainer : public Container {
protected:
Size2 get_minimum_size() const override;
- virtual void gui_input(const Ref<InputEvent> &p_gui_input) override;
void _gui_focus_changed(Control *p_control);
void _update_dimensions();
void _notification(int p_what);
@@ -80,6 +79,8 @@ protected:
void _update_scrollbar_position();
public:
+ virtual void gui_input(const Ref<InputEvent> &p_gui_input) override;
+
void set_h_scroll(int p_pos);
int get_h_scroll() const;
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 4cc425aad3..f8cabe172c 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -142,7 +142,7 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
void Slider::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_MOUSE_ENTER: {
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index f30206c943..94a4886fef 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -220,8 +220,8 @@ void SpinBox::_notification(int p_what) {
} else if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
_value_changed(0);
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
- call_deferred(SNAME("minimum_size_changed"));
- get_line_edit()->call_deferred(SNAME("minimum_size_changed"));
+ call_deferred(SNAME("update_minimum_size"));
+ get_line_edit()->call_deferred(SNAME("update_minimum_size"));
} else if (p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
update();
}
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 6b53c0220e..106bb7949f 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -201,7 +201,7 @@ void SplitContainer::_notification(int p_what) {
}
} break;
case NOTIFICATION_THEME_CHANGED: {
- minimum_size_changed();
+ update_minimum_size();
} break;
}
}
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index 57ee7fd494..da23b0dde8 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -164,7 +164,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (rb_hover != -1) {
- // pressed
+ // Right mouse button clicked.
emit_signal(SNAME("tab_rmb_clicked"), rb_hover);
}
@@ -174,7 +174,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (cb_hover != -1) {
- // pressed
+ // Close button pressed.
emit_signal(SNAME("tab_close_pressed"), cb_hover);
}
@@ -183,7 +183,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
if (mb->is_pressed() && (mb->get_button_index() == MouseButton::LEFT || (select_with_rmb && mb->get_button_index() == MouseButton::RIGHT))) {
- // clicks
+ // Clicks.
Point2 pos = mb->get_position();
if (buttons_visible) {
@@ -235,7 +235,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
return;
}
- if (tabs[i].cb_rect.has_point(pos)) {
+ if (tabs[i].cb_rect.has_point(pos) && (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current))) {
cb_pressing = true;
update();
return;
@@ -285,7 +285,7 @@ void TabBar::_notification(int p_what) {
_shape(i);
}
_update_cache();
- minimum_size_changed();
+ update_minimum_size();
update();
} break;
case NOTIFICATION_RESIZED: {
@@ -554,7 +554,7 @@ void TabBar::set_tab_title(int p_tab, const String &p_title) {
tabs.write[p_tab].text = p_title;
_shape(p_tab);
update();
- minimum_size_changed();
+ update_minimum_size();
}
String TabBar::get_tab_title(int p_tab) const {
@@ -621,7 +621,7 @@ void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].icon = p_icon;
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TabBar::get_tab_icon(int p_tab) const {
@@ -645,7 +645,7 @@ void TabBar::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_butto
tabs.write[p_tab].right_button = p_right_button;
_update_cache();
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TabBar::get_tab_right_button(int p_tab) const {
@@ -659,7 +659,7 @@ void TabBar::_update_hover() {
}
const Point2 &pos = get_local_mouse_position();
- // test hovering to display right or close button
+ // test hovering to display right or close button.
int hover_now = -1;
int hover_buttons = -1;
for (int i = offset; i < tabs.size(); i++) {
@@ -684,7 +684,7 @@ void TabBar::_update_hover() {
emit_signal(SNAME("tab_hovered"), hover);
}
- if (hover_buttons == -1) { // no hover
+ if (hover_buttons == -1) { // No hover.
rb_hover = hover_buttons;
cb_hover = hover_buttons;
}
@@ -777,7 +777,7 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
_update_cache();
call_deferred(SNAME("_update_hover"));
update();
- minimum_size_changed();
+ update_minimum_size();
}
void TabBar::clear_tabs() {
@@ -797,7 +797,7 @@ void TabBar::remove_tab(int p_idx) {
_update_cache();
call_deferred(SNAME("_update_hover"));
update();
- minimum_size_changed();
+ update_minimum_size();
if (current < 0) {
current = 0;
@@ -860,7 +860,7 @@ bool TabBar::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
if (from_path == to_path) {
return true;
} else if (get_tabs_rearrange_group() != -1) {
- // drag and drop between other TabBars
+ // Drag and drop between other TabBars.
Node *from_node = get_node(from_path);
TabBar *from_tabs = Object::cast_to<TabBar>(from_node);
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
@@ -895,7 +895,7 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
emit_signal(SNAME("active_tab_rearranged"), hover_now);
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
- // drag and drop between Tabs
+ // Drag and drop between Tabs.
Node *from_node = get_node(from_path);
TabBar *from_tabs = Object::cast_to<TabBar>(from_node);
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
@@ -945,7 +945,7 @@ void TabBar::set_clip_tabs(bool p_clip_tabs) {
}
clip_tabs = p_clip_tabs;
update();
- minimum_size_changed();
+ update_minimum_size();
}
bool TabBar::get_clip_tabs() const {
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index ff53d91ea3..562f523f53 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -600,7 +600,7 @@ void TabContainer::_on_theme_changed() {
_refresh_texts();
- minimum_size_changed();
+ update_minimum_size();
if (get_tab_count() > 0) {
_repaint();
update();
@@ -995,7 +995,7 @@ void TabContainer::set_tabs_visible(bool p_visible) {
}
update();
- minimum_size_changed();
+ update_minimum_size();
}
bool TabContainer::are_tabs_visible() const {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 2cb9d10fca..c54b4dda00 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -39,6 +39,7 @@
#include "core/os/os.h"
#include "core/string/string_builder.h"
#include "core/string/translation.h"
+#include "label.h"
#include "scene/main/window.h"
@@ -1055,7 +1056,7 @@ void TextEdit::_notification(int p_what) {
while (highlighted_word_col != -1) {
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start);
for (int j = 0; j < sel.size(); j++) {
- Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height);
+ Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (line_spacing / 2), sel[j].y - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
continue;
}
@@ -1065,9 +1066,9 @@ void TextEdit::_notification(int p_what) {
} else if (rect.position.x + rect.size.x > xmargin_end) {
rect.size.x = xmargin_end - rect.position.x;
}
- rect.position.y = TS->shaped_text_get_ascent(rid) + font->get_underline_position(font_size);
- rect.size.y = font->get_underline_thickness(font_size);
- draw_rect(rect, font_selected_color);
+ rect.position.y += ceil(TS->shaped_text_get_ascent(rid)) + ceil(font->get_underline_position(font_size));
+ rect.size.y = MAX(1, font->get_underline_thickness(font_size));
+ draw_rect(rect, color);
}
highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
@@ -1224,7 +1225,7 @@ void TextEdit::_notification(int p_what) {
if (caret.draw_pos.x >= xmargin_beg && caret.draw_pos.x < xmargin_end) {
caret.visible = true;
- if (draw_caret) {
+ if (draw_caret || drag_caret_force_displayed) {
if (caret_type == CaretType::CARET_TYPE_BLOCK || overtype_mode) {
//Block or underline caret, draw trailing carets at full height.
int h = font->get_height(font_size);
@@ -1391,7 +1392,7 @@ void TextEdit::_notification(int p_what) {
DisplayServer::get_singleton()->virtual_keyboard_hide();
}
- if (deselect_on_focus_loss_enabled) {
+ if (deselect_on_focus_loss_enabled && !selection.drag_attempt) {
deselect();
}
} break;
@@ -1411,6 +1412,30 @@ void TextEdit::_notification(int p_what) {
update();
}
} break;
+ case Control::NOTIFICATION_DRAG_BEGIN: {
+ selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
+ drag_action = true;
+ dragging_minimap = false;
+ dragging_selection = false;
+ can_drag_minimap = false;
+ click_select_held->stop();
+ } break;
+ case Control::NOTIFICATION_DRAG_END: {
+ if (is_drag_successful()) {
+ if (selection.drag_attempt) {
+ selection.drag_attempt = false;
+ if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) {
+ delete_selection();
+ } else if (deselect_on_focus_loss_enabled) {
+ deselect();
+ }
+ }
+ } else {
+ selection.drag_attempt = false;
+ }
+ drag_action = false;
+ drag_caret_force_displayed = false;
+ } break;
}
}
@@ -1495,6 +1520,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
set_caret_line(row, false, false);
set_caret_column(col);
+ selection.drag_attempt = false;
if (mb->is_shift_pressed() && (caret.column != prev_col || caret.line != prev_line)) {
if (!selection.active) {
@@ -1538,6 +1564,9 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
update();
}
+ } else if (is_mouse_over_selection()) {
+ selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
+ selection.drag_attempt = true;
} else {
selection.active = false;
selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER;
@@ -1551,6 +1580,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
if (!mb->is_double_click() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < triple_click_timeout && mb->get_position().distance_to(last_dblclk_pos) < triple_click_tolerance) {
// Triple-click select line.
selection.selecting_mode = SelectionMode::SELECTION_MODE_LINE;
+ selection.drag_attempt = false;
_update_selection_mode_line();
last_dblclk = 0;
} else if (mb->is_double_click() && text[caret.line].length()) {
@@ -1594,17 +1624,23 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
_generate_context_menu();
- menu->set_position(get_screen_transform().xform(mpos));
+ menu->set_position(get_screen_position() + mpos);
menu->reset_size();
menu->popup();
grab_focus();
}
} else {
if (mb->get_button_index() == MouseButton::LEFT) {
+ if (selection.drag_attempt && is_mouse_over_selection()) {
+ selection.active = false;
+ }
dragging_minimap = false;
dragging_selection = false;
can_drag_minimap = false;
click_select_held->stop();
+ if (!drag_action) {
+ selection.drag_attempt = false;
+ }
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
}
@@ -1689,6 +1725,14 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
hovered_gutter = current_hovered_gutter;
update();
}
+
+ if (drag_action && can_drop_data(mpos, get_viewport()->gui_get_drag_data())) {
+ drag_caret_force_displayed = true;
+ Point2i pos = get_line_column_at_pos(get_local_mouse_pos());
+ set_caret_line(pos.y, false);
+ set_caret_column(pos.x);
+ dragging_selection = true;
+ }
}
if (draw_minimap && !dragging_selection) {
@@ -1827,7 +1871,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
if (context_menu_enabled) {
_generate_context_menu();
adjust_viewport_to_caret();
- menu->set_position(get_screen_transform().xform(get_caret_draw_pos()));
+ menu->set_position(get_screen_position() + get_caret_draw_pos());
menu->reset_size();
menu->popup();
menu->grab_focus();
@@ -2406,6 +2450,75 @@ bool TextEdit::is_text_field() const {
return true;
}
+Variant TextEdit::get_drag_data(const Point2 &p_point) {
+ if (selection.active && selection.drag_attempt) {
+ String t = get_selected_text();
+ Label *l = memnew(Label);
+ l->set_text(t);
+ set_drag_preview(l);
+ return t;
+ }
+
+ return Variant();
+}
+
+bool TextEdit::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
+ bool drop_override = Control::can_drop_data(p_point, p_data); // In case user wants to drop custom data.
+ if (drop_override) {
+ return drop_override;
+ }
+
+ return is_editable() && p_data.get_type() == Variant::STRING;
+}
+
+void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
+ Control::drop_data(p_point, p_data);
+
+ if (p_data.get_type() == Variant::STRING && is_editable()) {
+ Point2i pos = get_line_column_at_pos(get_local_mouse_pos());
+ int caret_row_tmp = pos.y;
+ int caret_column_tmp = pos.x;
+ if (selection.drag_attempt) {
+ selection.drag_attempt = false;
+ if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CTRL))) {
+ begin_complex_operation();
+ if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) {
+ if (caret_row_tmp > selection.to_line) {
+ caret_row_tmp = caret_row_tmp - (selection.to_line - selection.from_line);
+ } else if (caret_row_tmp == selection.to_line && caret_column_tmp >= selection.to_column) {
+ caret_column_tmp = caret_column_tmp - (selection.to_column - selection.from_column);
+ }
+ delete_selection();
+ } else {
+ deselect();
+ }
+
+ set_caret_line(caret_row_tmp, true, false);
+ set_caret_column(caret_column_tmp);
+ insert_text_at_caret(p_data);
+ end_complex_operation();
+ }
+ } else if (is_mouse_over_selection()) {
+ caret_row_tmp = selection.from_line;
+ caret_column_tmp = selection.from_column;
+ set_caret_line(caret_row_tmp, true, false);
+ set_caret_column(caret_column_tmp);
+ insert_text_at_caret(p_data);
+ grab_focus();
+ } else {
+ deselect();
+ set_caret_line(caret_row_tmp, true, false);
+ set_caret_column(caret_column_tmp);
+ insert_text_at_caret(p_data);
+ grab_focus();
+ }
+
+ if (caret_row_tmp != caret.line || caret_column_tmp != caret.column) {
+ select(caret_row_tmp, caret_column_tmp, caret.line, caret.column);
+ }
+ }
+}
+
Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
Point2i pos = get_line_column_at_pos(p_pos);
int row = pos.y;
@@ -3580,6 +3693,21 @@ bool TextEdit::is_dragging_cursor() const {
return dragging_selection || dragging_minimap;
}
+bool TextEdit::is_mouse_over_selection(bool p_edges) const {
+ if (!has_selection()) {
+ return false;
+ }
+ Point2i pos = get_line_column_at_pos(get_local_mouse_pos());
+ int row = pos.y;
+ int col = pos.x;
+ if (p_edges) {
+ if ((row == selection.from_line && col == selection.from_column) || (row == selection.to_line && col == selection.to_column)) {
+ return true;
+ }
+ }
+ return (row >= selection.from_line && row <= selection.to_line && (row > selection.from_line || col > selection.from_column) && (row < selection.to_line || col < selection.to_column));
+}
+
/* Caret */
void TextEdit::set_caret_type(CaretType p_type) {
caret_type = p_type;
@@ -4776,6 +4904,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_minimap_line_at_pos", "position"), &TextEdit::get_minimap_line_at_pos);
ClassDB::bind_method(D_METHOD("is_dragging_cursor"), &TextEdit::is_dragging_cursor);
+ ClassDB::bind_method(D_METHOD("is_mouse_over_selection", "edges"), &TextEdit::is_mouse_over_selection);
/* Caret. */
BIND_ENUM_CONSTANT(CARET_TYPE_LINE);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 42b21cbe9c..a1b2ed59f5 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -375,6 +375,9 @@ private:
bool caret_mid_grapheme_enabled = false;
+ bool drag_action = false;
+ bool drag_caret_force_displayed = false;
+
void _emit_caret_changed();
void _reset_caret_blink_timer();
@@ -400,6 +403,7 @@ private:
int to_column = 0;
bool shiftclick_left = false;
+ bool drag_attempt = false;
} selection;
bool selecting_enabled = true;
@@ -611,6 +615,9 @@ public:
virtual Size2 get_minimum_size() const override;
virtual bool is_text_field() const override;
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+ virtual Variant get_drag_data(const Point2 &p_point) override;
+ virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override;
+ virtual void drop_data(const Point2 &p_point, const Variant &p_data) override;
virtual String get_tooltip(const Point2 &p_pos) const override;
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
@@ -731,6 +738,7 @@ public:
int get_minimap_line_at_pos(const Point2i &p_pos) const;
bool is_dragging_cursor() const;
+ bool is_mouse_over_selection(bool p_edges = true) const;
/* Caret */
void set_caret_type(CaretType p_type);
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 8659ea06a2..3f0d907a7e 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -289,19 +289,19 @@ void TextureButton::_bind_methods() {
void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
normal = p_normal;
update();
- minimum_size_changed();
+ update_minimum_size();
}
void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
pressed = p_pressed;
update();
- minimum_size_changed();
+ update_minimum_size();
}
void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
hover = p_hover;
update();
- minimum_size_changed();
+ update_minimum_size();
}
void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
@@ -312,7 +312,7 @@ void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
click_mask = p_click_mask;
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TextureButton::get_normal_texture() const {
@@ -349,7 +349,7 @@ bool TextureButton::get_expand() const {
void TextureButton::set_expand(bool p_expand) {
expand = p_expand;
- minimum_size_changed();
+ update_minimum_size();
update();
}
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index facbe06d4d..6a926a0364 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -35,7 +35,7 @@
void TextureProgressBar::set_under_texture(const Ref<Texture2D> &p_texture) {
under = p_texture;
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TextureProgressBar::get_under_texture() const {
@@ -46,7 +46,7 @@ void TextureProgressBar::set_over_texture(const Ref<Texture2D> &p_texture) {
over = p_texture;
update();
if (under.is_null()) {
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -58,7 +58,7 @@ void TextureProgressBar::set_stretch_margin(Side p_side, int p_size) {
ERR_FAIL_INDEX((int)p_side, 4);
stretch_margin[p_side] = p_size;
update();
- minimum_size_changed();
+ update_minimum_size();
}
int TextureProgressBar::get_stretch_margin(Side p_side) const {
@@ -69,7 +69,7 @@ int TextureProgressBar::get_stretch_margin(Side p_side) const {
void TextureProgressBar::set_nine_patch_stretch(bool p_stretch) {
nine_patch_stretch = p_stretch;
update();
- minimum_size_changed();
+ update_minimum_size();
}
bool TextureProgressBar::get_nine_patch_stretch() const {
@@ -93,7 +93,7 @@ Size2 TextureProgressBar::get_minimum_size() const {
void TextureProgressBar::set_progress_texture(const Ref<Texture2D> &p_texture) {
progress = p_texture;
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TextureProgressBar::get_progress_texture() const {
@@ -501,6 +501,7 @@ void TextureProgressBar::_notification(int p_what) {
}
p *= get_relative_center();
+ p += progress_offset;
p = p.floor();
draw_line(p - Point2(8, 0), p + Point2(8, 0), Color(0.9, 0.5, 0.5), 2);
draw_line(p - Point2(0, 8), p + Point2(0, 8), Color(0.9, 0.5, 0.5), 2);
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index 1cba88e06f..85c15cdae7 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -152,7 +152,7 @@ void TextureRect::_bind_methods() {
void TextureRect::_texture_changed() {
if (texture.is_valid()) {
update();
- minimum_size_changed();
+ update_minimum_size();
}
}
@@ -172,7 +172,7 @@ void TextureRect::set_texture(const Ref<Texture2D> &p_tex) {
}
update();
- minimum_size_changed();
+ update_minimum_size();
}
Ref<Texture2D> TextureRect::get_texture() const {
@@ -182,7 +182,7 @@ Ref<Texture2D> TextureRect::get_texture() const {
void TextureRect::set_expand(bool p_expand) {
expand = p_expand;
update();
- minimum_size_changed();
+ update_minimum_size();
}
bool TextureRect::has_expand() const {
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 89caaaafd0..050ba9f519 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2532,7 +2532,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
popup_menu->set_size(Size2(col_width, 0));
- popup_menu->set_position(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
+ popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
popup_menu->popup();
popup_edited_item = p_item;
popup_edited_item_col = col;
@@ -3441,7 +3441,7 @@ bool Tree::edit_selected() {
}
popup_menu->set_size(Size2(rect.size.width, 0));
- popup_menu->set_position(get_global_position() + rect.position + Point2i(0, rect.size.height));
+ popup_menu->set_position(get_screen_position() + rect.position + Point2i(0, rect.size.height));
popup_menu->popup();
popup_edited_item = s;
popup_edited_item_col = col;
@@ -4370,7 +4370,7 @@ void Tree::scroll_to_item(TreeItem *p_item) {
void Tree::set_h_scroll_enabled(bool p_enable) {
h_scroll_enabled = p_enable;
- minimum_size_changed();
+ update_minimum_size();
}
bool Tree::is_h_scroll_enabled() const {
@@ -4379,7 +4379,7 @@ bool Tree::is_h_scroll_enabled() const {
void Tree::set_v_scroll_enabled(bool p_enable) {
v_scroll_enabled = p_enable;
- minimum_size_changed();
+ update_minimum_size();
}
bool Tree::is_v_scroll_enabled() const {
@@ -4830,6 +4830,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_allow_reselect"), &Tree::get_allow_reselect);
ADD_PROPERTY(PropertyInfo(Variant::INT, "columns"), "set_columns", "get_columns");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "column_titles_visible"), "set_column_titles_visible", "are_column_titles_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden");
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_stream_player.cpp
index 989aabc549..a11d56a2ed 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* video_player.cpp */
+/* video_stream_player.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "video_player.h"
+#include "video_stream_player.h"
#include "core/os/os.h"
#include "scene/scene_string_names.h"
#include "servers/audio_server.h"
-int VideoPlayer::sp_get_channel_count() const {
+int VideoStreamPlayer::sp_get_channel_count() const {
if (playback.is_null()) {
return 0;
}
@@ -42,7 +42,7 @@ int VideoPlayer::sp_get_channel_count() const {
return playback->get_channels();
}
-bool VideoPlayer::mix(AudioFrame *p_buffer, int p_frames) {
+bool VideoStreamPlayer::mix(AudioFrame *p_buffer, int p_frames) {
// Check the amount resampler can really handle.
// If it cannot, wait "wait_resampler_phase_limit" times.
// This mechanism contributes to smoother pause/unpause operation.
@@ -56,11 +56,11 @@ bool VideoPlayer::mix(AudioFrame *p_buffer, int p_frames) {
}
// Called from main thread (e.g. VideoStreamPlaybackTheora::update).
-int VideoPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_frames) {
+int VideoStreamPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_frames) {
ERR_FAIL_NULL_V(p_udata, 0);
ERR_FAIL_NULL_V(p_data, 0);
- VideoPlayer *vp = (VideoPlayer *)p_udata;
+ VideoStreamPlayer *vp = (VideoStreamPlayer *)p_udata;
int todo = MIN(vp->resampler.get_writer_space(), p_frames);
@@ -75,13 +75,13 @@ int VideoPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_f
return todo;
}
-void VideoPlayer::_mix_audios(void *p_self) {
+void VideoStreamPlayer::_mix_audios(void *p_self) {
ERR_FAIL_NULL(p_self);
- reinterpret_cast<VideoPlayer *>(p_self)->_mix_audio();
+ reinterpret_cast<VideoStreamPlayer *>(p_self)->_mix_audio();
}
// Called from audio thread
-void VideoPlayer::_mix_audio() {
+void VideoStreamPlayer::_mix_audio() {
if (!stream.is_valid()) {
return;
}
@@ -126,7 +126,7 @@ void VideoPlayer::_mix_audio() {
}
}
-void VideoPlayer::_notification(int p_notification) {
+void VideoStreamPlayer::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_ENTER_TREE: {
AudioServer::get_singleton()->add_mix_callback(_mix_audios, this);
@@ -180,7 +180,7 @@ void VideoPlayer::_notification(int p_notification) {
};
};
-Size2 VideoPlayer::get_minimum_size() const {
+Size2 VideoStreamPlayer::get_minimum_size() const {
if (!expand && !texture.is_null()) {
return texture->get_size();
} else {
@@ -188,17 +188,17 @@ Size2 VideoPlayer::get_minimum_size() const {
}
}
-void VideoPlayer::set_expand(bool p_expand) {
+void VideoStreamPlayer::set_expand(bool p_expand) {
expand = p_expand;
update();
- minimum_size_changed();
+ update_minimum_size();
}
-bool VideoPlayer::has_expand() const {
+bool VideoStreamPlayer::has_expand() const {
return expand;
}
-void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) {
+void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
stop();
AudioServer::get_singleton()->lock();
@@ -241,15 +241,15 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) {
update();
if (!expand) {
- minimum_size_changed();
+ update_minimum_size();
}
};
-Ref<VideoStream> VideoPlayer::get_stream() const {
+Ref<VideoStream> VideoStreamPlayer::get_stream() const {
return stream;
};
-void VideoPlayer::play() {
+void VideoStreamPlayer::play() {
ERR_FAIL_COND(!is_inside_tree());
if (playback.is_null()) {
return;
@@ -262,7 +262,7 @@ void VideoPlayer::play() {
last_audio_time = 0;
};
-void VideoPlayer::stop() {
+void VideoStreamPlayer::stop() {
if (!is_inside_tree()) {
return;
}
@@ -277,7 +277,7 @@ void VideoPlayer::stop() {
last_audio_time = 0;
};
-bool VideoPlayer::is_playing() const {
+bool VideoStreamPlayer::is_playing() const {
if (playback.is_null()) {
return false;
}
@@ -285,7 +285,7 @@ bool VideoPlayer::is_playing() const {
return playback->is_playing();
};
-void VideoPlayer::set_paused(bool p_paused) {
+void VideoStreamPlayer::set_paused(bool p_paused) {
paused = p_paused;
if (playback.is_valid()) {
playback->set_paused(p_paused);
@@ -294,35 +294,35 @@ void VideoPlayer::set_paused(bool p_paused) {
last_audio_time = 0;
};
-bool VideoPlayer::is_paused() const {
+bool VideoStreamPlayer::is_paused() const {
return paused;
}
-void VideoPlayer::set_buffering_msec(int p_msec) {
+void VideoStreamPlayer::set_buffering_msec(int p_msec) {
buffering_ms = p_msec;
}
-int VideoPlayer::get_buffering_msec() const {
+int VideoStreamPlayer::get_buffering_msec() const {
return buffering_ms;
}
-void VideoPlayer::set_audio_track(int p_track) {
+void VideoStreamPlayer::set_audio_track(int p_track) {
audio_track = p_track;
}
-int VideoPlayer::get_audio_track() const {
+int VideoStreamPlayer::get_audio_track() const {
return audio_track;
}
-void VideoPlayer::set_volume(float p_vol) {
+void VideoStreamPlayer::set_volume(float p_vol) {
volume = p_vol;
};
-float VideoPlayer::get_volume() const {
+float VideoStreamPlayer::get_volume() const {
return volume;
};
-void VideoPlayer::set_volume_db(float p_db) {
+void VideoStreamPlayer::set_volume_db(float p_db) {
if (p_db < -79) {
set_volume(0);
} else {
@@ -330,7 +330,7 @@ void VideoPlayer::set_volume_db(float p_db) {
}
};
-float VideoPlayer::get_volume_db() const {
+float VideoStreamPlayer::get_volume_db() const {
if (volume == 0) {
return -80;
} else {
@@ -338,27 +338,27 @@ float VideoPlayer::get_volume_db() const {
}
};
-String VideoPlayer::get_stream_name() const {
+String VideoStreamPlayer::get_stream_name() const {
if (stream.is_null()) {
return "<No Stream>";
}
return stream->get_name();
};
-float VideoPlayer::get_stream_position() const {
+float VideoStreamPlayer::get_stream_position() const {
if (playback.is_null()) {
return 0;
}
return playback->get_playback_position();
};
-void VideoPlayer::set_stream_position(float p_position) {
+void VideoStreamPlayer::set_stream_position(float p_position) {
if (playback.is_valid()) {
playback->seek(p_position);
}
}
-Ref<Texture2D> VideoPlayer::get_video_texture() const {
+Ref<Texture2D> VideoStreamPlayer::get_video_texture() const {
if (playback.is_valid()) {
return playback->get_texture();
}
@@ -366,22 +366,22 @@ Ref<Texture2D> VideoPlayer::get_video_texture() const {
return Ref<Texture2D>();
}
-void VideoPlayer::set_autoplay(bool p_enable) {
+void VideoStreamPlayer::set_autoplay(bool p_enable) {
autoplay = p_enable;
};
-bool VideoPlayer::has_autoplay() const {
+bool VideoStreamPlayer::has_autoplay() const {
return autoplay;
};
-void VideoPlayer::set_bus(const StringName &p_bus) {
+void VideoStreamPlayer::set_bus(const StringName &p_bus) {
//if audio is active, must lock this
AudioServer::get_singleton()->lock();
bus = p_bus;
AudioServer::get_singleton()->unlock();
}
-StringName VideoPlayer::get_bus() const {
+StringName VideoStreamPlayer::get_bus() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == bus) {
return bus;
@@ -390,7 +390,7 @@ StringName VideoPlayer::get_bus() const {
return "Master";
}
-void VideoPlayer::_validate_property(PropertyInfo &p_property) const {
+void VideoStreamPlayer::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "bus") {
String options;
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
@@ -405,45 +405,45 @@ void VideoPlayer::_validate_property(PropertyInfo &p_property) const {
}
}
-void VideoPlayer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VideoPlayer::set_stream);
- ClassDB::bind_method(D_METHOD("get_stream"), &VideoPlayer::get_stream);
+void VideoStreamPlayer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VideoStreamPlayer::set_stream);
+ ClassDB::bind_method(D_METHOD("get_stream"), &VideoStreamPlayer::get_stream);
- ClassDB::bind_method(D_METHOD("play"), &VideoPlayer::play);
- ClassDB::bind_method(D_METHOD("stop"), &VideoPlayer::stop);
+ ClassDB::bind_method(D_METHOD("play"), &VideoStreamPlayer::play);
+ ClassDB::bind_method(D_METHOD("stop"), &VideoStreamPlayer::stop);
- ClassDB::bind_method(D_METHOD("is_playing"), &VideoPlayer::is_playing);
+ ClassDB::bind_method(D_METHOD("is_playing"), &VideoStreamPlayer::is_playing);
- ClassDB::bind_method(D_METHOD("set_paused", "paused"), &VideoPlayer::set_paused);
- ClassDB::bind_method(D_METHOD("is_paused"), &VideoPlayer::is_paused);
+ ClassDB::bind_method(D_METHOD("set_paused", "paused"), &VideoStreamPlayer::set_paused);
+ ClassDB::bind_method(D_METHOD("is_paused"), &VideoStreamPlayer::is_paused);
- ClassDB::bind_method(D_METHOD("set_volume", "volume"), &VideoPlayer::set_volume);
- ClassDB::bind_method(D_METHOD("get_volume"), &VideoPlayer::get_volume);
+ ClassDB::bind_method(D_METHOD("set_volume", "volume"), &VideoStreamPlayer::set_volume);
+ ClassDB::bind_method(D_METHOD("get_volume"), &VideoStreamPlayer::get_volume);
- ClassDB::bind_method(D_METHOD("set_volume_db", "db"), &VideoPlayer::set_volume_db);
- ClassDB::bind_method(D_METHOD("get_volume_db"), &VideoPlayer::get_volume_db);
+ ClassDB::bind_method(D_METHOD("set_volume_db", "db"), &VideoStreamPlayer::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"), &VideoStreamPlayer::get_volume_db);
- ClassDB::bind_method(D_METHOD("set_audio_track", "track"), &VideoPlayer::set_audio_track);
- ClassDB::bind_method(D_METHOD("get_audio_track"), &VideoPlayer::get_audio_track);
+ ClassDB::bind_method(D_METHOD("set_audio_track", "track"), &VideoStreamPlayer::set_audio_track);
+ ClassDB::bind_method(D_METHOD("get_audio_track"), &VideoStreamPlayer::get_audio_track);
- ClassDB::bind_method(D_METHOD("get_stream_name"), &VideoPlayer::get_stream_name);
+ ClassDB::bind_method(D_METHOD("get_stream_name"), &VideoStreamPlayer::get_stream_name);
- ClassDB::bind_method(D_METHOD("set_stream_position", "position"), &VideoPlayer::set_stream_position);
- ClassDB::bind_method(D_METHOD("get_stream_position"), &VideoPlayer::get_stream_position);
+ ClassDB::bind_method(D_METHOD("set_stream_position", "position"), &VideoStreamPlayer::set_stream_position);
+ ClassDB::bind_method(D_METHOD("get_stream_position"), &VideoStreamPlayer::get_stream_position);
- ClassDB::bind_method(D_METHOD("set_autoplay", "enabled"), &VideoPlayer::set_autoplay);
- ClassDB::bind_method(D_METHOD("has_autoplay"), &VideoPlayer::has_autoplay);
+ ClassDB::bind_method(D_METHOD("set_autoplay", "enabled"), &VideoStreamPlayer::set_autoplay);
+ ClassDB::bind_method(D_METHOD("has_autoplay"), &VideoStreamPlayer::has_autoplay);
- ClassDB::bind_method(D_METHOD("set_expand", "enable"), &VideoPlayer::set_expand);
- ClassDB::bind_method(D_METHOD("has_expand"), &VideoPlayer::has_expand);
+ ClassDB::bind_method(D_METHOD("set_expand", "enable"), &VideoStreamPlayer::set_expand);
+ ClassDB::bind_method(D_METHOD("has_expand"), &VideoStreamPlayer::has_expand);
- ClassDB::bind_method(D_METHOD("set_buffering_msec", "msec"), &VideoPlayer::set_buffering_msec);
- ClassDB::bind_method(D_METHOD("get_buffering_msec"), &VideoPlayer::get_buffering_msec);
+ ClassDB::bind_method(D_METHOD("set_buffering_msec", "msec"), &VideoStreamPlayer::set_buffering_msec);
+ ClassDB::bind_method(D_METHOD("get_buffering_msec"), &VideoStreamPlayer::get_buffering_msec);
- ClassDB::bind_method(D_METHOD("set_bus", "bus"), &VideoPlayer::set_bus);
- ClassDB::bind_method(D_METHOD("get_bus"), &VideoPlayer::get_bus);
+ ClassDB::bind_method(D_METHOD("set_bus", "bus"), &VideoStreamPlayer::set_bus);
+ ClassDB::bind_method(D_METHOD("get_bus"), &VideoStreamPlayer::get_bus);
- ClassDB::bind_method(D_METHOD("get_video_texture"), &VideoPlayer::get_video_texture);
+ ClassDB::bind_method(D_METHOD("get_video_texture"), &VideoStreamPlayer::get_video_texture);
ADD_SIGNAL(MethodInfo("finished"));
@@ -461,9 +461,9 @@ void VideoPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
}
-VideoPlayer::VideoPlayer() {}
+VideoStreamPlayer::VideoStreamPlayer() {}
-VideoPlayer::~VideoPlayer() {
+VideoStreamPlayer::~VideoStreamPlayer() {
// if (stream_rid.is_valid())
// AudioServer::get_singleton()->free(stream_rid);
resampler.clear(); //Not necessary here, but make in consistent with other "stream_player" classes
diff --git a/scene/gui/video_player.h b/scene/gui/video_stream_player.h
index 0edad296a1..ad4a3dd9e9 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_stream_player.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* video_player.h */
+/* video_stream_player.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VIDEO_PLAYER_H
-#define VIDEO_PLAYER_H
+#ifndef VIDEO_STREAM_PLAYER_H
+#define VIDEO_STREAM_PLAYER_H
#include "scene/gui/control.h"
#include "scene/resources/video_stream.h"
#include "servers/audio/audio_rb_resampler.h"
#include "servers/audio_server.h"
-class VideoPlayer : public Control {
- GDCLASS(VideoPlayer, Control);
+class VideoStreamPlayer : public Control {
+ GDCLASS(VideoStreamPlayer, Control);
struct Output {
AudioFrame vol;
@@ -119,8 +119,8 @@ public:
void set_bus(const StringName &p_bus);
StringName get_bus() const;
- VideoPlayer();
- ~VideoPlayer();
+ VideoStreamPlayer();
+ ~VideoStreamPlayer();
};
-#endif // VIDEO_PLAYER_H
+#endif // VIDEO_STREAM_PLAYER_H
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 22e3c3bf24..0fd3a963ae 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -275,9 +275,6 @@ void CanvasItem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
ERR_FAIL_COND(!is_inside_tree());
- _update_texture_filter_changed(false);
- _update_texture_repeat_changed(false);
-
first_draw = true;
Node *parent = get_parent();
if (parent) {
@@ -306,6 +303,10 @@ void CanvasItem::_notification(int p_what) {
}
}
_enter_canvas();
+
+ _update_texture_filter_changed(false);
+ _update_texture_repeat_changed(false);
+
if (!block_transform_notify && !xform_change.in_list()) {
get_tree()->xform_change_list.add(&xform_change);
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f9e96a0784..af4032a77d 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -396,14 +396,15 @@ void Viewport::_notification(int p_what) {
#ifndef _3D_DISABLED
PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create();
- RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
+ RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, false);
RenderingServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0);
RenderingServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid());
contact_3d_debug_instance = RenderingServer::get_singleton()->instance_create();
RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh);
RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world_3d()->get_scenario());
- //RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
+ RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
#endif // _3D_DISABLED
+ set_physics_process_internal(true);
}
} break;
@@ -1182,7 +1183,7 @@ void Viewport::_gui_show_tooltip() {
Control *tooltip_owner = nullptr;
String tooltip_text = _gui_get_tooltip(
gui.tooltip_control,
- gui.tooltip_control->get_global_transform().xform_inv(gui.last_mouse_pos),
+ gui.tooltip_control->get_screen_transform().xform_inv(gui.last_mouse_pos),
&tooltip_owner);
tooltip_text = tooltip_text.strip_edges();
if (tooltip_text.is_empty()) {
@@ -1707,13 +1708,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (mm->get_button_mask() == MouseButton::NONE) {
// Nothing pressed.
- bool can_tooltip = true;
-
bool is_tooltip_shown = false;
if (gui.tooltip_popup) {
- if (can_tooltip && gui.tooltip_control) {
- String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform().xform_inv(mpos));
+ if (gui.tooltip_control) {
+ String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_screen_transform().xform_inv(mpos));
if (tooltip.length() == 0) {
_gui_cancel_tooltip();
@@ -1737,7 +1736,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- if (can_tooltip && !is_tooltip_shown) {
+ if (!is_tooltip_shown && over->can_process()) {
if (gui.tooltip_timer.is_valid()) {
gui.tooltip_timer->release_connections();
gui.tooltip_timer = Ref<SceneTreeTimer>();
@@ -1870,14 +1869,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
- if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
- bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
+ bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
- if (!can_drop) {
- ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
- } else {
- ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
- }
+ if (!can_drop) {
+ ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
+ } else {
+ ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
}
}
@@ -2045,6 +2042,7 @@ void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *
if (p_control) {
_gui_set_drag_preview(p_base, p_control);
}
+ _propagate_viewport_notification(this, NOTIFICATION_DRAG_BEGIN);
}
void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 056ace5e4e..b8442e7f70 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -123,7 +123,7 @@
#include "scene/gui/texture_progress_bar.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tree.h"
-#include "scene/gui/video_player.h"
+#include "scene/gui/video_stream_player.h"
#include "scene/main/canvas_item.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/http_request.h"
@@ -232,7 +232,6 @@
#include "scene/3d/path_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/position_3d.h"
-#include "scene/3d/proximity_group_3d.h"
#include "scene/3d/ray_cast_3d.h"
#include "scene/3d/reflection_probe.h"
#include "scene/3d/remote_transform_3d.h"
@@ -361,7 +360,7 @@ void register_scene_types() {
GDREGISTER_CLASS(ItemList);
GDREGISTER_CLASS(LineEdit);
- GDREGISTER_CLASS(VideoPlayer);
+ GDREGISTER_CLASS(VideoStreamPlayer);
#ifndef ADVANCED_GUI_DISABLED
GDREGISTER_CLASS(FileDialog);
@@ -511,7 +510,6 @@ void register_scene_types() {
GDREGISTER_CLASS(VehicleBody3D);
GDREGISTER_CLASS(VehicleWheel3D);
GDREGISTER_CLASS(Area3D);
- GDREGISTER_CLASS(ProximityGroup3D);
GDREGISTER_CLASS(CollisionShape3D);
GDREGISTER_CLASS(CollisionPolygon3D);
GDREGISTER_CLASS(RayCast3D);
@@ -933,6 +931,7 @@ void register_scene_types() {
ClassDB::add_compatibility_class("KinematicBody2D", "CharacterBody2D");
ClassDB::add_compatibility_class("KinematicCollision", "KinematicCollision3D");
ClassDB::add_compatibility_class("Light", "Light3D");
+ ClassDB::add_compatibility_class("Light2D", "PointLight2D");
ClassDB::add_compatibility_class("LineShape2D", "WorldBoundaryShape2D");
ClassDB::add_compatibility_class("Listener", "AudioListener3D");
ClassDB::add_compatibility_class("MeshInstance", "MeshInstance3D");
@@ -964,7 +963,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("PinJoint", "PinJoint3D");
ClassDB::add_compatibility_class("PlaneShape", "WorldBoundaryShape3D");
ClassDB::add_compatibility_class("ProceduralSky", "Sky");
- ClassDB::add_compatibility_class("ProximityGroup", "ProximityGroup3D");
ClassDB::add_compatibility_class("RayCast", "RayCast3D");
ClassDB::add_compatibility_class("RayShape", "SeparationRayShape3D");
ClassDB::add_compatibility_class("RayShape2D", "SeparationRayShape2D");
@@ -986,13 +984,17 @@ void register_scene_types() {
ClassDB::add_compatibility_class("SpringArm", "SpringArm3D");
ClassDB::add_compatibility_class("Sprite", "Sprite2D");
ClassDB::add_compatibility_class("StaticBody", "StaticBody3D");
+ ClassDB::add_compatibility_class("StreamTexture", "StreamTexture2D");
ClassDB::add_compatibility_class("TextureProgress", "TextureProgressBar");
ClassDB::add_compatibility_class("VehicleBody", "VehicleBody3D");
ClassDB::add_compatibility_class("VehicleWheel", "VehicleWheel3D");
+ ClassDB::add_compatibility_class("VideoPlayer", "VideoStreamPlayer");
ClassDB::add_compatibility_class("ViewportContainer", "SubViewportContainer");
ClassDB::add_compatibility_class("Viewport", "SubViewport");
ClassDB::add_compatibility_class("VisibilityEnabler", "VisibleOnScreenEnabler3D");
ClassDB::add_compatibility_class("VisibilityNotifier", "VisibleOnScreenNotifier3D");
+ ClassDB::add_compatibility_class("VisibilityNotifier2D", "VisibleOnScreenNotifier2D");
+ ClassDB::add_compatibility_class("VisibilityNotifier3D", "VisibleOnScreenNotifier3D");
ClassDB::add_compatibility_class("VisualServer", "RenderingServer");
ClassDB::add_compatibility_class("VisualShaderNodeScalarConstant", "VisualShaderNodeFloatConstant");
ClassDB::add_compatibility_class("VisualShaderNodeScalarFunc", "VisualShaderNodeFloatFunc");
@@ -1010,11 +1012,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("VisualShaderNodeScalarSwitch", "VisualShaderNodeSwitch");
ClassDB::add_compatibility_class("VisualShaderNodeScalarTransformMult", "VisualShaderNodeTransformOp");
ClassDB::add_compatibility_class("World", "World3D");
- ClassDB::add_compatibility_class("StreamTexture", "StreamTexture2D");
- ClassDB::add_compatibility_class("Light2D", "PointLight2D");
- ClassDB::add_compatibility_class("VisibilityNotifier2D", "VisibleOnScreenNotifier2D");
- ClassDB::add_compatibility_class("VisibilityNotifier3D", "VisibleOnScreenNotifier3D");
-
#endif /* DISABLE_DEPRECATED */
OS::get_singleton()->yield(); // may take time to init
@@ -1031,6 +1028,16 @@ void register_scene_types() {
GLOBAL_DEF_BASIC(vformat("layer_names/3d_navigation/layer_%d", i + 1), "");
}
+ if (RenderingServer::get_singleton()) {
+ ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed.
+ }
+
+ SceneDebugger::initialize();
+
+ NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
+}
+
+void initialize_theme() {
bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String theme_path = GLOBAL_DEF_RST("gui/theme/custom", "");
@@ -1049,7 +1056,6 @@ void register_scene_types() {
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_hidpi, font);
- ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed.
}
if (theme_path != String()) {
@@ -1063,9 +1069,6 @@ void register_scene_types() {
ERR_PRINT("Error loading custom theme '" + theme_path + "'");
}
}
- SceneDebugger::initialize();
-
- NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
}
void unregister_scene_types() {
diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h
index 1ff542eef8..32ab165fb3 100644
--- a/scene/register_scene_types.h
+++ b/scene/register_scene_types.h
@@ -34,4 +34,6 @@
void register_scene_types();
void unregister_scene_types();
+void initialize_theme();
+
#endif
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index b87639de6a..bf3efd7599 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -33,15 +33,15 @@
#include "core/core_string_names.h"
template <class T>
-static _FORCE_INLINE_ T _bezier_interp(real_t t, T start, T control_1, T control_2, T end) {
+static _FORCE_INLINE_ T _bezier_interp(real_t p_t, T p_start, T p_control_1, T p_control_2, T p_end) {
/* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - t);
+ real_t omt = (1.0 - p_t);
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
+ real_t t2 = p_t * p_t;
+ real_t t3 = t2 * p_t;
- return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
+ return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
@@ -49,46 +49,46 @@ const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
Curve::Curve() {
}
-int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) {
+int Curve::add_point(Vector2 p_position, real_t p_left_tangent, real_t p_right_tangent, TangentMode p_left_mode, TangentMode p_right_mode) {
// Add a point and preserve order
// Curve bounds is in 0..1
- if (p_pos.x > MAX_X) {
- p_pos.x = MAX_X;
- } else if (p_pos.x < MIN_X) {
- p_pos.x = MIN_X;
+ if (p_position.x > MAX_X) {
+ p_position.x = MAX_X;
+ } else if (p_position.x < MIN_X) {
+ p_position.x = MIN_X;
}
int ret = -1;
if (_points.size() == 0) {
- _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode));
+ _points.push_back(Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode));
ret = 0;
} else if (_points.size() == 1) {
// TODO Is the `else` able to handle this block already?
- real_t diff = p_pos.x - _points[0].pos.x;
+ real_t diff = p_position.x - _points[0].position.x;
if (diff > 0) {
- _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode));
+ _points.push_back(Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode));
ret = 1;
} else {
- _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode));
+ _points.insert(0, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode));
ret = 0;
}
} else {
- int i = get_index(p_pos.x);
+ int i = get_index(p_position.x);
- if (i == 0 && p_pos.x < _points[0].pos.x) {
+ if (i == 0 && p_position.x < _points[0].position.x) {
// Insert before anything else
- _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode));
+ _points.insert(0, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode));
ret = 0;
} else {
// Insert between i and i+1
++i;
- _points.insert(i, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode));
+ _points.insert(i, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode));
ret = i;
}
}
@@ -100,7 +100,7 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, T
return ret;
}
-int Curve::get_index(real_t offset) const {
+int Curve::get_index(real_t p_offset) const {
// Lower-bound float binary search
int imin = 0;
@@ -109,13 +109,13 @@ int Curve::get_index(real_t offset) const {
while (imax - imin > 1) {
int m = (imin + imax) / 2;
- real_t a = _points[m].pos.x;
- real_t b = _points[m + 1].pos.x;
+ real_t a = _points[m].position.x;
+ real_t b = _points[m + 1].position.x;
- if (a < offset && b < offset) {
+ if (a < p_offset && b < p_offset) {
imin = m;
- } else if (a > offset) {
+ } else if (a > p_offset) {
imax = m;
} else {
@@ -124,7 +124,7 @@ int Curve::get_index(real_t offset) const {
}
// Will happen if the offset is out of bounds
- if (offset > _points[imax].pos.x) {
+ if (p_offset > _points[imax].position.x) {
return imax;
}
return imin;
@@ -134,7 +134,7 @@ void Curve::clean_dupes() {
bool dirty = false;
for (int i = 1; i < _points.size(); ++i) {
- real_t diff = _points[i - 1].pos.x - _points[i].pos.x;
+ real_t diff = _points[i - 1].position.x - _points[i].position.x;
if (diff <= CMP_EPSILON) {
_points.remove_at(i);
--i;
@@ -147,62 +147,62 @@ void Curve::clean_dupes() {
}
}
-void Curve::set_point_left_tangent(int i, real_t tangent) {
- ERR_FAIL_INDEX(i, _points.size());
- _points.write[i].left_tangent = tangent;
- _points.write[i].left_mode = TANGENT_FREE;
+void Curve::set_point_left_tangent(int p_index, real_t p_tangent) {
+ ERR_FAIL_INDEX(p_index, _points.size());
+ _points.write[p_index].left_tangent = p_tangent;
+ _points.write[p_index].left_mode = TANGENT_FREE;
mark_dirty();
}
-void Curve::set_point_right_tangent(int i, real_t tangent) {
- ERR_FAIL_INDEX(i, _points.size());
- _points.write[i].right_tangent = tangent;
- _points.write[i].right_mode = TANGENT_FREE;
+void Curve::set_point_right_tangent(int p_index, real_t p_tangent) {
+ ERR_FAIL_INDEX(p_index, _points.size());
+ _points.write[p_index].right_tangent = p_tangent;
+ _points.write[p_index].right_mode = TANGENT_FREE;
mark_dirty();
}
-void Curve::set_point_left_mode(int i, TangentMode p_mode) {
- ERR_FAIL_INDEX(i, _points.size());
- _points.write[i].left_mode = p_mode;
- if (i > 0) {
+void Curve::set_point_left_mode(int p_index, TangentMode p_mode) {
+ ERR_FAIL_INDEX(p_index, _points.size());
+ _points.write[p_index].left_mode = p_mode;
+ if (p_index > 0) {
if (p_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized();
- _points.write[i].left_tangent = v.y / v.x;
+ Vector2 v = (_points[p_index - 1].position - _points[p_index].position).normalized();
+ _points.write[p_index].left_tangent = v.y / v.x;
}
}
mark_dirty();
}
-void Curve::set_point_right_mode(int i, TangentMode p_mode) {
- ERR_FAIL_INDEX(i, _points.size());
- _points.write[i].right_mode = p_mode;
- if (i + 1 < _points.size()) {
+void Curve::set_point_right_mode(int p_index, TangentMode p_mode) {
+ ERR_FAIL_INDEX(p_index, _points.size());
+ _points.write[p_index].right_mode = p_mode;
+ if (p_index + 1 < _points.size()) {
if (p_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized();
- _points.write[i].right_tangent = v.y / v.x;
+ Vector2 v = (_points[p_index + 1].position - _points[p_index].position).normalized();
+ _points.write[p_index].right_tangent = v.y / v.x;
}
}
mark_dirty();
}
-real_t Curve::get_point_left_tangent(int i) const {
- ERR_FAIL_INDEX_V(i, _points.size(), 0);
- return _points[i].left_tangent;
+real_t Curve::get_point_left_tangent(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, _points.size(), 0);
+ return _points[p_index].left_tangent;
}
-real_t Curve::get_point_right_tangent(int i) const {
- ERR_FAIL_INDEX_V(i, _points.size(), 0);
- return _points[i].right_tangent;
+real_t Curve::get_point_right_tangent(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, _points.size(), 0);
+ return _points[p_index].right_tangent;
}
-Curve::TangentMode Curve::get_point_left_mode(int i) const {
- ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE);
- return _points[i].left_mode;
+Curve::TangentMode Curve::get_point_left_mode(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, _points.size(), TANGENT_FREE);
+ return _points[p_index].left_mode;
}
-Curve::TangentMode Curve::get_point_right_mode(int i) const {
- ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE);
- return _points[i].right_mode;
+Curve::TangentMode Curve::get_point_right_mode(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, _points.size(), TANGENT_FREE);
+ return _points[p_index].right_mode;
}
void Curve::remove_point(int p_index) {
@@ -216,18 +216,18 @@ void Curve::clear_points() {
mark_dirty();
}
-void Curve::set_point_value(int p_index, real_t pos) {
+void Curve::set_point_value(int p_index, real_t p_position) {
ERR_FAIL_INDEX(p_index, _points.size());
- _points.write[p_index].pos.y = pos;
+ _points.write[p_index].position.y = p_position;
update_auto_tangents(p_index);
mark_dirty();
}
-int Curve::set_point_offset(int p_index, float offset) {
+int Curve::set_point_offset(int p_index, real_t p_offset) {
ERR_FAIL_INDEX_V(p_index, _points.size(), -1);
Point p = _points[p_index];
remove_point(p_index);
- int i = add_point(Vector2(offset, p.pos.y));
+ int i = add_point(Vector2(p_offset, p.position.y));
_points.write[i].left_tangent = p.left_tangent;
_points.write[i].right_tangent = p.right_tangent;
_points.write[i].left_mode = p.left_mode;
@@ -241,7 +241,7 @@ int Curve::set_point_offset(int p_index, float offset) {
Vector2 Curve::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, _points.size(), Vector2(0, 0));
- return _points[p_index].pos;
+ return _points[p_index].position;
}
Curve::Point Curve::get_point(int p_index) const {
@@ -249,35 +249,35 @@ Curve::Point Curve::get_point(int p_index) const {
return _points[p_index];
}
-void Curve::update_auto_tangents(int i) {
- Point &p = _points.write[i];
+void Curve::update_auto_tangents(int p_index) {
+ Point &p = _points.write[p_index];
- if (i > 0) {
+ if (p_index > 0) {
if (p.left_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i - 1].pos - p.pos).normalized();
+ Vector2 v = (_points[p_index - 1].position - p.position).normalized();
p.left_tangent = v.y / v.x;
}
- if (_points[i - 1].right_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i - 1].pos - p.pos).normalized();
- _points.write[i - 1].right_tangent = v.y / v.x;
+ if (_points[p_index - 1].right_mode == TANGENT_LINEAR) {
+ Vector2 v = (_points[p_index - 1].position - p.position).normalized();
+ _points.write[p_index - 1].right_tangent = v.y / v.x;
}
}
- if (i + 1 < _points.size()) {
+ if (p_index + 1 < _points.size()) {
if (p.right_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i + 1].pos - p.pos).normalized();
+ Vector2 v = (_points[p_index + 1].position - p.position).normalized();
p.right_tangent = v.y / v.x;
}
- if (_points[i + 1].left_mode == TANGENT_LINEAR) {
- Vector2 v = (_points[i + 1].pos - p.pos).normalized();
- _points.write[i + 1].left_tangent = v.y / v.x;
+ if (_points[p_index + 1].left_mode == TANGENT_LINEAR) {
+ Vector2 v = (_points[p_index + 1].position - p.position).normalized();
+ _points.write[p_index + 1].left_tangent = v.y / v.x;
}
}
}
#define MIN_Y_RANGE 0.01
-void Curve::set_min_value(float p_min) {
+void Curve::set_min_value(real_t p_min) {
if (_minmax_set_once & 0b11 && p_min > _max_value - MIN_Y_RANGE) {
_min_value = _max_value - MIN_Y_RANGE;
} else {
@@ -289,7 +289,7 @@ void Curve::set_min_value(float p_min) {
emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
}
-void Curve::set_max_value(float p_max) {
+void Curve::set_max_value(real_t p_max) {
if (_minmax_set_once & 0b11 && p_max < _min_value + MIN_Y_RANGE) {
_max_value = _min_value + MIN_Y_RANGE;
} else {
@@ -299,32 +299,32 @@ void Curve::set_max_value(float p_max) {
emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
}
-real_t Curve::interpolate(real_t offset) const {
+real_t Curve::interpolate(real_t p_offset) const {
if (_points.size() == 0) {
return 0;
}
if (_points.size() == 1) {
- return _points[0].pos.y;
+ return _points[0].position.y;
}
- int i = get_index(offset);
+ int i = get_index(p_offset);
if (i == _points.size() - 1) {
- return _points[i].pos.y;
+ return _points[i].position.y;
}
- real_t local = offset - _points[i].pos.x;
+ real_t local = p_offset - _points[i].position.x;
if (i == 0 && local <= 0) {
- return _points[0].pos.y;
+ return _points[0].position.y;
}
return interpolate_local_nocheck(i, local);
}
-real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const {
- const Point a = _points[index];
- const Point b = _points[index + 1];
+real_t Curve::interpolate_local_nocheck(int p_index, real_t p_local_offset) const {
+ const Point a = _points[p_index];
+ const Point b = _points[p_index + 1];
/* Cubic bezier
*
@@ -341,16 +341,16 @@ real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const {
*/
// Control points are chosen at equal distances
- real_t d = b.pos.x - a.pos.x;
- if (Math::abs(d) <= CMP_EPSILON) {
- return b.pos.y;
+ real_t d = b.position.x - a.position.x;
+ if (Math::is_zero_approx(d)) {
+ return b.position.y;
}
- local_offset /= d;
+ p_local_offset /= d;
d /= 3.0;
- real_t yac = a.pos.y + d * a.right_tangent;
- real_t ybc = b.pos.y - d * b.left_tangent;
+ real_t yac = a.position.y + d * a.right_tangent;
+ real_t ybc = b.position.y - d * b.left_tangent;
- real_t y = _bezier_interp(local_offset, a.pos.y, yac, ybc, b.pos.y);
+ real_t y = _bezier_interp(p_local_offset, a.position.y, yac, ybc, b.position.y);
return y;
}
@@ -369,7 +369,7 @@ Array Curve::get_data() const {
const Point p = _points[j];
int i = j * ELEMS;
- output[i] = p.pos;
+ output[i] = p.position;
output[i + 1] = p.left_tangent;
output[i + 2] = p.right_tangent;
output[i + 3] = p.left_mode;
@@ -379,39 +379,39 @@ Array Curve::get_data() const {
return output;
}
-void Curve::set_data(Array input) {
+void Curve::set_data(const Array p_input) {
const unsigned int ELEMS = 5;
- ERR_FAIL_COND(input.size() % ELEMS != 0);
+ ERR_FAIL_COND(p_input.size() % ELEMS != 0);
_points.clear();
// Validate input
- for (int i = 0; i < input.size(); i += ELEMS) {
- ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2);
- ERR_FAIL_COND(!input[i + 1].is_num());
- ERR_FAIL_COND(input[i + 2].get_type() != Variant::FLOAT);
+ for (int i = 0; i < p_input.size(); i += ELEMS) {
+ ERR_FAIL_COND(p_input[i].get_type() != Variant::VECTOR2);
+ ERR_FAIL_COND(!p_input[i + 1].is_num());
+ ERR_FAIL_COND(p_input[i + 2].get_type() != Variant::FLOAT);
- ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT);
- int left_mode = input[i + 3];
+ ERR_FAIL_COND(p_input[i + 3].get_type() != Variant::INT);
+ int left_mode = p_input[i + 3];
ERR_FAIL_COND(left_mode < 0 || left_mode >= TANGENT_MODE_COUNT);
- ERR_FAIL_COND(input[i + 4].get_type() != Variant::INT);
- int right_mode = input[i + 4];
+ ERR_FAIL_COND(p_input[i + 4].get_type() != Variant::INT);
+ int right_mode = p_input[i + 4];
ERR_FAIL_COND(right_mode < 0 || right_mode >= TANGENT_MODE_COUNT);
}
- _points.resize(input.size() / ELEMS);
+ _points.resize(p_input.size() / ELEMS);
for (int j = 0; j < _points.size(); ++j) {
Point &p = _points.write[j];
int i = j * ELEMS;
- p.pos = input[i];
- p.left_tangent = input[i + 1];
- p.right_tangent = input[i + 2];
+ p.position = p_input[i];
+ p.left_tangent = p_input[i + 1];
+ p.right_tangent = p_input[i + 2];
// TODO For some reason the compiler won't convert from Variant to enum
- int left_mode = input[i + 3];
- int right_mode = input[i + 4];
+ int left_mode = p_input[i + 3];
+ int right_mode = p_input[i + 4];
p.left_mode = (TangentMode)left_mode;
p.right_mode = (TangentMode)right_mode;
}
@@ -431,8 +431,8 @@ void Curve::bake() {
}
if (_points.size() != 0) {
- _baked_cache.write[0] = _points[0].pos.y;
- _baked_cache.write[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y;
+ _baked_cache.write[0] = _points[0].position.y;
+ _baked_cache.write[_baked_cache.size() - 1] = _points[_points.size() - 1].position.y;
}
_baked_cache_dirty = false;
@@ -445,7 +445,7 @@ void Curve::set_bake_resolution(int p_resolution) {
_baked_cache_dirty = true;
}
-real_t Curve::interpolate_baked(real_t offset) const {
+real_t Curve::interpolate_baked(real_t p_offset) const {
if (_baked_cache_dirty) {
// Last-second bake if not done already
const_cast<Curve *>(this)->bake();
@@ -456,13 +456,13 @@ real_t Curve::interpolate_baked(real_t offset) const {
if (_points.size() == 0) {
return 0;
}
- return _points[0].pos.y;
+ return _points[0].position.y;
} else if (_baked_cache.size() == 1) {
return _baked_cache[0];
}
// Get interpolation index
- real_t fi = offset * _baked_cache.size();
+ real_t fi = p_offset * _baked_cache.size();
int i = Math::floor(fi);
if (i < 0) {
i = 0;
@@ -481,7 +481,7 @@ real_t Curve::interpolate_baked(real_t offset) const {
}
}
-void Curve::ensure_default_setup(float p_min, float p_max) {
+void Curve::ensure_default_setup(real_t p_min, real_t p_max) {
if (_points.size() == 0 && _min_value == 0 && _max_value == 1) {
add_point(Vector2(0, 1));
add_point(Vector2(1, 1));
@@ -535,9 +535,9 @@ int Curve2D::get_point_count() const {
return points.size();
}
-void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) {
+void Curve2D::add_point(const Vector2 &p_position, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) {
Point n;
- n.pos = p_pos;
+ n.position = p_position;
n.in = p_in;
n.out = p_out;
if (p_atpos >= 0 && p_atpos < points.size()) {
@@ -550,17 +550,17 @@ void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2
emit_signal(CoreStringNames::get_singleton()->changed);
}
-void Curve2D::set_point_position(int p_index, const Vector2 &p_pos) {
+void Curve2D::set_point_position(int p_index, const Vector2 &p_position) {
ERR_FAIL_INDEX(p_index, points.size());
- points.write[p_index].pos = p_pos;
+ points.write[p_index].position = p_position;
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
Vector2 Curve2D::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, points.size(), Vector2());
- return points[p_index].pos;
+ return points[p_index].position;
}
void Curve2D::set_point_in(int p_index, const Vector2 &p_in) {
@@ -604,19 +604,19 @@ void Curve2D::clear_points() {
}
}
-Vector2 Curve2D::interpolate(int p_index, float p_offset) const {
+Vector2 Curve2D::interpolate(int p_index, const real_t p_offset) const {
int pc = points.size();
ERR_FAIL_COND_V(pc == 0, Vector2());
if (p_index >= pc - 1) {
- return points[pc - 1].pos;
+ return points[pc - 1].position;
} else if (p_index < 0) {
- return points[0].pos;
+ return points[0].position;
}
- Vector2 p0 = points[p_index].pos;
+ Vector2 p0 = points[p_index].position;
Vector2 p1 = p0 + points[p_index].out;
- Vector2 p3 = points[p_index + 1].pos;
+ Vector2 p3 = points[p_index + 1].position;
Vector2 p2 = p3 + points[p_index + 1].in;
return _bezier_interp(p_offset, p0, p1, p2, p3);
@@ -632,15 +632,15 @@ Vector2 Curve2D::interpolatef(real_t p_findex) const {
return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
}
-void Curve2D::_bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, float p_tol) const {
- float mp = p_begin + (p_end - p_begin) * 0.5;
+void Curve2D::_bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const {
+ real_t mp = p_begin + (p_end - p_begin) * 0.5;
Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);
Vector2 na = (mid - beg).normalized();
Vector2 nb = (end - mid).normalized();
- float dp = na.dot(nb);
+ real_t dp = na.dot(nb);
if (dp < Math::cos(Math::deg2rad(p_tol))) {
r_bake[mp] = mid;
@@ -668,47 +668,47 @@ void Curve2D::_bake() const {
if (points.size() == 1) {
baked_point_cache.resize(1);
- baked_point_cache.set(0, points[0].pos);
+ baked_point_cache.set(0, points[0].position);
baked_dist_cache.resize(1);
baked_dist_cache.set(0, 0.0);
return;
}
- Vector2 pos = points[0].pos;
- float dist = 0.0;
+ Vector2 position = points[0].position;
+ real_t dist = 0.0;
List<Vector2> pointlist;
- List<float> distlist;
+ List<real_t> distlist;
- pointlist.push_back(pos); //start always from origin
+ pointlist.push_back(position); //start always from origin
distlist.push_back(0.0);
for (int i = 0; i < points.size() - 1; i++) {
- float step = 0.1; // at least 10 substeps ought to be enough?
- float p = 0.0;
+ real_t step = 0.1; // at least 10 substeps ought to be enough?
+ real_t p = 0.0;
while (p < 1.0) {
- float np = p + step;
+ real_t np = p + step;
if (np > 1.0) {
np = 1.0;
}
- Vector2 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos);
- float d = pos.distance_to(npp);
+ Vector2 npp = _bezier_interp(np, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position);
+ real_t d = position.distance_to(npp);
if (d > bake_interval) {
// OK! between P and NP there _has_ to be Something, let's go searching!
int iterations = 10; //lots of detail!
- float low = p;
- float hi = np;
- float mid = low + (hi - low) * 0.5;
+ real_t low = p;
+ real_t hi = np;
+ real_t mid = low + (hi - low) * 0.5;
for (int j = 0; j < iterations; j++) {
- npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos);
- d = pos.distance_to(npp);
+ npp = _bezier_interp(mid, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position);
+ d = position.distance_to(npp);
if (bake_interval < d) {
hi = mid;
@@ -718,11 +718,11 @@ void Curve2D::_bake() const {
mid = low + (hi - low) * 0.5;
}
- pos = npp;
+ position = npp;
p = mid;
dist += d;
- pointlist.push_back(pos);
+ pointlist.push_back(position);
distlist.push_back(dist);
} else {
p = np;
@@ -730,9 +730,9 @@ void Curve2D::_bake() const {
}
}
- Vector2 lastpos = points[points.size() - 1].pos;
+ Vector2 lastpos = points[points.size() - 1].position;
- float rem = pos.distance_to(lastpos);
+ real_t rem = position.distance_to(lastpos);
dist += rem;
baked_max_ofs = dist;
pointlist.push_back(lastpos);
@@ -742,7 +742,7 @@ void Curve2D::_bake() const {
baked_dist_cache.resize(distlist.size());
Vector2 *w = baked_point_cache.ptrw();
- float *wd = baked_dist_cache.ptrw();
+ real_t *wd = baked_dist_cache.ptrw();
for (int i = 0; i < pointlist.size(); i++) {
w[i] = pointlist[i];
@@ -750,7 +750,7 @@ void Curve2D::_bake() const {
}
}
-float Curve2D::get_baked_length() const {
+real_t Curve2D::get_baked_length() const {
if (baked_cache_dirty) {
_bake();
}
@@ -758,7 +758,7 @@ float Curve2D::get_baked_length() const {
return baked_max_ofs;
}
-Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const {
+Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
@@ -784,7 +784,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const {
int start = 0, end = bpc, idx = (end + start) / 2;
// binary search to find baked points
while (start < idx) {
- float offset = baked_dist_cache[idx];
+ real_t offset = baked_dist_cache[idx];
if (p_offset <= offset) {
end = idx;
} else {
@@ -793,13 +793,13 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const {
idx = (end + start) / 2;
}
- float offset_begin = baked_dist_cache[idx];
- float offset_end = baked_dist_cache[idx + 1];
+ real_t offset_begin = baked_dist_cache[idx];
+ real_t offset_end = baked_dist_cache[idx + 1];
- float idx_interval = offset_end - offset_begin;
+ real_t idx_interval = offset_end - offset_begin;
ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector2(), "failed to find baked segment");
- float frac = (p_offset - offset_begin) / idx_interval;
+ real_t frac = (p_offset - offset_begin) / idx_interval;
if (p_cubic) {
Vector2 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -818,13 +818,13 @@ PackedVector2Array Curve2D::get_baked_points() const {
return baked_point_cache;
}
-void Curve2D::set_bake_interval(float p_tolerance) {
+void Curve2D::set_bake_interval(real_t p_tolerance) {
bake_interval = p_tolerance;
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
-float Curve2D::get_bake_interval() const {
+real_t Curve2D::get_bake_interval() const {
return bake_interval;
}
@@ -846,16 +846,16 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
const Vector2 *r = baked_point_cache.ptr();
Vector2 nearest;
- float nearest_dist = -1.0f;
+ real_t nearest_dist = -1.0f;
for (int i = 0; i < pc - 1; i++) {
Vector2 origin = r[i];
Vector2 direction = (r[i + 1] - origin) / bake_interval;
- float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
Vector2 proj = origin + direction * d;
- float dist = proj.distance_squared_to(p_to_point);
+ real_t dist = proj.distance_squared_to(p_to_point);
if (nearest_dist < 0.0f || dist < nearest_dist) {
nearest = proj;
@@ -866,7 +866,7 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
return nearest;
}
-float Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
+real_t Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
// Brute force method
if (baked_cache_dirty) {
@@ -883,18 +883,18 @@ float Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
const Vector2 *r = baked_point_cache.ptr();
- float nearest = 0.0f;
- float nearest_dist = -1.0f;
- float offset = 0.0f;
+ real_t nearest = 0.0f;
+ real_t nearest_dist = -1.0f;
+ real_t offset = 0.0f;
for (int i = 0; i < pc - 1; i++) {
Vector2 origin = r[i];
Vector2 direction = (r[i + 1] - origin) / bake_interval;
- float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
Vector2 proj = origin + direction * d;
- float dist = proj.distance_squared_to(p_to_point);
+ real_t dist = proj.distance_squared_to(p_to_point);
if (nearest_dist < 0.0f || dist < nearest_dist) {
nearest = offset + d;
@@ -917,7 +917,7 @@ Dictionary Curve2D::_get_data() const {
for (int i = 0; i < points.size(); i++) {
w[i * 3 + 0] = points[i].in;
w[i * 3 + 1] = points[i].out;
- w[i * 3 + 2] = points[i].pos;
+ w[i * 3 + 2] = points[i].position;
}
dc["points"] = d;
@@ -937,42 +937,42 @@ void Curve2D::_set_data(const Dictionary &p_data) {
for (int i = 0; i < points.size(); i++) {
points.write[i].in = r[i * 3 + 0];
points.write[i].out = r[i * 3 + 1];
- points.write[i].pos = r[i * 3 + 2];
+ points.write[i].position = r[i * 3 + 2];
}
baked_cache_dirty = true;
}
-PackedVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const {
+PackedVector2Array Curve2D::tessellate(int p_max_stages, real_t p_tolerance) const {
PackedVector2Array tess;
if (points.size() == 0) {
return tess;
}
- Vector<Map<float, Vector2>> midpoints;
+ Vector<Map<real_t, Vector2>> midpoints;
midpoints.resize(points.size() - 1);
int pc = 1;
for (int i = 0; i < points.size() - 1; i++) {
- _bake_segment2d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance);
+ _bake_segment2d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance);
pc++;
pc += midpoints[i].size();
}
tess.resize(pc);
Vector2 *bpw = tess.ptrw();
- bpw[0] = points[0].pos;
+ bpw[0] = points[0].position;
int pidx = 0;
for (int i = 0; i < points.size() - 1; i++) {
- for (const KeyValue<float, Vector2> &E : midpoints[i]) {
+ for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
pidx++;
bpw[pidx] = E.value;
}
pidx++;
- bpw[pidx] = points[i + 1].pos;
+ bpw[pidx] = points[i + 1].position;
}
return tess;
@@ -1026,9 +1026,9 @@ int Curve3D::get_point_count() const {
return points.size();
}
-void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) {
+void Curve3D::add_point(const Vector3 &p_position, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) {
Point n;
- n.pos = p_pos;
+ n.position = p_position;
n.in = p_in;
n.out = p_out;
if (p_atpos >= 0 && p_atpos < points.size()) {
@@ -1041,20 +1041,20 @@ void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3
emit_signal(CoreStringNames::get_singleton()->changed);
}
-void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) {
+void Curve3D::set_point_position(int p_index, const Vector3 &p_position) {
ERR_FAIL_INDEX(p_index, points.size());
- points.write[p_index].pos = p_pos;
+ points.write[p_index].position = p_position;
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
Vector3 Curve3D::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, points.size(), Vector3());
- return points[p_index].pos;
+ return points[p_index].position;
}
-void Curve3D::set_point_tilt(int p_index, float p_tilt) {
+void Curve3D::set_point_tilt(int p_index, real_t p_tilt) {
ERR_FAIL_INDEX(p_index, points.size());
points.write[p_index].tilt = p_tilt;
@@ -1062,7 +1062,7 @@ void Curve3D::set_point_tilt(int p_index, float p_tilt) {
emit_signal(CoreStringNames::get_singleton()->changed);
}
-float Curve3D::get_point_tilt(int p_index) const {
+real_t Curve3D::get_point_tilt(int p_index) const {
ERR_FAIL_INDEX_V(p_index, points.size(), 0);
return points[p_index].tilt;
}
@@ -1108,19 +1108,19 @@ void Curve3D::clear_points() {
}
}
-Vector3 Curve3D::interpolate(int p_index, float p_offset) const {
+Vector3 Curve3D::interpolate(int p_index, real_t p_offset) const {
int pc = points.size();
ERR_FAIL_COND_V(pc == 0, Vector3());
if (p_index >= pc - 1) {
- return points[pc - 1].pos;
+ return points[pc - 1].position;
} else if (p_index < 0) {
- return points[0].pos;
+ return points[0].position;
}
- Vector3 p0 = points[p_index].pos;
+ Vector3 p0 = points[p_index].position;
Vector3 p1 = p0 + points[p_index].out;
- Vector3 p3 = points[p_index + 1].pos;
+ Vector3 p3 = points[p_index + 1].position;
Vector3 p2 = p3 + points[p_index + 1].in;
return _bezier_interp(p_offset, p0, p1, p2, p3);
@@ -1136,15 +1136,15 @@ Vector3 Curve3D::interpolatef(real_t p_findex) const {
return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
}
-void Curve3D::_bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const {
- float mp = p_begin + (p_end - p_begin) * 0.5;
+void Curve3D::_bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const {
+ real_t mp = p_begin + (p_end - p_begin) * 0.5;
Vector3 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
Vector3 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
Vector3 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);
Vector3 na = (mid - beg).normalized();
Vector3 nb = (end - mid).normalized();
- float dp = na.dot(nb);
+ real_t dp = na.dot(nb);
if (dp < Math::cos(Math::deg2rad(p_tol))) {
r_bake[mp] = mid;
@@ -1173,7 +1173,7 @@ void Curve3D::_bake() const {
if (points.size() == 1) {
baked_point_cache.resize(1);
- baked_point_cache.set(0, points[0].pos);
+ baked_point_cache.set(0, points[0].position);
baked_tilt_cache.resize(1);
baked_tilt_cache.set(0, points[0].tilt);
baked_dist_cache.resize(1);
@@ -1189,39 +1189,39 @@ void Curve3D::_bake() const {
return;
}
- Vector3 pos = points[0].pos;
- float dist = 0.0;
+ Vector3 position = points[0].position;
+ real_t dist = 0.0;
List<Plane> pointlist;
- List<float> distlist;
+ List<real_t> distlist;
- pointlist.push_back(Plane(pos, points[0].tilt));
+ pointlist.push_back(Plane(position, points[0].tilt));
distlist.push_back(0.0);
for (int i = 0; i < points.size() - 1; i++) {
- float step = 0.1; // at least 10 substeps ought to be enough?
- float p = 0.0;
+ real_t step = 0.1; // at least 10 substeps ought to be enough?
+ real_t p = 0.0;
while (p < 1.0) {
- float np = p + step;
+ real_t np = p + step;
if (np > 1.0) {
np = 1.0;
}
- Vector3 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos);
- float d = pos.distance_to(npp);
+ Vector3 npp = _bezier_interp(np, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position);
+ real_t d = position.distance_to(npp);
if (d > bake_interval) {
// OK! between P and NP there _has_ to be Something, let's go searching!
int iterations = 10; //lots of detail!
- float low = p;
- float hi = np;
- float mid = low + (hi - low) * 0.5;
+ real_t low = p;
+ real_t hi = np;
+ real_t mid = low + (hi - low) * 0.5;
for (int j = 0; j < iterations; j++) {
- npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos);
- d = pos.distance_to(npp);
+ npp = _bezier_interp(mid, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position);
+ d = position.distance_to(npp);
if (bake_interval < d) {
hi = mid;
@@ -1231,10 +1231,10 @@ void Curve3D::_bake() const {
mid = low + (hi - low) * 0.5;
}
- pos = npp;
+ position = npp;
p = mid;
Plane post;
- post.normal = pos;
+ post.normal = position;
post.d = Math::lerp(points[i].tilt, points[i + 1].tilt, mid);
dist += d;
@@ -1246,10 +1246,10 @@ void Curve3D::_bake() const {
}
}
- Vector3 lastpos = points[points.size() - 1].pos;
- float lastilt = points[points.size() - 1].tilt;
+ Vector3 lastpos = points[points.size() - 1].position;
+ real_t lastilt = points[points.size() - 1].tilt;
- float rem = pos.distance_to(lastpos);
+ real_t rem = position.distance_to(lastpos);
dist += rem;
baked_max_ofs = dist;
pointlist.push_back(Plane(lastpos, lastilt));
@@ -1266,7 +1266,7 @@ void Curve3D::_bake() const {
Vector3 *up_write = baked_up_vector_cache.ptrw();
baked_dist_cache.resize(pointlist.size());
- float *wd = baked_dist_cache.ptrw();
+ real_t *wd = baked_dist_cache.ptrw();
Vector3 sideways;
Vector3 up;
@@ -1288,7 +1288,7 @@ void Curve3D::_bake() const {
forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward;
- float y_dot = prev_up.dot(forward);
+ real_t y_dot = prev_up.dot(forward);
if (y_dot > (1.0f - CMP_EPSILON)) {
sideways = prev_sideways;
@@ -1315,7 +1315,7 @@ void Curve3D::_bake() const {
}
}
-float Curve3D::get_baked_length() const {
+real_t Curve3D::get_baked_length() const {
if (baked_cache_dirty) {
_bake();
}
@@ -1323,7 +1323,7 @@ float Curve3D::get_baked_length() const {
return baked_max_ofs;
}
-Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const {
+Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1349,7 +1349,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const {
int start = 0, end = bpc, idx = (end + start) / 2;
// binary search to find baked points
while (start < idx) {
- float offset = baked_dist_cache[idx];
+ real_t offset = baked_dist_cache[idx];
if (p_offset <= offset) {
end = idx;
} else {
@@ -1358,13 +1358,13 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const {
idx = (end + start) / 2;
}
- float offset_begin = baked_dist_cache[idx];
- float offset_end = baked_dist_cache[idx + 1];
+ real_t offset_begin = baked_dist_cache[idx];
+ real_t offset_end = baked_dist_cache[idx + 1];
- float idx_interval = offset_end - offset_begin;
+ real_t idx_interval = offset_end - offset_begin;
ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "failed to find baked segment");
- float frac = (p_offset - offset_begin) / idx_interval;
+ real_t frac = (p_offset - offset_begin) / idx_interval;
if (p_cubic) {
Vector3 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -1375,7 +1375,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const {
}
}
-float Curve3D::interpolate_baked_tilt(float p_offset) const {
+real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1399,7 +1399,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const {
}
int idx = Math::floor((double)p_offset / (double)bake_interval);
- float frac = Math::fmod(p_offset, bake_interval);
+ real_t frac = Math::fmod(p_offset, bake_interval);
if (idx >= bpc - 1) {
return r[bpc - 1];
@@ -1414,7 +1414,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const {
return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
}
-Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const {
+Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1432,10 +1432,10 @@ Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt)
const Vector3 *rp = baked_point_cache.ptr();
const real_t *rt = baked_tilt_cache.ptr();
- float offset = CLAMP(p_offset, 0.0f, baked_max_ofs);
+ real_t offset = CLAMP(p_offset, 0.0f, baked_max_ofs);
int idx = Math::floor((double)offset / (double)bake_interval);
- float frac = Math::fmod(offset, bake_interval) / bake_interval;
+ real_t frac = Math::fmod(offset, bake_interval) / bake_interval;
if (idx == count - 1) {
return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];
@@ -1503,16 +1503,16 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
const Vector3 *r = baked_point_cache.ptr();
Vector3 nearest;
- float nearest_dist = -1.0f;
+ real_t nearest_dist = -1.0f;
for (int i = 0; i < pc - 1; i++) {
Vector3 origin = r[i];
Vector3 direction = (r[i + 1] - origin) / bake_interval;
- float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
Vector3 proj = origin + direction * d;
- float dist = proj.distance_squared_to(p_to_point);
+ real_t dist = proj.distance_squared_to(p_to_point);
if (nearest_dist < 0.0f || dist < nearest_dist) {
nearest = proj;
@@ -1523,7 +1523,7 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
return nearest;
}
-float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
+real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
// Brute force method
if (baked_cache_dirty) {
@@ -1540,18 +1540,18 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
const Vector3 *r = baked_point_cache.ptr();
- float nearest = 0.0f;
- float nearest_dist = -1.0f;
- float offset = 0.0f;
+ real_t nearest = 0.0f;
+ real_t nearest_dist = -1.0f;
+ real_t offset = 0.0f;
for (int i = 0; i < pc - 1; i++) {
Vector3 origin = r[i];
Vector3 direction = (r[i + 1] - origin) / bake_interval;
- float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
Vector3 proj = origin + direction * d;
- float dist = proj.distance_squared_to(p_to_point);
+ real_t dist = proj.distance_squared_to(p_to_point);
if (nearest_dist < 0.0f || dist < nearest_dist) {
nearest = offset + d;
@@ -1564,13 +1564,13 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
return nearest;
}
-void Curve3D::set_bake_interval(float p_tolerance) {
+void Curve3D::set_bake_interval(real_t p_tolerance) {
bake_interval = p_tolerance;
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
-float Curve3D::get_bake_interval() const {
+real_t Curve3D::get_bake_interval() const {
return bake_interval;
}
@@ -1597,7 +1597,7 @@ Dictionary Curve3D::_get_data() const {
for (int i = 0; i < points.size(); i++) {
w[i * 3 + 0] = points[i].in;
w[i * 3 + 1] = points[i].out;
- w[i * 3 + 2] = points[i].pos;
+ w[i * 3 + 2] = points[i].position;
wt[i] = points[i].tilt;
}
@@ -1622,43 +1622,43 @@ void Curve3D::_set_data(const Dictionary &p_data) {
for (int i = 0; i < points.size(); i++) {
points.write[i].in = r[i * 3 + 0];
points.write[i].out = r[i * 3 + 1];
- points.write[i].pos = r[i * 3 + 2];
+ points.write[i].position = r[i * 3 + 2];
points.write[i].tilt = rt[i];
}
baked_cache_dirty = true;
}
-PackedVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const {
+PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) const {
PackedVector3Array tess;
if (points.size() == 0) {
return tess;
}
- Vector<Map<float, Vector3>> midpoints;
+ Vector<Map<real_t, Vector3>> midpoints;
midpoints.resize(points.size() - 1);
int pc = 1;
for (int i = 0; i < points.size() - 1; i++) {
- _bake_segment3d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance);
+ _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance);
pc++;
pc += midpoints[i].size();
}
tess.resize(pc);
Vector3 *bpw = tess.ptrw();
- bpw[0] = points[0].pos;
+ bpw[0] = points[0].position;
int pidx = 0;
for (int i = 0; i < points.size() - 1; i++) {
- for (const KeyValue<float, Vector3> &E : midpoints[i]) {
+ for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
pidx++;
bpw[pidx] = E.value;
}
pidx++;
- bpw[pidx] = points[i + 1].pos;
+ bpw[pidx] = points[i + 1].position;
}
return tess;
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 5808fd6508..16facda85a 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -50,7 +50,7 @@ public:
};
struct Point {
- Vector2 pos;
+ Vector2 position;
real_t left_tangent = 0.0;
real_t right_tangent = 0.0;
TangentMode left_mode = TANGENT_FREE;
@@ -59,12 +59,12 @@ public:
Point() {
}
- Point(Vector2 p_pos,
+ Point(const Vector2 &p_position,
real_t p_left = 0.0,
real_t p_right = 0.0,
TangentMode p_left_mode = TANGENT_FREE,
TangentMode p_right_mode = TANGENT_FREE) {
- pos = p_pos;
+ position = p_position;
left_tangent = p_left;
right_tangent = p_right;
left_mode = p_left_mode;
@@ -76,7 +76,7 @@ public:
int get_point_count() const { return _points.size(); }
- int add_point(Vector2 p_pos,
+ int add_point(Vector2 p_position,
real_t left_tangent = 0,
real_t right_tangent = 0,
TangentMode left_mode = TANGENT_FREE,
@@ -85,34 +85,34 @@ public:
void remove_point(int p_index);
void clear_points();
- int get_index(real_t offset) const;
+ int get_index(real_t p_offset) const;
- void set_point_value(int p_index, real_t pos);
- int set_point_offset(int p_index, float offset);
+ void set_point_value(int p_index, real_t p_position);
+ int set_point_offset(int p_index, real_t p_offset);
Vector2 get_point_position(int p_index) const;
Point get_point(int p_index) const;
- float get_min_value() const { return _min_value; }
- void set_min_value(float p_min);
+ real_t get_min_value() const { return _min_value; }
+ void set_min_value(real_t p_min);
- float get_max_value() const { return _max_value; }
- void set_max_value(float p_max);
+ real_t get_max_value() const { return _max_value; }
+ void set_max_value(real_t p_max);
- real_t interpolate(real_t offset) const;
- real_t interpolate_local_nocheck(int index, real_t local_offset) const;
+ real_t interpolate(real_t p_offset) const;
+ real_t interpolate_local_nocheck(int p_index, real_t p_local_offset) const;
void clean_dupes();
- void set_point_left_tangent(int i, real_t tangent);
- void set_point_right_tangent(int i, real_t tangent);
- void set_point_left_mode(int i, TangentMode p_mode);
- void set_point_right_mode(int i, TangentMode p_mode);
+ void set_point_left_tangent(int p_index, real_t p_tangent);
+ void set_point_right_tangent(int p_index, real_t p_tangent);
+ void set_point_left_mode(int p_index, TangentMode p_mode);
+ void set_point_right_mode(int p_index, TangentMode p_mode);
- real_t get_point_left_tangent(int i) const;
- real_t get_point_right_tangent(int i) const;
- TangentMode get_point_left_mode(int i) const;
- TangentMode get_point_right_mode(int i) const;
+ real_t get_point_left_tangent(int p_index) const;
+ real_t get_point_right_tangent(int p_index) const;
+ TangentMode get_point_left_mode(int p_index) const;
+ TangentMode get_point_right_mode(int p_index) const;
void update_auto_tangents(int i);
@@ -122,9 +122,9 @@ public:
void bake();
int get_bake_resolution() const { return _bake_resolution; }
void set_bake_resolution(int p_resolution);
- real_t interpolate_baked(real_t offset) const;
+ real_t interpolate_baked(real_t p_offset) const;
- void ensure_default_setup(float p_min, float p_max);
+ void ensure_default_setup(real_t p_min, real_t p_max);
protected:
static void _bind_methods();
@@ -136,8 +136,8 @@ private:
bool _baked_cache_dirty = false;
Vector<real_t> _baked_cache;
int _bake_resolution = 100;
- float _min_value = 0.0;
- float _max_value = 1.0;
+ real_t _min_value = 0.0;
+ real_t _max_value = 1.0;
int _minmax_set_once = 0b00; // Encodes whether min and max have been set a first time, first bit for min and second for max.
};
@@ -149,26 +149,26 @@ class Curve2D : public Resource {
struct Point {
Vector2 in;
Vector2 out;
- Vector2 pos;
+ Vector2 position;
};
Vector<Point> points;
struct BakedPoint {
- float ofs = 0.0;
+ real_t ofs = 0.0;
Vector2 point;
};
mutable bool baked_cache_dirty = false;
mutable PackedVector2Array baked_point_cache;
- mutable PackedFloat32Array baked_dist_cache;
- mutable float baked_max_ofs = 0.0;
+ mutable Vector<real_t> baked_dist_cache;
+ mutable real_t baked_max_ofs = 0.0;
void _bake() const;
- float bake_interval = 5.0;
+ real_t bake_interval = 5.0;
- void _bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, float p_tol) const;
+ void _bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const;
Dictionary _get_data() const;
void _set_data(const Dictionary &p_data);
@@ -177,8 +177,8 @@ protected:
public:
int get_point_count() const;
- void add_point(const Vector2 &p_pos, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1);
- void set_point_position(int p_index, const Vector2 &p_pos);
+ void add_point(const Vector2 &p_position, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1);
+ void set_point_position(int p_index, const Vector2 &p_position);
Vector2 get_point_position(int p_index) const;
void set_point_in(int p_index, const Vector2 &p_in);
Vector2 get_point_in(int p_index) const;
@@ -187,19 +187,19 @@ public:
void remove_point(int p_index);
void clear_points();
- Vector2 interpolate(int p_index, float p_offset) const;
+ Vector2 interpolate(int p_index, real_t p_offset) const;
Vector2 interpolatef(real_t p_findex) const;
- void set_bake_interval(float p_tolerance);
- float get_bake_interval() const;
+ void set_bake_interval(real_t p_tolerance);
+ real_t get_bake_interval() const;
- float get_baked_length() const;
- Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const;
+ real_t get_baked_length() const;
+ Vector2 interpolate_baked(real_t p_offset, bool p_cubic = false) const;
PackedVector2Array get_baked_points() const; //useful for going through
Vector2 get_closest_point(const Vector2 &p_to_point) const;
- float get_closest_offset(const Vector2 &p_to_point) const;
+ real_t get_closest_offset(const Vector2 &p_to_point) const;
- PackedVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
+ PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
Curve2D();
};
@@ -210,14 +210,14 @@ class Curve3D : public Resource {
struct Point {
Vector3 in;
Vector3 out;
- Vector3 pos;
- float tilt = 0.0;
+ Vector3 position;
+ real_t tilt = 0.0;
};
Vector<Point> points;
struct BakedPoint {
- float ofs = 0.0;
+ real_t ofs = 0.0;
Vector3 point;
};
@@ -225,15 +225,15 @@ class Curve3D : public Resource {
mutable PackedVector3Array baked_point_cache;
mutable Vector<real_t> baked_tilt_cache;
mutable PackedVector3Array baked_up_vector_cache;
- mutable PackedFloat32Array baked_dist_cache;
- mutable float baked_max_ofs = 0.0;
+ mutable Vector<real_t> baked_dist_cache;
+ mutable real_t baked_max_ofs = 0.0;
void _bake() const;
- float bake_interval = 0.2;
+ real_t bake_interval = 0.2;
bool up_vector_enabled = true;
- void _bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const;
+ void _bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const;
Dictionary _get_data() const;
void _set_data(const Dictionary &p_data);
@@ -242,11 +242,11 @@ protected:
public:
int get_point_count() const;
- void add_point(const Vector3 &p_pos, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1);
- void set_point_position(int p_index, const Vector3 &p_pos);
+ void add_point(const Vector3 &p_position, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1);
+ void set_point_position(int p_index, const Vector3 &p_position);
Vector3 get_point_position(int p_index) const;
- void set_point_tilt(int p_index, float p_tilt);
- float get_point_tilt(int p_index) const;
+ void set_point_tilt(int p_index, real_t p_tilt);
+ real_t get_point_tilt(int p_index) const;
void set_point_in(int p_index, const Vector3 &p_in);
Vector3 get_point_in(int p_index) const;
void set_point_out(int p_index, const Vector3 &p_out);
@@ -254,25 +254,25 @@ public:
void remove_point(int p_index);
void clear_points();
- Vector3 interpolate(int p_index, float p_offset) const;
+ Vector3 interpolate(int p_index, real_t p_offset) const;
Vector3 interpolatef(real_t p_findex) const;
- void set_bake_interval(float p_tolerance);
- float get_bake_interval() const;
+ void set_bake_interval(real_t p_tolerance);
+ real_t get_bake_interval() const;
void set_up_vector_enabled(bool p_enable);
bool is_up_vector_enabled() const;
- float get_baked_length() const;
- Vector3 interpolate_baked(float p_offset, bool p_cubic = false) const;
- float interpolate_baked_tilt(float p_offset) const;
- Vector3 interpolate_baked_up_vector(float p_offset, bool p_apply_tilt = false) const;
+ real_t get_baked_length() const;
+ Vector3 interpolate_baked(real_t p_offset, bool p_cubic = false) const;
+ real_t interpolate_baked_tilt(real_t p_offset) const;
+ Vector3 interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
PackedVector3Array get_baked_points() const; //useful for going through
Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
Vector3 get_closest_point(const Vector3 &p_to_point) const;
- float get_closest_offset(const Vector3 &p_to_point) const;
+ real_t get_closest_offset(const Vector3 &p_to_point) const;
- PackedVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
+ PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
Curve3D();
};
diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp
index fe7124de9e..4f9a055bfb 100644
--- a/scene/resources/immediate_mesh.cpp
+++ b/scene/resources/immediate_mesh.cpp
@@ -144,6 +144,7 @@ void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
active_surface_data.vertex_2d = true;
}
+
void ImmediateMesh::surface_end() {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface can't be created.");
@@ -185,7 +186,7 @@ void ImmediateMesh::surface_end() {
vtx[2] = vertices[i].z;
}
if (i == 0) {
- aabb.position = vertices[i];
+ aabb = AABB(vertices[i], SMALL_VEC3); // Must have a bit of size.
} else {
aabb.expand_to(vertices[i]);
}
diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h
index 6673ee6f3d..92bf91441d 100644
--- a/scene/resources/immediate_mesh.h
+++ b/scene/resources/immediate_mesh.h
@@ -75,6 +75,8 @@ class ImmediateMesh : public Mesh {
Vector<uint8_t> surface_vertex_create_cache;
Vector<uint8_t> surface_attribute_create_cache;
+ const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
+
protected:
static void _bind_methods();
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 8399b14a56..98bda4ad1b 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -1658,13 +1658,28 @@ bool BaseMaterial3D::get_feature(Feature p_feature) const {
void BaseMaterial3D::set_texture(TextureParam p_param, const Ref<Texture2D> &p_texture) {
ERR_FAIL_INDEX(p_param, TEXTURE_MAX);
+
+ if (get_texture(TEXTURE_ROUGHNESS).is_null() && p_texture.is_valid() && p_param == TEXTURE_ROUGHNESS) {
+ // If no roughness texture is currently set, automatically set the recommended value
+ // for roughness when using a roughness map.
+ set_roughness(1.0);
+ }
+
+ if (get_texture(TEXTURE_METALLIC).is_null() && p_texture.is_valid() && p_param == TEXTURE_METALLIC) {
+ // If no metallic texture is currently set, automatically set the recommended value
+ // for metallic when using a metallic map.
+ set_metallic(1.0);
+ }
+
textures[p_param] = p_texture;
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid);
+
if (p_texture.is_valid() && p_param == TEXTURE_ALBEDO) {
RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo_texture_size,
Vector2i(p_texture->get_width(), p_texture->get_height()));
}
+
notify_property_list_changed();
_queue_shader_change();
}
@@ -2884,7 +2899,7 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
idx++;
}
- print_line("remapped parameter not found: " + String(p_name));
+ WARN_PRINT("Godot 3.x SpatialMaterial remapped parameter not found: " + String(p_name));
return true;
}
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 51b4e1fbd8..e14d6be235 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -994,9 +994,9 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
//clear unused flags
- print_line("format pre: " + itos(old_format));
+ print_verbose("Mesh format pre-conversion: " + itos(old_format));
- print_line("format post: " + itos(new_format));
+ print_verbose("Mesh format post-conversion: " + itos(new_format));
ERR_FAIL_COND_V(!d.has("aabb"), false);
AABB aabb = d["aabb"];
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index e77f5a0be7..5ceb90d511 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -584,7 +584,7 @@ void ParticlesMaterial::_update_shader() {
code += " float base_angle = (tex_angle) * mix(initial_angle_min, initial_angle_max, rand_from_seed(alt_seed));\n";
code += " base_angle += CUSTOM.y * LIFETIME * (tex_angular_velocity) * mix(angular_velocity_min,angular_velocity_max, rand_from_seed(alt_seed));\n";
code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle
- code += " CUSTOM.z = (tex_anim_offset) * mix(anim_offset_min, anim_offset_max, rand_from_seed(alt_seed)) + CUSTOM.y * tex_anim_speed * mix(anim_speed_min, anim_speed_max, rand_from_seed(alt_seed));\n"; // angle
+ code += " CUSTOM.z = (tex_anim_offset) * mix(anim_offset_min, anim_offset_max, rand_from_seed(alt_seed)) + tv * tex_anim_speed * mix(anim_speed_min, anim_speed_max, rand_from_seed(alt_seed));\n"; // angle
// apply color
// apply hue rotation
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 951870fe34..e6870971d4 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -1647,6 +1647,21 @@ String VisualShaderNodeIntOp::generate_code(Shader::Mode p_mode, VisualShader::T
case OP_MIN:
code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
+ case OP_BITWISE_AND:
+ code += p_input_vars[0] + " & " + p_input_vars[1] + ";\n";
+ break;
+ case OP_BITWISE_OR:
+ code += p_input_vars[0] + " | " + p_input_vars[1] + ";\n";
+ break;
+ case OP_BITWISE_XOR:
+ code += p_input_vars[0] + " ^ " + p_input_vars[1] + ";\n";
+ break;
+ case OP_BITWISE_LEFT_SHIFT:
+ code += p_input_vars[0] + " << " + p_input_vars[1] + ";\n";
+ break;
+ case OP_BITWISE_RIGHT_SHIFT:
+ code += p_input_vars[0] + " >> " + p_input_vars[1] + ";\n";
+ break;
default:
break;
}
@@ -1677,7 +1692,7 @@ void VisualShaderNodeIntOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeIntOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeIntOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Max,Min,Bitwise AND,Bitwise OR,Bitwise XOR,Bitwise Left Shift,Bitwise Right Shift"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1686,6 +1701,11 @@ void VisualShaderNodeIntOp::_bind_methods() {
BIND_ENUM_CONSTANT(OP_MOD);
BIND_ENUM_CONSTANT(OP_MAX);
BIND_ENUM_CONSTANT(OP_MIN);
+ BIND_ENUM_CONSTANT(OP_BITWISE_AND);
+ BIND_ENUM_CONSTANT(OP_BITWISE_OR);
+ BIND_ENUM_CONSTANT(OP_BITWISE_XOR);
+ BIND_ENUM_CONSTANT(OP_BITWISE_LEFT_SHIFT);
+ BIND_ENUM_CONSTANT(OP_BITWISE_RIGHT_SHIFT);
BIND_ENUM_CONSTANT(OP_ENUM_SIZE);
}
@@ -2333,7 +2353,8 @@ String VisualShaderNodeIntFunc::generate_code(Shader::Mode p_mode, VisualShader:
static const char *functions[FUNC_MAX] = {
"abs($)",
"-($)",
- "sign($)"
+ "sign($)",
+ "~($)"
};
return " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n";
@@ -2362,11 +2383,12 @@ void VisualShaderNodeIntFunc::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIntFunc::set_function);
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIntFunc::get_function);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Abs,Negate,Sign"), "set_function", "get_function");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Abs,Negate,Sign,Bitwise NOT"), "set_function", "get_function");
BIND_ENUM_CONSTANT(FUNC_ABS);
BIND_ENUM_CONSTANT(FUNC_NEGATE);
BIND_ENUM_CONSTANT(FUNC_SIGN);
+ BIND_ENUM_CONSTANT(FUNC_BITWISE_NOT);
BIND_ENUM_CONSTANT(FUNC_MAX);
}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 2c952300fe..2f3400404c 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -579,6 +579,11 @@ public:
OP_MOD,
OP_MAX,
OP_MIN,
+ OP_BITWISE_AND,
+ OP_BITWISE_OR,
+ OP_BITWISE_XOR,
+ OP_BITWISE_LEFT_SHIFT,
+ OP_BITWISE_RIGHT_SHIFT,
OP_ENUM_SIZE,
};
@@ -882,6 +887,7 @@ public:
FUNC_ABS,
FUNC_NEGATE,
FUNC_SIGN,
+ FUNC_BITWISE_NOT,
FUNC_MAX,
};
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
index 1a829968e3..a7c20b2cb9 100644
--- a/scene/resources/visual_shader_particle_nodes.cpp
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -318,26 +318,24 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons
String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
- if (mesh.is_valid()) {
- if (is_output_port_connected(0)) { // position
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n";
- }
+ if (is_output_port_connected(0)) { // position
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n";
+ }
- if (is_output_port_connected(1)) { // normal
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n";
- }
+ if (is_output_port_connected(1)) { // normal
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n";
+ }
- if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n";
- }
+ if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n";
+ }
- if (is_output_port_connected(4)) { // uv
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n";
- }
+ if (is_output_port_connected(4)) { // uv
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n";
+ }
- if (is_output_port_connected(5)) { // uv2
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n";
- }
+ if (is_output_port_connected(5)) { // uv2
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n";
}
return code;
@@ -503,67 +501,97 @@ void VisualShaderNodeParticleMeshEmitter::_update_textures() {
Vector<Vector2> uvs;
Vector<Vector2> uvs2;
+ const int surface_count = mesh->get_surface_count();
+
if (use_all_surfaces) {
- for (int i = 0; i < max_surface_index; i++) {
+ for (int i = 0; i < surface_count; i++) {
+ const Array surface_arrays = mesh->surface_get_arrays(i);
+ const int surface_arrays_size = surface_arrays.size();
+
// position
- Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX];
- for (int j = 0; j < vertex_array.size(); j++) {
- vertices.push_back((Vector3)vertex_array[j]);
+ if (surface_arrays_size > Mesh::ARRAY_VERTEX) {
+ Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
+ for (int j = 0; j < vertex_array.size(); j++) {
+ vertices.push_back((Vector3)vertex_array[j]);
+ }
}
// normal
- Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL];
- for (int j = 0; j < normal_array.size(); j++) {
- normals.push_back((Vector3)normal_array[j]);
+ if (surface_arrays_size > Mesh::ARRAY_NORMAL) {
+ Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
+ for (int j = 0; j < normal_array.size(); j++) {
+ normals.push_back((Vector3)normal_array[j]);
+ }
}
// color
- Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR];
- for (int j = 0; j < color_array.size(); j++) {
- colors.push_back((Color)color_array[j]);
+ if (surface_arrays_size > Mesh::ARRAY_COLOR) {
+ Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
+ for (int j = 0; j < color_array.size(); j++) {
+ colors.push_back((Color)color_array[j]);
+ }
}
// uv
- Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV];
- for (int j = 0; j < uv_array.size(); j++) {
- uvs.push_back((Vector2)uv_array[j]);
+ if (surface_arrays_size > Mesh::ARRAY_TEX_UV) {
+ Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
+ for (int j = 0; j < uv_array.size(); j++) {
+ uvs.push_back((Vector2)uv_array[j]);
+ }
}
// uv2
- Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2];
- for (int j = 0; j < uv2_array.size(); j++) {
- uvs2.push_back((Vector2)uv2_array[j]);
+ if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) {
+ Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2];
+ for (int j = 0; j < uv2_array.size(); j++) {
+ uvs2.push_back((Vector2)uv2_array[j]);
+ }
}
}
} else {
- // position
- Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX];
- for (int i = 0; i < vertex_array.size(); i++) {
- vertices.push_back((Vector3)vertex_array[i]);
- }
+ if (surface_index >= 0 && surface_index < surface_count) {
+ const Array surface_arrays = mesh->surface_get_arrays(surface_index);
+ const int surface_arrays_size = surface_arrays.size();
- // normal
- Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL];
- for (int i = 0; i < normal_array.size(); i++) {
- normals.push_back((Vector3)normal_array[i]);
- }
+ // position
+ if (surface_arrays_size > Mesh::ARRAY_VERTEX) {
+ Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
+ for (int i = 0; i < vertex_array.size(); i++) {
+ vertices.push_back((Vector3)vertex_array[i]);
+ }
+ }
- // color
- Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR];
- for (int i = 0; i < color_array.size(); i++) {
- colors.push_back((Color)color_array[i]);
- }
+ // normal
+ if (surface_arrays_size > Mesh::ARRAY_NORMAL) {
+ Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
+ for (int i = 0; i < normal_array.size(); i++) {
+ normals.push_back((Vector3)normal_array[i]);
+ }
+ }
- // uv
- Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV];
- for (int j = 0; j < uv_array.size(); j++) {
- uvs.push_back((Vector2)uv_array[j]);
- }
+ // color
+ if (surface_arrays_size > Mesh::ARRAY_COLOR) {
+ Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
+ for (int i = 0; i < color_array.size(); i++) {
+ colors.push_back((Color)color_array[i]);
+ }
+ }
+
+ // uv
+ if (surface_arrays_size > Mesh::ARRAY_TEX_UV) {
+ Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
+ for (int j = 0; j < uv_array.size(); j++) {
+ uvs.push_back((Vector2)uv_array[j]);
+ }
+ }
- // uv2
- Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2];
- for (int j = 0; j < uv2_array.size(); j++) {
- uvs2.push_back((Vector2)uv2_array[j]);
+ // uv2
+ if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) {
+ Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2];
+ for (int j = 0; j < uv2_array.size(); j++) {
+ uvs2.push_back((Vector2)uv2_array[j]);
+ }
+ }
}
}
@@ -579,12 +607,6 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
return;
}
- if (p_mesh.is_valid()) {
- max_surface_index = p_mesh->get_surface_count();
- } else {
- max_surface_index = 0;
- }
-
if (mesh.is_valid()) {
Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures);
@@ -623,7 +645,16 @@ bool VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces() const {
}
void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) {
- if (p_surface_index == surface_index || p_surface_index < 0 || p_surface_index >= max_surface_index) {
+ if (mesh.is_valid()) {
+ if (mesh->get_surface_count() > 0) {
+ p_surface_index = CLAMP(p_surface_index, 0, mesh->get_surface_count() - 1);
+ } else {
+ p_surface_index = 0;
+ }
+ } else if (p_surface_index < 0) {
+ p_surface_index = 0;
+ }
+ if (surface_index == p_surface_index) {
return;
}
surface_index = p_surface_index;
diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h
index 79459432f1..ae7ea69225 100644
--- a/scene/resources/visual_shader_particle_nodes.h
+++ b/scene/resources/visual_shader_particle_nodes.h
@@ -111,7 +111,6 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt
Ref<Mesh> mesh;
bool use_all_surfaces = true;
int surface_index = 0;
- int max_surface_index = 0;
Ref<ImageTexture> position_texture;
Ref<ImageTexture> normal_texture;
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 186764e69e..a5ed27cb7b 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -61,6 +61,7 @@ SceneStringNames::SceneStringNames() {
animation_finished = StaticCString::create("animation_finished");
animation_changed = StaticCString::create("animation_changed");
animation_started = StaticCString::create("animation_started");
+ RESET = StaticCString::create("RESET");
pose_updated = StaticCString::create("pose_updated");
bone_pose_changed = StaticCString::create("bone_pose_changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 67007c85e0..b1ace1748c 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -97,6 +97,7 @@ public:
StringName animation_finished;
StringName animation_changed;
StringName animation_started;
+ StringName RESET;
StringName pose_updated;
StringName bone_pose_changed;