Skip to content

Commit 96619d4

Browse files
committed
Use AncestralClass to speed up Object::cast_to when possible.
1 parent 149a4b4 commit 96619d4

File tree

15 files changed

+62
-8
lines changed

15 files changed

+62
-8
lines changed

core/io/resource.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class Resource : public RefCounted {
5454
GDCLASS(Resource, RefCounted);
5555

5656
public:
57+
static constexpr AncestralClass static_ancestral_class = AncestralClass::RESOURCE;
58+
5759
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
5860
virtual String get_base_extension() const { return "res"; }
5961

core/object/object.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,8 @@ class Object {
605605
MESH_INSTANCE_3D = 1 << 14,
606606
};
607607

608+
static constexpr AncestralClass static_ancestral_class = (AncestralClass)0;
609+
608610
struct Connection {
609611
::Signal signal;
610612
Callable callable;
@@ -790,6 +792,8 @@ class Object {
790792

791793
bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
792794
void _define_ancestry(AncestralClass p_class) { _ancestry |= (uint32_t)p_class; }
795+
// Prefer using derives_from.
796+
bool _has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; }
793797

794798
virtual bool _uses_signal_mutex() const;
795799

@@ -821,16 +825,12 @@ class Object {
821825
static T *cast_to(Object *p_object) {
822826
// This is like dynamic_cast, but faster.
823827
// The reason is that we can assume no virtual and multiple inheritance.
824-
static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
825-
static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
826-
return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<T *>(p_object) : nullptr;
828+
return p_object && p_object->derives_from<T>() ? static_cast<T *>(p_object) : nullptr;
827829
}
828830

829831
template <typename T>
830832
static const T *cast_to(const Object *p_object) {
831-
static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
832-
static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
833-
return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<const T *>(p_object) : nullptr;
833+
return p_object && p_object->derives_from<T>() ? static_cast<const T *>(p_object) : nullptr;
834834
}
835835

836836
enum {
@@ -864,7 +864,8 @@ class Object {
864864
}
865865
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
866866

867-
bool has_ancestry(AncestralClass p_class) const { return _ancestry & (uint32_t)p_class; }
867+
template <typename T>
868+
bool derives_from() const;
868869

869870
const StringName &get_class_name() const;
870871

@@ -1024,7 +1025,7 @@ class Object {
10241025

10251026
void clear_internal_resource_paths();
10261027

1027-
_ALWAYS_INLINE_ bool is_ref_counted() const { return has_ancestry(AncestralClass::REF_COUNTED); }
1028+
_ALWAYS_INLINE_ bool is_ref_counted() const { return _has_ancestry(AncestralClass::REF_COUNTED); }
10281029

10291030
void cancel_free();
10301031

@@ -1035,6 +1036,29 @@ class Object {
10351036
bool predelete_handler(Object *p_object);
10361037
void postinitialize_handler(Object *p_object);
10371038

1039+
template <typename T>
1040+
bool Object::derives_from() const {
1041+
static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object.");
1042+
static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS.");
1043+
1044+
// If there is an explicitly set ancestral class on the type, we can use that.
1045+
if constexpr (T::static_ancestral_class != T::super_type::static_ancestral_class) {
1046+
return _has_ancestry(T::static_ancestral_class);
1047+
} else {
1048+
return is_class_ptr(T::get_class_ptr_static());
1049+
}
1050+
}
1051+
1052+
template <>
1053+
inline bool Object::derives_from<Object>() const {
1054+
return true;
1055+
}
1056+
1057+
template <>
1058+
inline bool Object::derives_from<const Object>() const {
1059+
return true;
1060+
}
1061+
10381062
class ObjectDB {
10391063
// This needs to add up to 63, 1 bit is for reference.
10401064
#define OBJECTDB_VALIDATOR_BITS 39

core/object/ref_counted.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class RefCounted : public Object {
4242
static void _bind_methods();
4343

4444
public:
45+
static constexpr AncestralClass static_ancestral_class = AncestralClass::REF_COUNTED;
46+
4547
_FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; }
4648
bool init_ref();
4749
bool reference(); // returns false if refcount is at zero and didn't get increased

core/object/script_language.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ class Script : public Resource {
140140
}
141141

142142
public:
143+
static constexpr AncestralClass static_ancestral_class = AncestralClass::SCRIPT;
144+
143145
virtual void reload_from_file() override;
144146

145147
virtual bool can_instantiate() const = 0;

scene/2d/node_2d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class Node2D : public CanvasItem {
5555
static void _bind_methods();
5656

5757
public:
58+
static constexpr AncestralClass static_ancestral_class = AncestralClass::NODE_2D;
59+
5860
#ifdef TOOLS_ENABLED
5961
virtual Dictionary _edit_get_state() const override;
6062
virtual void _edit_set_state(const Dictionary &p_state) override;

scene/2d/physics/area_2d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class Area2D : public CollisionObject2D {
3737
GDCLASS(Area2D, CollisionObject2D);
3838

3939
public:
40+
static constexpr AncestralClass static_ancestral_class = AncestralClass::AREA_2D;
41+
4042
enum SpaceOverride {
4143
SPACE_OVERRIDE_DISABLED,
4244
SPACE_OVERRIDE_COMBINE,

scene/2d/physics/collision_object_2d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class CollisionObject2D : public Node2D {
3939
GDCLASS(CollisionObject2D, Node2D);
4040

4141
public:
42+
static constexpr AncestralClass static_ancestral_class = AncestralClass::COLLISION_OBJECT_2D;
43+
4244
enum DisableMode {
4345
DISABLE_MODE_REMOVE,
4446
DISABLE_MODE_MAKE_STATIC,

scene/3d/mesh_instance_3d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class MeshInstance3D : public GeometryInstance3D {
7070
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
7171

7272
public:
73+
static constexpr AncestralClass static_ancestral_class = AncestralClass::MESH_INSTANCE_3D;
74+
7375
void set_mesh(const Ref<Mesh> &p_mesh);
7476
Ref<Mesh> get_mesh() const;
7577

scene/3d/node_3d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class Node3D : public Node {
5454
friend class SceneTreeFTITests;
5555

5656
public:
57+
static constexpr AncestralClass static_ancestral_class = AncestralClass::NODE_3D;
58+
5759
// Edit mode for the rotation.
5860
// THIS MODE ONLY AFFECTS HOW DATA IS EDITED AND SAVED
5961
// IT DOES _NOT_ AFFECT THE TRANSFORM LOGIC (see comment in TransformDirty).

scene/3d/physics/collision_object_3d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class CollisionObject3D : public Node3D {
3737
GDCLASS(CollisionObject3D, Node3D);
3838

3939
public:
40+
static constexpr AncestralClass static_ancestral_class = AncestralClass::COLLISION_OBJECT_3D;
41+
4042
enum DisableMode {
4143
DISABLE_MODE_REMOVE,
4244
DISABLE_MODE_MAKE_STATIC,

0 commit comments

Comments
 (0)