Provide quick access to Object ancestry

This commit is contained in:
lawnjelly
2025-06-09 17:37:23 +01:00
parent 6645716e32
commit ae786bd43a
17 changed files with 71 additions and 10 deletions

View File

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

View File

@@ -428,6 +428,29 @@ public:
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 {
Object *source;
StringName signal;
@@ -491,20 +514,24 @@ private:
#ifdef DEBUG_ENABLED
SafeRefCount _lock_index;
#endif
bool _block_signals;
int _predelete_ok;
Set<Object *> change_receptors;
ObjectID _instance_id;
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
bool _edited;
bool _edited : 1;
uint32_t _edited_version;
Set<String> editor_section_folding;
#endif
bool _predelete();
void _postinitialize();
ScriptInstance *script_instance;
RefPtr script;
Dictionary metadata;
@@ -586,6 +613,7 @@ protected:
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 _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; }
public: //should be protected, but bug in clang++
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_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 {
if (!_class_ptr) {
return *_get_class_namev();

View File

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

View File

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

View File

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

View File

@@ -2160,9 +2160,9 @@ Variant::Variant(const Object *p_object) {
Object *obj = const_cast<Object *>(p_object);
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;
} else {
_get_obj().rc = likely(obj) ? obj->_use_rc() : nullptr;

View File

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

View File

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

View File

@@ -479,6 +479,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;
@@ -494,6 +496,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
}
CollisionObject2D::CollisionObject2D() {
_define_ancestry(AncestralClass::COLLISION_OBJECT_2D);
//owner=
set_notify_transform(true);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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