summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/audio_stream_player_2d.cpp6
-rw-r--r--scene/2d/tile_map.cpp6
-rw-r--r--scene/3d/audio_stream_player_3d.cpp8
-rw-r--r--scene/3d/collision_object_3d.cpp18
-rw-r--r--scene/3d/collision_polygon_3d.cpp12
-rw-r--r--scene/3d/collision_shape_3d.cpp10
-rw-r--r--scene/3d/light_3d.cpp13
-rw-r--r--scene/3d/lightmap_gi.cpp2
-rw-r--r--scene/3d/lightmap_gi.h2
-rw-r--r--scene/3d/physics_body_3d.cpp13
-rw-r--r--scene/3d/soft_body_3d.cpp13
-rw-r--r--scene/3d/xr_nodes.cpp37
-rw-r--r--scene/3d/xr_nodes.h9
-rw-r--r--scene/audio/audio_stream_player.cpp6
-rw-r--r--scene/gui/dialogs.cpp4
-rw-r--r--scene/gui/line_edit.cpp50
-rw-r--r--scene/gui/text_edit.cpp14
-rw-r--r--scene/gui/text_edit.h2
-rw-r--r--scene/main/multiplayer_api.cpp2
-rw-r--r--scene/main/node.cpp1
-rw-r--r--scene/main/node.h1
-rw-r--r--scene/resources/audio_stream_polyphonic.cpp32
-rw-r--r--scene/resources/audio_stream_polyphonic.h5
-rw-r--r--scene/resources/camera_attributes.cpp4
-rw-r--r--scene/resources/material.cpp10
-rw-r--r--scene/resources/material.h3
-rw-r--r--scene/resources/mesh.cpp19
-rw-r--r--scene/resources/mesh.h2
-rw-r--r--scene/resources/packed_scene.cpp19
-rw-r--r--scene/resources/packed_scene.h2
-rw-r--r--scene/resources/polygon_path_finder.cpp4
-rw-r--r--scene/resources/texture.cpp53
-rw-r--r--scene/resources/texture.h19
33 files changed, 273 insertions, 128 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index c4de3a124b..7b681eac7a 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -391,10 +391,8 @@ bool AudioStreamPlayer2D::get_stream_paused() const {
}
Ref<AudioStreamPlayback> AudioStreamPlayer2D::get_stream_playback() {
- if (!stream_playbacks.is_empty()) {
- return stream_playbacks[stream_playbacks.size() - 1];
- }
- return nullptr;
+ ERR_FAIL_COND_V_MSG(stream_playbacks.is_empty(), Ref<AudioStreamPlayback>(), "Player is inactive. Call play() before requesting get_stream_playback().");
+ return stream_playbacks[stream_playbacks.size() - 1];
}
void AudioStreamPlayer2D::set_max_polyphony(int p_max_polyphony) {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 05d28e8a0e..8c5aab4c80 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -2568,7 +2568,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_fill_path(int p_lay
}
}
}
- ERR_FAIL_COND_V_MSG(found_bit == TileSet::CELL_NEIGHBOR_MAX, output, vformat("Invalid terrain path, %s is not a neighbouring tile of %s", p_path[i + 1], p_path[i]));
+ ERR_FAIL_COND_V_MSG(found_bit == TileSet::CELL_NEIGHBOR_MAX, output, vformat("Invalid terrain path, %s is not a neighboring tile of %s", p_path[i + 1], p_path[i]));
neighbor_list.push_back(found_bit);
}
@@ -3220,7 +3220,7 @@ Vector2i TileMap::local_to_map(const Vector2 &p_local_position) const {
ret = ret.floor();
}
- // Compute the tile offset, and if we might the output for a neighbour top tile
+ // Compute the tile offset, and if we might the output for a neighbor top tile
Vector2 in_tile_pos = raw_pos - ret;
bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0;
bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0;
@@ -3284,7 +3284,7 @@ Vector2i TileMap::local_to_map(const Vector2 &p_local_position) const {
ret = ret.floor();
}
- // Compute the tile offset, and if we might the output for a neighbour top tile
+ // Compute the tile offset, and if we might the output for a neighbor top tile
Vector2 in_tile_pos = raw_pos - ret;
bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0;
bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 574f5363d4..7ed18d2d41 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -784,10 +784,8 @@ bool AudioStreamPlayer3D::get_stream_paused() const {
}
Ref<AudioStreamPlayback> AudioStreamPlayer3D::get_stream_playback() {
- if (!stream_playbacks.is_empty()) {
- return stream_playbacks[stream_playbacks.size() - 1];
- }
- return nullptr;
+ ERR_FAIL_COND_V_MSG(stream_playbacks.is_empty(), Ref<AudioStreamPlayback>(), "Player is inactive. Call play() before requesting get_stream_playback().");
+ return stream_playbacks[stream_playbacks.size() - 1];
}
void AudioStreamPlayer3D::set_max_polyphony(int p_max_polyphony) {
@@ -841,7 +839,7 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer3D::_set_playing);
ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer3D::_is_active);
- ClassDB::bind_method(D_METHOD("set_max_distance", "metres"), &AudioStreamPlayer3D::set_max_distance);
+ ClassDB::bind_method(D_METHOD("set_max_distance", "meters"), &AudioStreamPlayer3D::set_max_distance);
ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer3D::get_max_distance);
ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer3D::set_area_mask);
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 26ada1da5a..19d1b83cab 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -43,6 +43,11 @@ void CollisionObject3D::_notification(int p_what) {
}
_update_debug_shapes();
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_notify_local_transform(true); // Used for warnings and only in editor.
+ }
+#endif
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -78,6 +83,14 @@ void CollisionObject3D::_notification(int p_what) {
_update_pickable();
} break;
+#ifdef TOOLS_ENABLED
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+ } break;
+#endif
+
case NOTIFICATION_TRANSFORM_CHANGED: {
if (only_update_transform_changes) {
return;
@@ -724,6 +737,11 @@ PackedStringArray CollisionObject3D::get_configuration_warnings() const {
warnings.push_back(RTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape."));
}
+ Vector3 scale = get_transform().get_basis().get_scale();
+ if (!(Math::is_zero_approx(scale.x - scale.y) && Math::is_zero_approx(scale.y - scale.z))) {
+ warnings.push_back(RTR("With a non-uniform scale this node will probably not function as expected.\nPlease make its scale uniform (i.e. the same on all axes), and change the size in children collision shapes instead."));
+ }
+
return warnings;
}
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index 5fb8970085..53a61c1368 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -104,6 +104,11 @@ void CollisionPolygon3D::_notification(int p_what) {
if (parent) {
_update_in_shape_owner(true);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+#endif
} break;
case NOTIFICATION_UNPARENTED: {
@@ -171,13 +176,18 @@ PackedStringArray CollisionPolygon3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
- warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
+ warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node.\nPlease only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
}
if (polygon.is_empty()) {
warnings.push_back(RTR("An empty CollisionPolygon3D has no effect on collision."));
}
+ Vector3 scale = get_transform().get_basis().get_scale();
+ if (!(Math::is_zero_approx(scale.x - scale.y) && Math::is_zero_approx(scale.y - scale.z))) {
+ warnings.push_back(RTR("A non-uniformly scaled CollisionPolygon3D node will probably not function as expected.\nPlease make its scale uniform (i.e. the same on all axes), and change its polygon's vertices instead."));
+ }
+
return warnings;
}
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index 1709a17bce..dbd50cfd19 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -99,6 +99,11 @@ void CollisionShape3D::_notification(int p_what) {
if (parent) {
_update_in_shape_owner(true);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ }
+#endif
} break;
case NOTIFICATION_UNPARENTED: {
@@ -134,6 +139,11 @@ PackedStringArray CollisionShape3D::get_configuration_warnings() const {
}
}
+ Vector3 scale = get_transform().get_basis().get_scale();
+ if (!(Math::is_zero_approx(scale.x - scale.y) && Math::is_zero_approx(scale.y - scale.z))) {
+ warnings.push_back(RTR("A non-uniformly scaled CollisionShape3D node will probably not function as expected.\nPlease make its scale uniform (i.e. the same on all axes), and change the size of its shape resource instead."));
+ }
+
return warnings;
}
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 77073ff763..cca84c2b85 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -157,9 +157,16 @@ AABB Light3D::get_aabb() const {
return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
} else if (type == RenderingServer::LIGHT_SPOT) {
- real_t len = param[PARAM_RANGE];
- real_t size = Math::tan(Math::deg_to_rad(param[PARAM_SPOT_ANGLE])) * len;
- return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ real_t cone_slant_height = param[PARAM_RANGE];
+ real_t cone_angle_rad = Math::deg_to_rad(param[PARAM_SPOT_ANGLE]);
+
+ if (cone_angle_rad > Math_PI / 2.0) {
+ // Just return the AABB of an omni light if the spot angle is above 90 degrees.
+ return AABB(Vector3(-1, -1, -1) * cone_slant_height, Vector3(2, 2, 2) * cone_slant_height);
+ }
+
+ real_t size = Math::sin(cone_angle_rad) * cone_slant_height;
+ return AABB(Vector3(-size, -size, -cone_slant_height), Vector3(2 * size, 2 * size, cone_slant_height));
}
return AABB();
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index f308ad0999..fb74cffc94 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1545,6 +1545,8 @@ void LightmapGI::_bind_methods() {
BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32);
BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SCENE_ROOT);
+ BIND_ENUM_CONSTANT(BAKE_ERROR_FOREIGN_DATA);
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index 1294571cc0..40ff9e4cad 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -124,6 +124,8 @@ public:
enum BakeError {
BAKE_ERROR_OK,
+ BAKE_ERROR_NO_SCENE_ROOT,
+ BAKE_ERROR_FOREIGN_DATA,
BAKE_ERROR_NO_LIGHTMAPPER,
BAKE_ERROR_NO_SAVE_PATH,
BAKE_ERROR_NO_MESHES,
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 106efbc596..f4ab09cd9b 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -977,12 +977,11 @@ TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const {
}
PackedStringArray RigidBody3D::get_configuration_warnings() const {
- Transform3D t = get_transform();
+ PackedStringArray warnings = CollisionObject3D::get_configuration_warnings();
- PackedStringArray warnings = Node::get_configuration_warnings();
-
- if (ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05) {
- warnings.push_back(RTR("Size changes to RigidBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
+ Vector3 scale = get_transform().get_basis().get_scale();
+ if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) {
+ warnings.push_back(RTR("Scale changes to RigidBody3D will be overridden by the physics engine when running.\nPlease change the size in children collision shapes instead."));
}
return warnings;
@@ -1347,7 +1346,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
motion = motion.slide(up_direction);
result.travel = Vector3();
} else {
- // Travel is too high to be safely cancelled, we take it into account.
+ // Travel is too high to be safely canceled, we take it into account.
result.travel = result.travel.slide(up_direction);
motion = motion.normalized() * result.travel.length();
}
@@ -1355,7 +1354,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
// Determines if you are on the ground, and limits the possibility of climbing on the walls because of the approximations.
_snap_on_floor(true, false);
} else {
- // If the movement is not cancelled we only keep the remaining.
+ // If the movement is not canceled we only keep the remaining.
motion = result.remainder;
}
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index e8b51ceb92..e7e3084037 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -302,14 +302,6 @@ void SoftBody3D::_notification(int p_what) {
_prepare_physics_server();
}
} break;
-
-#ifdef TOOLS_ENABLED
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- }
- } break;
-#endif
}
}
@@ -391,11 +383,6 @@ PackedStringArray SoftBody3D::get_configuration_warnings() const {
warnings.push_back(RTR("This body will be ignored until you set a mesh."));
}
- Transform3D t = get_transform();
- if ((ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05)) {
- warnings.push_back(RTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
- }
-
return warnings;
}
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index a758cc5e5e..ac0a47d1a1 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -432,15 +432,16 @@ PackedStringArray XRNode3D::get_configuration_warnings() const {
void XRController3D::_bind_methods() {
// passthroughs to information about our related joystick
ClassDB::bind_method(D_METHOD("is_button_pressed", "name"), &XRController3D::is_button_pressed);
- ClassDB::bind_method(D_METHOD("get_value", "name"), &XRController3D::get_value);
- ClassDB::bind_method(D_METHOD("get_axis", "name"), &XRController3D::get_axis);
+ ClassDB::bind_method(D_METHOD("get_input", "name"), &XRController3D::get_input);
+ ClassDB::bind_method(D_METHOD("get_float", "name"), &XRController3D::get_float);
+ ClassDB::bind_method(D_METHOD("get_vector2", "name"), &XRController3D::get_vector2);
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRController3D::get_tracker_hand);
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
- ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
- ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "value")));
+ ADD_SIGNAL(MethodInfo("input_float_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
+ ADD_SIGNAL(MethodInfo("input_vector2_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "value")));
};
void XRController3D::_bind_tracker() {
@@ -449,8 +450,8 @@ void XRController3D::_bind_tracker() {
// bind to input signals
tracker->connect("button_pressed", callable_mp(this, &XRController3D::_button_pressed));
tracker->connect("button_released", callable_mp(this, &XRController3D::_button_released));
- tracker->connect("input_value_changed", callable_mp(this, &XRController3D::_input_value_changed));
- tracker->connect("input_axis_changed", callable_mp(this, &XRController3D::_input_axis_changed));
+ tracker->connect("input_float_changed", callable_mp(this, &XRController3D::_input_float_changed));
+ tracker->connect("input_vector2_changed", callable_mp(this, &XRController3D::_input_vector2_changed));
}
}
@@ -459,8 +460,8 @@ void XRController3D::_unbind_tracker() {
// unbind input signals
tracker->disconnect("button_pressed", callable_mp(this, &XRController3D::_button_pressed));
tracker->disconnect("button_released", callable_mp(this, &XRController3D::_button_released));
- tracker->disconnect("input_value_changed", callable_mp(this, &XRController3D::_input_value_changed));
- tracker->disconnect("input_axis_changed", callable_mp(this, &XRController3D::_input_axis_changed));
+ tracker->disconnect("input_float_changed", callable_mp(this, &XRController3D::_input_float_changed));
+ tracker->disconnect("input_vector2_changed", callable_mp(this, &XRController3D::_input_vector2_changed));
}
XRNode3D::_unbind_tracker();
@@ -476,14 +477,14 @@ void XRController3D::_button_released(const String &p_name) {
emit_signal(SNAME("button_released"), p_name);
}
-void XRController3D::_input_value_changed(const String &p_name, float p_value) {
+void XRController3D::_input_float_changed(const String &p_name, float p_value) {
// just pass it on...
- emit_signal(SNAME("input_value_changed"), p_name, p_value);
+ emit_signal(SNAME("input_float_changed"), p_name, p_value);
}
-void XRController3D::_input_axis_changed(const String &p_name, Vector2 p_value) {
+void XRController3D::_input_vector2_changed(const String &p_name, Vector2 p_value) {
// just pass it on...
- emit_signal(SNAME("input_axis_changed"), p_name, p_value);
+ emit_signal(SNAME("input_vector2_changed"), p_name, p_value);
}
bool XRController3D::is_button_pressed(const StringName &p_name) const {
@@ -496,7 +497,15 @@ bool XRController3D::is_button_pressed(const StringName &p_name) const {
}
}
-float XRController3D::get_value(const StringName &p_name) const {
+Variant XRController3D::get_input(const StringName &p_name) const {
+ if (tracker.is_valid()) {
+ return tracker->get_input(p_name);
+ } else {
+ return Variant();
+ }
+}
+
+float XRController3D::get_float(const StringName &p_name) const {
if (tracker.is_valid()) {
// Inputs should already be of the correct type, our XR runtime handles conversions between raw input and the desired type, but just in case we convert
Variant input = tracker->get_input(p_name);
@@ -517,7 +526,7 @@ float XRController3D::get_value(const StringName &p_name) const {
}
}
-Vector2 XRController3D::get_axis(const StringName &p_name) const {
+Vector2 XRController3D::get_vector2(const StringName &p_name) const {
if (tracker.is_valid()) {
// Inputs should already be of the correct type, our XR runtime handles conversions between raw input and the desired type, but just in case we convert
Variant input = tracker->get_input(p_name);
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index c93cb14d62..6e56aa28de 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -131,13 +131,14 @@ protected:
void _button_pressed(const String &p_name);
void _button_released(const String &p_name);
- void _input_value_changed(const String &p_name, float p_value);
- void _input_axis_changed(const String &p_name, Vector2 p_value);
+ void _input_float_changed(const String &p_name, float p_value);
+ void _input_vector2_changed(const String &p_name, Vector2 p_value);
public:
bool is_button_pressed(const StringName &p_name) const;
- float get_value(const StringName &p_name) const;
- Vector2 get_axis(const StringName &p_name) const;
+ Variant get_input(const StringName &p_name) const;
+ float get_float(const StringName &p_name) const;
+ Vector2 get_vector2(const StringName &p_name) const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 42f76068e7..d40fc10441 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -308,10 +308,8 @@ void AudioStreamPlayer::_bus_layout_changed() {
}
Ref<AudioStreamPlayback> AudioStreamPlayer::get_stream_playback() {
- if (!stream_playbacks.is_empty()) {
- return stream_playbacks[stream_playbacks.size() - 1];
- }
- return nullptr;
+ ERR_FAIL_COND_V_MSG(stream_playbacks.is_empty(), Ref<AudioStreamPlayback>(), "Player is inactive. Call play() before requesting get_stream_playback().");
+ return stream_playbacks[stream_playbacks.size() - 1];
}
void AudioStreamPlayer::_bind_methods() {
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 4365db2ea2..dfe9ea3b08 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -136,7 +136,7 @@ void AcceptDialog::_cancel_pressed() {
call_deferred(SNAME("hide"));
- emit_signal(SNAME("cancelled"));
+ emit_signal(SNAME("canceled"));
cancel_pressed();
@@ -372,7 +372,7 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_ok_button_text"), &AcceptDialog::get_ok_button_text);
ADD_SIGNAL(MethodInfo("confirmed"));
- ADD_SIGNAL(MethodInfo("cancelled"));
+ ADD_SIGNAL(MethodInfo("canceled"));
ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action")));
ADD_PROPERTY(PropertyInfo(Variant::STRING, "ok_button_text"), "set_ok_button_text", "get_ok_button_text");
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index e5bb64b225..e2a5b0c8a3 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -952,9 +952,9 @@ void LineEdit::_notification(int p_what) {
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale);
- if (ime_text.length() == 0) {
+ if (ime_text.is_empty() || ime_selection.y == 0) {
// Normal caret.
- CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column);
+ CaretInfo caret = TS->shaped_text_get_carets(text_rid, ime_text.is_empty() ? caret_column : caret_column + ime_selection.x);
if (using_placeholder || (caret.l_caret == Rect2() && caret.t_caret == Rect2())) {
// No carets, add one at the start.
int h = theme_cache.font->get_height(theme_cache.font_size);
@@ -980,6 +980,7 @@ void LineEdit::_notification(int p_what) {
}
} break;
}
+
RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.l_caret, caret_color);
} else {
if (caret.l_caret != Rect2() && caret.l_dir == TextServer::DIRECTION_AUTO) {
@@ -1009,7 +1010,8 @@ void LineEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.t_caret, caret_color);
}
- } else {
+ }
+ if (!ime_text.is_empty()) {
{
// IME intermediate text range.
Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, caret_column, caret_column + ime_text.length());
@@ -1030,20 +1032,22 @@ void LineEdit::_notification(int p_what) {
}
{
// IME caret.
- Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, caret_column + ime_selection.x, caret_column + ime_selection.x + ime_selection.y);
- for (int i = 0; i < sel.size(); i++) {
- Rect2 rect = Rect2(sel[i].x + ofs.x, ofs.y, sel[i].y - sel[i].x, text_height);
- if (rect.position.x + rect.size.x <= x_ofs || rect.position.x > ofs_max) {
- continue;
- }
- if (rect.position.x < x_ofs) {
- rect.size.x -= (x_ofs - rect.position.x);
- rect.position.x = x_ofs;
- } else if (rect.position.x + rect.size.x > ofs_max) {
- rect.size.x = ofs_max - rect.position.x;
+ if (ime_selection.y > 0) {
+ Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, caret_column + ime_selection.x, caret_column + ime_selection.x + ime_selection.y);
+ for (int i = 0; i < sel.size(); i++) {
+ Rect2 rect = Rect2(sel[i].x + ofs.x, ofs.y, sel[i].y - sel[i].x, text_height);
+ if (rect.position.x + rect.size.x <= x_ofs || rect.position.x > ofs_max) {
+ continue;
+ }
+ if (rect.position.x < x_ofs) {
+ rect.size.x -= (x_ofs - rect.position.x);
+ rect.position.x = x_ofs;
+ } else if (rect.position.x + rect.size.x > ofs_max) {
+ rect.size.x = ofs_max - rect.position.x;
+ }
+ rect.size.y = caret_width * 3;
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, rect, caret_color);
}
- rect.size.y = caret_width * 3;
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, rect, caret_color);
}
}
}
@@ -1052,7 +1056,8 @@ void LineEdit::_notification(int p_what) {
if (has_focus()) {
if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
- DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + TS->shaped_text_get_size(text_rid).y), get_viewport()->get_window_id());
+ Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + theme_cache.font->get_height(theme_cache.font_size)) / 2);
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + pos, get_viewport()->get_window_id());
}
}
} break;
@@ -1071,8 +1076,8 @@ void LineEdit::_notification(int p_what) {
if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
- Point2 column = Point2(get_caret_column(), 1) * get_minimum_size().height;
- DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + column, get_viewport()->get_window_id());
+ Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + theme_cache.font->get_height(theme_cache.font_size)) / 2);
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + pos, get_viewport()->get_window_id());
}
show_virtual_keyboard();
@@ -1103,6 +1108,11 @@ void LineEdit::_notification(int p_what) {
if (has_focus()) {
ime_text = DisplayServer::get_singleton()->ime_get_text();
ime_selection = DisplayServer::get_singleton()->ime_get_selection();
+
+ if (!ime_text.is_empty()) {
+ selection_delete();
+ }
+
_shape();
set_caret_column(caret_column); // Update scroll_offset
@@ -2576,7 +2586,7 @@ LineEdit::LineEdit(const String &p_placeholder) {
set_placeholder(p_placeholder);
- set_editable(true); // Initialise to opposite first, so we get past the early-out in set_editable.
+ set_editable(true); // Initialize to opposite first, so we get past the early-out in set_editable.
}
LineEdit::~LineEdit() {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 8ffaa9e81f..56bd5c872a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1319,11 +1319,12 @@ void TextEdit::_notification(int p_what) {
if (!clipped && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index) {
carets.write[c].draw_pos.y = ofs_y + ldata->get_line_descent(line_wrap_index);
- if (ime_text.length() == 0) {
+ if (ime_text.is_empty() || ime_selection.y == 0) {
+ // Normal caret.
CaretInfo ts_caret;
- if (str.length() != 0) {
+ if (!str.is_empty() || !ime_text.is_empty()) {
// Get carets.
- ts_caret = TS->shaped_text_get_carets(rid, get_caret_column(c));
+ ts_caret = TS->shaped_text_get_carets(rid, ime_text.is_empty() ? get_caret_column(c) : get_caret_column(c) + ime_selection.x);
} else {
// No carets, add one at the start.
int h = font->get_height(font_size);
@@ -1426,7 +1427,8 @@ void TextEdit::_notification(int p_what) {
}
}
}
- } else {
+ }
+ if (!ime_text.is_empty()) {
{
// IME Intermediate text range.
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, get_caret_column(c), get_caret_column(c) + ime_text.length());
@@ -1546,6 +1548,10 @@ void TextEdit::_notification(int p_what) {
ime_text = DisplayServer::get_singleton()->ime_get_text();
ime_selection = DisplayServer::get_singleton()->ime_get_selection();
+ if (!ime_text.is_empty()) {
+ delete_selection();
+ }
+
for (int i = 0; i < carets.size(); i++) {
String t;
if (get_caret_column(i) >= 0) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 426acc4996..2ec2f39409 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -274,7 +274,7 @@ private:
void _update_placeholder();
- /* Initialise to opposite first, so we get past the early-out in set_editable. */
+ /* Initialize to opposite first, so we get past the early-out in set_editable. */
bool editable = false;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
index e36cbc4414..c54e61580f 100644
--- a/scene/main/multiplayer_api.cpp
+++ b/scene/main/multiplayer_api.cpp
@@ -135,7 +135,7 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint
return err;
}
if (r_buffer) {
- // The first byte is not used by the marshalling, so store the type
+ // The first byte is not used by the marshaling, so store the type
// so we know how to decompress and decode this variant.
r_buffer[0] = p_variant.get_type();
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index def91c424c..0b1f8f101c 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2947,6 +2947,7 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE);
BIND_CONSTANT(NOTIFICATION_DISABLED);
BIND_CONSTANT(NOTIFICATION_ENABLED);
+ BIND_CONSTANT(NOTIFICATION_NODE_RECACHE_REQUESTED);
BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE);
BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE);
diff --git a/scene/main/node.h b/scene/main/node.h
index dbdcca6170..493578bc5b 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -270,6 +270,7 @@ public:
NOTIFICATION_POST_ENTER_TREE = 27,
NOTIFICATION_DISABLED = 28,
NOTIFICATION_ENABLED = 29,
+ NOTIFICATION_NODE_RECACHE_REQUESTED = 30,
//keep these linked to node
NOTIFICATION_WM_MOUSE_ENTER = 1002,
diff --git a/scene/resources/audio_stream_polyphonic.cpp b/scene/resources/audio_stream_polyphonic.cpp
index 2e56ff3423..f7299b0789 100644
--- a/scene/resources/audio_stream_polyphonic.cpp
+++ b/scene/resources/audio_stream_polyphonic.cpp
@@ -87,7 +87,6 @@ void AudioStreamPlaybackPolyphonic::stop() {
AudioServer::get_singleton()->lock();
}
s.active.clear();
- s.finalizing.clear();
s.finish_request.clear();
s.stream_playback.unref();
s.stream.unref();
@@ -137,7 +136,7 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale,
continue;
}
- float volume_db = s.volume_db; // Copy because it can be overriden at any time.
+ float volume_db = s.volume_db; // Copy because it can be overridden at any time.
float next_volume = Math::db_to_linear(volume_db);
s.prev_volume_db = volume_db;
@@ -145,7 +144,6 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale,
if (s.pending_play.is_set()) {
// Did not get the chance to play, was finalized too soon.
s.active.clear();
- s.finalizing.set();
continue;
}
next_volume = 0;
@@ -163,6 +161,8 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale,
int offset = 0;
float volume = prev_volume;
+ bool stream_done = false;
+
while (todo) {
int to_mix = MIN(todo, int(INTERNAL_BUFFER_LEN));
int mixed = s.stream_playback->mix(internal_buffer, s.pitch_scale, to_mix);
@@ -175,7 +175,7 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale,
if (mixed < to_mix) {
// Stream is done.
s.active.clear();
- s.finalizing.set();
+ stream_done = true;
break;
}
@@ -183,34 +183,22 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale,
offset += to_mix;
}
+ if (stream_done) {
+ continue;
+ }
+
if (s.finish_request.is_set()) {
s.active.clear();
- s.finalizing.set();
}
}
return p_frames;
}
-void AudioStreamPlaybackPolyphonic::_check_finalized_streams() {
- if (!active) {
- return;
- }
-
- for (Stream &s : streams) {
- if (!s.active.is_set() && s.finalizing.is_set()) {
- s.stream_playback.unref();
- s.stream.unref();
- s.finalizing.clear();
- s.finish_request.clear();
- }
- }
-}
-
AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::play_stream(const Ref<AudioStream> &p_stream, float p_from_offset, float p_volume_db, float p_pitch_scale) {
ERR_FAIL_COND_V(p_stream.is_null(), INVALID_ID);
for (uint32_t i = 0; i < streams.size(); i++) {
- if (!streams[i].active.is_set() && !streams[i].finish_request.is_set() && !streams[i].finalizing.is_set()) {
+ if (!streams[i].active.is_set()) {
// Can use this stream, as it's not active.
streams[i].stream = p_stream;
streams[i].stream_playback = streams[i].stream->instantiate_playback();
@@ -219,6 +207,7 @@ AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::play_stream(con
streams[i].prev_volume_db = p_volume_db;
streams[i].pitch_scale = p_pitch_scale;
streams[i].id = id_counter++;
+ streams[i].finish_request.clear();
streams[i].pending_play.set();
streams[i].active.set();
return (ID(i) << INDEX_SHIFT) | ID(streams[i].id);
@@ -282,5 +271,4 @@ void AudioStreamPlaybackPolyphonic::_bind_methods() {
}
AudioStreamPlaybackPolyphonic::AudioStreamPlaybackPolyphonic() {
- SceneTree::get_singleton()->connect(SNAME("process_frame"), callable_mp(this, &AudioStreamPlaybackPolyphonic::_check_finalized_streams));
}
diff --git a/scene/resources/audio_stream_polyphonic.h b/scene/resources/audio_stream_polyphonic.h
index b5ccc7eb7f..e414401b6f 100644
--- a/scene/resources/audio_stream_polyphonic.h
+++ b/scene/resources/audio_stream_polyphonic.h
@@ -63,7 +63,6 @@ class AudioStreamPlaybackPolyphonic : public AudioStreamPlayback {
SafeFlag active;
SafeFlag pending_play;
SafeFlag finish_request;
- SafeFlag finalizing;
float play_offset = 0;
float pitch_scale = 1.0;
Ref<AudioStream> stream;
@@ -73,7 +72,7 @@ class AudioStreamPlaybackPolyphonic : public AudioStreamPlayback {
uint32_t id = 0;
Stream() :
- active(false), pending_play(false), finish_request(false), finalizing(false) {}
+ active(false), pending_play(false), finish_request(false) {}
};
LocalVector<Stream> streams;
@@ -84,8 +83,6 @@ class AudioStreamPlaybackPolyphonic : public AudioStreamPlayback {
_FORCE_INLINE_ Stream *_find_stream(int64_t p_id);
- void _check_finalized_streams();
-
friend class AudioStreamPolyphonic;
protected:
diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp
index b5e302cce5..61df56523d 100644
--- a/scene/resources/camera_attributes.cpp
+++ b/scene/resources/camera_attributes.cpp
@@ -286,10 +286,10 @@ void CameraAttributesPractical::_bind_methods() {
ADD_GROUP("DOF Blur", "dof_blur_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
ADD_GROUP("Auto Exposure", "auto_exposure_");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index db7385428b..f4aa0637f7 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -113,6 +113,12 @@ bool Material::_can_use_render_priority() const {
return ret;
}
+Ref<Resource> Material::create_placeholder() const {
+ Ref<PlaceholderMaterial> placeholder;
+ placeholder.instantiate();
+ return placeholder;
+}
+
void Material::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass);
ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass);
@@ -123,6 +129,8 @@ void Material::_bind_methods() {
ClassDB::bind_method(D_METHOD("inspect_native_shader_code"), &Material::inspect_native_shader_code);
ClassDB::set_method_flags(get_class_static(), _scs_create("inspect_native_shader_code"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Material::create_placeholder);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RENDER_PRIORITY_MIN) + "," + itos(RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "next_pass", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_next_pass", "get_next_pass");
@@ -188,7 +196,7 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
if (shader.is_valid()) {
const StringName *sn = remap_cache.getptr(p_name);
if (sn) {
- // Only return a parameter if it was previosly set.
+ // Only return a parameter if it was previously set.
r_ret = get_shader_parameter(*sn);
return true;
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 83c7a09cc4..fe1448cd4c 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -74,6 +74,9 @@ public:
virtual RID get_rid() const override;
virtual RID get_shader_rid() const;
virtual Shader::Mode get_shader_mode() const;
+
+ virtual Ref<Resource> create_placeholder() const;
+
Material();
virtual ~Material();
};
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index c93b51552f..cf9baa2907 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -615,6 +615,13 @@ Size2i Mesh::get_lightmap_size_hint() const {
return lightmap_size_hint;
}
+Ref<Resource> Mesh::create_placeholder() const {
+ Ref<PlaceholderMesh> placeholder;
+ placeholder.instantiate();
+ placeholder->set_aabb(get_aabb());
+ return placeholder;
+}
+
void Mesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint);
ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint);
@@ -627,6 +634,7 @@ void Mesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("surface_get_blend_shape_arrays", "surf_idx"), &Mesh::surface_get_blend_shape_arrays);
ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material"), &Mesh::surface_set_material);
ClassDB::bind_method(D_METHOD("surface_get_material", "surf_idx"), &Mesh::surface_get_material);
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Mesh::create_placeholder);
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
@@ -1122,17 +1130,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
int idx = sname.substr(8, sl - 8).to_int();
- // This is a bit of a hack to ensure compatibility with older material
- // overrides that start indexing at 1.
- // We assume that idx 0 is always read first, if its not, this won't work.
- if (idx == 0) {
- surface_index_0 = true;
- }
- if (!surface_index_0) {
- // This means the file was created when the indexing started at 1, so decrease by one.
- idx--;
- }
-
String what = sname.get_slicec('/', 1);
if (what == "material") {
surface_set_material(idx, p_value);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 1baa466312..1b870d996a 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -220,6 +220,8 @@ public:
virtual int get_builtin_bind_pose_count() const;
virtual Transform3D get_builtin_bind_pose(int p_index) const;
+ virtual Ref<Resource> create_placeholder() const;
+
Mesh();
};
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index c24186a109..e497a628aa 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -1046,6 +1046,25 @@ Ref<SceneState> SceneState::get_base_scene_state() const {
return Ref<SceneState>();
}
+void SceneState::update_instance_resource(String p_path, Ref<PackedScene> p_packed_scene) {
+ ERR_FAIL_COND(p_packed_scene.is_null());
+
+ for (const NodeData &nd : nodes) {
+ if (nd.instance >= 0) {
+ if (!(nd.instance & FLAG_INSTANCE_IS_PLACEHOLDER)) {
+ int instance_id = nd.instance & FLAG_MASK;
+ Ref<PackedScene> original_packed_scene = variants[instance_id];
+ if (original_packed_scene.is_valid()) {
+ if (original_packed_scene->get_path() == p_path) {
+ variants.remove_at(instance_id);
+ variants.insert(instance_id, p_packed_scene);
+ }
+ }
+ }
+ }
+ }
+}
+
int SceneState::find_node_by_path(const NodePath &p_node) const {
ERR_FAIL_COND_V_MSG(node_path_cache.size() == 0, -1, "This operation requires the node cache to have been built.");
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index ef7363dd44..5c53ffdb45 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -150,6 +150,8 @@ public:
Ref<SceneState> get_base_scene_state() const;
+ void update_instance_resource(String p_path, Ref<PackedScene> p_packed_scene);
+
//unbuild API
int get_node_count() const;
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index 85106883f9..3bbd0a0b5e 100644
--- a/scene/resources/polygon_path_finder.cpp
+++ b/scene/resources/polygon_path_finder.cpp
@@ -325,7 +325,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
}
const Point &np = points[least_cost_point];
- //open the neighbours for search
+ //open the neighbors for search
for (const int &E : np.connections) {
Point &p = points.write[E];
@@ -339,7 +339,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
p.distance = distance;
}
} else {
- //add to open neighbours
+ //add to open neighbors
p.prev = least_cost_point;
p.distance = distance;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index f106eebff5..85e21d6056 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -94,6 +94,13 @@ bool Texture2D::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Re
return true;
}
+Ref<Resource> Texture2D::create_placeholder() const {
+ Ref<PlaceholderTexture2D> placeholder;
+ placeholder.instantiate();
+ placeholder->set_size(get_size());
+ return placeholder;
+}
+
void Texture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_width"), &Texture2D::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &Texture2D::get_height);
@@ -103,6 +110,7 @@ void Texture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_image"), &Texture2D::get_image);
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Texture2D::create_placeholder);
ADD_GROUP("", "");
@@ -1137,6 +1145,7 @@ void Texture3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth);
ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps);
ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_datai);
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Texture3D::create_placeholder);
GDVIRTUAL_BIND(_get_format);
GDVIRTUAL_BIND(_get_width);
@@ -1145,6 +1154,14 @@ void Texture3D::_bind_methods() {
GDVIRTUAL_BIND(_has_mipmaps);
GDVIRTUAL_BIND(_get_data);
}
+
+Ref<Resource> Texture3D::create_placeholder() const {
+ Ref<PlaceholderTexture3D> placeholder;
+ placeholder.instantiate();
+ placeholder->set_size(Vector3i(get_width(), get_height(), get_depth()));
+ return placeholder;
+}
+
//////////////////////////////////////////
Image::Format ImageTexture3D::get_format() const {
@@ -3048,6 +3065,42 @@ ImageTextureLayered::~ImageTextureLayered() {
}
}
+void Texture2DArray::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Texture2DArray::create_placeholder);
+}
+
+Ref<Resource> Texture2DArray::create_placeholder() const {
+ Ref<PlaceholderTexture2DArray> placeholder;
+ placeholder.instantiate();
+ placeholder->set_size(Size2i(get_width(), get_height()));
+ placeholder->set_layers(get_layers());
+ return placeholder;
+}
+
+void Cubemap::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &Cubemap::create_placeholder);
+}
+
+Ref<Resource> Cubemap::create_placeholder() const {
+ Ref<PlaceholderCubemap> placeholder;
+ placeholder.instantiate();
+ placeholder->set_size(Size2i(get_width(), get_height()));
+ placeholder->set_layers(get_layers());
+ return placeholder;
+}
+
+void CubemapArray::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("create_placeholder"), &CubemapArray::create_placeholder);
+}
+
+Ref<Resource> CubemapArray::create_placeholder() const {
+ Ref<PlaceholderCubemapArray> placeholder;
+ placeholder.instantiate();
+ placeholder->set_size(Size2i(get_width(), get_height()));
+ placeholder->set_layers(get_layers());
+ return placeholder;
+}
+
///////////////////////////////////////////
void CompressedTextureLayered::set_path(const String &p_path, bool p_take_over) {
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index bb86910c0c..7f74ae6941 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -82,6 +82,8 @@ public:
virtual Ref<Image> get_image() const { return Ref<Image>(); }
+ virtual Ref<Resource> create_placeholder() const;
+
Texture2D();
};
@@ -450,25 +452,41 @@ public:
class Texture2DArray : public ImageTextureLayered {
GDCLASS(Texture2DArray, ImageTextureLayered)
+
+protected:
+ static void _bind_methods();
+
public:
Texture2DArray() :
ImageTextureLayered(LAYERED_TYPE_2D_ARRAY) {}
+
+ virtual Ref<Resource> create_placeholder() const;
};
class Cubemap : public ImageTextureLayered {
GDCLASS(Cubemap, ImageTextureLayered);
+protected:
+ static void _bind_methods();
+
public:
Cubemap() :
ImageTextureLayered(LAYERED_TYPE_CUBEMAP) {}
+
+ virtual Ref<Resource> create_placeholder() const;
};
class CubemapArray : public ImageTextureLayered {
GDCLASS(CubemapArray, ImageTextureLayered);
+protected:
+ static void _bind_methods();
+
public:
CubemapArray() :
ImageTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {}
+
+ virtual Ref<Resource> create_placeholder() const;
};
class CompressedTextureLayered : public TextureLayered {
@@ -580,6 +598,7 @@ public:
virtual int get_depth() const;
virtual bool has_mipmaps() const;
virtual Vector<Ref<Image>> get_data() const;
+ virtual Ref<Resource> create_placeholder() const;
};
class ImageTexture3D : public Texture3D {