diff options
Diffstat (limited to 'servers')
40 files changed, 398 insertions, 108 deletions
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/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 fead2f54da..33d1e72669 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; @@ -926,6 +934,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 +1017,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); @@ -1297,6 +1306,7 @@ void AudioServer::_bind_methods() { ADD_SIGNAL(MethodInfo("bus_layout_changed")); BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_31); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71); } diff --git a/servers/audio_server.h b/servers/audio_server.h index ba6569eb38..b12ca6e589 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 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/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 2f2f6d2908..86ef719f6f 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -31,7 +31,6 @@ #include "collision_solver_sw.h" #include "collision_solver_sat.h" -#include "collision_solver_sat.h" #include "gjk_epa.h" #define collision_solver sat_calculate_penetration diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp index 9b1a41e80d..60505c08c5 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ b/servers/physics/joints/generic_6dof_joint_sw.cpp @@ -83,7 +83,7 @@ int G6DOFRotationalLimitMotorSW::testLimitValue(real_t test_value) { real_t G6DOFRotationalLimitMotorSW::solveAngularLimits( real_t timeStep, Vector3 &axis, real_t jacDiagABInv, BodySW *body0, BodySW *body1) { - if (needApplyTorques() == false) return 0.0f; + if (!needApplyTorques()) return 0.0f; real_t target_velocity = m_targetVelocity; real_t maxMotorForce = m_maxMotorForce; diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h index b350546c5d..035525c9e6 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.h +++ b/servers/physics/joints/generic_6dof_joint_sw.h @@ -118,14 +118,12 @@ public: //! Is limited bool isLimited() { - if (m_loLimit >= m_hiLimit) return false; - return true; + return (m_loLimit < m_hiLimit); } //! Need apply correction bool needApplyTorques() { - if (m_currentLimit == 0 && m_enableMotor == false) return false; - return true; + return (m_enableMotor || m_currentLimit != 0); } //! calculates error diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index e1c985f44f..e7fc821c2c 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -1047,7 +1047,7 @@ void FaceShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_su /** FIND SUPPORT VERTEX **/ int vert_support_idx = -1; - real_t support_max; + real_t support_max = 0; for (int i = 0; i < 3; i++) { 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/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 2633edf7bb..93a05b74ef 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -138,7 +138,7 @@ void BodyPair2DSW::_validate_contacts() { Contact &c = contacts[i]; bool erase = false; - if (c.reused == false) { + if (!c.reused) { //was left behind in previous frame erase = true; } else { 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..2df09057c4 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -169,7 +169,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++; /* @@ -469,6 +471,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)) { @@ -744,6 +767,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); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index d4fc44b1d7..f41c599579 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -144,6 +144,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 +191,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; diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 5f5fd3866f..58517bf1a7 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); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index f36328c985..23c3c739c2 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); @@ -487,12 +500,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 +579,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 +594,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 +673,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 @@ -710,24 +747,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, p_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 +792,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 +883,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 +910,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 +928,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; } @@ -959,9 +1018,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (excluded) continue; + 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)) { - rcd.valid_dir = body_shape_xform.get_axis(1).normalized(); + rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); rcd.valid_depth = 10e20; } else { rcd.valid_dir = Vector2(); @@ -970,7 +1031,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co 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); + 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; } @@ -1233,6 +1294,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/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp index 0fb7af0c94..e4e1b03623 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/step_2d_sw.cpp @@ -222,7 +222,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { Constraint2DSW *prev_ci = NULL; while (ci) { - if (_setup_island(ci, p_delta) == true) { + if (_setup_island(ci, p_delta)) { //removed the root from the island graph because it is not to be processed 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..2e91d89c53 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, diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8c3736a1bf..f87f838fd6 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -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..3fe661090c 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -691,6 +691,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 ( @@ -2498,7 +2522,7 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT identifier = StringName(); - TkPos pos; + TkPos pos = { 0, 0 }; Token tk = _get_token(); @@ -3506,6 +3530,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 +3587,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 +4247,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..f07b1fade5 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -534,6 +534,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); diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 57e8d86468..baafe2f8d0 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -109,6 +109,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT; @@ -198,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..74a05ce4e4 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, Transform2D *r_extra_transforms, 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_extra_transforms, 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,8 @@ 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(); + Transform2D *child_extra_transforms = NULL; if (ci->clip) { if (p_canvas_clip != NULL) { @@ -99,6 +116,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, 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, child_extra_transforms, i); + SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); } @@ -110,9 +138,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 +180,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 +336,7 @@ 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_owner->ysort_children_count = -1; } canvas_item->parent = RID(); @@ -319,6 +356,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 +732,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 +819,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 +829,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 +869,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) { 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..b33ef21e78 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) @@ -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 cd0702d20b..33fa8d365f 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()); @@ -2831,7 +2832,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if ((!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid] == lc)) && lc.visible) { + if ((!probe_data->dynamic.light_cache_changes.has(rid) || probe_data->dynamic.light_cache_changes[rid] != lc) && lc.visible) { //erase light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, -1); @@ -2844,7 +2845,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if ((!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid] == lc)) && lc.visible) { + if ((!probe_data->dynamic.light_cache.has(rid) || probe_data->dynamic.light_cache[rid] != lc) && lc.visible) { //add light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, 1); @@ -3061,7 +3062,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; lc.visible = E->get()->visible; - if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { + if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { all_equal = false; } @@ -3081,7 +3082,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; lc.visible = E->get()->visible; - if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { + if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { all_equal = false; } @@ -3164,7 +3165,7 @@ void VisualServerScene::render_probes() { force_lighting = true; } - if (probe->invalid == false && probe->dynamic.enabled) { + if (!probe->invalid && probe->dynamic.enabled) { switch (probe->dynamic.updating_stage) { case GI_UPDATE_STAGE_CHECK: { diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index bcd6d1d972..0d4737f268 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -355,6 +355,11 @@ public: visible == p_cache.visible); } + bool operator!=(const LightCache &p_cache) { + + return !operator==(p_cache); + } + LightCache() { type = VS::LIGHT_DIRECTIONAL; 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..137fcb55f4 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) @@ -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..c1460ea4a9 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -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); @@ -1978,7 +1978,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 +2370,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 +2401,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..5af10ded28 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -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; @@ -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; |