Browse Source

Provide quick access to `Object` ancestry

lawnjelly 3 months ago
parent
commit
14a814586a

+ 3 - 1
core/io/resource.cpp

@@ -752,7 +752,9 @@ void Resource::_bind_methods() {
 }
 
 Resource::Resource() :
-		remapped_list(this) {}
+		remapped_list(this) {
+	_define_ancestry(AncestralClass::RESOURCE);
+}
 
 Resource::~Resource() {
 	if (unlikely(path_cache.is_empty())) {

+ 12 - 1
core/object/object.cpp

@@ -2204,9 +2204,20 @@ void Object::reset_internal_extension(ObjectGDExtension *p_extension) {
 #endif
 
 void Object::_construct_object(bool p_reference) {
-	type_is_reference = p_reference;
+	_block_signals = false;
+	_can_translate = true;
+	_emitting = false;
+
+	// ObjectDB::add_instance relies on AncestralClass::REF_COUNTED
+	// being already set in the case of references.
+	_ancestry = p_reference ? (uint32_t)AncestralClass::REF_COUNTED : 0;
+
 	_instance_id = ObjectDB::add_instance(this);
 
+#ifdef TOOLS_ENABLED
+	_edited = false;
+#endif
+
 #ifdef DEBUG_ENABLED
 	_lock_index.init(1);
 #endif

+ 34 - 6
core/object/object.h

@@ -587,6 +587,29 @@ public:
 		CONNECT_INHERITED = 32, // Used in editor builds.
 	};
 
+	// Store on each object a bitfield to quickly test whether it is derived from some "key" classes
+	// that are commonly tested in performance sensitive code.
+	// Ensure unsigned to bitpack.
+	enum class AncestralClass : unsigned int {
+		REF_COUNTED = 1 << 0,
+		NODE = 1 << 1,
+		RESOURCE = 1 << 2,
+		SCRIPT = 1 << 3,
+
+		CANVAS_ITEM = 1 << 4,
+		CONTROL = 1 << 5,
+		NODE_2D = 1 << 6,
+		COLLISION_OBJECT_2D = 1 << 7,
+		AREA_2D = 1 << 8,
+
+		NODE_3D = 1 << 9,
+		VISUAL_INSTANCE_3D = 1 << 10,
+		GEOMETRY_INSTANCE_3D = 1 << 11,
+		COLLISION_OBJECT_3D = 1 << 12,
+		PHYSICS_BODY_3D = 1 << 13,
+		MESH_INSTANCE_3D = 1 << 14,
+	};
+
 	struct Connection {
 		::Signal signal;
 		Callable callable;
@@ -628,16 +651,19 @@ private:
 #ifdef DEBUG_ENABLED
 	SafeRefCount _lock_index;
 #endif // DEBUG_ENABLED
-	bool _block_signals = false;
 	int _predelete_ok = 0;
 	ObjectID _instance_id;
 	bool _predelete();
 	void _initialize();
 	void _postinitialize();
-	bool _can_translate = true;
-	bool _emitting = false;
+
+	uint32_t _ancestry : 15;
+
+	bool _block_signals : 1;
+	bool _can_translate : 1;
+	bool _emitting : 1;
 #ifdef TOOLS_ENABLED
-	bool _edited = false;
+	bool _edited : 1;
 	uint32_t _edited_version = 0;
 	HashSet<String> editor_section_folding;
 #endif
@@ -663,7 +689,6 @@ private:
 	_FORCE_INLINE_ void _construct_object(bool p_reference);
 
 	friend class RefCounted;
-	bool type_is_reference = false;
 
 	BinaryMutex _instance_binding_mutex;
 	struct InstanceBinding {
@@ -769,6 +794,7 @@ protected:
 	static void _get_property_list_from_classdb(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator);
 
 	bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
+	void _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; }
 
 	virtual bool _uses_signal_mutex() const;
 
@@ -845,6 +871,8 @@ public:
 	}
 	virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
 
+	bool has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; }
+
 	const StringName &get_class_name() const;
 
 	StringName get_class_name_for_extension(const GDExtension *p_library) const;
@@ -1003,7 +1031,7 @@ public:
 
 	void clear_internal_resource_paths();
 
-	_ALWAYS_INLINE_ bool is_ref_counted() const { return type_is_reference; }
+	_ALWAYS_INLINE_ bool is_ref_counted() const { return has_ancestry(AncestralClass::REF_COUNTED); }
 
 	void cancel_free();
 

+ 1 - 0
core/object/ref_counted.cpp

@@ -95,6 +95,7 @@ bool RefCounted::unreference() {
 
 RefCounted::RefCounted() :
 		Object(true) {
+	_define_ancestry(AncestralClass::REF_COUNTED);
 	refcount.init();
 	refcount_init.init();
 }

+ 3 - 1
core/object/script_language.h

@@ -197,7 +197,9 @@ public:
 
 	virtual const Variant get_rpc_config() const = 0;
 
-	Script() {}
+	Script() {
+		_define_ancestry(AncestralClass::SCRIPT);
+	}
 };
 
 class ScriptLanguage : public Object {

+ 4 - 0
scene/2d/node_2d.cpp

@@ -510,3 +510,7 @@ void Node2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_skew", PROPERTY_HINT_NONE, "radians_as_degrees", PROPERTY_USAGE_NONE), "set_global_skew", "get_global_skew");
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
 }
+
+Node2D::Node2D() {
+	_define_ancestry(AncestralClass::NODE_2D);
+}

+ 2 - 0
scene/2d/node_2d.h

@@ -115,4 +115,6 @@ public:
 	Transform2D get_relative_transform_to_parent(const Node *p_parent) const;
 
 	Transform2D get_transform() const override;
+
+	Node2D();
 };

+ 2 - 0
scene/2d/physics/area_2d.cpp

@@ -678,6 +678,8 @@ void Area2D::_bind_methods() {
 
 Area2D::Area2D() :
 		CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) {
+	_define_ancestry(AncestralClass::AREA_2D);
+
 	set_gravity(980);
 	set_gravity_direction(Vector2(0, 1));
 	set_monitoring(true);

+ 3 - 0
scene/2d/physics/collision_object_2d.cpp

@@ -655,6 +655,8 @@ void CollisionObject2D::_bind_methods() {
 }
 
 CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT_2D);
+
 	rid = p_rid;
 	area = p_area;
 	pickable = true;
@@ -672,6 +674,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
 }
 
 CollisionObject2D::CollisionObject2D() {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT_2D);
 	//owner=
 
 	set_notify_transform(true);

