summaryrefslogtreecommitdiff
path: root/scene/2d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/animated_sprite.cpp7
-rw-r--r--scene/2d/area_2d.cpp8
-rw-r--r--scene/2d/audio_stream_player_2d.cpp4
-rw-r--r--scene/2d/audio_stream_player_2d.h2
-rw-r--r--scene/2d/camera_2d.cpp10
-rw-r--r--scene/2d/canvas_item.cpp1
-rw-r--r--scene/2d/canvas_item.h4
-rw-r--r--scene/2d/collision_object_2d.cpp7
-rw-r--r--scene/2d/collision_object_2d.h2
-rw-r--r--scene/2d/collision_shape_2d.h2
-rw-r--r--scene/2d/cpu_particles_2d.cpp137
-rw-r--r--scene/2d/cpu_particles_2d.h10
-rw-r--r--scene/2d/joints_2d.cpp4
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--scene/2d/line_2d.cpp106
-rw-r--r--scene/2d/line_2d.h7
-rw-r--r--scene/2d/line_builder.cpp120
-rw-r--r--scene/2d/line_builder.h1
-rw-r--r--scene/2d/mesh_instance_2d.h2
-rw-r--r--scene/2d/navigation_2d.cpp1
-rw-r--r--scene/2d/particles_2d.cpp27
-rw-r--r--scene/2d/particles_2d.h2
-rw-r--r--scene/2d/physics_body_2d.cpp34
-rw-r--r--scene/2d/physics_body_2d.h4
-rw-r--r--scene/2d/position_2d.cpp2
-rw-r--r--scene/2d/position_2d.h4
-rw-r--r--scene/2d/skeleton_2d.h2
-rw-r--r--scene/2d/sprite.cpp5
-rw-r--r--scene/2d/tile_map.cpp221
-rw-r--r--scene/2d/tile_map.h15
30 files changed, 514 insertions, 239 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 075b0e6252..b7ace804ef 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -69,10 +69,7 @@ bool AnimatedSprite::_edit_use_rect() const {
Ref<Texture> t;
if (animation)
t = frames->get_frame(animation, frame);
- if (t.is_null())
- return false;
-
- return true;
+ return t.is_valid();
}
Rect2 AnimatedSprite::get_anchorable_rect() const {
@@ -646,7 +643,7 @@ void AnimatedSprite::_reset_timeout() {
void AnimatedSprite::set_animation(const StringName &p_animation) {
ERR_EXPLAIN(vformat("There is no animation with name '%s'.", p_animation));
- ERR_FAIL_COND(frames == NULL)
+ ERR_FAIL_COND(frames == NULL);
ERR_FAIL_COND(frames->get_animation_names().find(p_animation) == -1);
if (animation == p_animation)
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index b322cfe8f1..b701e84a9c 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -657,10 +657,10 @@ void Area2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsBody2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsBody2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsBody2D")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsBody2D")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 73f583111b..932af469d0 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -457,8 +457,8 @@ void AudioStreamPlayer2D::set_stream_paused(bool p_pause) {
if (p_pause != stream_paused) {
stream_paused = p_pause;
- stream_paused_fade_in = p_pause ? false : true;
- stream_paused_fade_out = p_pause ? true : false;
+ stream_paused_fade_in = !p_pause;
+ stream_paused_fade_out = p_pause;
}
}
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index e9cdfa2303..ffa3d4edb4 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -37,7 +37,7 @@
class AudioStreamPlayer2D : public Node2D {
- GDCLASS(AudioStreamPlayer2D, Node2D)
+ GDCLASS(AudioStreamPlayer2D, Node2D);
private:
enum {
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 11846654c5..a0d74dd283 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -29,10 +29,11 @@
/*************************************************************************/
#include "camera_2d.h"
+
+#include "core/engine.h"
#include "core/math/math_funcs.h"
#include "scene/scene_string_names.h"
#include "servers/visual_server.h"
-#include <editor/editor_node.h>
void Camera2D::_update_scroll() {
@@ -44,15 +45,16 @@ void Camera2D::_update_scroll() {
return;
}
+ if (!viewport)
+ return;
+
if (current) {
ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
Transform2D xform = get_camera_transform();
- if (viewport) {
- viewport->set_canvas_transform(xform);
- }
+ viewport->set_canvas_transform(xform);
Size2 screen_size = viewport->get_visible_rect().size;
Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2());
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 78e98deb93..23f6404e3e 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -1074,6 +1074,7 @@ Vector2 CanvasItem::make_canvas_position_local(const Vector2 &screen_point) cons
Ref<InputEvent> CanvasItem::make_input_local(const Ref<InputEvent> &p_event) const {
+ ERR_FAIL_COND_V(p_event.is_null(), p_event);
ERR_FAIL_COND_V(!is_inside_tree(), p_event);
return p_event->xformed_by((get_canvas_transform() * get_global_transform()).affine_inverse());
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index a020ab5029..2604eb04e4 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -46,7 +46,7 @@ class StyleBox;
class CanvasItemMaterial : public Material {
- GDCLASS(CanvasItemMaterial, Material)
+ GDCLASS(CanvasItemMaterial, Material);
public:
enum BlendMode {
@@ -143,7 +143,7 @@ public:
void set_particles_anim_v_frames(int p_frames);
int get_particles_anim_v_frames() const;
- void set_particles_anim_loop(bool p_frames);
+ void set_particles_anim_loop(bool p_loop);
bool get_particles_anim_loop() const;
static void init_shaders();
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 375375285d..36c88e395a 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -218,12 +218,13 @@ void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transf
ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner];
+
sd.xform = p_transform;
for (int i = 0; i < sd.shapes.size(); i++) {
if (area) {
- Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform);
+ Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, sd.xform);
} else {
- Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform);
+ Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, sd.xform);
}
}
}
@@ -387,7 +388,7 @@ String CollisionObject2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
if (shapes.empty()) {
- if (warning == String()) {
+ if (!warning.empty()) {
warning += "\n";
}
warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape.");
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 8aa3330f37..4e7d01c8e6 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -36,7 +36,7 @@
class CollisionObject2D : public Node2D {
- GDCLASS(CollisionObject2D, Node2D)
+ GDCLASS(CollisionObject2D, Node2D);
bool area;
RID rid;
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index e913b4a866..26c61f47bd 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -38,7 +38,7 @@ class CollisionObject2D;
class CollisionShape2D : public Node2D {
- GDCLASS(CollisionShape2D, Node2D)
+ GDCLASS(CollisionShape2D, Node2D);
Ref<Shape2D> shape;
Rect2 rect;
uint32_t owner_id;
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index ff27e0a29a..75315bfc6e 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -29,8 +29,9 @@
/*************************************************************************/
#include "cpu_particles_2d.h"
-#include "particles_2d.h"
+
#include "scene/2d/canvas_item.h"
+#include "scene/2d/particles_2d.h"
#include "scene/resources/particles_material.h"
#include "servers/visual_server.h"
@@ -85,7 +86,9 @@ void CPUParticles2D::set_randomness_ratio(float p_ratio) {
void CPUParticles2D::set_use_local_coordinates(bool p_enable) {
local_coords = p_enable;
+ set_notify_transform(!p_enable);
}
+
void CPUParticles2D::set_speed_scale(float p_scale) {
speed_scale = p_scale;
@@ -247,6 +250,8 @@ void CPUParticles2D::restart() {
frame_remainder = 0;
cycle = 0;
+ set_emitting(true);
+
{
int pc = particles.size();
PoolVector<Particle>::Write w = particles.write();
@@ -324,9 +329,9 @@ void CPUParticles2D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
case PARAM_ANGULAR_VELOCITY: {
_adjust_curve_range(p_curve, -360, 360);
} break;
- /*case PARAM_ORBIT_VELOCITY: {
+ case PARAM_ORBIT_VELOCITY: {
_adjust_curve_range(p_curve, -500, 500);
- } break;*/
+ } break;
case PARAM_LINEAR_ACCEL: {
_adjust_curve_range(p_curve, -200, 200);
} break;
@@ -466,7 +471,7 @@ void CPUParticles2D::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
- if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_CIRCLE) {
+ if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
property.usage = 0;
}
@@ -489,12 +494,6 @@ void CPUParticles2D::_validate_property(PropertyInfo &property) const {
if (property.name == "emission_colors" && emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
property.usage = 0;
}
-
- /*
- if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) {
- property.usage = 0;
- }
- */
}
static uint32_t idhash(uint32_t x) {
@@ -533,7 +532,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
time = Math::fmod(time, lifetime);
cycle++;
if (one_shot && cycle > 0) {
- emitting = false;
+ set_emitting(false);
+ _change_notify();
}
}
@@ -545,6 +545,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
velocity_xform[2] = Vector2();
}
+ float system_phase = time / lifetime;
+
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];
@@ -552,21 +554,26 @@ void CPUParticles2D::_particles_process(float p_delta) {
if (!emitting && !p.active)
continue;
- float restart_time = (float(i) / float(pcount)) * lifetime;
float local_delta = p_delta;
+ // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
+ // While we use time in tests later on, for randomness we use the phase as done in the
+ // original shader code, and we later multiply by lifetime to get the time.
+ float restart_phase = float(i) / float(pcount);
+
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
- if (restart_time >= time) {
+ if (restart_phase >= system_phase) {
seed -= uint32_t(1);
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_time += randomness_ratio * random * 1.0 / float(pcount);
+ restart_phase += randomness_ratio * random * 1.0 / float(pcount);
}
- restart_time *= (1.0 - explosiveness_ratio);
+ restart_phase *= (1.0 - explosiveness_ratio);
+ float restart_time = restart_phase * lifetime;
bool restart = false;
if (time > prev_time) {
@@ -643,8 +650,9 @@ void CPUParticles2D::_particles_process(float p_delta) {
case EMISSION_SHAPE_POINT: {
//do none
} break;
- case EMISSION_SHAPE_CIRCLE: {
- p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0).normalized() * emission_sphere_radius;
+ case EMISSION_SHAPE_SPHERE: {
+ Vector3 sphere_shape = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0).normalized() * emission_sphere_radius;
+ p.transform[2] = Vector2(sphere_shape.x, sphere_shape.y);
} break;
case EMISSION_SHAPE_RECTANGLE: {
p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_rect_extents;
@@ -688,16 +696,12 @@ void CPUParticles2D::_particles_process(float p_delta) {
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(p.custom[1]);
}
- /*
- float tex_orbit_velocity = 0.0;
-
- if (flags[FLAG_DISABLE_Z]) {
- if (curve_parameters[PARAM_INITIAL_ORBIT_VELOCITY].is_valid()) {
- tex_orbit_velocity = curve_parameters[PARAM_INITIAL_ORBIT_VELOCITY]->interpolate(p.custom[1]);
- }
+ float tex_orbit_velocity = 0.0;
+ if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
+ tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(p.custom[1]);
}
-*/
+
float tex_angular_velocity = 0.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(p.custom[1]);
@@ -748,22 +752,19 @@ void CPUParticles2D::_particles_process(float p_delta) {
force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2();
//apply tangential acceleration;
Vector2 yx = Vector2(diff.y, diff.x);
- force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
+ force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
//apply attractor forces
p.velocity += force * local_delta;
//orbit velocity
-#if 0
- if (flags[FLAG_DISABLE_Z]) {
-
- float orbit_amount = (orbit_velocity + tex_orbit_velocity) * mix(1.0, rand_from_seed(alt_seed), orbit_velocity_random);
- if (orbit_amount != 0.0) {
- float ang = orbit_amount * DELTA * pi * 2.0;
- mat2 rot = mat2(vec2(cos(ang), -sin(ang)), vec2(sin(ang), cos(ang)));
- TRANSFORM[3].xy -= diff.xy;
- TRANSFORM[3].xy += rot * diff.xy;
- }
+ float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]);
+ if (orbit_amount != 0.0) {
+ float ang = orbit_amount * local_delta * Math_PI * 2.0;
+ // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix,
+ // but we use -ang here to reproduce its behavior.
+ Transform2D rot = Transform2D(-ang, Vector2());
+ p.transform[2] -= diff;
+ p.transform[2] += rot.basis_xform(diff);
}
-#endif
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
p.velocity = p.velocity.normalized() * tex_linear_velocity;
}
@@ -865,11 +866,6 @@ void CPUParticles2D::_update_particle_data_buffer() {
PoolVector<Particle>::Read r = particles.read();
float *ptr = w.ptr();
- Transform2D un_transform;
- if (!local_coords) {
- un_transform = get_global_transform().affine_inverse();
- }
-
if (draw_order != DRAW_ORDER_INDEX) {
ow = particle_order.write();
order = ow.ptr();
@@ -891,7 +887,7 @@ void CPUParticles2D::_update_particle_data_buffer() {
Transform2D t = r[idx].transform;
if (!local_coords) {
- t = un_transform * t;
+ t = inv_emission_transform * t;
}
if (r[idx].active) {
@@ -1060,6 +1056,42 @@ void CPUParticles2D::_notification(int p_what) {
_update_particle_data_buffer();
}
+
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
+
+ inv_emission_transform = get_global_transform().affine_inverse();
+
+ if (!local_coords) {
+
+ int pc = particles.size();
+
+ PoolVector<float>::Write w = particle_data.write();
+ PoolVector<Particle>::Read r = particles.read();
+ float *ptr = w.ptr();
+
+ for (int i = 0; i < pc; i++) {
+
+ Transform2D t = inv_emission_transform * r[i].transform;
+
+ if (r[i].active) {
+
+ ptr[0] = t.elements[0][0];
+ ptr[1] = t.elements[1][0];
+ ptr[2] = 0;
+ ptr[3] = t.elements[2][0];
+ ptr[4] = t.elements[0][1];
+ ptr[5] = t.elements[1][1];
+ ptr[6] = 0;
+ ptr[7] = t.elements[2][1];
+
+ } else {
+ zeromem(ptr, sizeof(float) * 8);
+ }
+
+ ptr += 13;
+ }
+ }
+ }
}
void CPUParticles2D::convert_from_particles(Node *p_particles) {
@@ -1174,15 +1206,16 @@ void CPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_GROUP("Drawing", "");
+ // No visibility_rect property contrarily to Particles2D, it's updated automatically.
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
@@ -1263,12 +1296,10 @@ void CPUParticles2D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY);
- /*
ADD_GROUP("Orbit Velocity", "orbit_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY);
-*/
ADD_GROUP("Linear Accel", "linear_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL);
@@ -1324,10 +1355,12 @@ void CPUParticles2D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY);
+ BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); // Unused, but exposed for consistency with 3D.
+ BIND_ENUM_CONSTANT(FLAG_DISABLE_Z); // Unused, but exposed for consistency with 3D.
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT);
- BIND_ENUM_CONSTANT(EMISSION_SHAPE_CIRCLE);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
@@ -1361,10 +1394,10 @@ CPUParticles2D::CPUParticles2D() {
set_spread(45);
set_flatness(0);
- set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1);
- //set_param(PARAM_ORBIT_VELOCITY, 0);
- set_param(PARAM_LINEAR_ACCEL, 0);
+ set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param(PARAM_ANGULAR_VELOCITY, 0);
+ set_param(PARAM_ORBIT_VELOCITY, 0);
+ set_param(PARAM_LINEAR_ACCEL, 0);
set_param(PARAM_RADIAL_ACCEL, 0);
set_param(PARAM_TANGENTIAL_ACCEL, 0);
set_param(PARAM_DAMPING, 0);
@@ -1377,7 +1410,7 @@ CPUParticles2D::CPUParticles2D() {
set_emission_sphere_radius(1);
set_emission_rect_extents(Vector2(1, 1));
- set_gravity(Vector2(0, 98.8));
+ set_gravity(Vector2(0, 98));
for (int i = 0; i < PARAM_MAX; i++) {
set_param_randomness(Parameter(i), 0);
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 23d2586331..813f5ddc6e 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -68,12 +68,14 @@ public:
enum Flags {
FLAG_ALIGN_Y_TO_VELOCITY,
+ FLAG_ROTATE_Y, // Unused, but exposed for consistency with 3D.
+ FLAG_DISABLE_Z, // Unused, but exposed for consistency with 3D.
FLAG_MAX
};
enum EmissionShape {
EMISSION_SHAPE_POINT,
- EMISSION_SHAPE_CIRCLE,
+ EMISSION_SHAPE_SPHERE,
EMISSION_SHAPE_RECTANGLE,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
@@ -116,7 +118,7 @@ private:
const Particle *particles;
bool operator()(int p_a, int p_b) const {
- return particles[p_a].time < particles[p_b].time;
+ return particles[p_a].time > particles[p_b].time;
}
};
@@ -142,6 +144,8 @@ private:
int fixed_fps;
bool fractional_delta;
+ Transform2D inv_emission_transform;
+
DrawOrder draw_order;
Ref<Texture> texture;
@@ -248,7 +252,7 @@ public:
void set_color(const Color &p_color);
Color get_color() const;
- void set_color_ramp(const Ref<Gradient> &p_texture);
+ void set_color_ramp(const Ref<Gradient> &p_ramp);
Ref<Gradient> get_color_ramp() const;
void set_particle_flag(Flags p_flag, bool p_enable);
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 5b14b3e8e1..d8156a0afe 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -61,9 +61,7 @@ void Joint2D::_update_joint(bool p_only_free) {
if (!body_a || !body_b)
return;
- if (!body_a) {
- SWAP(body_a, body_b);
- }
+ SWAP(body_a, body_b);
joint = _configure_joint(body_a, body_b);
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 6b12db9e44..7f01ff8806 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -435,7 +435,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_scale", PROPERTY_HINT_RANGE, "0.01,50,0.01"), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix,Mask"), "set_mode", "get_mode");
ADD_GROUP("Range", "range_");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "range_height", PROPERTY_HINT_RANGE, "-2048,2048,0.1,or_lesser,or_greater"), "set_height", "get_height");
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index e116d404d6..ad405fabbb 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -38,13 +38,13 @@ VARIANT_ENUM_CAST(Line2D::LineJointMode)
VARIANT_ENUM_CAST(Line2D::LineCapMode)
VARIANT_ENUM_CAST(Line2D::LineTextureMode)
-Line2D::Line2D() :
- Node2D() {
+Line2D::Line2D() {
_joint_mode = LINE_JOINT_SHARP;
_begin_cap_mode = LINE_CAP_NONE;
_end_cap_mode = LINE_CAP_NONE;
_width = 10;
_default_color = Color(0.4, 0.5, 1);
+ _texture_mode = LINE_TEXTURE_NONE;
_sharp_limit = 2.f;
_round_precision = 8;
}
@@ -84,10 +84,10 @@ void Line2D::set_points(const PoolVector<Vector2> &p_points) {
update();
}
-void Line2D::set_width(float width) {
- if (width < 0.0)
- width = 0.0;
- _width = width;
+void Line2D::set_width(float p_width) {
+ if (p_width < 0.0)
+ p_width = 0.0;
+ _width = p_width;
update();
}
@@ -95,17 +95,37 @@ float Line2D::get_width() const {
return _width;
}
+void Line2D::set_curve(const Ref<Curve> &p_curve) {
+ // Cleanup previous connection if any
+ if (_curve.is_valid()) {
+ _curve->disconnect(CoreStringNames::get_singleton()->changed, this, "_curve_changed");
+ }
+
+ _curve = p_curve;
+
+ // Connect to the curve so the line will update when it is changed
+ if (_curve.is_valid()) {
+ _curve->connect(CoreStringNames::get_singleton()->changed, this, "_curve_changed");
+ }
+
+ update();
+}
+
+Ref<Curve> Line2D::get_curve() const {
+ return _curve;
+}
+
PoolVector<Vector2> Line2D::get_points() const {
return _points;
}
-void Line2D::set_point_position(int i, Vector2 pos) {
- _points.set(i, pos);
+void Line2D::set_point_position(int i, Vector2 p_pos) {
+ _points.set(i, p_pos);
update();
}
Vector2 Line2D::get_point_position(int i) const {
- ERR_FAIL_INDEX_V(i, _points.size(), Vector2())
+ ERR_FAIL_INDEX_V(i, _points.size(), Vector2());
return _points.get(i);
}
@@ -121,11 +141,11 @@ void Line2D::clear_points() {
}
}
-void Line2D::add_point(Vector2 pos, int atpos) {
- if (atpos < 0 || _points.size() < atpos) {
- _points.append(pos);
+void Line2D::add_point(Vector2 p_pos, int p_atpos) {
+ if (p_atpos < 0 || _points.size() < p_atpos) {
+ _points.append(p_pos);
} else {
- _points.insert(atpos, pos);
+ _points.insert(p_atpos, p_pos);
}
update();
}
@@ -135,8 +155,8 @@ void Line2D::remove_point(int i) {
update();
}
-void Line2D::set_default_color(Color color) {
- _default_color = color;
+void Line2D::set_default_color(Color p_color) {
+ _default_color = p_color;
update();
}
@@ -144,18 +164,18 @@ Color Line2D::get_default_color() const {
return _default_color;
}
-void Line2D::set_gradient(const Ref<Gradient> &gradient) {
+void Line2D::set_gradient(const Ref<Gradient> &p_gradient) {
// Cleanup previous connection if any
if (_gradient.is_valid()) {
- (**_gradient).disconnect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
+ _gradient->disconnect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
}
- _gradient = gradient;
+ _gradient = p_gradient;
// Connect to the gradient so the line will update when the ColorRamp is changed
if (_gradient.is_valid()) {
- (**_gradient).connect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
+ _gradient->connect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
}
update();
@@ -165,8 +185,8 @@ Ref<Gradient> Line2D::get_gradient() const {
return _gradient;
}
-void Line2D::set_texture(const Ref<Texture> &texture) {
- _texture = texture;
+void Line2D::set_texture(const Ref<Texture> &p_texture) {
+ _texture = p_texture;
update();
}
@@ -174,8 +194,8 @@ Ref<Texture> Line2D::get_texture() const {
return _texture;
}
-void Line2D::set_texture_mode(const LineTextureMode mode) {
- _texture_mode = mode;
+void Line2D::set_texture_mode(const LineTextureMode p_mode) {
+ _texture_mode = p_mode;
update();
}
@@ -183,8 +203,8 @@ Line2D::LineTextureMode Line2D::get_texture_mode() const {
return _texture_mode;
}
-void Line2D::set_joint_mode(LineJointMode mode) {
- _joint_mode = mode;
+void Line2D::set_joint_mode(LineJointMode p_mode) {
+ _joint_mode = p_mode;
update();
}
@@ -192,8 +212,8 @@ Line2D::LineJointMode Line2D::get_joint_mode() const {
return _joint_mode;
}
-void Line2D::set_begin_cap_mode(LineCapMode mode) {
- _begin_cap_mode = mode;
+void Line2D::set_begin_cap_mode(LineCapMode p_mode) {
+ _begin_cap_mode = p_mode;
update();
}
@@ -201,8 +221,8 @@ Line2D::LineCapMode Line2D::get_begin_cap_mode() const {
return _begin_cap_mode;
}
-void Line2D::set_end_cap_mode(LineCapMode mode) {
- _end_cap_mode = mode;
+void Line2D::set_end_cap_mode(LineCapMode p_mode) {
+ _end_cap_mode = p_mode;
update();
}
@@ -218,10 +238,10 @@ void Line2D::_notification(int p_what) {
}
}
-void Line2D::set_sharp_limit(float limit) {
- if (limit < 0.f)
- limit = 0.f;
- _sharp_limit = limit;
+void Line2D::set_sharp_limit(float p_limit) {
+ if (p_limit < 0.f)
+ p_limit = 0.f;
+ _sharp_limit = p_limit;
update();
}
@@ -229,10 +249,10 @@ float Line2D::get_sharp_limit() const {
return _sharp_limit;
}
-void Line2D::set_round_precision(int precision) {
- if (precision < 1)
- precision = 1;
- _round_precision = precision;
+void Line2D::set_round_precision(int p_precision) {
+ if (p_precision < 1)
+ p_precision = 1;
+ _round_precision = p_precision;
update();
}
@@ -268,10 +288,11 @@ void Line2D::_draw() {
lb.round_precision = _round_precision;
lb.sharp_limit = _sharp_limit;
lb.width = _width;
+ lb.curve = *_curve;
RID texture_rid;
if (_texture.is_valid()) {
- texture_rid = (**_texture).get_rid();
+ texture_rid = _texture->get_rid();
lb.tile_aspect = _texture->get_size().aspect();
}
@@ -312,6 +333,10 @@ void Line2D::_gradient_changed() {
update();
}
+void Line2D::_curve_changed() {
+ update();
+}
+
// static
void Line2D::_bind_methods() {
@@ -331,6 +356,9 @@ void Line2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_width", "width"), &Line2D::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &Line2D::get_width);
+ ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Line2D::set_curve);
+ ClassDB::bind_method(D_METHOD("get_curve"), &Line2D::get_curve);
+
ClassDB::bind_method(D_METHOD("set_default_color", "color"), &Line2D::set_default_color);
ClassDB::bind_method(D_METHOD("get_default_color"), &Line2D::get_default_color);
@@ -360,6 +388,7 @@ void Line2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "width_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_color"), "set_default_color", "get_default_color");
ADD_GROUP("Fill", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
@@ -386,4 +415,5 @@ void Line2D::_bind_methods() {
BIND_ENUM_CONSTANT(LINE_TEXTURE_STRETCH);
ClassDB::bind_method(D_METHOD("_gradient_changed"), &Line2D::_gradient_changed);
+ ClassDB::bind_method(D_METHOD("_curve_changed"), &Line2D::_curve_changed);
}
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 8a6f7b2dc5..14afa463ba 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -35,7 +35,7 @@
class Line2D : public Node2D {
- GDCLASS(Line2D, Node2D)
+ GDCLASS(Line2D, Node2D);
public:
enum LineJointMode {
@@ -78,6 +78,9 @@ public:
void set_width(float width);
float get_width() const;
+ void set_curve(const Ref<Curve> &curve);
+ Ref<Curve> get_curve() const;
+
void set_default_color(Color color);
Color get_default_color() const;
@@ -113,6 +116,7 @@ protected:
private:
void _gradient_changed();
+ void _curve_changed();
private:
PoolVector<Vector2> _points;
@@ -120,6 +124,7 @@ private:
LineCapMode _begin_cap_mode;
LineCapMode _end_cap_mode;
float _width;
+ Ref<Curve> _curve;
Color _default_color;
Ref<Gradient> _gradient;
Ref<Texture> _texture;
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index eb09d3c9d3..9fe5fb98b6 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -95,6 +95,7 @@ static inline Vector2 interpolate(const Rect2 &r, const Vector2 &v) {
LineBuilder::LineBuilder() {
joint_mode = Line2D::LINE_JOINT_SHARP;
width = 10;
+ curve = NULL;
default_color = Color(0.4, 0.5, 1);
gradient = NULL;
sharp_limit = 2.f;
@@ -136,8 +137,8 @@ void LineBuilder::build() {
Vector2 pos1 = points[1];
Vector2 f0 = (pos1 - pos0).normalized();
Vector2 u0 = rotate90(f0);
- Vector2 pos_up0 = pos0 + u0 * hw;
- Vector2 pos_down0 = pos0 - u0 * hw;
+ Vector2 pos_up0 = pos0;
+ Vector2 pos_down0 = pos0;
Color color0;
Color color1;
@@ -145,12 +146,30 @@ void LineBuilder::build() {
float current_distance0 = 0.f;
float current_distance1 = 0.f;
float total_distance = 0.f;
+ float width_factor = 1.f;
_interpolate_color = gradient != NULL;
+ bool retrieve_curve = curve != NULL;
bool distance_required = _interpolate_color ||
+ retrieve_curve ||
texture_mode == Line2D::LINE_TEXTURE_TILE ||
texture_mode == Line2D::LINE_TEXTURE_STRETCH;
- if (distance_required)
+ if (distance_required) {
total_distance = calculate_total_distance(points);
+ //Ajust totalDistance.
+ // The line's outer length will be a little higher due to begin and end caps
+ if (begin_cap_mode == Line2D::LINE_CAP_BOX || begin_cap_mode == Line2D::LINE_CAP_ROUND) {
+ if (retrieve_curve)
+ total_distance += width * curve->interpolate_baked(0.f) * 0.5f;
+ else
+ total_distance += width * 0.5f;
+ }
+ if (end_cap_mode == Line2D::LINE_CAP_BOX || end_cap_mode == Line2D::LINE_CAP_ROUND) {
+ if (retrieve_curve)
+ total_distance += width * curve->interpolate_baked(1.f) * 0.5f;
+ else
+ total_distance += width * 0.5f;
+ }
+ }
if (_interpolate_color)
color0 = gradient->get_color(0);
else
@@ -159,22 +178,28 @@ void LineBuilder::build() {
float uvx0 = 0.f;
float uvx1 = 0.f;
+ if (retrieve_curve)
+ width_factor = curve->interpolate_baked(0.f);
+
+ pos_up0 += u0 * hw * width_factor;
+ pos_down0 -= u0 * hw * width_factor;
+
// Begin cap
if (begin_cap_mode == Line2D::LINE_CAP_BOX) {
// Push back first vertices a little bit
- pos_up0 -= f0 * hw;
- pos_down0 -= f0 * hw;
- // The line's outer length will be a little higher due to begin and end caps
- total_distance += width;
- current_distance0 += hw;
+ pos_up0 -= f0 * hw * width_factor;
+ pos_down0 -= f0 * hw * width_factor;
+
+ current_distance0 += hw * width_factor;
current_distance1 = current_distance0;
} else if (begin_cap_mode == Line2D::LINE_CAP_ROUND) {
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
- uvx0 = 0.5f / tile_aspect;
+ uvx0 = width_factor * 0.5f / tile_aspect;
+ } else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
+ uvx0 = width * width_factor / total_distance;
}
- new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, fmin(uvx0 * 2, 1.f), 1.f));
- total_distance += width;
- current_distance0 += hw;
+ new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, uvx0 * 2, 1.f));
+ current_distance0 += hw * width_factor;
current_distance1 = current_distance0;
}
@@ -206,13 +231,23 @@ void LineBuilder::build() {
const float dp = u0.dot(f1);
const Orientation orientation = (dp > 0.f ? UP : DOWN);
+ if (distance_required) {
+ current_distance1 += pos0.distance_to(pos1);
+ }
+ if (_interpolate_color) {
+ color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
+ }
+ if (retrieve_curve) {
+ width_factor = curve->interpolate_baked(current_distance1 / total_distance);
+ }
+
Vector2 inner_normal0, inner_normal1;
if (orientation == UP) {
- inner_normal0 = u0 * hw;
- inner_normal1 = u1 * hw;
+ inner_normal0 = u0 * hw * width_factor;
+ inner_normal1 = u1 * hw * width_factor;
} else {
- inner_normal0 = -u0 * hw;
- inner_normal1 = -u1 * hw;
+ inner_normal0 = -u0 * hw * width_factor;
+ inner_normal1 = -u1 * hw * width_factor;
}
/*
@@ -259,7 +294,8 @@ void LineBuilder::build() {
Vector2 pos_up1, pos_down1;
if (intersection_result == SEGMENT_INTERSECT) {
// Fallback on bevel if sharp angle is too high (because it would produce very long miters)
- if (current_joint_mode == Line2D::LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) {
+ float width_factor_sq = width_factor * width_factor;
+ if (current_joint_mode == Line2D::LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / (hw_sq * width_factor_sq) > sharp_limit_sq) {
current_joint_mode = Line2D::LINE_JOINT_BEVEL;
}
if (current_joint_mode == Line2D::LINE_JOINT_SHARP) {
@@ -271,9 +307,9 @@ void LineBuilder::build() {
// Bevel or round
if (orientation == UP) {
pos_up1 = corner_pos_up;
- pos_down1 = pos1 - u0 * hw;
+ pos_down1 = pos1 - u0 * hw * width_factor;
} else {
- pos_up1 = pos1 + u0 * hw;
+ pos_up1 = pos1 + u0 * hw * width_factor;
pos_down1 = corner_pos_down;
}
}
@@ -289,12 +325,6 @@ void LineBuilder::build() {
// Add current line body quad
// Triangles are clockwise
- if (distance_required) {
- current_distance1 += pos0.distance_to(pos1);
- }
- if (_interpolate_color) {
- color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
- }
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
uvx1 = current_distance1 / (width * tile_aspect);
} else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
@@ -315,15 +345,15 @@ void LineBuilder::build() {
} else {
if (orientation == UP) {
pos_up0 = corner_pos_up;
- pos_down0 = pos1 - u1 * hw;
+ pos_down0 = pos1 - u1 * hw * width_factor;
} else {
- pos_up0 = pos1 + u1 * hw;
+ pos_up0 = pos1 + u1 * hw * width_factor;
pos_down0 = corner_pos_down;
}
}
} else {
- pos_up0 = pos1 + u1 * hw;
- pos_down0 = pos1 - u1 * hw;
+ pos_up0 = pos1 + u1 * hw * width_factor;
+ pos_down0 = pos1 - u1 * hw * width_factor;
}
// From this point, bu0 and bd0 concern the next segment
@@ -362,26 +392,28 @@ void LineBuilder::build() {
strip_begin(pos_up0, pos_down0, color1, uvx1);
}
}
-
// Last (or only) segment
-
pos1 = points[points.size() - 1];
- Vector2 pos_up1 = pos1 + u0 * hw;
- Vector2 pos_down1 = pos1 - u0 * hw;
-
- // End cap (box)
- if (end_cap_mode == Line2D::LINE_CAP_BOX) {
- pos_up1 += f0 * hw;
- pos_down1 += f0 * hw;
- }
-
if (distance_required) {
current_distance1 += pos0.distance_to(pos1);
}
if (_interpolate_color) {
color1 = gradient->get_color(gradient->get_points_count() - 1);
}
+ if (retrieve_curve) {
+ width_factor = curve->interpolate_baked(1.f);
+ }
+
+ Vector2 pos_up1 = pos1 + u0 * hw * width_factor;
+ Vector2 pos_down1 = pos1 - u0 * hw * width_factor;
+
+ // End cap (box)
+ if (end_cap_mode == Line2D::LINE_CAP_BOX) {
+ pos_up1 += f0 * hw * width_factor;
+ pos_down1 += f0 * hw * width_factor;
+ }
+
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
uvx1 = current_distance1 / (width * tile_aspect);
} else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
@@ -394,7 +426,13 @@ void LineBuilder::build() {
if (end_cap_mode == Line2D::LINE_CAP_ROUND) {
// Note: color is not used in case we don't interpolate...
Color color = _interpolate_color ? gradient->get_color(gradient->get_points_count() - 1) : Color(0, 0, 0);
- new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f / tile_aspect, 0.f, 1.0f / tile_aspect, 1.f));
+ float dist = 0;
+ if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
+ dist = width_factor / tile_aspect;
+ } else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
+ dist = width * width_factor / total_distance;
+ }
+ new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f * dist, 0.f, dist, 1.f));
}
}
diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h
index b961385e33..91b4518f9b 100644
--- a/scene/2d/line_builder.h
+++ b/scene/2d/line_builder.h
@@ -45,6 +45,7 @@ public:
Line2D::LineCapMode begin_cap_mode;
Line2D::LineCapMode end_cap_mode;
float width;
+ Curve *curve;
Color default_color;
Gradient *gradient;
Line2D::LineTextureMode texture_mode;
diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h
index 4d81c8088a..af552415ca 100644
--- a/scene/2d/mesh_instance_2d.h
+++ b/scene/2d/mesh_instance_2d.h
@@ -34,7 +34,7 @@
#include "scene/2d/node_2d.h"
class MeshInstance2D : public Node2D {
- GDCLASS(MeshInstance2D, Node2D)
+ GDCLASS(MeshInstance2D, Node2D);
Ref<Mesh> mesh;
diff --git a/scene/2d/navigation_2d.cpp b/scene/2d/navigation_2d.cpp
index 72b5f2fb12..f644db462b 100644
--- a/scene/2d/navigation_2d.cpp
+++ b/scene/2d/navigation_2d.cpp
@@ -92,7 +92,6 @@ void Navigation2D::_navpoly_link(int p_id) {
if (!valid) {
nm.polygons.pop_back();
ERR_CONTINUE(!valid);
- continue;
}
p.center = center / plen;
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 9701998f5d..7759897420 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -41,6 +41,12 @@
void Particles2D::set_emitting(bool p_emitting) {
VS::get_singleton()->particles_set_emitting(particles, p_emitting);
+
+ if (p_emitting && one_shot) {
+ set_process_internal(true);
+ } else if (!p_emitting) {
+ set_process_internal(false);
+ }
}
void Particles2D::set_amount(int p_amount) {
@@ -60,8 +66,16 @@ void Particles2D::set_one_shot(bool p_enable) {
one_shot = p_enable;
VS::get_singleton()->particles_set_one_shot(particles, one_shot);
- if (!one_shot && is_emitting())
- VisualServer::get_singleton()->particles_restart(particles);
+
+ if (is_emitting()) {
+
+ set_process_internal(true);
+ if (!one_shot)
+ VisualServer::get_singleton()->particles_restart(particles);
+ }
+
+ if (!one_shot)
+ set_process_internal(false);
}
void Particles2D::set_pre_process_time(float p_time) {
@@ -278,6 +292,7 @@ void Particles2D::_validate_property(PropertyInfo &property) const {
void Particles2D::restart() {
VS::get_singleton()->particles_restart(particles);
+ VS::get_singleton()->particles_set_emitting(particles, true);
}
void Particles2D::_notification(int p_what) {
@@ -313,6 +328,14 @@ void Particles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
_update_particle_emission_transform();
}
+
+ if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
+
+ if (one_shot && !is_emitting()) {
+ _change_notify();
+ set_process_internal(false);
+ }
+ }
}
void Particles2D::_bind_methods() {
diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h
index a0104b4b16..0276978f83 100644
--- a/scene/2d/particles_2d.h
+++ b/scene/2d/particles_2d.h
@@ -37,7 +37,7 @@
class Particles2D : public Node2D {
private:
- GDCLASS(Particles2D, Node2D)
+ GDCLASS(Particles2D, Node2D);
public:
enum DrawOrder {
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 578c9aa5f9..95acf13fad 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -203,8 +203,8 @@ void StaticBody2D::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -217,8 +217,8 @@ void StaticBody2D::set_friction(real_t p_friction) {
real_t StaticBody2D::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -233,8 +233,8 @@ void StaticBody2D::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -247,8 +247,8 @@ void StaticBody2D::set_bounce(real_t p_bounce) {
real_t StaticBody2D::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
@@ -630,8 +630,8 @@ void RigidBody2D::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -643,8 +643,8 @@ void RigidBody2D::set_friction(real_t p_friction) {
}
real_t RigidBody2D::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -659,8 +659,8 @@ void RigidBody2D::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -672,8 +672,8 @@ void RigidBody2D::set_bounce(real_t p_bounce) {
}
real_t RigidBody2D::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
@@ -1541,7 +1541,7 @@ Vector2 KinematicCollision2D::get_remainder() const {
return collision.remainder;
}
Object *KinematicCollision2D::get_local_shape() const {
- ERR_FAIL_COND_V(!owner, NULL);
+ if (!owner) return NULL;
uint32_t ownerid = owner->shape_find_owner(collision.local_shape);
return owner->shape_owner_get_owner(ownerid);
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 89dd1e5341..66e5ce250f 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -157,8 +157,8 @@ private:
bool operator<(const ShapePair &p_sp) const {
if (body_shape == p_sp.body_shape)
return local_shape < p_sp.local_shape;
- else
- return body_shape < p_sp.body_shape;
+
+ return body_shape < p_sp.body_shape;
}
ShapePair() {}
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index 8bccf117fd..f0c46a5fb7 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -33,6 +33,8 @@
#include "core/engine.h"
#include "scene/resources/texture.h"
+const float DEFAULT_GIZMO_EXTENTS = 10.0;
+
void Position2D::_draw_cross() {
float extents = get_gizmo_extents();
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index dc9cc2df15..f5ec3ef01a 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -35,9 +35,7 @@
class Position2D : public Node2D {
- GDCLASS(Position2D, Node2D)
-
- const float DEFAULT_GIZMO_EXTENTS = 10.0;
+ GDCLASS(Position2D, Node2D);
void _draw_cross();
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index d24c0a1561..0f48b44387 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -36,7 +36,7 @@
class Skeleton2D;
class Bone2D : public Node2D {
- GDCLASS(Bone2D, Node2D)
+ GDCLASS(Bone2D, Node2D);
friend class Skeleton2D;
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index a8c7622828..6626fccf1c 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -63,10 +63,7 @@ Rect2 Sprite::_edit_get_rect() const {
}
bool Sprite::_edit_use_rect() const {
- if (texture.is_null())
- return false;
-
- return true;
+ return texture.is_valid();
}
Rect2 Sprite::get_anchorable_rect() const {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 2b43861eea..fc53c9e4ac 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -30,9 +30,11 @@
#include "tile_map.h"
+#include "collision_object_2d.h"
#include "core/io/marshalls.h"
#include "core/method_bind_ext.gen.inc"
#include "core/os/os.h"
+#include "scene/2d/area_2d.h"
#include "servers/physics_2d_server.h"
int TileMap::_get_quadrant_size() const {
@@ -60,14 +62,21 @@ void TileMap::_notification(int p_what) {
c = Object::cast_to<Node2D>(c->get_parent());
}
+ if (use_parent) {
+ _clear_quadrants();
+ collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
+ }
+
pending_update = true;
_recreate_quadrants();
update_dirty_quadrants();
RID space = get_world_2d()->get_space();
_update_quadrant_transform();
_update_quadrant_space(space);
+ update_configuration_warning();
} break;
+
case NOTIFICATION_EXIT_TREE: {
_update_quadrant_space(RID());
@@ -82,30 +91,46 @@ void TileMap::_notification(int p_what) {
q.navpoly_ids.clear();
}
+ if (collision_parent) {
+ collision_parent->remove_shape_owner(q.shape_owner_id);
+ q.shape_owner_id = -1;
+ }
+
for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) {
VS::get_singleton()->free(F->get().id);
}
q.occluder_instances.clear();
}
+ collision_parent = NULL;
navigation = NULL;
} break;
+
case NOTIFICATION_TRANSFORM_CHANGED: {
//move stuff
_update_quadrant_transform();
} break;
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+
+ if (use_parent) {
+ _recreate_quadrants();
+ }
+
+ } break;
}
}
void TileMap::_update_quadrant_space(const RID &p_space) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!use_parent) {
+ for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Physics2DServer::get_singleton()->body_set_space(q.body, p_space);
+ Quadrant &q = E->get();
+ Physics2DServer::get_singleton()->body_set_space(q.body, p_space);
+ }
}
}
@@ -116,6 +141,10 @@ void TileMap::_update_quadrant_transform() {
Transform2D global_transform = get_global_transform();
+ Transform2D local_transform;
+ if (collision_parent)
+ local_transform = get_transform();
+
Transform2D nav_rel;
if (navigation)
nav_rel = get_relative_transform_to_parent(navigation);
@@ -125,8 +154,11 @@ void TileMap::_update_quadrant_transform() {
Quadrant &q = E->get();
Transform2D xform;
xform.set_origin(q.pos);
- xform = global_transform * xform;
- Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
+
+ if (!use_parent) {
+ xform = global_transform * xform;
+ Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
+ }
if (navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
@@ -220,11 +252,39 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const
xform.elements[1].y = -xform.elements[1].y;
offset.y = s.y - offset.y;
}
-
- offset += cell_size / 2 - s / 2;
+ /* For a future CheckBox to Center Texture:
+ offset += cell_size / 2 - s / 2; */
xform.elements[2] += offset;
}
+void TileMap::_add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata) {
+ Physics2DServer *ps = Physics2DServer::get_singleton();
+
+ if (!use_parent) {
+ ps->body_add_shape(p_q.body, p_shape->get_rid(), p_xform);
+ ps->body_set_shape_metadata(p_q.body, shape_idx, p_metadata);
+ ps->body_set_shape_as_one_way_collision(p_q.body, shape_idx, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
+
+ } else if (collision_parent) {
+ Transform2D xform = p_xform;
+ xform.set_origin(xform.get_origin() + p_q.pos);
+
+ collision_parent->shape_owner_add_shape(p_q.shape_owner_id, p_shape);
+
+ int real_index = collision_parent->shape_owner_get_shape_index(p_q.shape_owner_id, shape_idx);
+ RID rid = collision_parent->get_rid();
+
+ if (Object::cast_to<Area2D>(collision_parent) != NULL) {
+ ps->area_set_shape_transform(rid, real_index, get_transform() * xform);
+ } else {
+ ps->body_set_shape_transform(rid, real_index, get_transform() * xform);
+ ps->body_set_shape_metadata(rid, real_index, p_metadata);
+ ps->body_set_shape_as_one_way_collision(rid, real_index, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
+ }
+ }
+ shape_idx++;
+}
+
void TileMap::update_dirty_quadrants() {
if (!pending_update)
@@ -268,7 +328,11 @@ void TileMap::update_dirty_quadrants() {
q.canvas_items.clear();
- ps->body_clear_shapes(q.body);
+ if (!use_parent) {
+ ps->body_clear_shapes(q.body);
+ } else if (collision_parent) {
+ collision_parent->shape_owner_clear_shapes(q.shape_owner_id);
+ }
int shape_idx = 0;
if (navigation) {
@@ -372,10 +436,11 @@ void TileMap::update_dirty_quadrants() {
if (c.transpose) {
SWAP(tile_ofs.x, tile_ofs.y);
+ /* For a future CheckBox to Center Texture:
rect.position.x += cell_size.x / 2 - rect.size.y / 2;
rect.position.y += cell_size.y / 2 - rect.size.x / 2;
} else {
- rect.position += cell_size / 2 - rect.size / 2;
+ rect.position += cell_size / 2 - rect.size / 2; */
}
if (c.flip_h) {
@@ -426,10 +491,7 @@ void TileMap::update_dirty_quadrants() {
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++;
+ _add_shape(shape_idx, q, convex, shapes[j], xform, Vector2(E->key().x, E->key().y));
#ifdef DEBUG_ENABLED
} else {
print_error("The TileSet assigned to the TileMap " + get_name() + " has an invalid convex shape.");
@@ -437,10 +499,7 @@ void TileMap::update_dirty_quadrants() {
}
}
} 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++;
+ _add_shape(shape_idx, q, shape, shapes[j], xform, Vector2(E->key().x, E->key().y));
}
}
}
@@ -615,22 +674,29 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons
xform.set_origin(q.pos);
//q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
- q.body = Physics2DServer::get_singleton()->body_create();
- Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC);
-
- Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id());
- Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
- Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
- Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction);
- Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce);
-
- if (is_inside_tree()) {
- xform = get_global_transform() * xform;
- RID space = get_world_2d()->get_space();
- Physics2DServer::get_singleton()->body_set_space(q.body, space);
- }
+ if (!use_parent) {
+ q.body = Physics2DServer::get_singleton()->body_create();
+ Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC);
- Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
+ Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id());
+ Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
+ Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
+ Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction);
+ Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce);
+
+ if (is_inside_tree()) {
+ xform = get_global_transform() * xform;
+ RID space = get_world_2d()->get_space();
+ Physics2DServer::get_singleton()->body_set_space(q.body, space);
+ }
+
+ Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
+ } else if (collision_parent) {
+ xform = get_transform() * xform;
+ q.shape_owner_id = collision_parent->create_shape_owner(this);
+ } else {
+ q.shape_owner_id = -1;
+ }
rect_cache_dirty = true;
quadrant_order_dirty = true;
@@ -640,7 +706,12 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons
void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) {
Quadrant &q = Q->get();
- Physics2DServer::get_singleton()->free(q.body);
+ if (!use_parent) {
+ Physics2DServer::get_singleton()->free(q.body);
+ } else if (collision_parent) {
+ collision_parent->remove_shape_owner(q.shape_owner_id);
+ }
+
for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
VisualServer::get_singleton()->free(E->get());
@@ -1134,20 +1205,24 @@ Rect2 TileMap::_edit_get_rect() const {
void TileMap::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!use_parent) {
+ for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
+ Quadrant &q = E->get();
+ Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
+ }
}
}
void TileMap::set_collision_mask(uint32_t p_mask) {
collision_mask = p_mask;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!use_parent) {
+ for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
+ Quadrant &q = E->get();
+ Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
+ }
}
}
@@ -1183,13 +1258,40 @@ void TileMap::set_collision_use_kinematic(bool p_use_kinematic) {
_recreate_quadrants();
}
+bool TileMap::get_collision_use_parent() const {
+
+ return use_parent;
+}
+
+void TileMap::set_collision_use_parent(bool p_use_parent) {
+
+ if (use_parent == p_use_parent) return;
+
+ _clear_quadrants();
+
+ use_parent = p_use_parent;
+ set_notify_local_transform(use_parent);
+
+ if (use_parent && is_inside_tree()) {
+ collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
+ } else {
+ collision_parent = NULL;
+ }
+
+ _recreate_quadrants();
+ _change_notify();
+ update_configuration_warning();
+}
+
void TileMap::set_collision_friction(float p_friction) {
friction = p_friction;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!use_parent) {
+ for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, p_friction);
+ Quadrant &q = E->get();
+ Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, p_friction);
+ }
}
}
@@ -1201,10 +1303,12 @@ float TileMap::get_collision_friction() const {
void TileMap::set_collision_bounce(float p_bounce) {
bounce = p_bounce;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!use_parent) {
+ for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, p_bounce);
+ Quadrant &q = E->get();
+ Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, p_bounce);
+ }
}
}
float TileMap::get_collision_bounce() const {
@@ -1403,6 +1507,12 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(p);
}
+void TileMap::_validate_property(PropertyInfo &property) const {
+ if (use_parent && property.name != "collision_use_parent" && property.name.begins_with("collision_")) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+}
+
Vector2 TileMap::map_to_world(const Vector2 &p_pos, bool p_ignore_ofs) const {
return _map_to_world(p_pos.x, p_pos.y, p_ignore_ofs);
@@ -1551,6 +1661,20 @@ bool TileMap::get_clip_uv() const {
return clip_uv;
}
+String TileMap::get_configuration_warning() const {
+
+ String warning = Node2D::get_configuration_warning();
+
+ if (use_parent && !collision_parent) {
+ if (!warning.empty()) {
+ warning += "\n";
+ }
+ return TTR("TileMap with Use Parent on needs a parent CollisionObject2D to give shapes to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
+ }
+
+ return warning;
+}
+
void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
@@ -1586,6 +1710,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_use_kinematic", "use_kinematic"), &TileMap::set_collision_use_kinematic);
ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"), &TileMap::get_collision_use_kinematic);
+ ClassDB::bind_method(D_METHOD("set_collision_use_parent", "use_parent"), &TileMap::set_collision_use_parent);
+ ClassDB::bind_method(D_METHOD("get_collision_use_parent"), &TileMap::get_collision_use_parent);
+
ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &TileMap::set_collision_layer);
ClassDB::bind_method(D_METHOD("get_collision_layer"), &TileMap::get_collision_layer);
@@ -1651,6 +1778,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv");
ADD_GROUP("Collision", "collision_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_parent", PROPERTY_HINT_NONE, ""), "set_collision_use_parent", "get_collision_use_parent");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
@@ -1699,6 +1827,8 @@ TileMap::TileMap() {
bounce = 0;
mode = MODE_SQUARE;
half_offset = HALF_OFFSET_DISABLED;
+ use_parent = false;
+ collision_parent = NULL;
use_kinematic = false;
navigation = NULL;
y_sort_mode = false;
@@ -1709,6 +1839,7 @@ TileMap::TileMap() {
fp_adjust = 0.00001;
tile_origin = TILE_ORIGIN_TOP_LEFT;
set_notify_transform(true);
+ set_notify_local_transform(false);
}
TileMap::~TileMap() {
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 6a1467aa48..1caaefa213 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -37,6 +37,8 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/tile_set.h"
+class CollisionObject2D;
+
class TileMap : public Node2D {
GDCLASS(TileMap, Node2D);
@@ -74,6 +76,8 @@ private:
Mode mode;
Transform2D custom_transform;
HalfOffset half_offset;
+ bool use_parent;
+ CollisionObject2D *collision_parent;
bool use_kinematic;
Navigation2D *navigation;
@@ -123,6 +127,7 @@ private:
Vector2 pos;
List<RID> canvas_items;
RID body;
+ uint32_t shape_owner_id;
SelfList<Quadrant> dirty_list;
@@ -145,6 +150,7 @@ private:
pos = q.pos;
canvas_items = q.canvas_items;
body = q.body;
+ shape_owner_id = q.shape_owner_id;
cells = q.cells;
navpoly_ids = q.navpoly_ids;
occluder_instances = q.occluder_instances;
@@ -154,6 +160,7 @@ private:
pos = q.pos;
canvas_items = q.canvas_items;
body = q.body;
+ shape_owner_id = q.shape_owner_id;
cells = q.cells;
occluder_instances = q.occluder_instances;
navpoly_ids = q.navpoly_ids;
@@ -188,6 +195,8 @@ private:
void _fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
+ void _add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata);
+
Map<PosKey, Quadrant>::Element *_create_quadrant(const PosKey &p_qk);
void _erase_quadrant(Map<PosKey, Quadrant>::Element *Q);
void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true);
@@ -218,6 +227,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const;
virtual void _changed_callback(Object *p_changed, const char *p_prop);
public:
@@ -271,6 +281,9 @@ public:
void set_collision_use_kinematic(bool p_use_kinematic);
bool get_collision_use_kinematic() const;
+ void set_collision_use_parent(bool p_use_parent);
+ bool get_collision_use_parent() const;
+
void set_collision_friction(float p_friction);
float get_collision_friction() const;
@@ -314,6 +327,8 @@ public:
void set_clip_uv(bool p_enable);
bool get_clip_uv() const;
+ String get_configuration_warning() const;
+
void fix_invalid_tiles();
void clear();