Browse Source

-Make sure monitorable cant be flipped while flushing queries, fixes #17330
-Also added set_deferred, this was missing.

Juan Linietsky 6 years ago
parent
commit
0b1e93ccd4

+ 6 - 0
core/object.cpp

@@ -1715,6 +1715,8 @@ void Object::_bind_methods() {
 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi);
 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi);
 	}
 	}
 
 
+	ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred);
+
 	ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
 	ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
 
 
 	ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
 	ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
@@ -1771,6 +1773,10 @@ void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
 	MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
 	MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
 }
 }
 
 
+void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
+	MessageQueue::get_singleton()->push_set(this, p_property, p_value);
+}
+
 void Object::set_block_signals(bool p_block) {
 void Object::set_block_signals(bool p_block) {
 
 
 	_block_signals = p_block;
 	_block_signals = p_block;

+ 1 - 0
core/object.h

@@ -698,6 +698,7 @@ public:
 	bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
 	bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
 
 
 	void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
 	void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
+	void set_deferred(const StringName &p_property, const Variant &p_value);
 
 
 	void set_block_signals(bool p_block);
 	void set_block_signals(bool p_block);
 	bool is_blocking_signals() const;
 	bool is_blocking_signals() const;

+ 2 - 0
modules/bullet/bullet_physics_server.h

@@ -397,6 +397,8 @@ public:
 	virtual void flush_queries();
 	virtual void flush_queries();
 	virtual void finish();
 	virtual void finish();
 
 
+	virtual bool is_flushing_queries() const { return false; }
+
 	virtual int get_process_info(ProcessInfo p_info);
 	virtual int get_process_info(ProcessInfo p_info);
 
 
 	CollisionObjectBullet *get_collisin_object(RID p_object) const;
 	CollisionObjectBullet *get_collisin_object(RID p_object) const;

+ 4 - 4
scene/2d/area_2d.cpp

@@ -399,7 +399,7 @@ void Area2D::set_monitoring(bool p_enable) {
 	if (p_enable == monitoring)
 	if (p_enable == monitoring)
 		return;
 		return;
 	if (locked) {
 	if (locked) {
-		ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_monitoring\",true/false)");
+		ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)");
 	}
 	}
 	ERR_FAIL_COND(locked);
 	ERR_FAIL_COND(locked);
 
 
@@ -424,10 +424,10 @@ bool Area2D::is_monitoring() const {
 
 
 void Area2D::set_monitorable(bool p_enable) {
 void Area2D::set_monitorable(bool p_enable) {
 
 
-	if (locked) {
-		ERR_EXPLAIN("This function can't be used during the in/out signal.");
+	if (locked || Physics2DServer::get_singleton()->is_flushing_queries()) {
+		ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
 	}
 	}
-	ERR_FAIL_COND(locked);
+	ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries());
 
 
 	if (p_enable == monitorable)
 	if (p_enable == monitorable)
 		return;
 		return;

+ 4 - 4
scene/3d/area.cpp

@@ -290,7 +290,7 @@ void Area::_notification(int p_what) {
 void Area::set_monitoring(bool p_enable) {
 void Area::set_monitoring(bool p_enable) {
 
 
 	if (locked) {
 	if (locked) {
-		ERR_EXPLAIN("This function can't be used during the in/out signal.");
+		ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)");
 	}
 	}
 	ERR_FAIL_COND(locked);
 	ERR_FAIL_COND(locked);
 
 
@@ -437,10 +437,10 @@ Array Area::get_overlapping_bodies() const {
 
 
 void Area::set_monitorable(bool p_enable) {
 void Area::set_monitorable(bool p_enable) {
 
 
-	if (locked) {
-		ERR_EXPLAIN("This function can't be used during the in/out signal.");
+	if (locked || PhysicsServer::get_singleton()->is_flushing_queries()) {
+		ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
 	}
 	}
-	ERR_FAIL_COND(locked);
+	ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries());
 
 
 	if (p_enable == monitorable)
 	if (p_enable == monitorable)
 		return;
 		return;

+ 17 - 0
servers/physics/physics_server_sw.cpp

@@ -40,6 +40,12 @@
 #include "joints/pin_joint_sw.h"
 #include "joints/pin_joint_sw.h"
 #include "joints/slider_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) {
 RID PhysicsServerSW::shape_create(ShapeType p_shape) {
 
 
 	ShapeSW *shape = NULL;
 	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) {
 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);
 	AreaSW *area = area_owner.get(p_area);
 	ERR_FAIL_COND(!area);
 	ERR_FAIL_COND(!area);
 	ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
 	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) {
 void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
 
 
+	FLUSH_QUERY_CHECK
+
 	AreaSW *area = area_owner.get(p_area);
 	AreaSW *area = area_owner.get(p_area);
 	ERR_FAIL_COND(!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) {
 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);
 	BodySW *body = body_owner.get(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
 	ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
@@ -1459,6 +1471,8 @@ void PhysicsServerSW::flush_queries() {
 
 
 	doing_sync = true;
 	doing_sync = true;
 
 
+	flushing_queries = true;
+
 	uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
 	uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
 
 
 	for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
 	for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1467,6 +1481,8 @@ void PhysicsServerSW::flush_queries() {
 		space->call_queries();
 		space->call_queries();
 	}
 	}
 
 
+	flushing_queries = false;
+
 	if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
 	if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
 
 
 		uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX];
 		uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX];
@@ -1580,6 +1596,7 @@ PhysicsServerSW::PhysicsServerSW() {
 	collision_pairs = 0;
 	collision_pairs = 0;
 
 
 	active = true;
 	active = true;
+	flushing_queries = false;
 };
 };
 
 
 PhysicsServerSW::~PhysicsServerSW(){
 PhysicsServerSW::~PhysicsServerSW(){

+ 4 - 0
servers/physics/physics_server_sw.h

@@ -51,6 +51,8 @@ class PhysicsServerSW : public PhysicsServer {
 	int active_objects;
 	int active_objects;
 	int collision_pairs;
 	int collision_pairs;
 
 
+	bool flushing_queries;
+
 	StepSW *stepper;
 	StepSW *stepper;
 	Set<const SpaceSW *> active_spaces;
 	Set<const SpaceSW *> active_spaces;
 
 
@@ -365,6 +367,8 @@ public:
 	virtual void flush_queries();
 	virtual void flush_queries();
 	virtual void finish();
 	virtual void finish();
 
 
+	virtual bool is_flushing_queries() const { return flushing_queries; }
+
 	int get_process_info(ProcessInfo p_info);
 	int get_process_info(ProcessInfo p_info);
 
 
 	PhysicsServerSW();
 	PhysicsServerSW();

+ 19 - 0
servers/physics_2d/physics_2d_server_sw.cpp

@@ -36,6 +36,12 @@
 #include "core/project_settings.h"
 #include "core/project_settings.h"
 #include "core/script_language.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) {
 RID Physics2DServerSW::_shape_create(ShapeType p_shape) {
 
 
 	Shape2DSW *shape = NULL;
 	Shape2DSW *shape = NULL;
@@ -401,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) {
 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);
 	Area2DSW *area = area_owner.get(p_area);
 	ERR_FAIL_COND(!area);
 	ERR_FAIL_COND(!area);
 
 
@@ -539,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) {
 void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
 
 
+	FLUSH_QUERY_CHECK
+
 	Area2DSW *area = area_owner.get(p_area);
 	Area2DSW *area = area_owner.get(p_area);
 	ERR_FAIL_COND(!area);
 	ERR_FAIL_COND(!area);
 
 
@@ -617,6 +627,8 @@ RID Physics2DServerSW::body_get_space(RID p_body) const {
 
 
 void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
 void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
 
 
+	FLUSH_QUERY_CHECK
+
 	Body2DSW *body = body_owner.get(p_body);
 	Body2DSW *body = body_owner.get(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
 
 
@@ -719,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) {
 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);
 	Body2DSW *body = body_owner.get(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
 
 
@@ -1348,6 +1362,8 @@ void Physics2DServerSW::flush_queries() {
 	if (!active)
 	if (!active)
 		return;
 		return;
 
 
+	flushing_queries = true;
+
 	uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
 	uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
 
 
 	for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
 	for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
@@ -1356,6 +1372,8 @@ void Physics2DServerSW::flush_queries() {
 		space->call_queries();
 		space->call_queries();
 	}
 	}
 
 
+	flushing_queries = false;
+
 	if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
 	if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
 
 
 		uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
 		uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
@@ -1434,6 +1452,7 @@ Physics2DServerSW::Physics2DServerSW() {
 	active_objects = 0;
 	active_objects = 0;
 	collision_pairs = 0;
 	collision_pairs = 0;
 	using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
 	using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
+	flushing_queries = false;
 };
 };
 
 
 Physics2DServerSW::~Physics2DServerSW(){
 Physics2DServerSW::~Physics2DServerSW(){

+ 4 - 0
servers/physics_2d/physics_2d_server_sw.h

@@ -54,6 +54,8 @@ class Physics2DServerSW : public Physics2DServer {
 
 
 	bool using_threads;
 	bool using_threads;
 
 
+	bool flushing_queries;
+
 	Step2DSW *stepper;
 	Step2DSW *stepper;
 	Set<const Space2DSW *> active_spaces;
 	Set<const Space2DSW *> active_spaces;
 
 
@@ -278,6 +280,8 @@ public:
 	virtual void end_sync();
 	virtual void end_sync();
 	virtual void finish();
 	virtual void finish();
 
 
+	virtual bool is_flushing_queries() const { return flushing_queries; }
+
 	int get_process_info(ProcessInfo p_info);
 	int get_process_info(ProcessInfo p_info);
 
 
 	Physics2DServerSW();
 	Physics2DServerSW();

+ 4 - 0
servers/physics_2d/physics_2d_server_wrap_mt.h

@@ -312,6 +312,10 @@ public:
 	virtual void flush_queries();
 	virtual void flush_queries();
 	virtual void finish();
 	virtual void finish();
 
 
+	virtual bool is_flushing_queries() const {
+		return physics_2d_server->is_flushing_queries();
+	}
+
 	int get_process_info(ProcessInfo p_info) {
 	int get_process_info(ProcessInfo p_info) {
 		return physics_2d_server->get_process_info(p_info);
 		return physics_2d_server->get_process_info(p_info);
 	}
 	}

+ 2 - 0
servers/physics_2d_server.h

@@ -584,6 +584,8 @@ public:
 	virtual void end_sync() = 0;
 	virtual void end_sync() = 0;
 	virtual void finish() = 0;
 	virtual void finish() = 0;
 
 
+	virtual bool is_flushing_queries() const = 0;
+
 	enum ProcessInfo {
 	enum ProcessInfo {
 
 
 		INFO_ACTIVE_OBJECTS,
 		INFO_ACTIVE_OBJECTS,

+ 2 - 0
servers/physics_server.h

@@ -744,6 +744,8 @@ public:
 	virtual void flush_queries() = 0;
 	virtual void flush_queries() = 0;
 	virtual void finish() = 0;
 	virtual void finish() = 0;
 
 
+	virtual bool is_flushing_queries() const = 0;
+
 	enum ProcessInfo {
 	enum ProcessInfo {
 
 
 		INFO_ACTIVE_OBJECTS,
 		INFO_ACTIVE_OBJECTS,