summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/extension/gdextension.cpp4
-rw-r--r--core/extension/gdextension_interface.h20
-rw-r--r--core/io/image.cpp1
-rw-r--r--core/math/a_star_grid_2d.cpp76
-rw-r--r--core/math/a_star_grid_2d.h19
-rw-r--r--core/object/make_virtuals.py27
-rw-r--r--core/object/object.h2
-rw-r--r--core/templates/cowdata.h7
8 files changed, 96 insertions, 60 deletions
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp
index 3bc7dde10a..bffa0e251f 100644
--- a/core/extension/gdextension.cpp
+++ b/core/extension/gdextension.cpp
@@ -301,6 +301,8 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
+ nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
+ nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
p_extension_funcs->class_userdata, // void *class_userdata;
};
@@ -375,6 +377,8 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
extension->gdextension.create_instance = p_extension_funcs->create_instance_func;
extension->gdextension.free_instance = p_extension_funcs->free_instance_func;
extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func;
+ extension->gdextension.get_virtual_call_data = p_extension_funcs->get_virtual_call_data_func;
+ extension->gdextension.call_virtual_with_data = p_extension_funcs->call_virtual_with_data_func;
extension->gdextension.get_rid = p_extension_funcs->get_rid_func;
ClassDB::register_extension_class(&extension->gdextension);
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index 4214fce5f9..48cb28832a 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -265,9 +265,11 @@ typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance,
typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
-typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata);
-typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
-typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name);
+typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata);
+typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
+typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
+typedef void *(*GDExtensionClassGetVirtualCallData)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
+typedef void (*GDExtensionClassCallVirtualWithData)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef struct {
GDExtensionBool is_virtual;
@@ -306,7 +308,17 @@ typedef struct {
GDExtensionClassUnreference unreference_func;
GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
- GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
+ // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
+ GDExtensionClassGetVirtual get_virtual_func;
+ // Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
+ // need or benefit from extra data when calling virtual functions.
+ // Returns user data that will be passed to `call_virtual_with_data_func`.
+ // Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
+ // Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
+ // You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
+ GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
+ // Used to call virtual functions when `get_virtual_call_data_func` is not null.
+ GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo2;
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 204db687d8..674af6b0a6 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -3412,6 +3412,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("convert", "format"), &Image::convert);
+ ClassDB::bind_method(D_METHOD("get_mipmap_count"), &Image::get_mipmap_count);
ClassDB::bind_method(D_METHOD("get_mipmap_offset", "mipmap"), &Image::get_mipmap_offset);
ClassDB::bind_method(D_METHOD("resize_to_po2", "square", "interpolation"), &Image::resize_to_po2, DEFVAL(false), DEFVAL(INTERPOLATE_BILINEAR));
diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp
index 9ba4c2ff9a..9a3744fef8 100644
--- a/core/math/a_star_grid_2d.cpp
+++ b/core/math/a_star_grid_2d.cpp
@@ -32,8 +32,6 @@
#include "core/variant/typed_array.h"
-#define GET_POINT_UNCHECKED(m_id) points[m_id.y - region.position.y][m_id.x - region.position.x]
-
static real_t heuristic_euclidian(const Vector2i &p_from, const Vector2i &p_to) {
real_t dx = (real_t)ABS(p_to.x - p_from.x);
real_t dy = (real_t)ABS(p_to.y - p_from.y);
@@ -110,19 +108,22 @@ Size2 AStarGrid2D::get_cell_size() const {
void AStarGrid2D::update() {
points.clear();
- const int64_t end_x = region.position.x + region.size.width;
- const int64_t end_y = region.position.y + region.size.height;
- for (int64_t y = region.position.y; y < end_y; y++) {
+
+ const int32_t end_x = region.get_end().x;
+ const int32_t end_y = region.get_end().y;
+
+ for (int32_t y = region.position.y; y < end_y; y++) {
LocalVector<Point> line;
- for (int64_t x = region.position.x; x < end_x; x++) {
+ for (int32_t x = region.position.x; x < end_x; x++) {
line.push_back(Point(Vector2i(x, y), offset + Vector2(x, y) * cell_size));
}
points.push_back(line);
}
+
dirty = false;
}
-bool AStarGrid2D::is_in_bounds(int p_x, int p_y) const {
+bool AStarGrid2D::is_in_bounds(int32_t p_x, int32_t p_y) const {
return region.has_point(Vector2i(p_x, p_y));
}
@@ -172,40 +173,38 @@ AStarGrid2D::Heuristic AStarGrid2D::get_default_estimate_heuristic() const {
void AStarGrid2D::set_point_solid(const Vector2i &p_id, bool p_solid) {
ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_MSG(!is_in_boundsv(p_id), vformat("Can't set if point is disabled. Point %s out of bounds %s.", p_id, region));
- GET_POINT_UNCHECKED(p_id).solid = p_solid;
+ _get_point_unchecked(p_id)->solid = p_solid;
}
bool AStarGrid2D::is_point_solid(const Vector2i &p_id) const {
ERR_FAIL_COND_V_MSG(dirty, false, "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), false, vformat("Can't get if point is disabled. Point %s out of bounds %s.", p_id, region));
- return GET_POINT_UNCHECKED(p_id).solid;
+ return _get_point_unchecked(p_id)->solid;
}
void AStarGrid2D::set_point_weight_scale(const Vector2i &p_id, real_t p_weight_scale) {
ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_MSG(!is_in_boundsv(p_id), vformat("Can't set point's weight scale. Point %s out of bounds %s.", p_id, region));
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale));
- GET_POINT_UNCHECKED(p_id).weight_scale = p_weight_scale;
+ _get_point_unchecked(p_id)->weight_scale = p_weight_scale;
}
real_t AStarGrid2D::get_point_weight_scale(const Vector2i &p_id) const {
ERR_FAIL_COND_V_MSG(dirty, 0, "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), 0, vformat("Can't get point's weight scale. Point %s out of bounds %s.", p_id, region));
- return GET_POINT_UNCHECKED(p_id).weight_scale;
+ return _get_point_unchecked(p_id)->weight_scale;
}
void AStarGrid2D::fill_solid_region(const Rect2i &p_region, bool p_solid) {
ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method.");
- Rect2i safe_region = p_region.intersection(region);
- int from_x = safe_region.get_position().x;
- int from_y = safe_region.get_position().y;
- int end_x = safe_region.get_end().x;
- int end_y = safe_region.get_end().y;
+ const Rect2i safe_region = p_region.intersection(region);
+ const int32_t end_x = safe_region.get_end().x;
+ const int32_t end_y = safe_region.get_end().y;
- for (int x = from_x; x < end_x; x++) {
- for (int y = from_y; y < end_y; y++) {
- GET_POINT_UNCHECKED(Vector2i(x, y)).solid = p_solid;
+ for (int32_t y = safe_region.position.y; y < end_y; y++) {
+ for (int32_t x = safe_region.position.x; x < end_x; x++) {
+ _get_point_unchecked(x, y)->solid = p_solid;
}
}
}
@@ -214,14 +213,13 @@ void AStarGrid2D::fill_weight_scale_region(const Rect2i &p_region, real_t p_weig
ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale));
- Rect2i safe_region = p_region.intersection(region);
- int from_x = safe_region.get_position().x;
- int from_y = safe_region.get_position().y;
- int end_x = safe_region.get_end().x;
- int end_y = safe_region.get_end().y;
- for (int x = from_x; x < end_x; x++) {
- for (int y = from_y; y < end_y; y++) {
- GET_POINT_UNCHECKED(Vector2i(x, y)).weight_scale = p_weight_scale;
+ const Rect2i safe_region = p_region.intersection(region);
+ const int32_t end_x = safe_region.get_end().x;
+ const int32_t end_y = safe_region.get_end().y;
+
+ for (int32_t y = safe_region.position.y; y < end_y; y++) {
+ for (int32_t x = safe_region.position.x; x < end_x; x++) {
+ _get_point_unchecked(x, y)->weight_scale = p_weight_scale;
}
}
}
@@ -234,14 +232,14 @@ AStarGrid2D::Point *AStarGrid2D::_jump(Point *p_from, Point *p_to) {
return p_to;
}
- int64_t from_x = p_from->id.x;
- int64_t from_y = p_from->id.y;
+ int32_t from_x = p_from->id.x;
+ int32_t from_y = p_from->id.y;
- int64_t to_x = p_to->id.x;
- int64_t to_y = p_to->id.y;
+ int32_t to_x = p_to->id.x;
+ int32_t to_y = p_to->id.y;
- int64_t dx = to_x - from_x;
- int64_t dy = to_y - from_y;
+ int32_t dx = to_x - from_x;
+ int32_t dy = to_y - from_y;
if (diagonal_mode == DIAGONAL_MODE_ALWAYS || diagonal_mode == DIAGONAL_MODE_AT_LEAST_ONE_WALKABLE) {
if (dx != 0 && dy != 0) {
@@ -516,7 +514,7 @@ void AStarGrid2D::clear() {
Vector2 AStarGrid2D::get_point_position(const Vector2i &p_id) const {
ERR_FAIL_COND_V_MSG(dirty, Vector2(), "Grid is not initialized. Call the update method.");
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), Vector2(), vformat("Can't get point's position. Point %s out of bounds %s.", p_id, region));
- return GET_POINT_UNCHECKED(p_id).pos;
+ return _get_point_unchecked(p_id)->pos;
}
Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vector2i &p_to_id) {
@@ -542,7 +540,7 @@ Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vec
}
Point *p = end_point;
- int64_t pc = 1;
+ int32_t pc = 1;
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -555,7 +553,7 @@ Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vec
Vector2 *w = path.ptrw();
p = end_point;
- int64_t idx = pc - 1;
+ int32_t idx = pc - 1;
while (p != begin_point) {
w[idx--] = p->pos;
p = p->prev_point;
@@ -590,7 +588,7 @@ TypedArray<Vector2i> AStarGrid2D::get_id_path(const Vector2i &p_from_id, const V
}
Point *p = end_point;
- int64_t pc = 1;
+ int32_t pc = 1;
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -601,7 +599,7 @@ TypedArray<Vector2i> AStarGrid2D::get_id_path(const Vector2i &p_from_id, const V
{
p = end_point;
- int64_t idx = pc - 1;
+ int32_t idx = pc - 1;
while (p != begin_point) {
path[idx--] = p->id;
p = p->prev_point;
@@ -671,5 +669,3 @@ void AStarGrid2D::_bind_methods() {
BIND_ENUM_CONSTANT(DIAGONAL_MODE_ONLY_IF_NO_OBSTACLES);
BIND_ENUM_CONSTANT(DIAGONAL_MODE_MAX);
}
-
-#undef GET_POINT_UNCHECKED
diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h
index ecc9bb01f9..619551b754 100644
--- a/core/math/a_star_grid_2d.h
+++ b/core/math/a_star_grid_2d.h
@@ -105,24 +105,32 @@ private:
uint64_t pass = 1;
private: // Internal routines.
- _FORCE_INLINE_ bool _is_walkable(int64_t p_x, int64_t p_y) const {
+ _FORCE_INLINE_ bool _is_walkable(int32_t p_x, int32_t p_y) const {
if (region.has_point(Vector2i(p_x, p_y))) {
return !points[p_y - region.position.y][p_x - region.position.x].solid;
}
return false;
}
- _FORCE_INLINE_ Point *_get_point(int64_t p_x, int64_t p_y) {
+ _FORCE_INLINE_ Point *_get_point(int32_t p_x, int32_t p_y) {
if (region.has_point(Vector2i(p_x, p_y))) {
return &points[p_y - region.position.y][p_x - region.position.x];
}
return nullptr;
}
- _FORCE_INLINE_ Point *_get_point_unchecked(int64_t p_x, int64_t p_y) {
+ _FORCE_INLINE_ Point *_get_point_unchecked(int32_t p_x, int32_t p_y) {
return &points[p_y - region.position.y][p_x - region.position.x];
}
+ _FORCE_INLINE_ Point *_get_point_unchecked(const Vector2i &p_id) {
+ return &points[p_id.y - region.position.y][p_id.x - region.position.x];
+ }
+
+ _FORCE_INLINE_ const Point *_get_point_unchecked(const Vector2i &p_id) const {
+ return &points[p_id.y - region.position.y][p_id.x - region.position.x];
+ }
+
void _get_nbors(Point *p_point, LocalVector<Point *> &r_nbors);
Point *_jump(Point *p_from, Point *p_to);
bool _solve(Point *p_begin_point, Point *p_end_point);
@@ -151,10 +159,7 @@ public:
void update();
- int get_width() const;
- int get_height() const;
-
- bool is_in_bounds(int p_x, int p_y) const;
+ bool is_in_bounds(int32_t p_x, int32_t p_y) const;
bool is_in_boundsv(const Vector2i &p_id) const;
bool is_dirty() const;
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 38682d6d92..c2e69dc8e2 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -2,7 +2,7 @@ proto = """
#define GDVIRTUAL$VER($RET m_name $ARG) \\
StringName _gdvirtual_##m_name##_sn = #m_name;\\
mutable bool _gdvirtual_##m_name##_initialized = false;\\
-mutable GDExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
+mutable void* _gdvirtual_##m_name = nullptr;\\
template<bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\
@@ -16,15 +16,24 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
} \\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\
+ _gdvirtual_##m_name = nullptr;\\
+ if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\
+ _gdvirtual_##m_name = _get_extension()->get_virtual_call_data(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\
+ } else if (_get_extension()->get_virtual) {\\
+ _gdvirtual_##m_name = (void *)_get_extension()->get_virtual(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\
+ }\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
$CALLPTRARGS\\
$CALLPTRRETDEF\\
- _gdvirtual_##m_name(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\
- $CALLPTRRET\\
+ if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\
+ _get_extension()->call_virtual_with_data(_get_extension_instance(), &_gdvirtual_##m_name##_sn, _gdvirtual_##m_name, $CALLPTRARGPASS,$CALLPTRRETPASS);\\
+ $CALLPTRRET\\
+ } else {\\
+ ((GDExtensionClassCallVirtual)_gdvirtual_##m_name)(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\
+ $CALLPTRRET\\
+ }\\
return true;\\
}\\
\\
@@ -41,8 +50,12 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\
return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\
+ _gdvirtual_##m_name = nullptr;\\
+ if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\
+ _gdvirtual_##m_name = _get_extension()->get_virtual_call_data(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\
+ } else if (_get_extension()->get_virtual) {\\
+ _gdvirtual_##m_name = (void *)_get_extension()->get_virtual(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\
+ }\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
diff --git a/core/object/object.h b/core/object/object.h
index 3a698f7526..7da1c68edf 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -347,6 +347,8 @@ struct ObjectGDExtension {
GDExtensionClassCreateInstance create_instance;
GDExtensionClassFreeInstance free_instance;
GDExtensionClassGetVirtual get_virtual;
+ GDExtensionClassGetVirtualCallData get_virtual_call_data;
+ GDExtensionClassCallVirtualWithData call_virtual_with_data;
};
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index d446c81721..46d9797d6c 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -90,6 +90,10 @@ private:
}
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
+ if (unlikely(p_elements == 0)) {
+ *out = 0;
+ return true;
+ }
#if defined(__GNUC__)
size_t o;
size_t p;
@@ -101,13 +105,12 @@ private:
if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) {
return false; // No longer allocated here.
}
- return true;
#else
// Speed is more important than correctness here, do the operations unchecked
// and hope for the best.
*out = _get_alloc_size(p_elements);
- return true;
#endif
+ return *out;
}
void _unref(void *p_data);