+ 1 - 0
scene/3d/mesh_instance_3d.cpp

@@ -925,6 +925,7 @@ void MeshInstance3D::_bind_methods() {
 }
 
 MeshInstance3D::MeshInstance3D() {
+	_define_ancestry(AncestralClass::MESH_INSTANCE_3D);
 }
 
 MeshInstance3D::~MeshInstance3D() {

+ 2 - 0
scene/3d/node_3d.cpp

@@ -1529,6 +1529,8 @@ void Node3D::_bind_methods() {
 
 Node3D::Node3D() :
 		xform_change(this), _client_physics_interpolation_node_3d_list(this) {
+	_define_ancestry(AncestralClass::NODE_3D);
+
 	// Default member initializer for bitfield is a C++20 extension, so:
 
 	data.top_level = false;

+ 4 - 0
scene/3d/physics/collision_object_3d.cpp

@@ -746,6 +746,8 @@ PackedStringArray CollisionObject3D::get_configuration_warnings() const {
 }
 
 CollisionObject3D::CollisionObject3D() {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT_3D);
+
 	set_notify_transform(true);
 	//owner=
 
@@ -753,6 +755,8 @@ CollisionObject3D::CollisionObject3D() {
 }
 
 CollisionObject3D::~CollisionObject3D() {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT_3D);
+
 	ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
 	PhysicsServer3D::get_singleton()->free(rid);
 }

+ 4 - 0
scene/3d/physics/physics_body_3d.cpp

@@ -220,6 +220,10 @@ PackedStringArray PhysicsBody3D::get_configuration_warnings() const {
 	return warnings;
 }
 
+PhysicsBody3D::PhysicsBody3D() {
+	_define_ancestry(AncestralClass::PHYSICS_BODY_3D);
+}
+
 ///////////////////////////////////////
 
 //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.

+ 2 - 0
scene/3d/physics/physics_body_3d.h

@@ -65,4 +65,6 @@ public:
 	TypedArray<PhysicsBody3D> get_collision_exceptions();
 	void add_collision_exception_with(Node *p_node); //must be physicsbody
 	void remove_collision_exception_with(Node *p_node);
+
+	PhysicsBody3D();
 };

+ 3 - 0
scene/3d/visual_instance_3d.cpp

@@ -204,6 +204,8 @@ RID VisualInstance3D::get_base() const {
 }
 
 VisualInstance3D::VisualInstance3D() {
+	_define_ancestry(AncestralClass::VISUAL_INSTANCE_3D);
+
 	instance = RenderingServer::get_singleton()->instance_create();
 	RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
 	_set_notify_transform_when_fti_off(true);
@@ -645,6 +647,7 @@ void GeometryInstance3D::_bind_methods() {
 }
 
 GeometryInstance3D::GeometryInstance3D() {
+	_define_ancestry(AncestralClass::GEOMETRY_INSTANCE_3D);
 }
 
 GeometryInstance3D::~GeometryInstance3D() {

+ 2 - 0
scene/gui/control.cpp

@@ -4399,6 +4399,8 @@ void Control::_bind_methods() {
 }
 
 Control::Control() {
+	_define_ancestry(AncestralClass::CONTROL);
+
 	data.theme_owner = memnew(ThemeOwner(this));
 
 	set_physics_interpolation_mode(Node::PHYSICS_INTERPOLATION_MODE_OFF);

+ 2 - 0
scene/main/canvas_item.cpp

@@ -1727,6 +1727,8 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat_in_tree() const {
 
 CanvasItem::CanvasItem() :
 		xform_change(this) {
+	_define_ancestry(AncestralClass::CANVAS_ITEM);
+
 	canvas_item = RenderingServer::get_singleton()->canvas_item_create();
 }
 

+ 2 - 0
scene/main/node.cpp

@@ -4031,6 +4031,8 @@ String Node::_get_name_num_separator() {
 }
 
 Node::Node() {
+	_define_ancestry(AncestralClass::NODE);
+
 	orphan_node_count++;
 
 	// Default member initializer for bitfield is a C++20 extension, so: