summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/animated_sprite.cpp28
-rw-r--r--scene/2d/animated_sprite.h3
-rw-r--r--scene/2d/area_2d.cpp2
-rw-r--r--scene/2d/collision_object_2d.cpp7
-rw-r--r--scene/2d/collision_polygon_2d.cpp35
-rw-r--r--scene/2d/cpu_particles_2d.cpp86
-rw-r--r--scene/2d/cpu_particles_2d.h3
-rw-r--r--scene/2d/line_2d.cpp10
-rw-r--r--scene/2d/line_2d.h2
-rw-r--r--scene/2d/parallax_background.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp11
-rw-r--r--scene/2d/polygon_2d.cpp4
-rw-r--r--scene/2d/sprite.cpp2
-rw-r--r--scene/2d/tile_map.cpp51
-rw-r--r--scene/2d/tile_map.h2
-rw-r--r--scene/3d/area.cpp3
-rw-r--r--scene/3d/collision_object.cpp2
-rw-r--r--scene/3d/collision_shape.cpp4
-rw-r--r--scene/3d/cpu_particles.cpp84
-rw-r--r--scene/3d/cpu_particles.h3
-rw-r--r--scene/3d/gi_probe.cpp10
-rw-r--r--scene/3d/gi_probe.h2
-rw-r--r--scene/3d/light.cpp7
-rw-r--r--scene/3d/light.h1
-rw-r--r--scene/3d/physics_body.cpp12
-rw-r--r--scene/3d/physics_body.h4
-rw-r--r--scene/3d/skeleton.cpp46
-rw-r--r--scene/3d/skeleton.h4
-rw-r--r--scene/3d/spatial.cpp2
-rw-r--r--scene/animation/animation_node_state_machine.cpp6
-rw-r--r--scene/animation/animation_player.cpp3
-rw-r--r--scene/animation/animation_tree.cpp30
-rw-r--r--scene/animation/tween.cpp5
-rw-r--r--scene/audio/audio_stream_player.cpp4
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/container.cpp13
-rw-r--r--scene/gui/container.h2
-rw-r--r--scene/gui/control.cpp7
-rw-r--r--scene/gui/file_dialog.cpp3
-rw-r--r--scene/gui/graph_edit.cpp9
-rw-r--r--scene/gui/graph_node.cpp6
-rw-r--r--scene/gui/line_edit.cpp10
-rw-r--r--scene/gui/popup_menu.cpp4
-rw-r--r--scene/gui/rich_text_label.cpp25
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/scroll_container.cpp6
-rw-r--r--scene/gui/text_edit.cpp53
-rw-r--r--scene/gui/text_edit.h1
-rw-r--r--scene/gui/texture_button.cpp3
-rw-r--r--scene/gui/tree.cpp10
-rw-r--r--scene/main/canvas_layer.cpp51
-rw-r--r--scene/main/canvas_layer.h10
-rw-r--r--scene/main/node.cpp14
-rw-r--r--scene/main/node.h16
-rw-r--r--scene/main/scene_tree.cpp4
-rw-r--r--scene/main/scene_tree.h2
-rw-r--r--scene/main/viewport.cpp219
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/resources/animation.cpp10
-rw-r--r--scene/resources/audio_stream_sample.cpp11
-rw-r--r--scene/resources/audio_stream_sample.h2
-rw-r--r--scene/resources/bit_map.cpp3
-rw-r--r--scene/resources/mesh.cpp30
-rw-r--r--scene/resources/mesh.h1
-rw-r--r--scene/resources/mesh_library.cpp26
-rw-r--r--scene/resources/mesh_library.h3
-rw-r--r--scene/resources/packed_scene.cpp6
-rw-r--r--scene/resources/resource_format_text.cpp6
-rw-r--r--scene/resources/sky.cpp8
-rw-r--r--scene/resources/sky.h2
-rw-r--r--scene/resources/texture.cpp6
-rw-r--r--scene/resources/texture.h1
-rw-r--r--scene/resources/tile_set.cpp30
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--scene/resources/visual_shader.cpp2
75 files changed, 662 insertions, 444 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 3d7ff5f1fd..7a50574be2 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -93,7 +93,7 @@ Rect2 AnimatedSprite::_get_rect() const {
Point2 ofs = offset;
if (centered)
- ofs -= s / 2;
+ ofs -= Size2(s) / 2;
if (s == Size2(0, 0))
s = Size2(1, 1);
@@ -393,19 +393,30 @@ void AnimatedSprite::_notification(int p_what) {
timeout = _get_frame_duration();
int fc = frames->get_frame_count(animation);
- if (frame >= fc - 1) {
+ if ((!backwards && frame >= fc - 1) || (backwards && frame <= 0)) {
if (frames->get_animation_loop(animation)) {
- frame = 0;
+ if (backwards)
+ frame = fc - 1;
+ else
+ frame = 0;
+
emit_signal(SceneStringNames::get_singleton()->animation_finished);
} else {
- frame = fc - 1;
+ if (backwards)
+ frame = 0;
+ else
+ frame = fc - 1;
+
if (!is_over) {
is_over = true;
emit_signal(SceneStringNames::get_singleton()->animation_finished);
}
}
} else {
- frame++;
+ if (backwards)
+ frame--;
+ else
+ frame++;
}
update();
@@ -594,10 +605,12 @@ bool AnimatedSprite::_is_playing() const {
return playing;
}
-void AnimatedSprite::play(const StringName &p_animation) {
+void AnimatedSprite::play(const StringName &p_animation, const bool p_backwards) {
if (p_animation)
set_animation(p_animation);
+
+ backwards = p_backwards;
_set_playing(true);
}
@@ -666,7 +679,7 @@ void AnimatedSprite::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_playing", "playing"), &AnimatedSprite::_set_playing);
ClassDB::bind_method(D_METHOD("_is_playing"), &AnimatedSprite::_is_playing);
- ClassDB::bind_method(D_METHOD("play", "anim"), &AnimatedSprite::play, DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("play", "anim", "backwards"), &AnimatedSprite::play, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("stop"), &AnimatedSprite::stop);
ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite::is_playing);
@@ -713,6 +726,7 @@ AnimatedSprite::AnimatedSprite() {
frame = 0;
speed_scale = 1.0f;
playing = false;
+ backwards = false;
animation = "default";
timeout = 0;
is_over = false;
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index 8753f88799..2cc372bd93 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -128,6 +128,7 @@ class AnimatedSprite : public Node2D {
Ref<SpriteFrames> frames;
bool playing;
+ bool backwards;
StringName animation;
int frame;
float speed_scale;
@@ -169,7 +170,7 @@ public:
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
Ref<SpriteFrames> get_sprite_frames() const;
- void play(const StringName &p_animation = StringName());
+ void play(const StringName &p_animation = StringName(), const bool p_backwards = false);
void stop();
bool is_playing() const;
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 9e8bf62fc5..2a225e5797 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -428,8 +428,8 @@ void Area2D::set_monitorable(bool p_enable) {
if (locked || (is_inside_tree() && Physics2DServer::get_singleton()->is_flushing_queries())) {
ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
+ ERR_FAIL();
}
- ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index d54070df8d..f43d97eb2a 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "collision_object_2d.h"
+
#include "scene/scene_string_names.h"
#include "servers/physics_2d_server.h"
@@ -56,7 +57,7 @@ void CollisionObject2D::_notification(int p_what) {
_update_pickable();
//get space
- }
+ } break;
case NOTIFICATION_ENTER_CANVAS: {
@@ -64,7 +65,7 @@ void CollisionObject2D::_notification(int p_what) {
Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, get_canvas_layer_instance_id());
else
Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, get_canvas_layer_instance_id());
- }
+ } break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -101,7 +102,7 @@ void CollisionObject2D::_notification(int p_what) {
Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, 0);
else
Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, 0);
- }
+ } break;
}
}
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 5edd49b3a3..ef7644fcab 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -78,40 +78,7 @@ void CollisionPolygon2D::_build_polygon() {
}
Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() {
-
- Vector<Vector<Vector2> > decomp;
- List<TriangulatorPoly> in_poly, out_poly;
-
- TriangulatorPoly inp;
- inp.Init(polygon.size());
- for (int i = 0; i < polygon.size(); i++) {
- inp.GetPoint(i) = polygon[i];
- }
- inp.SetOrientation(TRIANGULATOR_CCW);
- in_poly.push_back(inp);
- TriangulatorPartition tpart;
- if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
- ERR_PRINT("Convex decomposing failed!");
- return decomp;
- }
-
- decomp.resize(out_poly.size());
- int idx = 0;
-
- for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) {
-
- TriangulatorPoly &tp = I->get();
-
- decomp.write[idx].resize(tp.GetNumPoints());
-
- for (int i = 0; i < tp.GetNumPoints(); i++) {
-
- decomp.write[idx].write[i] = tp.GetPoint(i);
- }
-
- idx++;
- }
-
+ Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon_in_convex(polygon);
return decomp;
}
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index c50a8d4a1a..721b52edaa 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -37,20 +37,8 @@
void CPUParticles2D::set_emitting(bool p_emitting) {
emitting = p_emitting;
- if (!is_processing_internal()) {
+ if (emitting)
set_process_internal(true);
- if (is_inside_tree()) {
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true);
-
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
- }
}
void CPUParticles2D::set_amount(int p_amount) {
@@ -365,7 +353,8 @@ void CPUParticles2D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
} break;
case PARAM_ANIM_OFFSET: {
} break;
- default: {}
+ default: {
+ }
}
}
Ref<Curve> CPUParticles2D::get_param_curve(Parameter p_param) const {
@@ -586,7 +575,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
if (restart_time >= prev_time && restart_time < time) {
restart = true;
if (fractional_delta) {
- local_delta = (time - restart_time) * lifetime;
+ local_delta = time - restart_time;
}
}
@@ -594,13 +583,13 @@ void CPUParticles2D::_particles_process(float p_delta) {
if (restart_time >= prev_time) {
restart = true;
if (fractional_delta) {
- local_delta = (lifetime - restart_time + time) * lifetime;
+ local_delta = lifetime - restart_time + time;
}
} else if (restart_time < time) {
restart = true;
if (fractional_delta) {
- local_delta = (time - restart_time) * lifetime;
+ local_delta = time - restart_time;
}
}
}
@@ -941,6 +930,26 @@ void CPUParticles2D::_update_particle_data_buffer() {
#endif
}
+void CPUParticles2D::_set_redraw(bool p_redraw) {
+ if (redraw == p_redraw)
+ return;
+ redraw = p_redraw;
+#ifndef NO_THREADS
+ update_mutex->lock();
+#endif
+ if (redraw) {
+ VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
+ VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true);
+ } else {
+ VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
+ VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false);
+ }
+#ifndef NO_THREADS
+ update_mutex->unlock();
+#endif
+ update(); // redraw to update render list
+}
+
void CPUParticles2D::_update_render_thread() {
#ifndef NO_THREADS
@@ -957,38 +966,19 @@ void CPUParticles2D::_update_render_thread() {
void CPUParticles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- if (is_processing_internal()) {
-
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true);
-
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
+ set_process_internal(emitting);
}
if (p_what == NOTIFICATION_EXIT_TREE) {
- if (is_processing_internal()) {
-
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false);
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
+ _set_redraw(false);
}
if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
}
if (p_what == NOTIFICATION_DRAW) {
+ if (!redraw)
+ return; // dont add to render list
RID texrid;
if (texture.is_valid()) {
@@ -1005,26 +995,20 @@ void CPUParticles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- if (particles.size() == 0 || !is_visible_in_tree())
+ if (particles.size() == 0 || !is_visible_in_tree()) {
+ _set_redraw(false);
return;
+ }
float delta = get_process_delta_time();
if (emitting) {
-
inactive_time = 0;
} else {
inactive_time += delta;
if (inactive_time > lifetime * 1.2) {
set_process_internal(false);
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false);
+ _set_redraw(false);
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
//reset variables
time = 0;
inactive_time = 0;
@@ -1033,6 +1017,7 @@ void CPUParticles2D::_notification(int p_what) {
return;
}
}
+ _set_redraw(true);
if (time == 0 && pre_process_time > 0.0) {
@@ -1354,6 +1339,7 @@ CPUParticles2D::CPUParticles2D() {
inactive_time = 0;
frame_remainder = 0;
cycle = 0;
+ redraw = false;
mesh = VisualServer::get_singleton()->mesh_create();
multimesh = VisualServer::get_singleton()->multimesh_create();
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index b1adf62980..23d2586331 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -103,6 +103,7 @@ private:
float inactive_time;
float frame_remainder;
int cycle;
+ bool redraw;
RID mesh;
RID multimesh;
@@ -179,6 +180,8 @@ private:
void _update_mesh_texture();
+ void _set_redraw(bool p_redraw);
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 105eb82afb..73692e0535 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -112,6 +112,14 @@ int Line2D::get_point_count() const {
return _points.size();
}
+void Line2D::clear_points() {
+ int count = _points.size();
+ if (count > 0) {
+ _points.resize(0);
+ update();
+ }
+}
+
void Line2D::add_point(Vector2 pos) {
_points.append(pos);
update();
@@ -313,6 +321,8 @@ void Line2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_point", "position"), &Line2D::add_point);
ClassDB::bind_method(D_METHOD("remove_point", "i"), &Line2D::remove_point);
+ ClassDB::bind_method(D_METHOD("clear_points"), &Line2D::clear_points);
+
ClassDB::bind_method(D_METHOD("set_width", "width"), &Line2D::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &Line2D::get_width);
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 5bbd38e460..32befab2d3 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -70,6 +70,8 @@ public:
int get_point_count() const;
+ void clear_points();
+
void add_point(Vector2 pos);
void remove_point(int i);
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 96e13396c5..4ead1bbd1e 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -207,7 +207,7 @@ void ParallaxBackground::_bind_methods() {
ParallaxBackground::ParallaxBackground() {
scale = 1.0;
- set_layer(-1); //behind all by default
+ set_layer(-100); //behind all by default
base_scale = Vector2(1, 1);
ignore_camera_zoom = false;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index eeabe15b08..690f1d4b4a 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -199,7 +199,7 @@ real_t StaticBody2D::get_constant_angular_velocity() const {
#ifndef DISABLE_DEPRECATED
void StaticBody2D::set_friction(real_t p_friction) {
- if (p_friction == 1.0) { // default value, don't create an override for that
+ if (p_friction == 1.0 && physics_material_override.is_null()) { // default value, don't create an override for that
return;
}
@@ -229,7 +229,7 @@ real_t StaticBody2D::get_friction() const {
void StaticBody2D::set_bounce(real_t p_bounce) {
- if (p_bounce == 0.0) { // default value, don't create an override for that
+ if (p_bounce == 0.0 && physics_material_override.is_null()) { // default value, don't create an override for that
return;
}
@@ -626,7 +626,7 @@ real_t RigidBody2D::get_weight() const {
#ifndef DISABLE_DEPRECATED
void RigidBody2D::set_friction(real_t p_friction) {
- if (p_friction == 1.0) { // default value, don't create an override for that
+ if (p_friction == 1.0 && physics_material_override.is_null()) { // default value, don't create an override for that
return;
}
@@ -655,7 +655,7 @@ real_t RigidBody2D::get_friction() const {
void RigidBody2D::set_bounce(real_t p_bounce) {
- if (p_bounce == 0.0) { // default value, don't create an override for that
+ if (p_bounce == 0.0 && physics_material_override.is_null()) { // default value, don't create an override for that
return;
}
@@ -1198,6 +1198,9 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
+ if (sync_to_physics) {
+ ERR_PRINT("Functions move_and_slide and move_and_collide do not work together with 'sync to physics' option. Please read the documentation.");
+ }
Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes);
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 1c58073f1d..f6f1bad581 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -307,7 +307,9 @@ void Polygon2D::_notification(int p_what) {
if (invert || polygons.size() == 0) {
Vector<int> indices = Geometry::triangulate_polygon(points);
- VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
+ if (indices.size()) {
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
+ }
} else {
//draw individual polygons
Vector<int> total_indices;
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index ba103a8bf0..a8c7622828 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -363,7 +363,7 @@ Rect2 Sprite::get_rect() const {
Point2 ofs = offset;
if (centered)
- ofs -= s / 2;
+ ofs -= Size2(s) / 2;
if (s == Size2(0, 0))
s = Size2(1, 1);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 91e4f061cb..3562011bc2 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -479,10 +479,28 @@ void TileMap::update_dirty_quadrants() {
vs->canvas_item_add_set_transform(debug_canvas_item, xform);
shape->draw(debug_canvas_item, debug_collision_color);
}
- ps->body_add_shape(q.body, shape->get_rid(), xform);
- ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
- ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin);
- shape_idx++;
+
+ if (shape->has_meta("decomposed")) {
+ Array _shapes = shape->get_meta("decomposed");
+ for (int k = 0; k < _shapes.size(); k++) {
+ Ref<ConvexPolygonShape2D> convex = _shapes[k];
+ if (convex.is_valid()) {
+ ps->body_add_shape(q.body, convex->get_rid(), xform);
+ ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
+ ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin);
+ shape_idx++;
+#ifdef DEBUG_ENABLED
+ } else {
+ print_error("The TileSet asigned to the TileMap " + get_name() + " has an invalid convex shape.");
+#endif
+ }
+ }
+ } else {
+ ps->body_add_shape(q.body, shape->get_rid(), xform);
+ ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
+ ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin);
+ shape_idx++;
+ }
}
}
}
@@ -755,6 +773,7 @@ void TileMap::set_cell(int p_x, int p_y, int p_tile, bool p_flip_x, bool p_flip_
else
_make_quadrant_dirty(Q);
+ used_size_cache_dirty = true;
return;
}
@@ -1373,15 +1392,17 @@ Vector2 TileMap::_map_to_world(int p_x, int p_y, bool p_ignore_ofs) const {
if (!p_ignore_ofs) {
switch (half_offset) {
- case HALF_OFFSET_X: {
+ case HALF_OFFSET_X:
+ case HALF_OFFSET_NEGATIVE_X: {
if (ABS(p_y) & 1) {
- ret += get_cell_transform()[0] * 0.5;
+ ret += get_cell_transform()[0] * (half_offset == HALF_OFFSET_X ? 0.5 : -0.5);
}
} break;
- case HALF_OFFSET_Y: {
+ case HALF_OFFSET_Y:
+ case HALF_OFFSET_NEGATIVE_Y: {
if (ABS(p_x) & 1) {
- ret += get_cell_transform()[1] * 0.5;
+ ret += get_cell_transform()[1] * (half_offset == HALF_OFFSET_Y ? 0.5 : -0.5);
}
} break;
default: {}
@@ -1444,11 +1465,21 @@ Vector2 TileMap::world_to_map(const Vector2 &p_pos) const {
ret.x -= 0.5;
}
} break;
+ case HALF_OFFSET_NEGATIVE_X: {
+ if (ret.y > 0 ? int(ret.y) & 1 : (int(ret.y) - 1) & 1) {
+ ret.x += 0.5;
+ }
+ } break;
case HALF_OFFSET_Y: {
if (ret.x > 0 ? int(ret.x) & 1 : (int(ret.x) - 1) & 1) {
ret.y -= 0.5;
}
} break;
+ case HALF_OFFSET_NEGATIVE_Y: {
+ if (ret.x > 0 ? int(ret.x) & 1 : (int(ret.x) - 1) & 1) {
+ ret.y += 0.5;
+ }
+ } break;
default: {}
}
@@ -1659,7 +1690,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size", PROPERTY_HINT_RANGE, "1,8192,1"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_quadrant_size", "get_quadrant_size");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "cell_custom_transform"), "set_custom_transform", "get_custom_transform");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_half_offset", PROPERTY_HINT_ENUM, "Offset X,Offset Y,Disabled"), "set_half_offset", "get_half_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_half_offset", PROPERTY_HINT_ENUM, "Offset X,Offset Y,Disabled,Offset Negative X,Offset Negative Y"), "set_half_offset", "get_half_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_tile_origin", PROPERTY_HINT_ENUM, "Top Left,Center,Bottom Left"), "set_tile_origin", "get_tile_origin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_y_sort"), "set_y_sort_mode", "is_y_sort_mode_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv");
@@ -1685,6 +1716,8 @@ void TileMap::_bind_methods() {
BIND_ENUM_CONSTANT(HALF_OFFSET_X);
BIND_ENUM_CONSTANT(HALF_OFFSET_Y);
BIND_ENUM_CONSTANT(HALF_OFFSET_DISABLED);
+ BIND_ENUM_CONSTANT(HALF_OFFSET_NEGATIVE_X);
+ BIND_ENUM_CONSTANT(HALF_OFFSET_NEGATIVE_Y);
BIND_ENUM_CONSTANT(TILE_ORIGIN_TOP_LEFT);
BIND_ENUM_CONSTANT(TILE_ORIGIN_CENTER);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index e450e1e256..6a1467aa48 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -52,6 +52,8 @@ public:
HALF_OFFSET_X,
HALF_OFFSET_Y,
HALF_OFFSET_DISABLED,
+ HALF_OFFSET_NEGATIVE_X,
+ HALF_OFFSET_NEGATIVE_Y,
};
enum TileOrigin {
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 9e15a416b2..13d9181082 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -441,8 +441,8 @@ void Area::set_monitorable(bool p_enable) {
if (locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries())) {
ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
+ ERR_FAIL();
}
- ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
@@ -756,7 +756,6 @@ Area::Area() :
monitorable = false;
collision_mask = 1;
collision_layer = 1;
- set_ray_pickable(false);
set_monitoring(true);
set_monitorable(true);
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index d8c2042c88..f542b021be 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -52,7 +52,7 @@ void CollisionObject::_notification(int p_what) {
_update_pickable();
//get space
- };
+ } break;
case NOTIFICATION_TRANSFORM_CHANGED: {
diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp
index daee291ba3..ac33e2b714 100644
--- a/scene/3d/collision_shape.cpp
+++ b/scene/3d/collision_shape.cpp
@@ -124,6 +124,10 @@ String CollisionShape::get_configuration_warning() const {
return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!");
}
+ if (shape->is_class("PlaneShape")) {
+ return TTR("Plane shapes don't work well and will be removed in future versions. Please don't use them.");
+ }
+
return String();
}
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index 11dfbdb1f9..469a1e87db 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -47,20 +47,8 @@ PoolVector<Face3> CPUParticles::get_faces(uint32_t p_usage_flags) const {
void CPUParticles::set_emitting(bool p_emitting) {
emitting = p_emitting;
- if (!is_processing_internal()) {
+ if (emitting)
set_process_internal(true);
- if (is_inside_tree()) {
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
-
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
- }
}
void CPUParticles::set_amount(int p_amount) {
@@ -343,7 +331,8 @@ void CPUParticles::set_param_curve(Parameter p_param, const Ref<Curve> &p_curve)
} break;
case PARAM_ANIM_OFFSET: {
} break;
- default: {}
+ default: {
+ }
}
}
Ref<Curve> CPUParticles::get_param_curve(Parameter p_param) const {
@@ -556,7 +545,7 @@ void CPUParticles::_particles_process(float p_delta) {
if (restart_time >= prev_time && restart_time < time) {
restart = true;
if (fractional_delta) {
- local_delta = (time - restart_time) * lifetime;
+ local_delta = time - restart_time;
}
}
@@ -564,13 +553,13 @@ void CPUParticles::_particles_process(float p_delta) {
if (restart_time >= prev_time) {
restart = true;
if (fractional_delta) {
- local_delta = (1.0 - restart_time + time) * lifetime;
+ local_delta = lifetime - restart_time + time;
}
} else if (restart_time < time) {
restart = true;
if (fractional_delta) {
- local_delta = (time - restart_time) * lifetime;
+ local_delta = time - restart_time;
}
}
}
@@ -1004,6 +993,27 @@ void CPUParticles::_update_particle_data_buffer() {
#endif
}
+void CPUParticles::_set_redraw(bool p_redraw) {
+ if (redraw == p_redraw)
+ return;
+ redraw = p_redraw;
+#ifndef NO_THREADS
+ update_mutex->lock();
+#endif
+ if (redraw) {
+ VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
+ VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
+ VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1);
+ } else {
+ VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
+ VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
+ VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
+ }
+#ifndef NO_THREADS
+ update_mutex->unlock();
+#endif
+}
+
void CPUParticles::_update_render_thread() {
#ifndef NO_THREADS
@@ -1022,31 +1032,11 @@ void CPUParticles::_update_render_thread() {
void CPUParticles::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- if (is_processing_internal()) {
-
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
+ set_process_internal(emitting);
}
if (p_what == NOTIFICATION_EXIT_TREE) {
- if (is_processing_internal()) {
-
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
- }
+ _set_redraw(false);
}
if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
@@ -1054,26 +1044,20 @@ void CPUParticles::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- if (particles.size() == 0 || !is_visible_in_tree())
+ if (particles.size() == 0 || !is_visible_in_tree()) {
+ _set_redraw(false);
return;
+ }
float delta = get_process_delta_time();
if (emitting) {
-
inactive_time = 0;
} else {
inactive_time += delta;
if (inactive_time > lifetime * 1.2) {
set_process_internal(false);
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
+ _set_redraw(false);
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
//reset variables
time = 0;
inactive_time = 0;
@@ -1082,6 +1066,7 @@ void CPUParticles::_notification(int p_what) {
return;
}
}
+ _set_redraw(true);
bool processed = false;
@@ -1406,6 +1391,7 @@ CPUParticles::CPUParticles() {
inactive_time = 0;
frame_remainder = 0;
cycle = 0;
+ redraw = false;
multimesh = VisualServer::get_singleton()->multimesh_create();
set_base(multimesh);
diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h
index b50befe7be..b863a3cb3f 100644
--- a/scene/3d/cpu_particles.h
+++ b/scene/3d/cpu_particles.h
@@ -104,6 +104,7 @@ private:
float inactive_time;
float frame_remainder;
int cycle;
+ bool redraw;
RID multimesh;
@@ -178,6 +179,8 @@ private:
void _update_render_thread();
+ void _set_redraw(bool p_redraw);
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 5b08ea7790..c491275f00 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -30,6 +30,8 @@
#include "gi_probe.h"
+#include "core/os/os.h"
+
#include "mesh_instance.h"
#include "voxel_light_baker.h"
@@ -490,6 +492,14 @@ PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
return PoolVector<Face3>();
}
+String GIProbe::get_configuration_warning() const {
+
+ if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+ return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
+ }
+ return String();
+}
+
void GIProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data);
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index 87664e06b8..4badabbadf 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -168,6 +168,8 @@ public:
virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual String get_configuration_warning() const;
+
GIProbe();
~GIProbe();
};
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 3b514dab8c..cf1af918f7 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -210,6 +210,13 @@ bool Light::is_editor_only() const {
return editor_only;
}
+void Light::_validate_property(PropertyInfo &property) const {
+
+ if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+}
+
void Light::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light::set_editor_only);
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 85e0ce3c24..ddd5bc6b3a 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -92,6 +92,7 @@ protected:
static void _bind_methods();
void _notification(int p_what);
+ virtual void _validate_property(PropertyInfo &property) const;
Light(VisualServer::LightType p_type);
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index ab1eed0859..05214ed669 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1104,10 +1104,10 @@ void RigidBody::_reload_physics_characteristics() {
//////////////////////////////////////////////////////
//////////////////////////
-Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_test_only) {
+Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
Collision col;
- if (move_and_collide(p_motion, p_infinite_inertia, col, p_test_only)) {
+ if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
if (motion_cache.is_null()) {
motion_cache.instance();
motion_cache->owner = this;
@@ -1121,11 +1121,11 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_inf
return Ref<KinematicCollision>();
}
-bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_test_only) {
+bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
Transform gt = get_global_transform();
PhysicsServer::MotionResult result;
- bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result);
+ bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes);
if (colliding) {
r_collision.collider_metadata = result.collider_metadata;
@@ -1280,7 +1280,7 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity
Collision col;
Transform gt = get_global_transform();
- if (move_and_collide(p_snap, p_infinite_inertia, col, true)) {
+ if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
bool apply = true;
if (p_floor_direction != Vector3()) {
@@ -1415,7 +1415,7 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) {
void KinematicBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 5570d0c86b..589af98062 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -310,14 +310,14 @@ private:
_FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const;
- Ref<KinematicCollision> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_test_only = false);
+ Ref<KinematicCollision> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
Ref<KinematicCollision> _get_slide_collision(int p_bounce);
protected:
static void _bind_methods();
public:
- bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collisionz, bool p_test_only = false);
+ bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collisionz, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision);
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index ceea50f74a..b7279e4d4f 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -198,11 +198,7 @@ void Skeleton::_notification(int p_what) {
case NOTIFICATION_ENTER_WORLD: {
- if (dirty) {
-
- dirty = false;
- _make_dirty(); // property make it dirty
- }
+ VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
} break;
case NOTIFICATION_EXIT_WORLD: {
@@ -210,21 +206,7 @@ void Skeleton::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (dirty)
- break; //will be eventually updated
-
- //if moved, just update transforms
- VisualServer *vs = VisualServer::get_singleton();
- const Bone *bonesptr = bones.ptr();
- int len = bones.size();
- Transform global_transform = get_global_transform();
- Transform global_transform_inverse = global_transform.affine_inverse();
-
- for (int i = 0; i < len; i++) {
-
- const Bone &b = bonesptr[i];
- vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse));
- }
+ VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
} break;
case NOTIFICATION_UPDATE_SKELETON: {
@@ -257,9 +239,6 @@ void Skeleton::_notification(int p_what) {
rest_global_inverse_dirty = false;
}
- Transform global_transform = get_global_transform();
- Transform global_transform_inverse = global_transform.affine_inverse();
-
for (int i = 0; i < len; i++) {
Bone &b = bonesptr[order[i]];
@@ -320,7 +299,7 @@ void Skeleton::_notification(int p_what) {
}
b.transform_final = b.pose_global * b.rest_global_inverse;
- vs->skeleton_bone_set_transform(skeleton, order[i], global_transform * (b.transform_final * global_transform_inverse));
+ vs->skeleton_bone_set_transform(skeleton, order[i], b.transform_final);
for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
@@ -594,10 +573,6 @@ void Skeleton::_make_dirty() {
if (dirty)
return;
- if (!is_inside_tree()) {
- dirty = true;
- return;
- }
MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON);
dirty = true;
}
@@ -771,6 +746,16 @@ void Skeleton::physical_bones_remove_collision_exception(RID p_exception) {
#endif // _3D_DISABLED
+void Skeleton::set_use_bones_in_world_transform(bool p_enable) {
+ use_bones_in_world_transform = p_enable;
+ if (is_inside_tree()) {
+ VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
+ }
+}
+bool Skeleton::is_using_bones_in_world_transform() const {
+ return use_bones_in_world_transform;
+}
+
void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton::add_bone);
@@ -807,6 +792,9 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform);
+ ClassDB::bind_method(D_METHOD("set_use_bones_in_world_transform", "enable"), &Skeleton::set_use_bones_in_world_transform);
+ ClassDB::bind_method(D_METHOD("is_using_bones_in_world_transform"), &Skeleton::is_using_bones_in_world_transform);
+
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation);
@@ -818,6 +806,7 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones_in_world_transform"), "set_use_bones_in_world_transform", "is_using_bones_in_world_transform");
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
}
@@ -828,6 +817,7 @@ Skeleton::Skeleton() {
process_order_dirty = true;
skeleton = VisualServer::get_singleton()->skeleton_create();
set_notify_transform(true);
+ use_bones_in_world_transform = false;
}
Skeleton::~Skeleton() {
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index 0f463c9ea7..5f43b3c6c3 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -100,6 +100,7 @@ class Skeleton : public Spatial {
void _make_dirty();
bool dirty;
+ bool use_bones_in_world_transform;
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
@@ -179,6 +180,9 @@ public:
void localize_rests(); // used for loaders and tools
int get_process_order(int p_idx);
+ void set_use_bones_in_world_transform(bool p_enable);
+ bool is_using_bones_in_world_transform() const;
+
#ifndef _3D_DISABLED
// Physical bone API
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index d6544c39da..83f99a2e3c 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -178,7 +178,7 @@ void Spatial::_notification(int p_what) {
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, NULL, 0);
}
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this);
get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 5df3da93e1..68ad71d01c 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -440,13 +440,13 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *sm,
bool goto_next = false;
- if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_IMMEDIATE) {
- goto_next = fading_from == StringName();
- } else {
+ if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_AT_END) {
goto_next = next_xfade >= (len_current - pos_current) || loops_current > 0;
if (loops_current > 0) {
next_xfade = 0;
}
+ } else {
+ goto_next = fading_from == StringName();
}
if (goto_next) { //loops should be used because fade time may be too small or zero and animation may have looped
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 43ec8cebb0..016db15b73 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -287,7 +287,6 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
// broken track (nonexistent bone)
p_anim->node_cache[i]->skeleton = NULL;
p_anim->node_cache[i]->spatial = NULL;
- printf("bone is %ls\n", String(bone_name).c_str());
ERR_CONTINUE(p_anim->node_cache[i]->bone_idx < 0);
}
} else {
@@ -1133,8 +1132,6 @@ void AnimationPlayer::play_backwards(const StringName &p_name, float p_custom_bl
void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float p_custom_scale, bool p_from_end) {
- //printf("animation is %ls\n", String(p_name).c_str());
- //ERR_FAIL_COND(!is_inside_scene());
StringName name = p_name;
if (String(name) == "")
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 0b6fa26bfc..fe1b8247ff 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -883,16 +883,16 @@ void AnimationTree::_process_graph(float p_delta) {
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- if (t->process_pass != process_pass) {
+ if (track->root_motion) {
- t->process_pass = process_pass;
- t->loc = Vector3();
- t->rot = Quat();
- t->rot_blend_accum = 0;
- t->scale = Vector3();
- }
+ if (t->process_pass != process_pass) {
- if (track->root_motion) {
+ t->process_pass = process_pass;
+ t->loc = Vector3();
+ t->rot = Quat();
+ t->rot_blend_accum = 0;
+ t->scale = Vector3();
+ }
float prev_time = time - delta;
if (prev_time < 0) {
@@ -946,6 +946,15 @@ void AnimationTree::_process_graph(float p_delta) {
Error err = a->transform_track_interpolate(i, time, &loc, &rot, &scale);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
+ if (t->process_pass != process_pass) {
+
+ t->process_pass = process_pass;
+ t->loc = loc;
+ t->rot = rot;
+ t->rot_blend_accum = 0;
+ t->scale = Vector3();
+ }
+
scale -= Vector3(1.0, 1.0, 1.0); //helps make it work properly with Add nodes
if (err != OK)
@@ -978,8 +987,7 @@ void AnimationTree::_process_graph(float p_delta) {
continue;
if (t->process_pass != process_pass) {
- Variant::CallError ce;
- t->value = Variant::construct(value.get_type(), NULL, 0, ce); //reset
+ t->value = value;
t->process_pass = process_pass;
}
@@ -1036,7 +1044,7 @@ void AnimationTree::_process_graph(float p_delta) {
float bezier = a->bezier_track_interpolate(i, time);
if (t->process_pass != process_pass) {
- t->value = 0;
+ t->value = bezier;
t->process_pass = process_pass;
}
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 6a5d7839f4..23998183b8 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -223,6 +223,7 @@ void Tween::_bind_methods() {
ADD_SIGNAL(MethodInfo("tween_started", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::NODE_PATH, "key")));
ADD_SIGNAL(MethodInfo("tween_step", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::NODE_PATH, "key"), PropertyInfo(Variant::REAL, "elapsed"), PropertyInfo(Variant::OBJECT, "value")));
ADD_SIGNAL(MethodInfo("tween_completed", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::NODE_PATH, "key")));
+ ADD_SIGNAL(MethodInfo("tween_all_completed"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "repeat"), "set_repeat", "is_repeat");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_tween_process_mode", "get_tween_process_mode");
@@ -628,8 +629,10 @@ void Tween::_tween_process(float p_delta) {
}
pending_update--;
- if (all_finished)
+ if (all_finished) {
set_active(false);
+ emit_signal("tween_all_completed");
+ }
}
void Tween::set_tween_process_mode(TweenProcessMode p_mode) {
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 5c95cf4279..2688041d18 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -91,8 +91,10 @@ void AudioStreamPlayer::_mix_internal(bool p_fadeout) {
void AudioStreamPlayer::_mix_audio() {
- if (!stream_playback.is_valid() || !active)
+ if (!stream_playback.is_valid() || !active ||
+ (stream_paused && !stream_fade)) {
return;
+ }
if (stream_fade) {
_mix_internal(true);
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index c734136895..65e9cccd05 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "button.h"
+
#include "core/translation.h"
#include "servers/visual_server.h"
@@ -102,6 +103,7 @@ void Button::_notification(int p_what) {
break;
}
+ FALLTHROUGH;
}
case DRAW_PRESSED: {
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 2579321773..7f1ca58d58 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -169,6 +169,19 @@ void Container::_notification(int p_what) {
}
}
+String Container::get_configuration_warning() const {
+
+ String warning = Control::get_configuration_warning();
+
+ if (get_class() == "Container" && get_script().is_null()) {
+ if (warning != String()) {
+ warning += "\n";
+ }
+ warning += TTR("Container by itself serves no purpose unless a script configures it's children placement behavior.\nIf you dont't intend to add a script, then please use a plain 'Control' node instead.");
+ }
+ return warning;
+}
+
void Container::_bind_methods() {
ClassDB::bind_method(D_METHOD("_sort_children"), &Container::_sort_children);
diff --git a/scene/gui/container.h b/scene/gui/container.h
index 0b014137f4..80d3f6ee5d 100644
--- a/scene/gui/container.h
+++ b/scene/gui/container.h
@@ -57,6 +57,8 @@ public:
void fit_child_in_rect(Control *p_child, const Rect2 &p_rect);
+ virtual String get_configuration_warning() const;
+
Container();
};
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 998e91cfc2..c7cd2bb6d8 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1388,7 +1388,10 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo
}
update();
- _change_notify("anchor");
+ _change_notify("anchor_left");
+ _change_notify("anchor_right");
+ _change_notify("anchor_top");
+ _change_notify("anchor_bottom");
}
void Control::_set_anchor(Margin p_margin, float p_anchor) {
@@ -2721,7 +2724,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
- ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size);
+ ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size);
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5599c64daa..059e59ea21 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -861,7 +861,7 @@ FileDialog::FileDialog() {
HBoxContainer *hbc = memnew(HBoxContainer);
dir_up = memnew(ToolButton);
- dir_up->set_tooltip(RTR("Go to parent folder"));
+ dir_up->set_tooltip(RTR("Go to parent folder."));
hbc->add_child(dir_up);
dir_up->connect("pressed", this, "_go_up");
@@ -871,6 +871,7 @@ FileDialog::FileDialog() {
dir->set_h_size_flags(SIZE_EXPAND_FILL);
refresh = memnew(ToolButton);
+ refresh->set_tooltip(RTR("Refresh"));
refresh->connect("pressed", this, "_update_file_list");
hbc->add_child(refresh);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index f3f2e586a6..30ad81bb2e 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -261,8 +261,9 @@ void GraphEdit::add_child_notify(Node *p_child) {
void GraphEdit::remove_child_notify(Node *p_child) {
Control::remove_child_notify(p_child);
-
- top_layer->call_deferred("raise"); //top layer always on top!
+ if (is_inside_tree()) {
+ top_layer->call_deferred("raise"); //top layer always on top!
+ }
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
if (gn) {
gn->disconnect("offset_changed", this, "_graph_node_moved");
@@ -769,7 +770,9 @@ void GraphEdit::_top_layer_draw() {
}
if (box_selecting)
- top_layer->draw_rect(box_selecting_rect, Color(0.7, 0.7, 1.0, 0.3));
+ top_layer->draw_rect(
+ box_selecting_rect,
+ get_color("accent_color", "Editor") * Color(1, 1, 1, 0.375));
}
void GraphEdit::set_selected(Node *p_child) {
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 8c588109d6..e8692d56d2 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -164,7 +164,6 @@ void GraphNode::_resort() {
vofs += size.y;
}
- _change_notify();
update();
connpos_dirty = true;
}
@@ -409,9 +408,12 @@ Size2 GraphNode::get_minimum_size() const {
void GraphNode::set_title(const String &p_title) {
+ if (title == p_title)
+ return;
title = p_title;
- minimum_size_changed();
update();
+ _change_notify("title");
+ minimum_size_changed();
}
String GraphNode::get_title() const {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index bf6833e512..0c5dc39273 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "line_edit.h"
+
#include "core/message_queue.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -320,7 +321,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
handled = false;
break;
}
- // numlock disabled. fallthrough to key_left
+ FALLTHROUGH;
}
case KEY_LEFT: {
@@ -367,7 +368,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
handled = false;
break;
}
- // numlock disabled. fallthrough to key_right
+ FALLTHROUGH;
}
case KEY_RIGHT: {
@@ -474,7 +475,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
handled = false;
break;
}
- // numlock disabled. fallthrough to key_home
+ FALLTHROUGH;
}
case KEY_HOME: {
@@ -487,7 +488,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
handled = false;
break;
}
- // numlock disabled. fallthrough to key_end
+ FALLTHROUGH;
}
case KEY_END: {
@@ -1223,6 +1224,7 @@ void LineEdit::append_at_cursor(String p_text) {
void LineEdit::clear_internal() {
+ deselect();
_clear_undo_stack();
cached_width = 0;
cursor_pos = 0;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 28b124d143..94c73b2e42 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -594,7 +594,7 @@ void PopupMenu::add_item(const String &p_label, int p_ID, uint32_t p_accel) {
item.text = p_label;
item.xl_text = tr(p_label);
item.accel = p_accel;
- item.ID = p_ID;
+ item.ID = p_ID == -1 ? items.size() : p_ID;
items.push_back(item);
update();
minimum_size_changed();
@@ -632,7 +632,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel
item.text = p_label;
item.xl_text = tr(p_label);
item.accel = p_accel;
- item.ID = p_ID;
+ item.ID = p_ID == -1 ? items.size() : p_ID;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
update();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index d4b008e277..00d6ac3b94 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -900,21 +900,13 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const {
- if (!underline_meta || selection.click)
+ if (selection.click)
return CURSOR_ARROW;
if (main->first_invalid_line < main->lines.size())
return CURSOR_ARROW; //invalid
- int line = 0;
- Item *item = NULL;
-
- ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line);
-
- if (item && ((RichTextLabel *)(this))->_find_meta(item, NULL))
- return CURSOR_POINTING_HAND;
-
- return CURSOR_ARROW;
+ return get_default_cursor_shape();
}
void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
@@ -1133,18 +1125,19 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
Variant meta;
- if (item && !outside && _find_meta(item, &meta)) {
- if (meta_hovering != item) {
+ ItemMeta *item_meta;
+ if (item && !outside && _find_meta(item, &meta, &item_meta)) {
+ if (meta_hovering != item_meta) {
if (meta_hovering) {
emit_signal("meta_hover_ended", current_meta);
}
- meta_hovering = static_cast<ItemMeta *>(item);
+ meta_hovering = item_meta;
current_meta = meta;
emit_signal("meta_hover_started", meta);
}
} else if (meta_hovering) {
- emit_signal("meta_hover_ended", current_meta);
meta_hovering = NULL;
+ emit_signal("meta_hover_ended", current_meta);
current_meta = false;
}
}
@@ -1269,7 +1262,7 @@ bool RichTextLabel::_find_strikethrough(Item *p_item) {
return false;
}
-bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) {
+bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
Item *item = p_item;
@@ -1280,6 +1273,8 @@ bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) {
ItemMeta *meta = static_cast<ItemMeta *>(item);
if (r_meta)
*r_meta = meta->meta;
+ if (r_item)
+ *r_item = meta;
return true;
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index bec2c5ac02..114c6103e2 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -285,7 +285,7 @@ private:
Color _find_color(Item *p_item, const Color &p_default_color);
bool _find_underline(Item *p_item);
bool _find_strikethrough(Item *p_item);
- bool _find_meta(Item *p_item, Variant *r_meta);
+ bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL);
void _update_scroll();
void _scroll_changed(double);
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 28292309b9..e50a71b0ff 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -368,8 +368,10 @@ void ScrollContainer::update_scrollbars() {
Ref<StyleBox> sb = get_stylebox("bg");
size -= sb->get_minimum_size();
- Size2 hmin = h_scroll->get_combined_minimum_size();
- Size2 vmin = v_scroll->get_combined_minimum_size();
+ Size2 hmin;
+ Size2 vmin;
+ if (scroll_h) hmin = h_scroll->get_combined_minimum_size();
+ if (scroll_v) vmin = v_scroll->get_combined_minimum_size();
Size2 min = child_max_size;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index f38bc62a3c..9acf8d40c9 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -666,7 +666,7 @@ void TextEdit::_notification(int p_what) {
bool brace_close_matching = false;
bool brace_close_mismatch = false;
- if (brace_matching_enabled) {
+ if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
if (cursor.column < text[cursor.line].length()) {
//check for open
@@ -2517,7 +2517,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_left
+ FALLTHROUGH;
}
case KEY_LEFT: {
@@ -2580,7 +2580,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_right
+ FALLTHROUGH;
}
case KEY_RIGHT: {
@@ -2641,7 +2641,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_up
+ FALLTHROUGH;
}
case KEY_UP: {
@@ -2694,7 +2694,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_down
+ FALLTHROUGH;
}
case KEY_DOWN: {
@@ -2817,11 +2817,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_home
+ FALLTHROUGH;
}
-#ifdef APPLE_STYLE_KEYS
case KEY_HOME: {
-
+#ifdef APPLE_STYLE_KEYS
if (k->get_shift())
_pre_shift_selection();
@@ -2831,11 +2830,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
_post_shift_selection();
else if (k->get_command() || k->get_control())
deselect();
-
- } break;
#else
- case KEY_HOME: {
-
if (k->get_shift())
_pre_shift_selection();
@@ -2876,19 +2871,17 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
deselect();
_cancel_completion();
completion_hint = "";
-
- } break;
#endif
+ } break;
case KEY_KP_1: {
if (k->get_unicode() != 0) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_end
+ FALLTHROUGH;
}
-#ifdef APPLE_STYLE_KEYS
case KEY_END: {
-
+#ifdef APPLE_STYLE_KEYS
if (k->get_shift())
_pre_shift_selection();
@@ -2898,11 +2891,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
_post_shift_selection();
else if (k->get_command() || k->get_control())
deselect();
-
- } break;
#else
- case KEY_END: {
-
if (k->get_shift())
_pre_shift_selection();
@@ -2929,15 +2918,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
_cancel_completion();
completion_hint = "";
-
- } break;
#endif
+ } break;
case KEY_KP_9: {
if (k->get_unicode() != 0) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_pageup
+ FALLTHROUGH;
}
case KEY_PAGEUP: {
@@ -2960,7 +2948,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- // numlock disabled. fallthrough to key_pagedown
+ FALLTHROUGH;
}
case KEY_PAGEDOWN: {
@@ -3139,21 +3127,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (scancode_handled)
accept_event();
- /*
- if (!scancode_handled && !k->get_command() && !k->get_alt()) {
-
- if (k->get_unicode()>=32) {
- if (readonly)
- break;
-
- accept_event();
- } else {
-
- break;
- }
- }
-*/
if (k->get_scancode() == KEY_INSERT) {
set_insert_mode(!insert_mode);
accept_event();
@@ -3196,7 +3170,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
end_complex_operation();
}
accept_event();
- } else {
}
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 95f1fbbee5..33f0a3f45d 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -683,6 +683,7 @@ protected:
TextEdit *text_editor;
public:
+ virtual ~SyntaxHighlighter() {}
virtual void _update_cache() = 0;
virtual Map<int, TextEdit::HighlighterInfo> _get_line_syntax_highlighting(int p_line) = 0;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 19bef9fdf5..795b25cce0 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -223,8 +223,7 @@ void TextureButton::_notification(int p_what) {
}
if (has_focus() && focused.is_valid()) {
- Rect2 drect(Point2(), get_size());
- draw_texture_rect(focused, drect, false);
+ draw_texture_rect(focused, _position_rect, false);
};
} break;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 236c4dbe63..679b752fa3 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -29,7 +29,6 @@
/*************************************************************************/
#include "tree.h"
-#include <limits.h>
#include "core/math/math_funcs.h"
#include "core/os/input.h"
@@ -43,6 +42,8 @@
#include "editor/editor_node.h"
#endif
+#include <limits.h>
+
void TreeItem::move_to_top() {
if (!parent || parent->children == this)
@@ -940,6 +941,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
int check_icon_h = cache.checked->get_height();
if (height < check_icon_h)
height = check_icon_h;
+ FALLTHROUGH;
}
case TreeItem::CELL_MODE_STRING:
case TreeItem::CELL_MODE_CUSTOM:
@@ -1416,12 +1418,15 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
TreeItem *c = p_item->children;
+ int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+
while (c) {
if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
+
if (c->get_children() != NULL)
root_pos -= Point2i(cache.arrow->get_width(), 0);
@@ -1434,12 +1439,13 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (root_pos.y + line_width >= 0) {
VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width);
+ VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width);
}
if (htotal < 0) {
return -1;
}
+ prev_ofs = root_pos.y;
}
if (htotal >= 0) {
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 2b1991ebb0..8cab1b1280 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -153,6 +153,7 @@ void CanvasLayer::_notification(int p_what) {
VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
+ _update_follow_viewport();
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -160,6 +161,7 @@ void CanvasLayer::_notification(int p_what) {
vp->_canvas_layer_remove(this);
VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
viewport = RID();
+ _update_follow_viewport(false);
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
@@ -235,6 +237,41 @@ RID CanvasLayer::get_canvas() const {
return canvas;
}
+
+void CanvasLayer::set_follow_viewport(bool p_enable) {
+ if (follow_viewport == p_enable) {
+ return;
+ }
+
+ follow_viewport = p_enable;
+ _update_follow_viewport();
+}
+
+bool CanvasLayer::is_following_viewport() const {
+ return follow_viewport;
+}
+
+void CanvasLayer::set_follow_viewport_scale(float p_ratio) {
+ follow_viewport_scale = p_ratio;
+ _update_follow_viewport();
+}
+
+float CanvasLayer::get_follow_viewport_scale() const {
+ return follow_viewport_scale;
+}
+
+void CanvasLayer::_update_follow_viewport(bool p_force_exit) {
+
+ if (!is_inside_tree()) {
+ return;
+ }
+ if (p_force_exit || !follow_viewport) {
+ VS::get_singleton()->canvas_set_parent(canvas, RID(), 1.0);
+ } else {
+ VS::get_singleton()->canvas_set_parent(canvas, vp->get_world_2d()->get_canvas(), follow_viewport_scale);
+ }
+}
+
void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer", "layer"), &CanvasLayer::set_layer);
@@ -255,18 +292,30 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale);
+ ClassDB::bind_method(D_METHOD("set_follow_viewport", "enable"), &CanvasLayer::set_follow_viewport);
+ ClassDB::bind_method(D_METHOD("is_following_viewport"), &CanvasLayer::is_following_viewport);
+
+ ClassDB::bind_method(D_METHOD("set_follow_viewport_scale", "scale"), &CanvasLayer::set_follow_viewport_scale);
+ ClassDB::bind_method(D_METHOD("get_follow_viewport_scale"), &CanvasLayer::get_follow_viewport_scale);
+
ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &CanvasLayer::set_custom_viewport);
ClassDB::bind_method(D_METHOD("get_custom_viewport"), &CanvasLayer::get_custom_viewport);
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasLayer::get_canvas);
+ ADD_GROUP("Layer", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
+ ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1080,1080,0.1,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
+ ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
+ ADD_GROUP("Follow Viewport", "follow_viewport");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_viewport_enable"), "set_follow_viewport", "is_following_viewport");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "follow_viewport_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,or_lesser"), "set_follow_viewport_scale", "get_follow_viewport_scale");
}
CanvasLayer::CanvasLayer() {
@@ -280,6 +329,8 @@ CanvasLayer::CanvasLayer() {
custom_viewport = NULL;
custom_viewport_id = 0;
sort_index = 0;
+ follow_viewport = false;
+ follow_viewport_scale = 1.0;
}
CanvasLayer::~CanvasLayer() {
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 5d67245102..fa2558556c 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -55,8 +55,12 @@ class CanvasLayer : public Node {
int sort_index;
+ bool follow_viewport;
+ float follow_viewport_scale;
+
void _update_xform();
void _update_locrotscale();
+ void _update_follow_viewport(bool p_force_exit = false);
protected:
void _notification(int p_what);
@@ -91,6 +95,12 @@ public:
void reset_sort_index();
int get_sort_index();
+ void set_follow_viewport(bool p_enable);
+ bool is_following_viewport() const;
+
+ void set_follow_viewport_scale(float p_ratio);
+ float get_follow_viewport_scale() const;
+
RID get_canvas() const;
CanvasLayer();
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index d217701532..128168ca72 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2834,10 +2834,22 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN);
BIND_CONSTANT(NOTIFICATION_DRAG_END);
BIND_CONSTANT(NOTIFICATION_PATH_CHANGED);
- BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
+ BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
+ BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
+ BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
+ BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
+ BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
+ BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
+ BIND_CONSTANT(NOTIFICATION_CRASH);
+ BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
+
BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT);
BIND_ENUM_CONSTANT(PAUSE_MODE_STOP);
BIND_ENUM_CONSTANT(PAUSE_MODE_PROCESS);
diff --git a/scene/main/node.h b/scene/main/node.h
index e6189389cb..b490db37c5 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -216,6 +216,7 @@ protected:
public:
enum {
+
// you can make your own, but don't use the same numbers as other notifications in other nodes
NOTIFICATION_ENTER_TREE = 10,
NOTIFICATION_EXIT_TREE = 11,
@@ -231,10 +232,23 @@ public:
NOTIFICATION_DRAG_BEGIN = 21,
NOTIFICATION_DRAG_END = 22,
NOTIFICATION_PATH_CHANGED = 23,
- NOTIFICATION_TRANSLATION_CHANGED = 24,
+ //NOTIFICATION_TRANSLATION_CHANGED = 24, moved below
NOTIFICATION_INTERNAL_PROCESS = 25,
NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26,
NOTIFICATION_POST_ENTER_TREE = 27,
+ //keep these linked to node
+ NOTIFICATION_WM_MOUSE_ENTER = MainLoop::NOTIFICATION_WM_MOUSE_ENTER,
+ NOTIFICATION_WM_MOUSE_EXIT = MainLoop::NOTIFICATION_WM_MOUSE_EXIT,
+ NOTIFICATION_WM_FOCUS_IN = MainLoop::NOTIFICATION_WM_FOCUS_IN,
+ NOTIFICATION_WM_FOCUS_OUT = MainLoop::NOTIFICATION_WM_FOCUS_OUT,
+ NOTIFICATION_WM_QUIT_REQUEST = MainLoop::NOTIFICATION_WM_QUIT_REQUEST,
+ NOTIFICATION_WM_GO_BACK_REQUEST = MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST,
+ NOTIFICATION_WM_UNFOCUS_REQUEST = MainLoop::NOTIFICATION_WM_UNFOCUS_REQUEST,
+ NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING,
+ NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED,
+ NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT,
+ NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH,
+ NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE
};
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 689f18a09d..81c38cec89 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -658,13 +658,15 @@ void SceneTree::_notification(int p_notification) {
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
if (!Engine::get_singleton()->is_editor_hint()) {
- get_root()->propagate_notification(Node::NOTIFICATION_TRANSLATION_CHANGED);
+ get_root()->propagate_notification(p_notification);
}
} break;
case NOTIFICATION_WM_UNFOCUS_REQUEST: {
notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST);
+ get_root()->propagate_notification(p_notification);
+
} break;
case NOTIFICATION_WM_ABOUT: {
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index e15a64604d..e098b3d53c 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -287,7 +287,7 @@ protected:
public:
enum {
- NOTIFICATION_TRANSFORM_CHANGED = 29
+ NOTIFICATION_TRANSFORM_CHANGED = 2000
};
enum GroupCallFlags {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 090e6bdcb0..2524af9cfb 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -232,16 +232,16 @@ void Viewport::update_worlds() {
find_world()->_update(get_tree()->get_frame());
}
-void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape, bool p_discard_empty_motion) {
+void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
Transform object_transform = p_object->get_global_transform();
Transform camera_transform = p_camera->get_global_transform();
ObjectID id = p_object->get_instance_id();
- if (p_discard_empty_motion) {
- //avoid sending the event unnecessarily if nothing really changed in the context
+ //avoid sending the fake event unnecessarily if nothing really changed in the context
+ if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
Ref<InputEventMouseMotion> mm = p_input_event;
- if (mm.is_valid() && object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
+ if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
return; //discarded
}
}
@@ -251,31 +251,6 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *
physics_last_id = id;
}
-void Viewport::_test_new_mouseover(ObjectID new_collider) {
-#ifndef _3D_DISABLED
- if (new_collider != physics_object_over) {
-
- if (physics_object_over) {
-
- CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
- if (co) {
- co->_mouse_exit();
- }
- }
-
- if (new_collider) {
-
- CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(new_collider));
- if (co) {
- co->_mouse_enter();
- }
- }
-
- physics_object_over = new_collider;
- }
-#endif
-}
-
void Viewport::_notification(int p_what) {
switch (p_what) {
@@ -422,22 +397,22 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState::RayResult result;
Physics2DDirectSpaceState *ss2d = Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
- bool discard_empty_motion = false;
-
- { // if no motion event exists, create a new one. This is necessary because objects or camera may have moved.
+ if (physics_has_last_mousepos) {
+ // if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
// while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
- bool has_mouse_motion = false;
+ bool has_mouse_event = false;
for (List<Ref<InputEvent> >::Element *E = physics_picking_events.front(); E; E = E->next()) {
- Ref<InputEventMouseMotion> mm = E->get();
- if (mm.is_valid()) {
- has_mouse_motion = true;
+ Ref<InputEventMouse> m = E->get();
+ if (m.is_valid()) {
+ has_mouse_event = true;
break;
}
}
- if (!has_mouse_motion && physics_has_last_mousepos) {
+ if (!has_mouse_event) {
Ref<InputEventMouseMotion> mm;
mm.instance();
+ mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos);
mm->set_alt(physics_last_mouse_state.alt);
@@ -446,25 +421,24 @@ void Viewport::_notification(int p_what) {
mm->set_metakey(physics_last_mouse_state.meta);
mm->set_button_mask(physics_last_mouse_state.mouse_mask);
physics_picking_events.push_back(mm);
- discard_empty_motion = true;
}
}
- bool motion_tested = false;
-
while (physics_picking_events.size()) {
Ref<InputEvent> ev = physics_picking_events.front()->get();
physics_picking_events.pop_front();
Vector2 pos;
+ bool is_mouse = false;
Ref<InputEventMouseMotion> mm = ev;
if (mm.is_valid()) {
pos = mm->get_position();
- motion_tested = true;
+ is_mouse = true;
+
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
physics_last_mouse_state.alt = mm->get_alt();
@@ -477,7 +451,12 @@ void Viewport::_notification(int p_what) {
Ref<InputEventMouseButton> mb = ev;
if (mb.is_valid()) {
+
pos = mb->get_position();
+ is_mouse = true;
+
+ physics_has_last_mousepos = true;
+ physics_last_mousepos = pos;
physics_last_mouse_state.alt = mb->get_alt();
physics_last_mouse_state.shift = mb->get_shift();
physics_last_mouse_state.control = mb->get_control();
@@ -487,6 +466,11 @@ void Viewport::_notification(int p_what) {
physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
} else {
physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1));
+
+ // If touch mouse raised, assume we don't know last mouse pos until new events come
+ if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
+ physics_has_last_mousepos = false;
+ }
}
}
@@ -539,40 +523,51 @@ void Viewport::_notification(int p_what) {
if (res[i].collider_id && res[i].collider) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
if (co) {
-
- Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
- if (!F) {
- F = physics_2d_mouseover.insert(res[i].collider_id, frame);
- co->_mouse_enter();
- } else {
- F->get() = frame;
+ bool send_event = true;
+ if (is_mouse) {
+ Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
+
+ if (!F) {
+ F = physics_2d_mouseover.insert(res[i].collider_id, frame);
+ co->_mouse_enter();
+ } else {
+ F->get() = frame;
+ // It was already hovered, so don't send the event if it's faked
+ if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
+ send_event = false;
+ }
+ }
}
- co->_input_event(this, ev, res[i].shape);
+ if (send_event) {
+ co->_input_event(this, ev, res[i].shape);
+ }
}
}
}
}
- List<Map<ObjectID, uint64_t>::Element *> to_erase;
+ if (is_mouse) {
+ List<Map<ObjectID, uint64_t>::Element *> to_erase;
- for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
- if (E->get() != frame) {
- Object *o = ObjectDB::get_instance(E->key());
- if (o) {
+ for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
+ if (E->get() != frame) {
+ Object *o = ObjectDB::get_instance(E->key());
+ if (o) {
- CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
- co->_mouse_exit();
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
+ if (co) {
+ co->_mouse_exit();
+ }
}
+ to_erase.push_back(E);
}
- to_erase.push_back(E);
}
- }
- while (to_erase.size()) {
- physics_2d_mouseover.erase(to_erase.front()->get());
- to_erase.pop_front();
+ while (to_erase.size()) {
+ physics_2d_mouseover.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
}
}
@@ -583,7 +578,7 @@ void Viewport::_notification(int p_what) {
CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_capture));
if (co) {
- _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0, discard_empty_motion);
+ _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
captured = true;
if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
physics_object_capture = 0;
@@ -601,7 +596,7 @@ void Viewport::_notification(int p_what) {
if (last_id) {
if (ObjectDB::get_instance(last_id) && last_object) {
//good, exists
- _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape, discard_empty_motion);
+ _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
physics_object_capture = last_id;
}
@@ -624,7 +619,7 @@ void Viewport::_notification(int p_what) {
CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
if (co) {
- _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape, discard_empty_motion);
+ _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
last_object = co;
last_id = result.collider_id;
new_collider = last_id;
@@ -634,42 +629,41 @@ void Viewport::_notification(int p_what) {
}
}
- if (mm.is_valid()) {
- _test_new_mouseover(new_collider);
- }
- }
+ if (is_mouse && new_collider != physics_object_over) {
- last_pos = pos;
- }
- }
- }
+ if (physics_object_over) {
- if (!motion_tested && camera && physics_has_last_mousepos) {
+ CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
+ if (co) {
+ co->_mouse_exit();
+ }
+ }
- //test anyway for mouseenter/exit because objects might move
- Vector3 from = camera->project_ray_origin(physics_last_mousepos);
- Vector3 dir = camera->project_ray_normal(physics_last_mousepos);
+ if (new_collider) {
- PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
- if (space) {
+ CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(new_collider));
+ if (co) {
+ co->_mouse_enter();
+ }
+ }
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
- ObjectID new_collider = 0;
- if (col) {
- CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
- if (co) {
- new_collider = result.collider_id;
+ physics_object_over = new_collider;
+ }
}
- }
- _test_new_mouseover(new_collider);
+ last_pos = pos;
+ }
}
#endif
}
}
} break;
+ case SceneTree::NOTIFICATION_WM_MOUSE_EXIT:
case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
+
+ _drop_physics_mouseover();
+
if (gui.mouse_focus) {
//if mouse is being pressed, send a release event
_drop_mouse_focus();
@@ -1486,7 +1480,8 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_popup->set_as_toplevel(true);
//gui.tooltip_popup->hide();
- Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_popup->get_minimum_size());
+ Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset");
+ Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_minimum_size());
Rect2 vr = gui.tooltip_popup->get_viewport_rect();
if (r.size.x + r.position.x > vr.size.x)
r.position.x = vr.size.x - r.size.x;
@@ -1783,13 +1778,15 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
*/
gui.mouse_focus = _gui_find_control(pos);
- gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1);
gui.last_mouse_focus = gui.mouse_focus;
if (!gui.mouse_focus) {
+ gui.mouse_focus_mask = 0;
return;
}
+ gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1);
+
if (mb->get_button_index() == BUTTON_LEFT) {
gui.drag_accum = Vector2();
gui.drag_attempted = false;
@@ -2303,32 +2300,32 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (from && p_event->is_pressed()) {
Control *next = NULL;
- if (p_event->is_action("ui_focus_next")) {
+ if (p_event->is_action_pressed("ui_focus_next")) {
next = from->find_next_valid_focus();
}
- if (p_event->is_action("ui_focus_prev")) {
+ if (p_event->is_action_pressed("ui_focus_prev")) {
next = from->find_prev_valid_focus();
}
- if (!mods && p_event->is_action("ui_up")) {
+ if (!mods && p_event->is_action_pressed("ui_up")) {
next = from->_get_focus_neighbour(MARGIN_TOP);
}
- if (!mods && p_event->is_action("ui_left")) {
+ if (!mods && p_event->is_action_pressed("ui_left")) {
next = from->_get_focus_neighbour(MARGIN_LEFT);
}
- if (!mods && p_event->is_action("ui_right")) {
+ if (!mods && p_event->is_action_pressed("ui_right")) {
next = from->_get_focus_neighbour(MARGIN_RIGHT);
}
- if (!mods && p_event->is_action("ui_down")) {
+ if (!mods && p_event->is_action_pressed("ui_down")) {
next = from->_get_focus_neighbour(MARGIN_BOTTOM);
}
@@ -2568,6 +2565,31 @@ void Viewport::_drop_mouse_focus() {
}
}
+void Viewport::_drop_physics_mouseover() {
+
+ physics_has_last_mousepos = false;
+
+ while (physics_2d_mouseover.size()) {
+ Object *o = ObjectDB::get_instance(physics_2d_mouseover.front()->key());
+ if (o) {
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
+ co->_mouse_exit();
+ }
+ physics_2d_mouseover.erase(physics_2d_mouseover.front());
+ }
+
+#ifndef _3D_DISABLED
+ if (physics_object_over) {
+ CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
+ if (co) {
+ co->_mouse_exit();
+ }
+ }
+
+ physics_object_over = physics_object_capture = 0;
+#endif
+}
+
List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
gui.modal_stack.push_back(p_control);
@@ -2923,6 +2945,13 @@ bool Viewport::is_handling_input_locally() const {
return handle_input_locally;
}
+void Viewport::_validate_property(PropertyInfo &property) const {
+
+ if (VisualServer::get_singleton()->is_low_end() && property.name == "hdr") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+}
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 4d0a4e8c87..d67b4ac348 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -221,12 +221,11 @@ private:
} physics_last_mouse_state;
- void _collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape, bool p_discard_empty_motion);
+ void _collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
bool handle_input_locally;
bool local_input_handled;
- void _test_new_mouseover(ObjectID new_collider);
Map<ObjectID, uint64_t> physics_2d_mouseover;
Ref<World2D> world_2d;
@@ -384,12 +383,14 @@ private:
void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
void _drop_mouse_focus();
+ void _drop_physics_mouseover();
void _update_canvas_items(Node *p_node);
protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const;
public:
Listener *get_listener() const;
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 2af92a788e..f73914b186 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1836,9 +1836,14 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const {
void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const {
if (from_time != length && to_time == length)
- to_time = length * 1.01; //include a little more if at the end
+ to_time = length * 1.001; //include a little more if at the end
int to = _find(vt->values, to_time);
+ if (to >= 0 && from_time == to_time && vt->values[to].time == from_time) {
+ //find exact (0 delta), return if found
+ p_indices->push_back(to);
+ return;
+ }
// can't really send the events == time, will be sent in the next frame.
// if event>=len then it will probably never be requested by the anim player.
@@ -1884,7 +1889,7 @@ void Animation::value_track_get_key_indices(int p_track, float p_time, float p_d
if (from_time > to_time) {
// handle loop by splitting
- _value_track_get_key_indices_in_range(vt, length - from_time, length, p_indices);
+ _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
_value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
return;
}
@@ -2633,6 +2638,7 @@ void Animation::copy_track(int p_track, Ref<Animation> p_to_animation) {
p_to_animation->track_set_enabled(dst_track, track_is_enabled(p_track));
p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(p_track));
p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(p_track));
+ p_to_animation->value_track_set_update_mode(dst_track, value_track_get_update_mode(p_track));
for (int i = 0; i < track_get_key_count(p_track); i++) {
p_to_animation->track_insert_key(dst_track, track_get_key_time(p_track, i), track_get_key_value(p_track, i), track_get_key_transition(p_track, i));
}
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index a89cf108bc..4b3e392013 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -515,10 +515,10 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const {
return pv;
}
-void AudioStreamSample::save_to_wav(String p_path) {
+Error AudioStreamSample::save_to_wav(const String &p_path) {
if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
WARN_PRINTS("Saving IMA_ADPC samples are not supported yet");
- return;
+ return ERR_UNAVAILABLE;
}
int sub_chunk_2_size = data_bytes; //Subchunk2Size = Size of data in bytes
@@ -544,8 +544,9 @@ void AudioStreamSample::save_to_wav(String p_path) {
file_path += ".wav";
}
- Error err;
- FileAccess *file = FileAccess::open(file_path, FileAccess::WRITE, &err); //Overrides existing file if present
+ FileAccessRef file = FileAccess::open(file_path, FileAccess::WRITE); //Overrides existing file if present
+
+ ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
// Create WAV Header
file->store_string("RIFF"); //ChunkID
@@ -583,6 +584,8 @@ void AudioStreamSample::save_to_wav(String p_path) {
}
file->close();
+
+ return OK;
}
Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() {
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index bd701ddd12..d4c5511f34 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -141,7 +141,7 @@ public:
void set_data(const PoolVector<uint8_t> &p_data);
PoolVector<uint8_t> get_data() const;
- void save_to_wav(String p_path);
+ Error save_to_wav(const String &p_path);
virtual Ref<AudioStreamPlayback> instance_playback();
virtual String get_stream_name() const;
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index d2e4d28b44..55264bcdf9 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -96,7 +96,7 @@ int BitMap::get_true_bit_count() const {
const uint8_t *d = bitmask.ptr();
int c = 0;
- //fast, almot branchless version
+ //fast, almost branchless version
for (int i = 0; i < ds; i++) {
@@ -106,6 +106,7 @@ int BitMap::get_true_bit_count() const {
c += (d[i] & (1 << 4)) >> 4;
c += (d[i] & (1 << 3)) >> 3;
c += (d[i] & (1 << 2)) >> 2;
+ c += (d[i] & (1 << 1)) >> 1;
c += d[i] & 1;
}
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 98402dbeaf..85018f38d7 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -1028,34 +1028,6 @@ AABB ArrayMesh::get_custom_aabb() const {
return custom_aabb;
}
-void ArrayMesh::center_geometry() {
-
- /*
- Vector3 ofs = aabb.pos+aabb.size*0.5;
-
- for(int i=0;i<get_surface_count();i++) {
-
- PoolVector<Vector3> geom = surface_get_array(i,ARRAY_VERTEX);
- int gc =geom.size();
- PoolVector<Vector3>::Write w = geom.write();
- surfaces[i].aabb.pos-=ofs;
-
- for(int i=0;i<gc;i++) {
-
- w[i]-=ofs;
- }
-
- w = PoolVector<Vector3>::Write();
-
- surface_set_array(i,ARRAY_VERTEX,geom);
-
- }
-
- aabb.pos-=ofs;
-
-*/
-}
-
void ArrayMesh::regen_normalmaps() {
Vector<Ref<SurfaceTool> > surfs;
@@ -1295,8 +1267,6 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape);
ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape);
ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline);
- ClassDB::bind_method(D_METHOD("center_geometry"), &ArrayMesh::center_geometry);
- ClassDB::set_method_flags(get_class_static(), _scs_create("center_geometry"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps);
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ClassDB::bind_method(D_METHOD("lightmap_unwrap", "transform", "texel_size"), &ArrayMesh::lightmap_unwrap);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 2d0aef8ab0..dabfc6ea60 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -223,7 +223,6 @@ public:
AABB get_aabb() const;
virtual RID get_rid() const;
- void center_geometry();
void regen_normalmaps();
Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index c5125d576d..d40a5dee2e 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -56,6 +56,8 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
set_item_preview(idx, p_value);
else if (what == "navmesh")
set_item_navmesh(idx, p_value);
+ else if (what == "navmesh_transform")
+ set_item_navmesh_transform(idx, p_value);
else
return false;
@@ -80,6 +82,8 @@ bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = _get_item_shapes(idx);
else if (what == "navmesh")
r_ret = get_item_navmesh(idx);
+ else if (what == "navmesh_transform")
+ r_ret = get_item_navmesh_transform(idx);
else if (what == "preview")
r_ret = get_item_preview(idx);
else
@@ -95,8 +99,10 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
String name = "item/" + itos(E->key()) + "/";
p_list->push_back(PropertyInfo(Variant::STRING, name + "name"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "mesh_transform"));
p_list->push_back(PropertyInfo(Variant::ARRAY, name + "shapes"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "navmesh_transform"));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "preview", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER));
}
}
@@ -116,6 +122,7 @@ void MeshLibrary::set_item_name(int p_item, const String &p_name) {
emit_changed();
_change_notify();
}
+
void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) {
ERR_FAIL_COND(!item_map.has(p_item));
@@ -145,6 +152,15 @@ void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navm
_change_notify();
}
+void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_transform) {
+
+ ERR_FAIL_COND(!item_map.has(p_item));
+ item_map[p_item].navmesh_transform = p_transform;
+ notify_change_to_owners();
+ emit_changed();
+ _change_notify();
+}
+
void MeshLibrary::set_item_preview(int p_item, const Ref<Texture> &p_preview) {
ERR_FAIL_COND(!item_map.has(p_item));
@@ -152,11 +168,13 @@ void MeshLibrary::set_item_preview(int p_item, const Ref<Texture> &p_preview) {
emit_changed();
_change_notify();
}
+
String MeshLibrary::get_item_name(int p_item) const {
ERR_FAIL_COND_V(!item_map.has(p_item), "");
return item_map[p_item].name;
}
+
Ref<Mesh> MeshLibrary::get_item_mesh(int p_item) const {
ERR_FAIL_COND_V(!item_map.has(p_item), Ref<Mesh>());
@@ -175,6 +193,12 @@ Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const {
return item_map[p_item].navmesh;
}
+Transform MeshLibrary::get_item_navmesh_transform(int p_item) const {
+
+ ERR_FAIL_COND_V(!item_map.has(p_item), Transform());
+ return item_map[p_item].navmesh_transform;
+}
+
Ref<Texture> MeshLibrary::get_item_preview(int p_item) const {
ERR_FAIL_COND_V(!item_map.has(p_item), Ref<Texture>());
@@ -268,11 +292,13 @@ void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name);
ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh);
ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh);
+ ClassDB::bind_method(D_METHOD("set_item_navmesh_transform", "id", "navmesh"), &MeshLibrary::set_item_navmesh_transform);
ClassDB::bind_method(D_METHOD("set_item_shapes", "id", "shapes"), &MeshLibrary::_set_item_shapes);
ClassDB::bind_method(D_METHOD("set_item_preview", "id", "texture"), &MeshLibrary::set_item_preview);
ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name);
ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh);
ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh);
+ ClassDB::bind_method(D_METHOD("get_item_navmesh_transform", "id"), &MeshLibrary::get_item_navmesh_transform);
ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes);
ClassDB::bind_method(D_METHOD("get_item_preview", "id"), &MeshLibrary::get_item_preview);
ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item);
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 849a0577eb..4ae4fc6483 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -52,6 +52,7 @@ public:
Ref<Mesh> mesh;
Vector<ShapeData> shapes;
Ref<Texture> preview;
+ Transform navmesh_transform;
Ref<NavigationMesh> navmesh;
};
@@ -72,11 +73,13 @@ public:
void set_item_name(int p_item, const String &p_name);
void set_item_mesh(int p_item, const Ref<Mesh> &p_mesh);
void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
+ void set_item_navmesh_transform(int p_item, const Transform &p_transform);
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
void set_item_preview(int p_item, const Ref<Texture> &p_preview);
String get_item_name(int p_item) const;
Ref<Mesh> get_item_mesh(int p_item) const;
Ref<NavigationMesh> get_item_navmesh(int p_item) const;
+ Transform get_item_navmesh_transform(int p_item) const;
Vector<ShapeData> get_item_shapes(int p_item) const;
Ref<Texture> get_item_preview(int p_item) const;
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 0d12d388ef..626ed9f5b4 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -92,6 +92,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
if (i > 0) {
+ ERR_EXPLAIN(vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name]))
+ ERR_FAIL_COND_V(n.parent == -1, NULL)
NODE_FROM_ID(nparent, n.parent);
#ifdef DEBUG_ENABLED
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
@@ -175,8 +177,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
node = Object::cast_to<Node>(obj);
} else {
- print_line("Class is disabled for: " + itos(n.type));
- print_line("name: " + String(snames[n.type]));
+ //print_line("Class is disabled for: " + itos(n.type));
+ //print_line("name: " + String(snames[n.type]));
}
if (node) {
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 210fbe9f20..b6efca9acc 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -1645,7 +1645,8 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
}
- f->store_string("\n");
+ if (E->next())
+ f->store_line(String());
}
if (packed_scene.is_valid()) {
@@ -1714,7 +1715,8 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
f->store_string(_valprop(String(state->get_node_property_name(i, j))) + " = " + vars + "\n");
}
- f->store_line(String());
+ if (i < state->get_node_count() - 1)
+ f->store_line(String());
}
for (int i = 0; i < state->get_connection_count(); i++) {
diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp
index dfbf619c01..f9f8ff19e4 100644
--- a/scene/resources/sky.cpp
+++ b/scene/resources/sky.cpp
@@ -536,7 +536,7 @@ void ProceduralSky::_bind_methods() {
BIND_ENUM_CONSTANT(TEXTURE_SIZE_MAX);
}
-ProceduralSky::ProceduralSky() {
+ProceduralSky::ProceduralSky(bool p_desaturate) {
sky = VS::get_singleton()->sky_create();
texture = VS::get_singleton()->texture_create();
@@ -552,6 +552,12 @@ ProceduralSky::ProceduralSky() {
ground_curve = 0.02;
ground_energy = 1;
+ if (p_desaturate) {
+ sky_top_color.set_hsv(sky_top_color.get_h(),0,sky_top_color.get_v());
+ sky_horizon_color.set_hsv(sky_horizon_color.get_h(),0,sky_horizon_color.get_v());
+ ground_bottom_color.set_hsv(ground_bottom_color.get_h(),0,ground_bottom_color.get_v());
+ ground_horizon_color.set_hsv(ground_horizon_color.get_h(),0,ground_horizon_color.get_v());
+ }
sun_color = Color(1, 1, 1);
sun_latitude = 35;
sun_longitude = 0;
diff --git a/scene/resources/sky.h b/scene/resources/sky.h
index 3b410396e0..7327b2a627 100644
--- a/scene/resources/sky.h
+++ b/scene/resources/sky.h
@@ -191,7 +191,7 @@ public:
virtual RID get_rid() const;
- ProceduralSky();
+ ProceduralSky(bool p_desaturate=false);
~ProceduralSky();
};
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 08b2a05d43..3ca2b56d08 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -842,6 +842,12 @@ void StreamTexture::reload_from_file() {
load(path);
}
+void StreamTexture::_validate_property(PropertyInfo &property) const {
+ if (property.name == "flags") {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
void StreamTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture::load);
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 21d3782897..281a33929c 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -203,6 +203,7 @@ private:
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
public:
typedef void (*TextureFormatRequestCallback)(const Ref<StreamTexture> &);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3c83de91fd..4ddfc0331b 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -30,6 +30,7 @@
#include "tile_set.h"
#include "core/array.h"
+#include "core/engine.h"
bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
@@ -662,6 +663,7 @@ void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_sha
if (tile_map[p_id].shapes_data.size() <= p_shape_id)
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
tile_map[p_id].shapes_data.write[p_shape_id].shape = p_shape;
+ _decompose_convex_shape(p_shape);
emit_changed();
}
@@ -844,6 +846,9 @@ void TileSet::tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].shapes_data = p_shapes;
+ for (int i = 0; i < p_shapes.size(); i++) {
+ _decompose_convex_shape(p_shapes[i].shape);
+ }
emit_changed();
}
@@ -888,9 +893,10 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
} else if (p_shapes[i].get_type() == Variant::DICTIONARY) {
Dictionary d = p_shapes[i];
- if (d.has("shape") && d["shape"].get_type() == Variant::OBJECT)
+ if (d.has("shape") && d["shape"].get_type() == Variant::OBJECT) {
s.shape = d["shape"];
- else
+ _decompose_convex_shape(s.shape);
+ } else
continue;
if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D)
@@ -956,6 +962,26 @@ Array TileSet::_get_tiles_ids() const {
return arr;
}
+void TileSet::_decompose_convex_shape(Ref<Shape2D> p_shape) {
+ if (Engine::get_singleton()->is_editor_hint())
+ return;
+ Ref<ConvexPolygonShape2D> convex = p_shape;
+ if (!convex.is_valid())
+ return;
+ Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon_in_convex(convex->get_points());
+ if (decomp.size() > 1) {
+ Array sub_shapes;
+ for (int i = 0; i < decomp.size(); i++) {
+ Ref<ConvexPolygonShape2D> _convex = memnew(ConvexPolygonShape2D);
+ _convex->set_points(decomp[i]);
+ sub_shapes.append(_convex);
+ }
+ convex->set_meta("decomposed", sub_shapes);
+ } else {
+ convex->set_meta("decomposed", Variant());
+ }
+}
+
void TileSet::get_tile_list(List<int> *p_tiles) const {
for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) {
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 4800371d3c..fac48243d0 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -35,6 +35,7 @@
#include "core/resource.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/navigation_polygon.h"
+#include "scene/resources/convex_polygon_shape_2d.h"
#include "scene/resources/shape_2d.h"
#include "scene/resources/texture.h"
@@ -134,6 +135,7 @@ protected:
void _tile_set_shapes(int p_id, const Array &p_shapes);
Array _tile_get_shapes(int p_id) const;
Array _get_tiles_ids() const;
+ void _decompose_convex_shape(Ref<Shape2D> p_shape);
static void _bind_methods();
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 692c28ed99..4e5909eb2e 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -1087,6 +1087,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "attenuation", "ATTENUATION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "albedo", "ALBEDO" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "transmission", "TRANSMISSION" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "diffuse", "DIFFUSE_LIGHT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "specular", "SPECULAR_LIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" },