summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_rb_resampler.cpp32
-rw-r--r--servers/audio/audio_stream.cpp16
-rw-r--r--servers/audio/audio_stream.h2
-rw-r--r--servers/audio/effects/audio_effect_filter.h13
-rw-r--r--servers/audio/effects/reverb.cpp24
-rw-r--r--servers/audio_server.cpp19
-rw-r--r--servers/audio_server.h2
-rw-r--r--servers/physics/area_pair_sw.cpp4
-rw-r--r--servers/physics/collision_solver_sat.cpp1
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp48
-rw-r--r--servers/physics/physics_server_sw.cpp17
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics/space_sw.cpp29
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp4
-rw-r--r--servers/physics_2d/body_2d_sw.cpp3
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp4
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp1
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp60
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h10
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h10
-rw-r--r--servers/physics_2d/space_2d_sw.cpp205
-rw-r--r--servers/physics_2d/space_2d_sw.h3
-rw-r--r--servers/physics_2d_server.cpp26
-rw-r--r--servers/physics_2d_server.h12
-rw-r--r--servers/physics_server.h10
-rw-r--r--servers/visual/rasterizer.h10
-rw-r--r--servers/visual/shader_language.cpp100
-rw-r--r--servers/visual/shader_language.h13
-rw-r--r--servers/visual/shader_types.cpp1
-rw-r--r--servers/visual/visual_server_canvas.cpp78
-rw-r--r--servers/visual/visual_server_canvas.h14
-rw-r--r--servers/visual/visual_server_raster.h6
-rw-r--r--servers/visual/visual_server_scene.cpp91
-rw-r--r--servers/visual/visual_server_scene.h13
-rw-r--r--servers/visual/visual_server_viewport.cpp10
-rw-r--r--servers/visual/visual_server_viewport.h19
-rw-r--r--servers/visual/visual_server_wrap_mt.h6
-rw-r--r--servers/visual_server.cpp13
-rw-r--r--servers/visual_server.h8
40 files changed, 722 insertions, 223 deletions
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 84a87de2e2..d9b3579812 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -79,53 +79,27 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
p_dest[i] = AudioFrame(v0, v1);
}
- // For now, channels higher than stereo are almost ignored
+ // This will probably never be used, but added anyway
if (C == 4) {
- // FIXME: v2 and v3 are not being used (thus were commented out to prevent
- // compilation warnings, but they should likely be uncommented *and* used).
- // See also C == 6 with similar issues.
float v0 = rb[(pos << 2) + 0];
float v1 = rb[(pos << 2) + 1];
- /*
- float v2 = rb[(pos << 2) + 2];
- float v3 = rb[(pos << 2) + 3];
- */
float v0n = rb[(pos_next << 2) + 0];
float v1n = rb[(pos_next << 2) + 1];
- /*
- float v2n = rb[(pos_next << 2) + 2];
- float v3n = rb[(pos_next << 2) + 3];
- */
-
v0 += (v0n - v0) * frac;
v1 += (v1n - v1) * frac;
- /*
- v2 += (v2n - v2) * frac;
- v3 += (v3n - v3) * frac;
- */
p_dest[i] = AudioFrame(v0, v1);
}
if (C == 6) {
- // FIXME: Lot of unused assignments here, but it seems like intermediate calculations
- // should be done as for C == 2 (C == 4 also has some unused assignments).
float v0 = rb[(pos * 6) + 0];
float v1 = rb[(pos * 6) + 1];
- /*
- float v2 = rb[(pos * 6) + 2];
- float v3 = rb[(pos * 6) + 3];
- float v4 = rb[(pos * 6) + 4];
- float v5 = rb[(pos * 6) + 5];
float v0n = rb[(pos_next * 6) + 0];
float v1n = rb[(pos_next * 6) + 1];
- float v2n = rb[(pos_next * 6) + 2];
- float v3n = rb[(pos_next * 6) + 3];
- float v4n = rb[(pos_next * 6) + 4];
- float v5n = rb[(pos_next * 6) + 5];
- */
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
p_dest[i] = AudioFrame(v0, v1);
}
}
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 7de0695e8c..02a0bed964 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -136,16 +136,20 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
unsigned int input_size = AudioDriver::get_singleton()->get_input_size();
+ int mix_rate = AudioDriver::get_singleton()->get_mix_rate();
+ int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1);
+#ifdef DEBUG_ENABLED
+ unsigned int input_position = AudioDriver::get_singleton()->get_input_position();
+#endif
- // p_frames is multiplied by two since an AudioFrame is stereo
- if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) {
+ if (playback_delay > input_size) {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0.0f, 0.0f);
}
input_ofs = 0;
} else {
for (int i = 0; i < p_frames; i++) {
- if (input_size >= input_ofs) {
+ if (input_size > input_ofs) {
float l = (buf[input_ofs++] >> 16) / 32768.f;
if (input_ofs >= buf.size()) {
input_ofs = 0;
@@ -162,6 +166,12 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
}
}
+#ifdef DEBUG_ENABLED
+ if (input_ofs > input_position && (input_ofs - input_position) < (p_frames * 2)) {
+ print_verbose(String(get_class_name()) + " buffer underrun: input_position=" + itos(input_position) + " input_ofs=" + itos(input_ofs) + " input_size=" + itos(input_size));
+ }
+#endif
+
AudioDriver::get_singleton()->unlock();
}
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 2740f86d55..f6ed45cc9c 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -122,8 +122,6 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback)
friend class AudioStreamMicrophone;
- static const int MICROPHONE_PLAYBACK_DELAY = 256;
-
bool active;
unsigned int input_ofs;
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index 11978882bc..e8f12e5efa 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -96,6 +96,11 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
class AudioEffectLowPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter)
+
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectLowPassFilter() :
AudioEffectFilter(AudioFilterSW::LOWPASS) {}
@@ -103,6 +108,10 @@ public:
class AudioEffectHighPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter)
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectHighPassFilter() :
AudioEffectFilter(AudioFilterSW::HIGHPASS) {}
@@ -110,6 +119,10 @@ public:
class AudioEffectBandPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter)
+ void _validate_property(PropertyInfo &property) const {
+ if (property.name == "gain") property.usage = 0;
+ }
+
public:
AudioEffectBandPassFilter() :
AudioEffectFilter(AudioFilterSW::BANDPASS) {}
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index ef23e4aaf3..b032c91da2 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -36,22 +36,22 @@
const float Reverb::comb_tunings[MAX_COMBS] = {
//freeverb comb tunings
- 0.025306122448979593,
- 0.026938775510204082,
- 0.028956916099773241,
- 0.03074829931972789,
- 0.032244897959183672,
- 0.03380952380952381,
- 0.035306122448979592,
- 0.036666666666666667
+ 0.025306122448979593f,
+ 0.026938775510204082f,
+ 0.028956916099773241f,
+ 0.03074829931972789f,
+ 0.032244897959183672f,
+ 0.03380952380952381f,
+ 0.035306122448979592f,
+ 0.036666666666666667f
};
const float Reverb::allpass_tunings[MAX_ALLPASS] = {
//freeverb allpass tunings
- 0.0051020408163265302,
- 0.007732426303854875,
- 0.01,
- 0.012607709750566893
+ 0.0051020408163265302f,
+ 0.007732426303854875f,
+ 0.01f,
+ 0.012607709750566893f
};
void Reverb::process(float *p_src, float *p_dst, int p_frames) {
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index d36057b465..6fd996c3d3 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -80,6 +80,14 @@ double AudioDriver::get_mix_time() const {
return total;
}
+void AudioDriver::input_buffer_init(int driver_buffer_frames) {
+
+ const int input_buffer_channels = 2;
+ input_buffer.resize(driver_buffer_frames * input_buffer_channels * 4);
+ input_position = 0;
+ input_size = 0;
+}
+
void AudioDriver::input_buffer_write(int32_t sample) {
input_buffer.write[input_position++] = sample;
@@ -452,6 +460,14 @@ void AudioServer::_mix_step() {
to_mix = buffer_size;
}
+bool AudioServer::thread_has_channel_mix_buffer(int p_bus, int p_buffer) const {
+ if (p_bus < 0 || p_bus >= buses.size())
+ return false;
+ if (p_buffer < 0 || p_buffer >= buses[p_bus]->channels.size())
+ return false;
+ return true;
+}
+
AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus, int p_buffer) {
ERR_FAIL_INDEX_V(p_bus, buses.size(), NULL);
@@ -926,6 +942,7 @@ void AudioServer::init() {
channel_disable_threshold_db = GLOBAL_DEF_RST("audio/channel_disable_threshold_db", -60.0);
channel_disable_frames = float(GLOBAL_DEF_RST("audio/channel_disable_time", 2.0)) * get_mix_rate();
+ ProjectSettings::get_singleton()->set_custom_property_info("audio/channel_disable_time", PropertyInfo(Variant::REAL, "audio/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
buffer_size = 1024; //hardcoded for now
init_channels_and_buffers();
@@ -1008,7 +1025,7 @@ void AudioServer::update() {
void AudioServer::load_default_bus_layout() {
- if (FileAccess::exists("res://default_bus_layout.tres")) {
+ if (ResourceLoader::exists("res://default_bus_layout.tres")) {
Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres");
if (default_layout.is_valid()) {
set_bus_layout(default_layout);
diff --git a/servers/audio_server.h b/servers/audio_server.h
index ba6569eb38..52fa84e3e6 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -59,6 +59,7 @@ protected:
void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
void update_mix_time(int p_frames);
+ void input_buffer_init(int driver_buffer_frames);
void input_buffer_write(int32_t sample);
#ifdef DEBUG_ENABLED
@@ -281,6 +282,7 @@ public:
}
//do not use from outside audio thread
+ bool thread_has_channel_mix_buffer(int p_bus, int p_buffer) const;
AudioFrame *thread_get_channel_mix_buffer(int p_bus, int p_buffer);
int thread_get_mix_buffer_size() const;
int thread_find_bus_index(const StringName &p_name);
diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index d2fef0ab77..5e295edcd1 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -147,10 +147,10 @@ Area2PairSW::~Area2PairSW() {
if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ if (area_b->has_area_monitor_callback())
area_b->remove_area_from_query(area_a, shape_a, shape_b);
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ if (area_a->has_area_monitor_callback())
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index 087ae570fb..f17f6f7014 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -98,7 +98,6 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
Vector3 c = rel_A.cross(rel_B).cross(rel_B);
- //if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
if (Math::abs(rel_A.dot(c)) < CMP_EPSILON) {
// should handle somehow..
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index 60505c08c5..3a965ff800 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -503,6 +503,24 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJoi
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
}
@@ -585,6 +603,24 @@ real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJ
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning
}
return 0;
@@ -610,6 +646,12 @@ void Generic6DOFJointSW::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
}
@@ -632,6 +674,12 @@ bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
// Not implemented in GodotPhysics backend
} break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
+ // Not implemented in GodotPhysics backend
+ } break;
case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 76a6138817..fddb531a4f 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -40,6 +40,12 @@
#include "joints/pin_joint_sw.h"
#include "joints/slider_joint_sw.h"
+#define FLUSH_QUERY_CHECK \
+ if (flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred()/set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
+ }
+
RID PhysicsServerSW::shape_create(ShapeType p_shape) {
ShapeSW *shape = NULL;
@@ -352,6 +358,8 @@ void PhysicsServerSW::area_clear_shapes(RID p_area) {
void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
@@ -435,6 +443,8 @@ void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
+ FLUSH_QUERY_CHECK
+
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -582,6 +592,8 @@ RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const {
void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
@@ -1459,6 +1471,8 @@ void PhysicsServerSW::flush_queries() {
doing_sync = true;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1467,6 +1481,8 @@ void PhysicsServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX];
@@ -1580,6 +1596,7 @@ PhysicsServerSW::PhysicsServerSW() {
collision_pairs = 0;
active = true;
+ flushing_queries = false;
};
PhysicsServerSW::~PhysicsServerSW(){
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 4131c5e248..b3c61403aa 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -51,6 +51,8 @@ class PhysicsServerSW : public PhysicsServer {
int active_objects;
int collision_pairs;
+ bool flushing_queries;
+
StepSW *stepper;
Set<const SpaceSW *> active_spaces;
@@ -365,6 +367,8 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
PhysicsServerSW();
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 731749b8ce..3b5344f020 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -544,14 +544,24 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
AABB body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
}
+ if (!shapes_found) {
+ return 0;
+ }
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
@@ -691,13 +701,23 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
r_result->collider_shape = 0;
}
AABB body_aabb;
+ bool shapes_found = false;
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -1183,6 +1203,7 @@ SpaceSW::SpaceSW() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::REAL, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
body_angular_velocity_damp_ratio = 10;
broadphase = BroadPhaseSW::create_func();
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 9d515d2183..cdd35cf657 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -147,10 +147,10 @@ Area2Pair2DSW::~Area2Pair2DSW() {
if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ if (area_b->has_area_monitor_callback())
area_b->remove_area_from_query(area_a, shape_a, shape_b);
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ if (area_a->has_area_monitor_callback())
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index aa063d6c1e..52362386d2 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -511,8 +511,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
if (continuous_cd_mode != Physics2DServer::CCD_MODE_DISABLED) {
- motion = new_transform.get_origin() - get_transform().get_origin();
- //linear_velocity*p_step;
+ motion = linear_velocity * p_step;
do_motion = true;
}
}
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 950f0f9d24..95195c8fff 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -635,11 +635,15 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() {
BroadPhase2DHashGrid::BroadPhase2DHashGrid() {
hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size", 4096);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/bp_hash_table_size", PropertyInfo(Variant::INT, "physics/2d/bp_hash_table_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
hash_table_size = Math::larger_prime(hash_table_size);
hash_table = memnew_arr(PosBin *, hash_table_size);
cell_size = GLOBAL_DEF("physics/2d/cell_size", 128);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/cell_size", PropertyInfo(Variant::INT, "physics/2d/cell_size", PROPERTY_HINT_RANGE, "0,512,1,or_greater"));
+
large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/large_object_surface_threshold_in_cells", PropertyInfo(Variant::INT, "physics/2d/large_object_surface_threshold_in_cells", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"));
for (uint32_t i = 0; i < hash_table_size; i++)
hash_table[i] = NULL;
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 4dd5b2040f..2f5b484040 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -244,6 +244,7 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) {
type = p_type;
space = NULL;
instance_id = 0;
+ canvas_instance_id = 0;
collision_mask = 1;
collision_layer = 1;
pickable = true;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index f2b2363499..f256910f52 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -49,6 +49,7 @@ private:
Type type;
RID self;
ObjectID instance_id;
+ ObjectID canvas_instance_id;
bool pickable;
struct Shape {
@@ -102,6 +103,9 @@ public:
_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
+ _FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; }
+ _FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; }
+
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 000e38c4a2..45310ec4b3 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -36,6 +36,12 @@
#include "core/project_settings.h"
#include "core/script_language.h"
+#define FLUSH_QUERY_CHECK \
+ if (flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
+ }
+
RID Physics2DServerSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = NULL;
@@ -169,7 +175,9 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
cbk->invalid_by_dir++;
return;
}
- if (cbk->valid_dir.dot((p_point_A - p_point_B).normalized()) < 0.7071) {
+ Vector2 rel_dir = (p_point_A - p_point_B).normalized();
+
+ if (cbk->valid_dir.dot(rel_dir) < 0.7071) { //sqrt(2)/2.0 - 45 degrees
cbk->invalid_by_dir++;
/*
@@ -399,6 +407,8 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co
void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -469,6 +479,27 @@ ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const {
return area->get_instance_id();
}
+void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) {
+
+ if (space_owner.owns(p_area)) {
+ Space2DSW *space = space_owner.get(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_canvas_instance_id(p_ID);
+}
+ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const {
+
+ if (space_owner.owns(p_area)) {
+ Space2DSW *space = space_owner.get(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+ return area->get_canvas_instance_id();
+}
+
void Physics2DServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
if (space_owner.owns(p_area)) {
@@ -516,6 +547,8 @@ void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) {
void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
+ FLUSH_QUERY_CHECK
+
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -594,6 +627,8 @@ RID Physics2DServerSW::body_get_space(RID p_body) const {
void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
+ FLUSH_QUERY_CHECK
+
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -696,6 +731,8 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) {
void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ FLUSH_QUERY_CHECK
+
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -744,6 +781,22 @@ uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const {
return body->get_instance_id();
};
+void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_canvas_instance_id(p_ID);
+};
+
+uint32_t Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_canvas_instance_id();
+};
+
void Physics2DServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
Body2DSW *body = body_owner.get(p_body);
@@ -1309,6 +1362,8 @@ void Physics2DServerSW::flush_queries() {
if (!active)
return;
+ flushing_queries = true;
+
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1317,6 +1372,8 @@ void Physics2DServerSW::flush_queries() {
space->call_queries();
}
+ flushing_queries = false;
+
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
@@ -1395,6 +1452,7 @@ Physics2DServerSW::Physics2DServerSW() {
active_objects = 0;
collision_pairs = 0;
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
+ flushing_queries = false;
};
Physics2DServerSW::~Physics2DServerSW(){
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index d4fc44b1d7..4f33873219 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -54,6 +54,8 @@ class Physics2DServerSW : public Physics2DServer {
bool using_threads;
+ bool flushing_queries;
+
Step2DSW *stepper;
Set<const Space2DSW *> active_spaces;
@@ -144,6 +146,9 @@ public:
virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
virtual ObjectID area_get_object_instance_id(RID p_area) const;
+ virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID);
+ virtual ObjectID area_get_canvas_instance_id(RID p_area) const;
+
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
virtual void area_set_transform(RID p_area, const Transform2D &p_transform);
@@ -188,6 +193,9 @@ public:
virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
virtual uint32_t body_get_object_instance_id(RID p_body) const;
+ virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID);
+ virtual uint32_t body_get_canvas_instance_id(RID p_body) const;
+
virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode);
virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const;
@@ -272,6 +280,8 @@ public:
virtual void end_sync();
virtual void finish();
+ virtual bool is_flushing_queries() const { return flushing_queries; }
+
int get_process_info(ProcessInfo p_info);
Physics2DServerSW();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 5f5fd3866f..e736854077 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -154,6 +154,9 @@ public:
FUNC2(area_attach_object_instance_id, RID, ObjectID);
FUNC1RC(ObjectID, area_get_object_instance_id, RID);
+ FUNC2(area_attach_canvas_instance_id, RID, ObjectID);
+ FUNC1RC(ObjectID, area_get_canvas_instance_id, RID);
+
FUNC3(area_set_param, RID, AreaParameter, const Variant &);
FUNC2(area_set_transform, RID, const Transform2D &);
@@ -199,6 +202,9 @@ public:
FUNC2(body_attach_object_instance_id, RID, uint32_t);
FUNC1RC(uint32_t, body_get_object_instance_id, RID);
+ FUNC2(body_attach_canvas_instance_id, RID, uint32_t);
+ FUNC1RC(uint32_t, body_get_canvas_instance_id, RID);
+
FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode);
FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID);
@@ -306,6 +312,10 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const {
+ return physics_2d_server->is_flushing_queries();
+ }
+
int get_process_info(ProcessInfo p_info) {
return physics_2d_server->get_process_info(p_info);
}
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index f36328c985..720742c198 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -31,9 +31,9 @@
#include "space_2d_sw.h"
#include "collision_solver_2d_sw.h"
+#include "core/os/os.h"
#include "core/pair.h"
#include "physics_2d_server_sw.h"
-
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
@@ -49,7 +49,7 @@ _FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint
return true;
}
-int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+int Physics2DDirectSpaceStateSW::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
if (p_result_max <= 0)
return 0;
@@ -75,6 +75,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
if (p_pick_point && !col_obj->is_pickable())
continue;
+ if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id)
+ continue;
+
int shape_idx = space->intersection_query_subindex_results[i];
Shape2DSW *shape = col_obj->get_shape(shape_idx);
@@ -100,6 +103,16 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
return cc;
}
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+ return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point);
+}
+
+int Physics2DDirectSpaceStateSW::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+ return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id);
+}
+
bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
ERR_FAIL_COND_V(space->locked, false);
@@ -352,6 +365,8 @@ struct _RestCallbackData2D {
const CollisionObject2DSW *object;
const CollisionObject2DSW *best_object;
+ int local_shape;
+ int best_local_shape;
int shape;
int best_shape;
Vector2 best_contact;
@@ -382,6 +397,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
rd->best_normal = contact_rel / len;
rd->best_object = rd->object;
rd->best_shape = rd->shape;
+ rd->best_local_shape = rd->local_shape;
}
bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
@@ -415,6 +431,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.valid_depth = 0;
rcd.object = col_obj;
rcd.shape = shape_idx;
+ rcd.local_shape = 0;
bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
if (!sc)
continue;
@@ -487,12 +504,23 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
Rect2 body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ return 0;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -555,9 +583,11 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
}
}
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
cbk.valid_depth = p_margin; //only valid depth is the collision margin
cbk.invalid_by_dir = 0;
@@ -568,7 +598,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
}
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) {
if (cbk.amount > 0) {
collided = true;
}
@@ -647,12 +677,23 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
Rect2 body_aabb;
+ bool shapes_found = false;
+
for (int i = 0; i < p_body->get_shape_count(); i++) {
- if (i == 0)
+ if (p_body->is_shape_set_as_disabled(i))
+ continue;
+
+ if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
- else
+ shapes_found = true;
+ } else {
body_aabb = body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+ }
+
+ if (!shapes_found) {
+ return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
@@ -663,6 +704,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
+ float separation_margin = MIN(p_margin, MAX(0.0, p_motion.length() - CMP_EPSILON)); //don't separate by more than the intended motion
+
Transform2D body_transform = p_from;
{
@@ -710,24 +753,42 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
}
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+
cbk.valid_depth = p_margin; //only valid depth is the collision margin
cbk.invalid_by_dir = 0;
+ if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC || b->get_mode() == Physics2DServer::BODY_MODE_RIGID) {
+ //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
+ Vector2 lv = b->get_linear_velocity();
+ //compute displacement from linear velocity
+ Vector2 motion = lv * Physics2DDirectBodyStateSW::singleton->step;
+ float motion_len = motion.length();
+ motion.normalize();
+ cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0);
+ }
+ }
} else {
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
cbk.invalid_by_dir = 0;
}
+ int current_collisions = cbk.amount;
+ bool did_collide = false;
+
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
- collided = cbk.amount > 0;
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, separation_margin)) {
+ did_collide = cbk.amount > current_collisions;
}
- if (!collided && cbk.invalid_by_dir > 0) {
+ if (!did_collide && cbk.invalid_by_dir > 0) {
//this shape must be excluded
if (excluded_shape_pair_count < max_excluded_shape_pairs) {
ExcludedShapeSW esp;
@@ -737,6 +798,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
excluded_shape_pairs[excluded_shape_pair_count++] = esp;
}
}
+
+ if (did_collide) {
+ collided = true;
+ }
}
}
@@ -824,14 +889,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
continue;
}
- Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+ if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
continue;
}
//test initial overlap
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
continue;
@@ -851,7 +916,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
real_t ofs = (low + hi) * 0.5;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_xform, Vector2(), NULL, NULL, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, &sep, 0);
if (collided) {
@@ -869,12 +934,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.max = 1;
cbk.amount = 0;
cbk.ptr = cd;
- cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+ cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
cbk.valid_depth = 10e20;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -907,16 +972,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool collided = false;
if (safe >= 1) {
- //not collided
- collided = false;
- if (r_result) {
-
- r_result->motion = p_motion;
- r_result->remainder = Vector2();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
- }
+ best_shape = -1; //no best shape with cast, reset to -1
+ }
- } else {
+ {
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
@@ -927,52 +986,61 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.best_object = NULL;
rcd.best_shape = 0;
- Transform2D body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
- Shape2DSW *body_shape = p_body->get_shape(best_shape);
+ //optimization
+ int from_shape = best_shape != -1 ? best_shape : 0;
+ int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
- body_aabb.position += p_motion * unsafe;
+ for (int j = from_shape; j < to_shape; j++) {
+ Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
+ Shape2DSW *body_shape = p_body->get_shape(j);
- int amount = _cull_aabb_for_body(p_body, body_aabb);
+ body_aabb.position += p_motion * unsafe;
+
+ int amount = _cull_aabb_for_body(p_body, body_aabb);
- for (int i = 0; i < amount; i++) {
+ for (int i = 0; i < amount; i++) {
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
+ const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ int shape_idx = intersection_query_subindex_results[i];
- if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
- if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
- continue;
+ if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
}
- }
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
+ Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- bool excluded = false;
- for (int k = 0; k < excluded_shape_pair_count; k++) {
+ bool excluded = false;
+ for (int k = 0; k < excluded_shape_pair_count; k++) {
- if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
- excluded = true;
- break;
+ if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
+ excluded = true;
+ break;
+ }
}
- }
- if (excluded)
- continue;
+ if (excluded)
+ continue;
- if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
+ Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
- rcd.valid_dir = body_shape_xform.get_axis(1).normalized();
- rcd.valid_depth = 10e20;
- } else {
- rcd.valid_dir = Vector2();
- rcd.valid_depth = 0;
- }
+ if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
- rcd.object = col_obj;
- rcd.shape = shape_idx;
- bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
- if (!sc)
- continue;
+ rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+ rcd.valid_depth = 10e20;
+ } else {
+ rcd.valid_dir = Vector2();
+ rcd.valid_depth = 0;
+ }
+
+ rcd.object = col_obj;
+ rcd.shape = shape_idx;
+ rcd.local_shape = j;
+ bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
+ if (!sc)
+ continue;
+ }
}
if (rcd.best_len != 0) {
@@ -981,7 +1049,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
r_result->collider = rcd.best_object->get_self();
r_result->collider_id = rcd.best_object->get_instance_id();
r_result->collider_shape = rcd.best_shape;
- r_result->collision_local_shape = best_shape;
+ r_result->collision_local_shape = rcd.best_local_shape;
r_result->collision_normal = rcd.best_normal;
r_result->collision_point = rcd.best_contact;
r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape);
@@ -996,16 +1064,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
collided = true;
- } else {
- if (r_result) {
+ }
+ }
- r_result->motion = p_motion;
- r_result->remainder = Vector2();
- r_result->motion += (body_transform.get_origin() - p_from.get_origin());
- }
+ if (!collided && r_result) {
- collided = false;
- }
+ r_result->motion = p_motion;
+ r_result->remainder = Vector2();
+ r_result->motion += (body_transform.get_origin() - p_from.get_origin());
}
return collided;
@@ -1233,6 +1299,7 @@ Space2DSW::Space2DSW() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::REAL, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
broadphase = BroadPhase2DSW::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index c894eb9c40..bf4ea12eb5 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -45,10 +45,13 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState);
+ int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
+
public:
Space2DSW *space;
virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 3ca6e29f0b..2ed8a4c478 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -328,7 +328,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam
return ret;
}
-Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+Array Physics2DDirectSpaceState::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
Set<RID> exclude;
for (int i = 0; i < p_exclude.size(); i++)
@@ -337,7 +337,12 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
Vector<ShapeResult> ret;
ret.resize(p_max_results);
- int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+ int rc;
+ if (p_filter_by_canvas)
+ rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+ else
+ rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+
if (rc == 0)
return Array();
@@ -356,6 +361,16 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
return r;
}
+Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+ return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+}
+
+Array Physics2DDirectSpaceState::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+ return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id);
+}
+
Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
@@ -400,6 +415,7 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
void Physics2DDirectSpaceState::_bind_methods() {
ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion);
@@ -575,6 +591,9 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &Physics2DServer::area_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id);
+ ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &Physics2DServer::area_attach_canvas_instance_id);
+ ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &Physics2DServer::area_get_canvas_instance_id);
+
ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable);
@@ -606,6 +625,9 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id);
+ ClassDB::bind_method(D_METHOD("body_attach_canvas_instance_id", "body", "id"), &Physics2DServer::body_attach_canvas_instance_id);
+ ClassDB::bind_method(D_METHOD("body_get_canvas_instance_id", "body"), &Physics2DServer::body_get_canvas_instance_id);
+
ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &Physics2DServer::body_set_continuous_collision_detection_mode);
ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &Physics2DServer::body_get_continuous_collision_detection_mode);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 7c23fcdaea..32e1dd1a08 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -147,8 +147,9 @@ class Physics2DDirectSpaceState : public Object {
GDCLASS(Physics2DDirectSpaceState, Object);
Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
-
Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query);
Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
@@ -181,6 +182,7 @@ public:
};
virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+ virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
@@ -348,6 +350,9 @@ public:
virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0;
virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
+ virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) = 0;
+ virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0;
+
virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0;
@@ -401,6 +406,9 @@ public:
virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0;
virtual uint32_t body_get_object_instance_id(RID p_body) const = 0;
+ virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) = 0;
+ virtual uint32_t body_get_canvas_instance_id(RID p_body) const = 0;
+
enum CCDMode {
CCD_MODE_DISABLED,
CCD_MODE_CAST_RAY,
@@ -576,6 +584,8 @@ public:
virtual void end_sync() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
diff --git a/servers/physics_server.h b/servers/physics_server.h
index d80d76305a..15b353f768 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -697,6 +697,9 @@ public:
G6DOF_JOINT_LINEAR_DAMPING,
G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_LINEAR_SPRING_DAMPING,
+ G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -706,6 +709,9 @@ public:
G6DOF_JOINT_ANGULAR_ERP,
G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
+ G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
+ G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
+ G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
G6DOF_JOINT_MAX
};
@@ -713,6 +719,8 @@ public:
G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
+ G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
+ G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
G6DOF_JOINT_FLAG_ENABLE_MOTOR,
G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
G6DOF_JOINT_FLAG_MAX
@@ -744,6 +752,8 @@ public:
virtual void flush_queries() = 0;
virtual void finish() = 0;
+ virtual bool is_flushing_queries() const = 0;
+
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 8c3736a1bf..4329203ccb 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -73,7 +73,7 @@ public:
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+ virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
virtual bool is_environment(RID p_env) = 0;
@@ -120,9 +120,7 @@ public:
Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
virtual void base_removed() = 0;
- virtual void base_changed() = 0;
- virtual void base_material_changed() = 0;
-
+ virtual void base_changed(bool p_aabb, bool p_materials) = 0;
InstanceBase() :
dependency_item(this) {
@@ -520,6 +518,8 @@ public:
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
virtual void particles_restart(RID p_particles) = 0;
+ virtual bool particles_is_inactive(RID p_particles) const = 0;
+
virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0;
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
@@ -800,8 +800,6 @@ public:
RID particles;
RID texture;
RID normal_map;
- int h_frames;
- int v_frames;
CommandParticles() { type = TYPE_PARTICLES; }
};
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 67a810bf1c..1acec7ccaf 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -131,7 +131,6 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
- "INTERPOLATION_NO_PERSPECTIVE",
"INTERPOLATION_SMOOTH",
"PRECISION_LOW",
"PRECISION_MID",
@@ -271,7 +270,6 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
@@ -691,6 +689,30 @@ String ShaderLanguage::token_debug(const String &p_code) {
return output;
}
+bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) {
+ return (
+ p_type == TK_TYPE_VOID ||
+ p_type == TK_TYPE_BOOL ||
+ p_type == TK_TYPE_BVEC2 ||
+ p_type == TK_TYPE_BVEC3 ||
+ p_type == TK_TYPE_BVEC4 ||
+ p_type == TK_TYPE_INT ||
+ p_type == TK_TYPE_IVEC2 ||
+ p_type == TK_TYPE_IVEC3 ||
+ p_type == TK_TYPE_IVEC4 ||
+ p_type == TK_TYPE_UINT ||
+ p_type == TK_TYPE_UVEC2 ||
+ p_type == TK_TYPE_UVEC3 ||
+ p_type == TK_TYPE_UVEC4 ||
+ p_type == TK_TYPE_FLOAT ||
+ p_type == TK_TYPE_VEC2 ||
+ p_type == TK_TYPE_VEC3 ||
+ p_type == TK_TYPE_VEC4 ||
+ p_type == TK_TYPE_MAT2 ||
+ p_type == TK_TYPE_MAT3 ||
+ p_type == TK_TYPE_MAT4);
+}
+
bool ShaderLanguage::is_token_datatype(TokenType p_type) {
return (
@@ -735,7 +757,6 @@ bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
return (
p_type == TK_INTERPOLATION_FLAT ||
- p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
p_type == TK_INTERPOLATION_SMOOTH);
}
@@ -743,8 +764,6 @@ ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenT
if (p_type == TK_INTERPOLATION_FLAT)
return INTERPOLATION_FLAT;
- else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
- return INTERPOLATION_NO_PERSPECTIVE;
else
return INTERPOLATION_SMOOTH;
}
@@ -1196,6 +1215,15 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) {
valid = true;
ret_type = TYPE_MAT4;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
+ valid = true;
+ ret_type = TYPE_VEC2;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) {
+ valid = true;
+ ret_type = TYPE_VEC3;
+ } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) {
+ valid = true;
+ ret_type = TYPE_VEC4;
}
} break;
case OP_ASSIGN_BIT_AND:
@@ -2013,6 +2041,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
};
+const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
+ //constructors
+ { "modf", 1 },
+ { NULL, 0 }
+};
+
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type) {
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, NULL);
@@ -2056,6 +2090,41 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
if (!fail) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ int arg_idx = builtin_func_out_args[outarg_idx].argument;
+
+ if (arg_idx < argcount) {
+
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable");
+ return false;
+ }
+ StringName var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
+
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name)) {
+ valid = true;
+ break;
+ }
+ b = b->parent_block;
+ }
+
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable");
+ return false;
+ }
+ }
+ }
+
+ outarg_idx++;
+ }
+
if (r_ret_type)
*r_ret_type = builtin_func_defs[idx].rettype;
@@ -2288,7 +2357,7 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBE;
}
-Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) {
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
@@ -2332,7 +2401,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
break;
case ShaderLanguage::TYPE_VEC4:
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
break;
case ShaderLanguage::TYPE_MAT2:
value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
@@ -2498,7 +2571,7 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
identifier = StringName();
- TkPos pos;
+ TkPos pos = { 0, 0 };
Token tk = _get_token();
@@ -3506,6 +3579,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
nv.sint = -cn->values[i].sint;
} break;
case TYPE_UINT: {
+ // FIXME: This can't work on uint
nv.uint = -cn->values[i].uint;
} break;
case TYPE_FLOAT: {
@@ -3562,6 +3636,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
}
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for variable (samplers not allowed)");
+ return ERR_PARSE_ERROR;
+ }
+
DataType type = get_token_datatype(tk.type);
tk = _get_token();
@@ -4217,6 +4296,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for function return (samplers not allowed)");
+ return ERR_PARSE_ERROR;
+ }
+
type = get_token_datatype(tk.type);
_get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name);
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 08c4d06992..2d1851928e 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -80,7 +80,6 @@ public:
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
- TK_INTERPOLATION_NO_PERSPECTIVE,
TK_INTERPOLATION_SMOOTH,
TK_PRECISION_LOW,
TK_PRECISION_MID,
@@ -210,7 +209,6 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
- INTERPOLATION_NO_PERSPECTIVE,
INTERPOLATION_SMOOTH,
};
@@ -333,6 +331,7 @@ public:
virtual DataType get_datatype() const { return datatype_cache; }
VariableNode() {
+
type = TYPE_VARIABLE;
datatype_cache = TYPE_VOID;
}
@@ -534,6 +533,7 @@ public:
static String get_token_text(Token p_token);
static bool is_token_datatype(TokenType p_type);
+ static bool is_token_variable_datatype(TokenType p_type);
static DataType get_token_datatype(TokenType p_type);
static bool is_token_interpolation(TokenType p_type);
static DataInterpolation get_token_interpolation(TokenType p_type);
@@ -548,7 +548,7 @@ public:
static int get_cardinality(DataType p_type);
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
- static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type);
+ static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
@@ -642,6 +642,12 @@ private:
const DataType args[MAX_ARGS];
};
+ struct BuiltinFuncOutArgs { //arguments used as out in built in funcions
+
+ const char *name;
+ int argument;
+ };
+
CompletionType completion_type;
int completion_line;
BlockNode *completion_block;
@@ -652,6 +658,7 @@ private:
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
+ static const BuiltinFuncOutArgs builtin_func_out_args[];
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 69acf52e17..baafe2f8d0 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -199,6 +199,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 16cda0326d..734c295a72 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -51,6 +51,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) {
+ int child_item_count = p_canvas_item->child_items.size();
+ VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
+ for (int i = 0; i < child_item_count; i++) {
+ if (r_items) {
+ r_items[r_index] = child_items[i];
+ child_items[i]->ysort_xform = p_transform;
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ }
+
+ r_index++;
+
+ if (child_items[i]->sort_y)
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
+ }
+}
+
void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
Item *ci = p_canvas_item;
@@ -58,10 +75,10 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (!ci->visible)
return;
- if (p_canvas_item->children_order_dirty) {
+ if (ci->children_order_dirty) {
- p_canvas_item->child_items.sort_custom<ItemIndexSort>();
- p_canvas_item->children_order_dirty = false;
+ ci->child_items.sort_custom<ItemIndexSort>();
+ ci->children_order_dirty = false;
}
Rect2 rect = ci->get_rect();
@@ -82,8 +99,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
return;
int child_item_count = ci->child_items.size();
- Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *));
- copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *));
+ Item **child_items = ci->child_items.ptrw();
if (ci->clip) {
if (p_canvas_clip != NULL) {
@@ -99,6 +115,17 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->sort_y) {
+ if (ci->ysort_children_count == -1) {
+ ci->ysort_children_count = 0;
+ _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count);
+ }
+
+ child_item_count = ci->ysort_children_count;
+ child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+
+ int i = 0;
+ _collect_ysort_children(ci, Transform2D(), child_items, i);
+
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
}
@@ -110,9 +137,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (!child_items[i]->behind)
+ if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
if (ci->copy_back_buffer) {
@@ -148,9 +179,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
for (int i = 0; i < child_item_count; i++) {
- if (child_items[i]->behind)
+ if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
- _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ if (ci->sort_y) {
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ } else {
+ _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
+ }
}
}
@@ -300,6 +335,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
canvas_item->parent = RID();
@@ -319,6 +360,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
item_owner->child_items.push_back(canvas_item);
item_owner->children_order_dirty = true;
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
+
} else {
ERR_EXPLAIN("Invalid parent");
@@ -689,7 +736,7 @@ void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2
if (indices.empty()) {
ERR_EXPLAIN("Bad Polygon!");
- ERR_FAIL_V();
+ ERR_FAIL();
}
Item::CommandPolygon *polygon = memnew(Item::CommandPolygon);
@@ -776,7 +823,7 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID
canvas_item->commands.push_back(m);
}
-void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames) {
+void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -786,8 +833,6 @@ void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles,
part->particles = p_particles;
part->texture = p_texture;
part->normal_map = p_normal;
- part->h_frames = p_h_frames;
- part->v_frames = p_v_frames;
//take the chance and request processing for them, at least once until they become visible again
VSG::storage->particles_request_process(p_particles);
@@ -828,6 +873,7 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e
ERR_FAIL_COND(!canvas_item);
canvas_item->sort_y = p_enable;
+ canvas_item->ysort_children_count = -1;
}
void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
@@ -1304,6 +1350,12 @@ bool VisualServerCanvas::free(RID p_rid) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 966b51d341..4b7422b15a 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -48,6 +48,9 @@ public:
bool use_parent_material;
int index;
bool children_order_dirty;
+ int ysort_children_count;
+ Transform2D ysort_xform;
+ Vector2 ysort_pos;
Vector<Item *> child_items;
@@ -61,6 +64,9 @@ public:
use_parent_material = false;
z_relative = true;
index = 0;
+ ysort_children_count = -1;
+ ysort_xform = Transform2D();
+ ysort_pos = Vector2();
}
};
@@ -76,10 +82,10 @@ public:
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
- if (Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON)
- return p_left->xform.elements[2].x < p_right->xform.elements[2].x;
+ if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON)
+ return p_left->ysort_pos.x < p_right->ysort_pos.x;
else
- return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+ return p_left->ysort_pos.y < p_right->ysort_pos.y;
}
};
@@ -186,7 +192,7 @@ public:
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID());
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
- void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames);
+ void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 62ba2eab69..d37fe28ac6 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -474,7 +474,7 @@ public:
BIND2(viewport_set_transparent_background, RID, bool)
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- BIND3(viewport_set_canvas_layer, RID, RID, int)
+ BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
BIND2(viewport_set_shadow_atlas_size, RID, int)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
@@ -511,7 +511,7 @@ public:
BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- BIND6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
BIND5(environment_set_fog_height, RID, bool, float, float, float)
/* SCENARIO API */
@@ -599,7 +599,7 @@ public:
BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID)
BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
- BIND6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ BIND4(canvas_item_add_particles, RID, RID, RID, RID)
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
BIND2(canvas_item_add_clip_ignore, RID, bool)
BIND2(canvas_item_set_sort_children_by_y, RID, bool)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 654994b83f..1deca7bc66 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -601,8 +601,9 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
Instance *instance = instance_owner.get(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->update_item.in_list()) {
- _update_dirty_instance(instance);
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ //may not have been updated yet
+ instance->materials.resize(VSG::storage->mesh_get_surface_count(instance->base));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -611,7 +612,7 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
VSG::storage->material_remove_instance_owner(instance->materials[p_surface], instance);
}
instance->materials.write[p_surface] = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_add_instance_owner(instance->materials[p_surface], instance);
@@ -839,7 +840,7 @@ void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instanc
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
- instance->base_material_changed(); // to actually compute if shadows are visible or not
+ instance->base_changed(false, true); // to actually compute if shadows are visible or not
}
void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
@@ -850,7 +851,7 @@ void VisualServerScene::instance_geometry_set_material_override(RID p_instance,
VSG::storage->material_remove_instance_owner(instance->material_override, instance);
}
instance->material_override = p_material;
- instance->base_material_changed();
+ instance->base_changed(false, true);
if (instance->material_override.is_valid()) {
VSG::storage->material_add_instance_owner(instance->material_override, instance);
@@ -1263,13 +1264,15 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
}
}
-void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
+bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform light_transform = p_instance->transform;
light_transform.orthonormalize(); //scale does not count on lights
+ bool animated_material_found = false;
+
switch (VSG::storage->light_get_type(p_instance->base)) {
case VS::LIGHT_DIRECTIONAL: {
@@ -1302,6 +1305,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
continue;
}
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
+
float max, min;
instance->transformed_aabb.project_range_in_plane(base, min, max);
@@ -1557,6 +1564,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
+
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1608,6 +1619,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1644,6 +1658,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
j--;
} else {
+ if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+ animated_material_found = true;
+ }
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
}
@@ -1654,6 +1671,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
} break;
}
+
+ return animated_material_found;
}
void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
@@ -1893,9 +1912,14 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (ins->base_type == VS::INSTANCE_PARTICLES) {
//particles visible? process them
- VSG::storage->particles_request_process(ins->base);
- //particles visible? request redraw
- VisualServerRaster::redraw_request();
+ if (VSG::storage->particles_is_inactive(ins->base)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ VSG::storage->particles_request_process(ins->base);
+ //particles visible? request redraw
+ VisualServerRaster::redraw_request();
+ }
}
if (geom->lighting_dirty) {
@@ -2095,7 +2119,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
if (redraw) {
//must redraw!
- _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
}
}
}
@@ -3243,11 +3267,13 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
bool can_cast_shadows = true;
+ bool is_animated = false;
if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows = false;
} else if (p_instance->material_override.is_valid()) {
can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override);
+ is_animated = VSG::storage->material_is_animated(p_instance->material_override);
} else {
if (p_instance->base_type == VS::INSTANCE_MESH) {
@@ -3262,12 +3288,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3289,12 +3318,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ } else {
+
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
@@ -3311,6 +3343,10 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
} else {
can_cast_shadows = false;
}
+
+ if (mat.is_valid() && VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
} else if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3330,12 +3366,15 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!mat.is_valid()) {
cast_shadows = true;
- break;
- }
+ } else {
- if (VSG::storage->material_casts_shadows(mat)) {
- cast_shadows = true;
- break;
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows = true;
+ }
+
+ if (VSG::storage->material_is_animated(mat)) {
+ is_animated = true;
+ }
}
}
}
@@ -3355,6 +3394,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
geom->can_cast_shadows = can_cast_shadows;
}
+
+ geom->material_is_animated = is_animated;
}
}
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 0d4737f268..38c5258116 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -192,14 +192,9 @@ public:
singleton->instance_set_base(self, RID());
}
- virtual void base_changed() {
+ virtual void base_changed(bool p_aabb, bool p_materials) {
- singleton->_instance_queue_update(this, true, true);
- }
-
- virtual void base_material_changed() {
-
- singleton->_instance_queue_update(this, false, true);
+ singleton->_instance_queue_update(this, p_aabb, p_materials);
}
Instance() :
@@ -247,6 +242,7 @@ public:
List<Instance *> lighting;
bool lighting_dirty;
bool can_cast_shadows;
+ bool material_is_animated;
List<Instance *> reflection_probes;
bool reflection_dirty;
@@ -261,6 +257,7 @@ public:
lighting_dirty = false;
reflection_dirty = true;
can_cast_shadows = true;
+ material_is_animated = true;
gi_probes_dirty = true;
}
};
@@ -488,7 +485,7 @@ public:
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
- _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index b286533590..571b71db85 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -137,7 +137,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
}
- canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get();
+ canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
}
if (lights_with_shadow) {
@@ -176,7 +176,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VSG::rasterizer->restore_render_target();
- if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
if (!can_draw_3d) {
@@ -209,7 +209,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect);
i++;
- if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) {
+ if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
if (!can_draw_3d) {
@@ -496,6 +496,7 @@ void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas)
canvas->viewports.insert(p_viewport);
viewport->canvas_map[p_canvas] = Viewport::CanvasData();
viewport->canvas_map[p_canvas].layer = 0;
+ viewport->canvas_map[p_canvas].sublayer = 0;
viewport->canvas_map[p_canvas].canvas = canvas;
}
@@ -534,13 +535,14 @@ void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,
viewport->global_transform = p_transform;
}
-void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) {
+void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
viewport->canvas_map[p_canvas].layer = p_layer;
+ viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index cb7912d6f4..66baa48458 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -78,17 +78,21 @@ public:
struct CanvasKey {
- int layer;
+ int64_t stacking;
RID canvas;
bool operator<(const CanvasKey &p_canvas) const {
- if (layer == p_canvas.layer) return canvas < p_canvas.canvas;
- return layer < p_canvas.layer;
+ if (stacking == p_canvas.stacking)
+ return canvas < p_canvas.canvas;
+ return stacking < p_canvas.stacking;
+ }
+ CanvasKey() {
+ stacking = 0;
}
- CanvasKey() { layer = 0; }
- CanvasKey(const RID &p_canvas, int p_layer) {
+ CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
canvas = p_canvas;
- layer = p_layer;
+ stacking = ((int64_t)p_layer << 32) + p_sublayer;
}
+ int get_layer() const { return stacking >> 32; }
};
struct CanvasData {
@@ -96,6 +100,7 @@ public:
CanvasBase *canvas;
Transform2D transform;
int layer;
+ int sublayer;
};
Transform2D global_transform;
@@ -176,7 +181,7 @@ public:
void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
- void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer);
+ void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index e4d69121f0..1aeb2756ba 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -400,7 +400,7 @@ public:
FUNC2(viewport_set_transparent_background, RID, bool)
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
- FUNC3(viewport_set_canvas_layer, RID, RID, int)
+ FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
FUNC2(viewport_set_shadow_atlas_size, RID, int)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
@@ -437,7 +437,7 @@ public:
FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float)
- FUNC6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+ FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
FUNCRID(scenario)
@@ -516,7 +516,7 @@ public:
FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID)
FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
- FUNC6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
+ FUNC4(canvas_item_add_particles, RID, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 9d684d33d6..e1db123f58 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -343,7 +343,7 @@ RID VisualServer::get_white_texture() {
#define SMALL_VEC2 Vector2(0.00001, 0.00001)
#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb) {
+Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) {
PoolVector<uint8_t>::Write vw = r_vertex_array.write();
@@ -1890,7 +1890,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform);
ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background);
ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform);
- ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &VisualServer::viewport_set_canvas_stacking);
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);
@@ -1915,7 +1915,9 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &VisualServer::environment_set_ssr);
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "ao_channel_affect", "color", "quality", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao);
ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &VisualServer::environment_set_fog);
- ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth);
+
+ ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_end", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth);
+
ClassDB::bind_method(D_METHOD("environment_set_fog_height", "env", "enable", "min_height", "max_height", "height_curve"), &VisualServer::environment_set_fog_height);
ClassDB::bind_method(D_METHOD("scenario_create"), &VisualServer::scenario_create);
@@ -1978,7 +1980,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID()));
- ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &VisualServer::canvas_item_add_particles);
ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform);
ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore);
ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y);
@@ -2370,6 +2372,7 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096);
GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
@@ -2400,6 +2403,8 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno");
+
+ GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false);
}
VisualServer::~VisualServer() {
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 9d98fca21b..743e010034 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -61,7 +61,7 @@ protected:
RID white_texture;
RID test_material;
- Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb);
+ Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb);
static VisualServer *(*create_func)();
static void _bind_methods();
@@ -644,7 +644,7 @@ public:
virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0;
virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
- virtual void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) = 0;
+ virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
@@ -763,7 +763,7 @@ public:
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+ virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
/* SCENARIO API */
@@ -895,7 +895,7 @@ public:
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
- virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, int p_h_frames, int p_v_frames) = 0;
+ virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0;
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0;