Merge pull request #107868 from lawnjelly/quick_ancestry4
Provide quick access to `Object` ancestry
This commit is contained in:
@ -758,7 +758,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())) {
|
||||
|
||||
@ -2228,9 +2228,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
|
||||
|
||||
@ -582,6 +582,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;
|
||||
@ -623,16 +646,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
|
||||
@ -658,7 +684,6 @@ private:
|
||||
_FORCE_INLINE_ void _construct_object(bool p_reference);
|
||||
|
||||
friend class RefCounted;
|
||||
bool type_is_reference = false;
|
||||
|
||||
BinaryMutex _instance_binding_mutex;
|
||||
struct InstanceBinding {
|
||||
@ -764,6 +789,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;
|
||||
|
||||
@ -838,6 +864,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;
|
||||
@ -996,7 +1024,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();
|
||||
|
||||
|
||||
@ -95,6 +95,7 @@ bool RefCounted::unreference() {
|
||||
|
||||
RefCounted::RefCounted() :
|
||||
Object(true) {
|
||||
_define_ancestry(AncestralClass::REF_COUNTED);
|
||||
refcount.init();
|
||||
refcount_init.init();
|
||||
}
|
||||
|
||||
@ -197,7 +197,9 @@ public:
|
||||
|
||||
virtual const Variant get_rpc_config() const = 0;
|
||||
|
||||
Script() {}
|
||||
Script() {
|
||||
_define_ancestry(AncestralClass::SCRIPT);
|
||||
}
|
||||
};
|
||||
|
||||
class ScriptLanguage : public Object {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -115,4 +115,6 @@ public:
|
||||
Transform2D get_relative_transform_to_parent(const Node *p_parent) const;
|
||||
|
||||
Transform2D get_transform() const override;
|
||||
|
||||
Node2D();
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -925,6 +925,7 @@ void MeshInstance3D::_bind_methods() {
|
||||
}
|
||||
|
||||
MeshInstance3D::MeshInstance3D() {
|
||||
_define_ancestry(AncestralClass::MESH_INSTANCE_3D);
|
||||
}
|
||||
|
||||
MeshInstance3D::~MeshInstance3D() {
|
||||
|
||||
@ -1546,6 +1546,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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -202,6 +202,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(true);
|
||||
@ -643,6 +645,7 @@ void GeometryInstance3D::_bind_methods() {
|
||||
}
|
||||
|
||||
GeometryInstance3D::GeometryInstance3D() {
|
||||
_define_ancestry(AncestralClass::GEOMETRY_INSTANCE_3D);
|
||||
}
|
||||
|
||||
GeometryInstance3D::~GeometryInstance3D() {
|
||||
|
||||
@ -4392,6 +4392,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);
|
||||
|
||||
@ -1755,6 +1755,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();
|
||||
}
|
||||
|
||||
|
||||
@ -4041,6 +4041,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:
|
||||
|
||||
Reference in New Issue
Block a user