Browse Source

Provide quick access to `Object` ancestry

lawnjelly 2 months ago
parent
commit
ae786bd43a

+ 1 - 0
core/object.cpp

@@ -1937,6 +1937,7 @@ Object::Object() {
 	_can_translate = true;
 	_can_translate = true;
 	_is_queued_for_deletion = false;
 	_is_queued_for_deletion = false;
 	_emitting = false;
 	_emitting = false;
+	_ancestry = 0;
 	memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
 	memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
 	script_instance = nullptr;
 	script_instance = nullptr;
 	_rc.store(nullptr, std::memory_order_release);
 	_rc.store(nullptr, std::memory_order_release);

+ 36 - 6
core/object.h

@@ -428,6 +428,29 @@ public:
 		CONNECT_REFERENCE_COUNTED = 8,
 		CONNECT_REFERENCE_COUNTED = 8,
 	};
 	};
 
 
+	// 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 {
+		REFERENCE = 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,
+
+		SPATIAL = 1 << 9,
+		VISUAL_INSTANCE = 1 << 10,
+		GEOMETRY_INSTANCE = 1 << 11,
+		COLLISION_OBJECT = 1 << 12,
+		PHYSICS_BODY = 1 << 13,
+		MESH_INSTANCE = 1 << 14,
+	};
+
 	struct Connection {
 	struct Connection {
 		Object *source;
 		Object *source;
 		StringName signal;
 		StringName signal;
@@ -491,20 +514,24 @@ private:
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	SafeRefCount _lock_index;
 	SafeRefCount _lock_index;
 #endif
 #endif
-	bool _block_signals;
 	int _predelete_ok;
 	int _predelete_ok;
 	Set<Object *> change_receptors;
 	Set<Object *> change_receptors;
 	ObjectID _instance_id;
 	ObjectID _instance_id;
 	std::atomic<ObjectRC *> _rc;
 	std::atomic<ObjectRC *> _rc;
-	bool _predelete();
-	void _postinitialize();
-	bool _can_translate;
-	bool _emitting;
+
+	uint32_t _ancestry : 15;
+	bool _block_signals : 1;
+	bool _can_translate : 1;
+	bool _emitting : 1;
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
-	bool _edited;
+	bool _edited : 1;
 	uint32_t _edited_version;
 	uint32_t _edited_version;
 	Set<String> editor_section_folding;
 	Set<String> editor_section_folding;
 #endif
 #endif
+
+	bool _predelete();
+	void _postinitialize();
+
 	ScriptInstance *script_instance;
 	ScriptInstance *script_instance;
 	RefPtr script;
 	RefPtr script;
 	Dictionary metadata;
 	Dictionary metadata;
@@ -586,6 +613,7 @@ protected:
 	virtual void _validate_property(PropertyInfo &property) const;
 	virtual void _validate_property(PropertyInfo &property) const;
 
 
 	void _disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force = false);
 	void _disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force = false);
+	void _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; }
 
 
 public: //should be protected, but bug in clang++
 public: //should be protected, but bug in clang++
 	static void initialize_class();
 	static void initialize_class();
@@ -660,6 +688,8 @@ public:
 	virtual bool is_class(const String &p_class) const { return (p_class == "Object"); }
 	virtual bool is_class(const String &p_class) const { return (p_class == "Object"); }
 	virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
 	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; }
+
 	_FORCE_INLINE_ const StringName &get_class_name() const {
 	_FORCE_INLINE_ const StringName &get_class_name() const {
 		if (!_class_ptr) {
 		if (!_class_ptr) {
 			return *_get_class_namev();
 			return *_get_class_namev();

+ 1 - 0
core/reference.cpp

@@ -97,6 +97,7 @@ bool Reference::unreference() {
 }
 }
 
 
 Reference::Reference() {
 Reference::Reference() {
+	_define_ancestry(AncestralClass::REFERENCE);
 	refcount.init();
 	refcount.init();
 	refcount_init.init();
 	refcount_init.init();
 }
 }

+ 1 - 0
core/resource.cpp

@@ -381,6 +381,7 @@ void Resource::_bind_methods() {
 
 
 Resource::Resource() :
 Resource::Resource() :
 		remapped_list(this) {
 		remapped_list(this) {
+	_define_ancestry(AncestralClass::RESOURCE);
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	last_modified_time = 0;
 	last_modified_time = 0;
 	import_last_modified_time = 0;
 	import_last_modified_time = 0;

+ 3 - 1
core/script_language.h

@@ -155,7 +155,9 @@ public:
 
 
 	virtual bool is_placeholder_fallback_enabled() const { return false; }
 	virtual bool is_placeholder_fallback_enabled() const { return false; }
 
 
-	Script() {}
+	Script() {
+		_define_ancestry(AncestralClass::SCRIPT);
+	}
 };
 };
 
 
 class ScriptInstance {
 class ScriptInstance {

+ 3 - 3
core/variant.cpp

@@ -2160,9 +2160,9 @@ Variant::Variant(const Object *p_object) {
 	Object *obj = const_cast<Object *>(p_object);
 	Object *obj = const_cast<Object *>(p_object);
 
 
 	memnew_placement(_data._mem, ObjData);
 	memnew_placement(_data._mem, ObjData);
-	Reference *ref = Object::cast_to<Reference>(obj);
-	if (unlikely(ref)) {
-		*reinterpret_cast<Ref<Reference> *>(_get_obj().ref.get_data()) = Ref<Reference>(ref);
+
+	if (obj && obj->has_ancestry(Object::AncestralClass::REFERENCE)) {
+		*reinterpret_cast<Ref<Reference> *>(_get_obj().ref.get_data()) = Ref<Reference>((Reference *)obj);
 		_get_obj().rc = nullptr;
 		_get_obj().rc = nullptr;
 	} else {
 	} else {
 		_get_obj().rc = likely(obj) ? obj->_use_rc() : nullptr;
 		_get_obj().rc = likely(obj) ? obj->_use_rc() : nullptr;

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

@@ -571,6 +571,8 @@ void Area2D::_bind_methods() {
 
 
 Area2D::Area2D() :
 Area2D::Area2D() :
 		CollisionObject2D(RID_PRIME(Physics2DServer::get_singleton()->area_create()), true) {
 		CollisionObject2D(RID_PRIME(Physics2DServer::get_singleton()->area_create()), true) {
+	_define_ancestry(AncestralClass::AREA_2D);
+
 	space_override = SPACE_OVERRIDE_DISABLED;
 	space_override = SPACE_OVERRIDE_DISABLED;
 	set_gravity(98);
 	set_gravity(98);
 	set_gravity_vector(Vector2(0, 1));
 	set_gravity_vector(Vector2(0, 1));

+ 2 - 0
scene/2d/canvas_item.cpp

@@ -1367,6 +1367,8 @@ int CanvasItem::get_canvas_layer() const {
 
 
 CanvasItem::CanvasItem() :
 CanvasItem::CanvasItem() :
 		xform_change(this) {
 		xform_change(this) {
+	_define_ancestry(AncestralClass::CANVAS_ITEM);
+
 	canvas_item = RID_PRIME(VisualServer::get_singleton()->canvas_item_create());
 	canvas_item = RID_PRIME(VisualServer::get_singleton()->canvas_item_create());
 	visible = true;
 	visible = true;
 	pending_update = false;
 	pending_update = false;

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

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

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

@@ -452,6 +452,8 @@ StringName Node2D::get_property_store_alias(const StringName &p_property) const
 #endif
 #endif
 
 
 Node2D::Node2D() {
 Node2D::Node2D() {
+	_define_ancestry(AncestralClass::NODE_2D);
+
 	angle = 0;
 	angle = 0;
 	_scale = Vector2(1, 1);
 	_scale = Vector2(1, 1);
 	_xform_dirty = false;
 	_xform_dirty = false;

+ 4 - 0
scene/3d/collision_object.cpp

@@ -541,6 +541,8 @@ uint32_t CollisionObject::shape_find_owner(int p_shape_index) const {
 }
 }
 
 
 CollisionObject::CollisionObject(RID p_rid, bool p_area) {
 CollisionObject::CollisionObject(RID p_rid, bool p_area) {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT);
+
 	rid = p_rid;
 	rid = p_rid;
 	area = p_area;
 	area = p_area;
 	capture_input_on_drag = false;
 	capture_input_on_drag = false;
@@ -578,6 +580,8 @@ String CollisionObject::get_configuration_warning() const {
 }
 }
 
 
 CollisionObject::CollisionObject() {
 CollisionObject::CollisionObject() {
+	_define_ancestry(AncestralClass::COLLISION_OBJECT);
+
 	capture_input_on_drag = false;
 	capture_input_on_drag = false;
 	ray_pickable = true;
 	ray_pickable = true;
 	set_notify_transform(true);
 	set_notify_transform(true);

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

@@ -913,6 +913,8 @@ void MeshInstance::_bind_methods() {
 }
 }
 
 
 MeshInstance::MeshInstance() {
 MeshInstance::MeshInstance() {
+	_define_ancestry(AncestralClass::MESH_INSTANCE);
+
 	skeleton_path = NodePath("..");
 	skeleton_path = NodePath("..");
 	software_skinning = nullptr;
 	software_skinning = nullptr;
 	software_skinning_flags = SoftwareSkinning::FLAG_TRANSFORM_NORMALS;
 	software_skinning_flags = SoftwareSkinning::FLAG_TRANSFORM_NORMALS;

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

@@ -113,6 +113,7 @@ String PhysicsBody::get_configuration_warning() const {
 
 
 PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) :
 PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) :
 		CollisionObject(RID_PRIME(PhysicsServer::get_singleton()->body_create(p_mode)), false) {
 		CollisionObject(RID_PRIME(PhysicsServer::get_singleton()->body_create(p_mode)), false) {
+	_define_ancestry(AncestralClass::PHYSICS_BODY);
 }
 }
 
 
 #ifndef DISABLE_DEPRECATED
 #ifndef DISABLE_DEPRECATED

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

@@ -1268,6 +1268,8 @@ void Spatial::_bind_methods() {
 
 
 Spatial::Spatial() :
 Spatial::Spatial() :
 		xform_change(this), _client_physics_interpolation_spatials_list(this) {
 		xform_change(this), _client_physics_interpolation_spatials_list(this) {
+	_define_ancestry(AncestralClass::SPATIAL);
+
 	data.dirty = DIRTY_NONE;
 	data.dirty = DIRTY_NONE;
 	data.children_lock = 0;
 	data.children_lock = 0;
 
 

+ 4 - 0
scene/3d/visual_instance.cpp

@@ -208,6 +208,8 @@ RID VisualInstance::get_base() const {
 }
 }
 
 
 VisualInstance::VisualInstance() {
 VisualInstance::VisualInstance() {
+	_define_ancestry(AncestralClass::VISUAL_INSTANCE);
+
 	instance = RID_PRIME(VisualServer::get_singleton()->instance_create());
 	instance = RID_PRIME(VisualServer::get_singleton()->instance_create());
 	VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
 	VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
 	layers = 1;
 	layers = 1;
@@ -357,6 +359,8 @@ void GeometryInstance::_bind_methods() {
 }
 }
 
 
 GeometryInstance::GeometryInstance() {
 GeometryInstance::GeometryInstance() {
+	_define_ancestry(AncestralClass::GEOMETRY_INSTANCE);
+
 	for (int i = 0; i < FLAG_MAX; i++) {
 	for (int i = 0; i < FLAG_MAX; i++) {
 		flags[i] = false;
 		flags[i] = false;
 	}
 	}

+ 2 - 0
scene/gui/control.cpp

@@ -2959,6 +2959,8 @@ void Control::_bind_methods() {
 }
 }
 
 
 Control::Control() {
 Control::Control() {
+	_define_ancestry(AncestralClass::CONTROL);
+
 	data.parent = nullptr;
 	data.parent = nullptr;
 
 
 	data.mouse_filter = MOUSE_FILTER_STOP;
 	data.mouse_filter = MOUSE_FILTER_STOP;

+ 2 - 0
scene/main/node.cpp

@@ -3291,6 +3291,8 @@ String Node::_get_name_num_separator() {
 }
 }
 
 
 Node::Node() {
 Node::Node() {
+	_define_ancestry(AncestralClass::NODE);
+
 	data.pos = -1;
 	data.pos = -1;
 	data.depth = -1;
 	data.depth = -1;
 	data.blocked = 0;
 	data.blocked = 0;