You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-24 15:26:15 +00:00
Merge pull request #106996 from Ivorforce/no-oa-hashmap
Core: Remove `OAHashMap`, in favour of `AHashMap`
This commit is contained in:
@@ -49,10 +49,9 @@ void AStar3D::add_point(int64_t p_id, const Vector3 &p_pos, real_t p_weight_scal
|
|||||||
ERR_FAIL_COND_MSG(p_id < 0, vformat("Can't add a point with negative id: %d.", p_id));
|
ERR_FAIL_COND_MSG(p_id < 0, vformat("Can't add a point with negative id: %d.", p_id));
|
||||||
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't add a point with weight scale less than 0.0: %f.", p_weight_scale));
|
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't add a point with weight scale less than 0.0: %f.", p_weight_scale));
|
||||||
|
|
||||||
Point *found_pt;
|
Point **point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, found_pt);
|
|
||||||
|
|
||||||
if (!p_exists) {
|
if (!point_entry) {
|
||||||
Point *pt = memnew(Point);
|
Point *pt = memnew(Point);
|
||||||
pt->id = p_id;
|
pt->id = p_id;
|
||||||
pt->pos = p_pos;
|
pt->pos = p_pos;
|
||||||
@@ -61,89 +60,86 @@ void AStar3D::add_point(int64_t p_id, const Vector3 &p_pos, real_t p_weight_scal
|
|||||||
pt->open_pass = 0;
|
pt->open_pass = 0;
|
||||||
pt->closed_pass = 0;
|
pt->closed_pass = 0;
|
||||||
pt->enabled = true;
|
pt->enabled = true;
|
||||||
points.set(p_id, pt);
|
points.insert_new(p_id, pt);
|
||||||
} else {
|
} else {
|
||||||
|
Point *found_pt = *point_entry;
|
||||||
found_pt->pos = p_pos;
|
found_pt->pos = p_pos;
|
||||||
found_pt->weight_scale = p_weight_scale;
|
found_pt->weight_scale = p_weight_scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 AStar3D::get_point_position(int64_t p_id) const {
|
Vector3 AStar3D::get_point_position(int64_t p_id) const {
|
||||||
Point *p = nullptr;
|
Point *const *point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_V_MSG(!point_entry, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
|
|
||||||
|
|
||||||
return p->pos;
|
return (*point_entry)->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
|
void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
|
||||||
Point *p = nullptr;
|
Point **point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_MSG(!point_entry, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
|
|
||||||
|
|
||||||
p->pos = p_pos;
|
(*point_entry)->pos = p_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
|
real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
|
||||||
Point *p = nullptr;
|
Point *const *point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_V_MSG(!point_entry, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
|
|
||||||
|
|
||||||
return p->weight_scale;
|
return (*point_entry)->weight_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
|
void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
|
||||||
Point *p = nullptr;
|
Point **point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_MSG(!point_entry, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
|
|
||||||
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));
|
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));
|
||||||
|
|
||||||
p->weight_scale = p_weight_scale;
|
(*point_entry)->weight_scale = p_weight_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::remove_point(int64_t p_id) {
|
void AStar3D::remove_point(int64_t p_id) {
|
||||||
Point *p = nullptr;
|
Point **point_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_MSG(!point_entry, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
|
Point *p = *point_entry;
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) {
|
for (KeyValue<int64_t, Point *> &kv : p->neighbors) {
|
||||||
Segment s(p_id, (*it.key));
|
Segment s(p_id, kv.key);
|
||||||
segments.erase(s);
|
segments.erase(s);
|
||||||
|
|
||||||
(*it.value)->neighbors.remove(p->id);
|
kv.value->neighbors.erase(p->id);
|
||||||
(*it.value)->unlinked_neighbours.remove(p->id);
|
kv.value->unlinked_neighbours.erase(p->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = p->unlinked_neighbours.iter(); it.valid; it = p->unlinked_neighbours.next_iter(it)) {
|
for (KeyValue<int64_t, Point *> &kv : p->unlinked_neighbours) {
|
||||||
Segment s(p_id, (*it.key));
|
Segment s(p_id, kv.key);
|
||||||
segments.erase(s);
|
segments.erase(s);
|
||||||
|
|
||||||
(*it.value)->neighbors.remove(p->id);
|
kv.value->neighbors.erase(p->id);
|
||||||
(*it.value)->unlinked_neighbours.remove(p->id);
|
kv.value->unlinked_neighbours.erase(p->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
memdelete(p);
|
memdelete(p);
|
||||||
points.remove(p_id);
|
points.erase(p_id);
|
||||||
last_free_id = p_id;
|
last_free_id = p_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
|
void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
|
||||||
ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
|
ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
|
||||||
|
|
||||||
Point *a = nullptr;
|
Point **a_entry = points.getptr(p_id);
|
||||||
bool from_exists = points.lookup(p_id, a);
|
ERR_FAIL_COND_MSG(!a_entry, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!from_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id));
|
Point *a = *a_entry;
|
||||||
|
|
||||||
Point *b = nullptr;
|
Point **b_entry = points.getptr(p_with_id);
|
||||||
bool to_exists = points.lookup(p_with_id, b);
|
ERR_FAIL_COND_MSG(!b_entry, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id));
|
||||||
ERR_FAIL_COND_MSG(!to_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id));
|
Point *b = *b_entry;
|
||||||
|
|
||||||
a->neighbors.set(b->id, b);
|
a->neighbors.insert(b->id, b);
|
||||||
|
|
||||||
if (bidirectional) {
|
if (bidirectional) {
|
||||||
b->neighbors.set(a->id, a);
|
b->neighbors.insert(a->id, a);
|
||||||
} else {
|
} else {
|
||||||
b->unlinked_neighbours.set(a->id, a);
|
b->unlinked_neighbours.insert(a->id, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Segment s(p_id, p_with_id);
|
Segment s(p_id, p_with_id);
|
||||||
@@ -156,8 +152,8 @@ void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional
|
|||||||
s.direction |= element->direction;
|
s.direction |= element->direction;
|
||||||
if (s.direction == Segment::BIDIRECTIONAL) {
|
if (s.direction == Segment::BIDIRECTIONAL) {
|
||||||
// Both are neighbors of each other now
|
// Both are neighbors of each other now
|
||||||
a->unlinked_neighbours.remove(b->id);
|
a->unlinked_neighbours.erase(b->id);
|
||||||
b->unlinked_neighbours.remove(a->id);
|
b->unlinked_neighbours.erase(a->id);
|
||||||
}
|
}
|
||||||
segments.remove(element);
|
segments.remove(element);
|
||||||
}
|
}
|
||||||
@@ -166,13 +162,13 @@ void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
|
void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
|
||||||
Point *a = nullptr;
|
Point **a_entry = points.getptr(p_id);
|
||||||
bool a_exists = points.lookup(p_id, a);
|
ERR_FAIL_COND_MSG(!a_entry, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
|
Point *a = *a_entry;
|
||||||
|
|
||||||
Point *b = nullptr;
|
Point **b_entry = points.getptr(p_with_id);
|
||||||
bool b_exists = points.lookup(p_with_id, b);
|
ERR_FAIL_COND_MSG(!b_entry, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id));
|
||||||
ERR_FAIL_COND_MSG(!b_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id));
|
Point *b = *b_entry;
|
||||||
|
|
||||||
Segment s(p_id, p_with_id);
|
Segment s(p_id, p_with_id);
|
||||||
int remove_direction = bidirectional ? (int)Segment::BIDIRECTIONAL : (int)s.direction;
|
int remove_direction = bidirectional ? (int)Segment::BIDIRECTIONAL : (int)s.direction;
|
||||||
@@ -183,18 +179,18 @@ void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectio
|
|||||||
// Erase the directions to be removed
|
// Erase the directions to be removed
|
||||||
s.direction = (element->direction & ~remove_direction);
|
s.direction = (element->direction & ~remove_direction);
|
||||||
|
|
||||||
a->neighbors.remove(b->id);
|
a->neighbors.erase(b->id);
|
||||||
if (bidirectional) {
|
if (bidirectional) {
|
||||||
b->neighbors.remove(a->id);
|
b->neighbors.erase(a->id);
|
||||||
if (element->direction != Segment::BIDIRECTIONAL) {
|
if (element->direction != Segment::BIDIRECTIONAL) {
|
||||||
a->unlinked_neighbours.remove(b->id);
|
a->unlinked_neighbours.erase(b->id);
|
||||||
b->unlinked_neighbours.remove(a->id);
|
b->unlinked_neighbours.erase(a->id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s.direction == Segment::NONE) {
|
if (s.direction == Segment::NONE) {
|
||||||
b->unlinked_neighbours.remove(a->id);
|
b->unlinked_neighbours.erase(a->id);
|
||||||
} else {
|
} else {
|
||||||
a->unlinked_neighbours.set(b->id, b);
|
a->unlinked_neighbours.insert(b->id, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,22 +208,21 @@ bool AStar3D::has_point(int64_t p_id) const {
|
|||||||
PackedInt64Array AStar3D::get_point_ids() {
|
PackedInt64Array AStar3D::get_point_ids() {
|
||||||
PackedInt64Array point_list;
|
PackedInt64Array point_list;
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
|
for (KeyValue<int64_t, Point *> &kv : points) {
|
||||||
point_list.push_back(*(it.key));
|
point_list.push_back(kv.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return point_list;
|
return point_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<int64_t> AStar3D::get_point_connections(int64_t p_id) {
|
Vector<int64_t> AStar3D::get_point_connections(int64_t p_id) {
|
||||||
Point *p = nullptr;
|
Point **p_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_V_MSG(!p_entry, Vector<int64_t>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_V_MSG(!p_exists, Vector<int64_t>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
|
|
||||||
|
|
||||||
Vector<int64_t> point_list;
|
Vector<int64_t> point_list;
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) {
|
for (KeyValue<int64_t, Point *> &kv : (*p_entry)->neighbors) {
|
||||||
point_list.push_back((*it.key));
|
point_list.push_back(kv.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return point_list;
|
return point_list;
|
||||||
@@ -243,15 +238,15 @@ bool AStar3D::are_points_connected(int64_t p_id, int64_t p_with_id, bool bidirec
|
|||||||
|
|
||||||
void AStar3D::clear() {
|
void AStar3D::clear() {
|
||||||
last_free_id = 0;
|
last_free_id = 0;
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
|
for (KeyValue<int64_t, Point *> &kv : points) {
|
||||||
memdelete(*(it.value));
|
memdelete(kv.value);
|
||||||
}
|
}
|
||||||
segments.clear();
|
segments.clear();
|
||||||
points.clear();
|
points.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AStar3D::get_point_count() const {
|
int64_t AStar3D::get_point_count() const {
|
||||||
return points.get_num_elements();
|
return points.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AStar3D::get_point_capacity() const {
|
int64_t AStar3D::get_point_capacity() const {
|
||||||
@@ -267,15 +262,15 @@ int64_t AStar3D::get_closest_point(const Vector3 &p_point, bool p_include_disabl
|
|||||||
int64_t closest_id = -1;
|
int64_t closest_id = -1;
|
||||||
real_t closest_dist = 1e20;
|
real_t closest_dist = 1e20;
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
|
for (const KeyValue<int64_t, Point *> &kv : points) {
|
||||||
if (!p_include_disabled && !(*it.value)->enabled) {
|
if (!p_include_disabled && !kv.value->enabled) {
|
||||||
continue; // Disabled points should not be considered.
|
continue; // Disabled points should not be considered.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the closest point's ID, and in case of multiple closest IDs,
|
// Keep the closest point's ID, and in case of multiple closest IDs,
|
||||||
// the smallest one (makes it deterministic).
|
// the smallest one (makes it deterministic).
|
||||||
real_t d = p_point.distance_squared_to((*it.value)->pos);
|
real_t d = p_point.distance_squared_to(kv.value->pos);
|
||||||
int64_t id = *(it.key);
|
int64_t id = kv.key;
|
||||||
if (d <= closest_dist) {
|
if (d <= closest_dist) {
|
||||||
if (d == closest_dist && id > closest_id) { // Keep lowest ID.
|
if (d == closest_dist && id > closest_id) { // Keep lowest ID.
|
||||||
continue;
|
continue;
|
||||||
@@ -293,9 +288,8 @@ Vector3 AStar3D::get_closest_position_in_segment(const Vector3 &p_point) const {
|
|||||||
Vector3 closest_point;
|
Vector3 closest_point;
|
||||||
|
|
||||||
for (const Segment &E : segments) {
|
for (const Segment &E : segments) {
|
||||||
Point *from_point = nullptr, *to_point = nullptr;
|
const Point *from_point = *points.getptr(E.key.first);
|
||||||
points.lookup(E.key.first, from_point);
|
const Point *to_point = *points.getptr(E.key.second);
|
||||||
points.lookup(E.key.second, to_point);
|
|
||||||
|
|
||||||
if (!(from_point->enabled && to_point->enabled)) {
|
if (!(from_point->enabled && to_point->enabled)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -348,8 +342,8 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_
|
|||||||
open_list.remove_at(open_list.size() - 1);
|
open_list.remove_at(open_list.size() - 1);
|
||||||
p->closed_pass = pass; // Mark the point as closed.
|
p->closed_pass = pass; // Mark the point as closed.
|
||||||
|
|
||||||
for (OAHashMap<int64_t, Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) {
|
for (const KeyValue<int64_t, Point *> &kv : p->neighbors) {
|
||||||
Point *e = *(it.value); // The neighbor point.
|
Point *e = kv.value; // The neighbor point.
|
||||||
|
|
||||||
if (!e->enabled || e->closed_pass == pass) {
|
if (!e->enabled || e->closed_pass == pass) {
|
||||||
continue;
|
continue;
|
||||||
@@ -390,13 +384,13 @@ real_t AStar3D::_estimate_cost(int64_t p_from_id, int64_t p_end_id) {
|
|||||||
return scost;
|
return scost;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point *from_point = nullptr;
|
Point **from_entry = points.getptr(p_from_id);
|
||||||
bool from_exists = points.lookup(p_from_id, from_point);
|
ERR_FAIL_COND_V_MSG(!from_entry, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
|
Point *from_point = *from_entry;
|
||||||
|
|
||||||
Point *end_point = nullptr;
|
Point **end_entry = points.getptr(p_end_id);
|
||||||
bool end_exists = points.lookup(p_end_id, end_point);
|
ERR_FAIL_COND_V_MSG(!end_entry, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_end_id));
|
||||||
ERR_FAIL_COND_V_MSG(!end_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_end_id));
|
Point *end_point = *end_entry;
|
||||||
|
|
||||||
return from_point->pos.distance_to(end_point->pos);
|
return from_point->pos.distance_to(end_point->pos);
|
||||||
}
|
}
|
||||||
@@ -407,25 +401,25 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
|
|||||||
return scost;
|
return scost;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point *from_point = nullptr;
|
Point **from_entry = points.getptr(p_from_id);
|
||||||
bool from_exists = points.lookup(p_from_id, from_point);
|
ERR_FAIL_COND_V_MSG(!from_entry, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
|
Point *from_point = *from_entry;
|
||||||
|
|
||||||
Point *to_point = nullptr;
|
Point **to_entry = points.getptr(p_to_id);
|
||||||
bool to_exists = points.lookup(p_to_id, to_point);
|
ERR_FAIL_COND_V_MSG(!to_entry, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
|
Point *to_point = *to_entry;
|
||||||
|
|
||||||
return from_point->pos.distance_to(to_point->pos);
|
return from_point->pos.distance_to(to_point->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
||||||
Point *a = nullptr;
|
Point **a_entry = points.getptr(p_from_id);
|
||||||
bool from_exists = points.lookup(p_from_id, a);
|
ERR_FAIL_COND_V_MSG(!a_entry, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
|
Point *a = *a_entry;
|
||||||
|
|
||||||
Point *b = nullptr;
|
Point **b_entry = points.getptr(p_to_id);
|
||||||
bool to_exists = points.lookup(p_to_id, b);
|
ERR_FAIL_COND_V_MSG(!b_entry, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
Point *b = *b_entry;
|
||||||
|
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
Vector<Vector3> ret;
|
Vector<Vector3> ret;
|
||||||
@@ -473,13 +467,13 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
||||||
Point *a = nullptr;
|
Point **a_entry = points.getptr(p_from_id);
|
||||||
bool from_exists = points.lookup(p_from_id, a);
|
ERR_FAIL_COND_V_MSG(!a_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
|
Point *a = *a_entry;
|
||||||
|
|
||||||
Point *b = nullptr;
|
Point **b_entry = points.getptr(p_to_id);
|
||||||
bool to_exists = points.lookup(p_to_id, b);
|
ERR_FAIL_COND_V_MSG(!b_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
Point *b = *b_entry;
|
||||||
|
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
Vector<int64_t> ret;
|
Vector<int64_t> ret;
|
||||||
@@ -527,17 +521,17 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
|
void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
|
||||||
Point *p = nullptr;
|
Point **p_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_MSG(!p_entry, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
|
Point *p = *p_entry;
|
||||||
|
|
||||||
p->enabled = !p_disabled;
|
p->enabled = !p_disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AStar3D::is_point_disabled(int64_t p_id) const {
|
bool AStar3D::is_point_disabled(int64_t p_id) const {
|
||||||
Point *p = nullptr;
|
Point *const *p_entry = points.getptr(p_id);
|
||||||
bool p_exists = points.lookup(p_id, p);
|
ERR_FAIL_COND_V_MSG(!p_entry, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
|
||||||
ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
|
Point *p = *p_entry;
|
||||||
|
|
||||||
return !p->enabled;
|
return !p->enabled;
|
||||||
}
|
}
|
||||||
@@ -674,13 +668,13 @@ real_t AStar2D::_estimate_cost(int64_t p_from_id, int64_t p_end_id) {
|
|||||||
return scost;
|
return scost;
|
||||||
}
|
}
|
||||||
|
|
||||||
AStar3D::Point *from_point = nullptr;
|
AStar3D::Point **from_entry = astar.points.getptr(p_from_id);
|
||||||
bool from_exists = astar.points.lookup(p_from_id, from_point);
|
ERR_FAIL_COND_V_MSG(!from_entry, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
|
AStar3D::Point *from_point = *from_entry;
|
||||||
|
|
||||||
AStar3D::Point *end_point = nullptr;
|
AStar3D::Point **end_entry = astar.points.getptr(p_end_id);
|
||||||
bool to_exists = astar.points.lookup(p_end_id, end_point);
|
ERR_FAIL_COND_V_MSG(!end_entry, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_end_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_end_id));
|
AStar3D::Point *end_point = *end_entry;
|
||||||
|
|
||||||
return from_point->pos.distance_to(end_point->pos);
|
return from_point->pos.distance_to(end_point->pos);
|
||||||
}
|
}
|
||||||
@@ -691,25 +685,25 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
|
|||||||
return scost;
|
return scost;
|
||||||
}
|
}
|
||||||
|
|
||||||
AStar3D::Point *from_point = nullptr;
|
AStar3D::Point **from_entry = astar.points.getptr(p_from_id);
|
||||||
bool from_exists = astar.points.lookup(p_from_id, from_point);
|
ERR_FAIL_COND_V_MSG(!from_entry, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
|
AStar3D::Point *from_point = *from_entry;
|
||||||
|
|
||||||
AStar3D::Point *to_point = nullptr;
|
AStar3D::Point **to_entry = astar.points.getptr(p_to_id);
|
||||||
bool to_exists = astar.points.lookup(p_to_id, to_point);
|
ERR_FAIL_COND_V_MSG(!to_entry, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
|
AStar3D::Point *to_point = *to_entry;
|
||||||
|
|
||||||
return from_point->pos.distance_to(to_point->pos);
|
return from_point->pos.distance_to(to_point->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
||||||
AStar3D::Point *a = nullptr;
|
AStar3D::Point **a_entry = astar.points.getptr(p_from_id);
|
||||||
bool from_exists = astar.points.lookup(p_from_id, a);
|
ERR_FAIL_COND_V_MSG(!a_entry, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
|
AStar3D::Point *a = *a_entry;
|
||||||
|
|
||||||
AStar3D::Point *b = nullptr;
|
AStar3D::Point **b_entry = astar.points.getptr(p_to_id);
|
||||||
bool to_exists = astar.points.lookup(p_to_id, b);
|
ERR_FAIL_COND_V_MSG(!b_entry, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
AStar3D::Point *b = *b_entry;
|
||||||
|
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
Vector<Vector2> ret = { Vector2(a->pos.x, a->pos.y) };
|
Vector<Vector2> ret = { Vector2(a->pos.x, a->pos.y) };
|
||||||
@@ -756,13 +750,13 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_allow_partial_path) {
|
||||||
AStar3D::Point *a = nullptr;
|
AStar3D::Point **a_entry = astar.points.getptr(p_from_id);
|
||||||
bool from_exists = astar.points.lookup(p_from_id, a);
|
ERR_FAIL_COND_V_MSG(!a_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
|
||||||
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
|
AStar3D::Point *a = *a_entry;
|
||||||
|
|
||||||
AStar3D::Point *b = nullptr;
|
AStar3D::Point **to_entry = astar.points.getptr(p_to_id);
|
||||||
bool to_exists = astar.points.lookup(p_to_id, b);
|
ERR_FAIL_COND_V_MSG(!to_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
||||||
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
AStar3D::Point *b = *to_entry;
|
||||||
|
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
Vector<int64_t> ret;
|
Vector<int64_t> ret;
|
||||||
@@ -845,8 +839,8 @@ bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, boo
|
|||||||
open_list.remove_at(open_list.size() - 1);
|
open_list.remove_at(open_list.size() - 1);
|
||||||
p->closed_pass = astar.pass; // Mark the point as closed.
|
p->closed_pass = astar.pass; // Mark the point as closed.
|
||||||
|
|
||||||
for (OAHashMap<int64_t, AStar3D::Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) {
|
for (KeyValue<int64_t, AStar3D::Point *> &kv : p->neighbors) {
|
||||||
AStar3D::Point *e = *(it.value); // The neighbor point.
|
AStar3D::Point *e = kv.value; // The neighbor point.
|
||||||
|
|
||||||
if (!e->enabled || e->closed_pass == astar.pass) {
|
if (!e->enabled || e->closed_pass == astar.pass) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "core/object/gdvirtual.gen.inc"
|
#include "core/object/gdvirtual.gen.inc"
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A* pathfinding algorithm.
|
A* pathfinding algorithm.
|
||||||
@@ -50,8 +50,8 @@ class AStar3D : public RefCounted {
|
|||||||
real_t weight_scale = 0;
|
real_t weight_scale = 0;
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
|
||||||
OAHashMap<int64_t, Point *> neighbors = 4u;
|
AHashMap<int64_t, Point *> neighbors = 4u;
|
||||||
OAHashMap<int64_t, Point *> unlinked_neighbours = 4u;
|
AHashMap<int64_t, Point *> unlinked_neighbours = 4u;
|
||||||
|
|
||||||
// Used for pathfinding.
|
// Used for pathfinding.
|
||||||
Point *prev_point = nullptr;
|
Point *prev_point = nullptr;
|
||||||
@@ -110,7 +110,7 @@ class AStar3D : public RefCounted {
|
|||||||
mutable int64_t last_free_id = 0;
|
mutable int64_t last_free_id = 0;
|
||||||
uint64_t pass = 1;
|
uint64_t pass = 1;
|
||||||
|
|
||||||
OAHashMap<int64_t, Point *> points;
|
AHashMap<int64_t, Point *> points;
|
||||||
HashSet<Segment, Segment> segments;
|
HashSet<Segment, Segment> segments;
|
||||||
Point *last_closest_point = nullptr;
|
Point *last_closest_point = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ subject to the following restrictions:
|
|||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/aabb.h"
|
#include "core/math/aabb.h"
|
||||||
#include "core/math/math_defs.h"
|
#include "core/math/math_defs.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/paged_allocator.h"
|
#include "core/templates/paged_allocator.h"
|
||||||
|
|
||||||
//#define DEBUG_CONVEX_HULL
|
//#define DEBUG_CONVEX_HULL
|
||||||
@@ -2267,7 +2267,7 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
|
|||||||
|
|
||||||
// Copy the edges over. There's two "half-edges" for every edge, so we pick only one of them.
|
// Copy the edges over. There's two "half-edges" for every edge, so we pick only one of them.
|
||||||
r_mesh.edges.resize(ch.edges.size() / 2);
|
r_mesh.edges.resize(ch.edges.size() / 2);
|
||||||
OAHashMap<uint64_t, int32_t> edge_map(ch.edges.size() * 4); // The higher the capacity, the faster the insert
|
AHashMap<uint64_t, int32_t> edge_map(ch.edges.size() * 4); // The higher the capacity, the faster the insert
|
||||||
|
|
||||||
uint32_t edges_copied = 0;
|
uint32_t edges_copied = 0;
|
||||||
for (uint32_t i = 0; i < ch.edges.size(); i++) {
|
for (uint32_t i = 0; i < ch.edges.size(); i++) {
|
||||||
@@ -2292,11 +2292,11 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
|
|||||||
uint64_t key = b;
|
uint64_t key = b;
|
||||||
key <<= 32;
|
key <<= 32;
|
||||||
key |= a;
|
key |= a;
|
||||||
int32_t index;
|
int32_t *index_ptr = edge_map.getptr(key);
|
||||||
if (!edge_map.lookup(key, index)) {
|
if (!index_ptr) {
|
||||||
ERR_PRINT("Invalid edge");
|
ERR_PRINT("Invalid edge");
|
||||||
} else {
|
} else {
|
||||||
r_mesh.edges[index].face_b = edge_faces[i];
|
r_mesh.edges[*index_ptr].face_b = edge_faces[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
#include "core/math/aabb.h"
|
#include "core/math/aabb.h"
|
||||||
#include "core/math/projection.h"
|
#include "core/math/projection.h"
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/list.h"
|
#include "core/templates/list.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
#include "thirdparty/misc/r128.h"
|
#include "thirdparty/misc/r128.h"
|
||||||
@@ -260,7 +260,7 @@ public:
|
|||||||
circum_sphere_compute(points, root);
|
circum_sphere_compute(points, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
OAHashMap<Triangle, uint32_t, TriangleHasher> triangles_inserted;
|
AHashMap<Triangle, uint32_t, TriangleHasher> triangles_inserted;
|
||||||
LocalVector<Triangle> triangles;
|
LocalVector<Triangle> triangles;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < point_count; i++) {
|
for (uint32_t i = 0; i < point_count; i++) {
|
||||||
@@ -293,7 +293,7 @@ public:
|
|||||||
|
|
||||||
for (uint32_t k = 0; k < 4; k++) {
|
for (uint32_t k = 0; k < 4; k++) {
|
||||||
Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]);
|
Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]);
|
||||||
uint32_t *p = triangles_inserted.lookup_ptr(t);
|
uint32_t *p = triangles_inserted.getptr(t);
|
||||||
if (p) {
|
if (p) {
|
||||||
// This Delaunay implementation uses the Bowyer-Watson algorithm.
|
// This Delaunay implementation uses the Bowyer-Watson algorithm.
|
||||||
// The rule is that you don't reuse any triangles that were
|
// The rule is that you don't reuse any triangles that were
|
||||||
|
|||||||
@@ -1,402 +0,0 @@
|
|||||||
/**************************************************************************/
|
|
||||||
/* oa_hash_map.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/os/memory.h"
|
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
#include "core/templates/pair.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A HashMap implementation that uses open addressing with Robin Hood hashing.
|
|
||||||
* Robin Hood hashing swaps out entries that have a smaller probing distance
|
|
||||||
* than the to-be-inserted entry, that evens out the average probing distance
|
|
||||||
* and enables faster lookups. Backward shift deletion is employed to further
|
|
||||||
* improve the performance and to avoid infinite loops in rare cases.
|
|
||||||
*
|
|
||||||
* The entries are stored inplace, so huge keys or values might fill cache lines
|
|
||||||
* a lot faster.
|
|
||||||
*
|
|
||||||
* Only used keys and values are constructed. For free positions there's space
|
|
||||||
* in the arrays for each, but that memory is kept uninitialized.
|
|
||||||
*
|
|
||||||
* The assignment operator copy the pairs from one map to the other.
|
|
||||||
*/
|
|
||||||
template <typename TKey, typename TValue,
|
|
||||||
typename Hasher = HashMapHasherDefault,
|
|
||||||
typename Comparator = HashMapComparatorDefault<TKey>>
|
|
||||||
class OAHashMap {
|
|
||||||
private:
|
|
||||||
TValue *values = nullptr;
|
|
||||||
TKey *keys = nullptr;
|
|
||||||
uint32_t *hashes = nullptr;
|
|
||||||
|
|
||||||
uint32_t capacity = 0;
|
|
||||||
|
|
||||||
uint32_t num_elements = 0;
|
|
||||||
|
|
||||||
static const uint32_t EMPTY_HASH = 0;
|
|
||||||
|
|
||||||
_FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const {
|
|
||||||
uint32_t hash = Hasher::hash(p_key);
|
|
||||||
|
|
||||||
if (hash == EMPTY_HASH) {
|
|
||||||
hash = EMPTY_HASH + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) const {
|
|
||||||
uint32_t original_pos = p_hash % capacity;
|
|
||||||
return (p_pos - original_pos + capacity) % capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void _construct(uint32_t p_pos, uint32_t p_hash, const TKey &p_key, const TValue &p_value) {
|
|
||||||
memnew_placement(&keys[p_pos], TKey(p_key));
|
|
||||||
memnew_placement(&values[p_pos], TValue(p_value));
|
|
||||||
hashes[p_pos] = p_hash;
|
|
||||||
|
|
||||||
num_elements++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
|
|
||||||
uint32_t hash = _hash(p_key);
|
|
||||||
uint32_t pos = hash % capacity;
|
|
||||||
uint32_t distance = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (hashes[pos] == EMPTY_HASH) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distance > _get_probe_length(pos, hashes[pos])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashes[pos] == hash && Comparator::compare(keys[pos], p_key)) {
|
|
||||||
r_pos = pos;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = (pos + 1) % capacity;
|
|
||||||
distance++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _insert_with_hash(uint32_t p_hash, const TKey &p_key, const TValue &p_value) {
|
|
||||||
uint32_t hash = p_hash;
|
|
||||||
uint32_t distance = 0;
|
|
||||||
uint32_t pos = hash % capacity;
|
|
||||||
|
|
||||||
TKey key = p_key;
|
|
||||||
TValue value = p_value;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (hashes[pos] == EMPTY_HASH) {
|
|
||||||
_construct(pos, hash, key, value);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not an empty slot, let's check the probing length of the existing one
|
|
||||||
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos]);
|
|
||||||
if (existing_probe_len < distance) {
|
|
||||||
SWAP(hash, hashes[pos]);
|
|
||||||
SWAP(key, keys[pos]);
|
|
||||||
SWAP(value, values[pos]);
|
|
||||||
distance = existing_probe_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = (pos + 1) % capacity;
|
|
||||||
distance++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _resize_and_rehash(uint32_t p_new_capacity) {
|
|
||||||
uint32_t old_capacity = capacity;
|
|
||||||
|
|
||||||
// Capacity can't be 0.
|
|
||||||
capacity = MAX(1u, p_new_capacity);
|
|
||||||
|
|
||||||
TKey *old_keys = keys;
|
|
||||||
TValue *old_values = values;
|
|
||||||
uint32_t *old_hashes = hashes;
|
|
||||||
|
|
||||||
num_elements = 0;
|
|
||||||
keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
|
|
||||||
values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
|
|
||||||
static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
|
|
||||||
hashes = static_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
|
|
||||||
|
|
||||||
if (old_capacity == 0) {
|
|
||||||
// Nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < old_capacity; i++) {
|
|
||||||
if (old_hashes[i] == EMPTY_HASH) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_insert_with_hash(old_hashes[i], old_keys[i], old_values[i]);
|
|
||||||
|
|
||||||
old_keys[i].~TKey();
|
|
||||||
old_values[i].~TValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory::free_static(old_keys);
|
|
||||||
Memory::free_static(old_values);
|
|
||||||
Memory::free_static(old_hashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _resize_and_rehash() {
|
|
||||||
_resize_and_rehash(capacity * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
_FORCE_INLINE_ uint32_t get_capacity() const { return capacity; }
|
|
||||||
_FORCE_INLINE_ uint32_t get_num_elements() const { return num_elements; }
|
|
||||||
|
|
||||||
bool is_empty() const {
|
|
||||||
return num_elements == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
for (uint32_t i = 0; i < capacity; i++) {
|
|
||||||
if (hashes[i] == EMPTY_HASH) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes[i] = EMPTY_HASH;
|
|
||||||
values[i].~TValue();
|
|
||||||
keys[i].~TKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
num_elements = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert(const TKey &p_key, const TValue &p_value) {
|
|
||||||
if (num_elements + 1 > 0.9 * capacity) {
|
|
||||||
_resize_and_rehash();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t hash = _hash(p_key);
|
|
||||||
|
|
||||||
_insert_with_hash(hash, p_key, p_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(const TKey &p_key, const TValue &p_data) {
|
|
||||||
uint32_t pos = 0;
|
|
||||||
bool exists = _lookup_pos(p_key, pos);
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
values[pos] = p_data;
|
|
||||||
} else {
|
|
||||||
insert(p_key, p_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns true if the value was found, false otherwise.
|
|
||||||
*
|
|
||||||
* if r_data is not nullptr then the value will be written to the object
|
|
||||||
* it points to.
|
|
||||||
*/
|
|
||||||
bool lookup(const TKey &p_key, TValue &r_data) const {
|
|
||||||
uint32_t pos = 0;
|
|
||||||
bool exists = _lookup_pos(p_key, pos);
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
r_data = values[pos];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TValue *lookup_ptr(const TKey &p_key) const {
|
|
||||||
uint32_t pos = 0;
|
|
||||||
bool exists = _lookup_pos(p_key, pos);
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
return &values[pos];
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TValue *lookup_ptr(const TKey &p_key) {
|
|
||||||
uint32_t pos = 0;
|
|
||||||
bool exists = _lookup_pos(p_key, pos);
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
return &values[pos];
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool has(const TKey &p_key) const {
|
|
||||||
uint32_t _pos = 0;
|
|
||||||
return _lookup_pos(p_key, _pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(const TKey &p_key) {
|
|
||||||
uint32_t pos = 0;
|
|
||||||
bool exists = _lookup_pos(p_key, pos);
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t next_pos = (pos + 1) % capacity;
|
|
||||||
while (hashes[next_pos] != EMPTY_HASH &&
|
|
||||||
_get_probe_length(next_pos, hashes[next_pos]) != 0) {
|
|
||||||
SWAP(hashes[next_pos], hashes[pos]);
|
|
||||||
SWAP(keys[next_pos], keys[pos]);
|
|
||||||
SWAP(values[next_pos], values[pos]);
|
|
||||||
pos = next_pos;
|
|
||||||
next_pos = (pos + 1) % capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes[pos] = EMPTY_HASH;
|
|
||||||
values[pos].~TValue();
|
|
||||||
keys[pos].~TKey();
|
|
||||||
|
|
||||||
num_elements--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reserves space for a number of elements, useful to avoid many resizes and rehashes
|
|
||||||
* if adding a known (possibly large) number of elements at once, must be larger than old
|
|
||||||
* capacity.
|
|
||||||
**/
|
|
||||||
void reserve(uint32_t p_new_capacity) {
|
|
||||||
ERR_FAIL_COND_MSG(p_new_capacity < get_num_elements(), "reserve() called with a capacity smaller than the current size. This is likely a mistake.");
|
|
||||||
if (p_new_capacity <= capacity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_resize_and_rehash(p_new_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Iterator {
|
|
||||||
bool valid;
|
|
||||||
|
|
||||||
const TKey *key;
|
|
||||||
TValue *value = nullptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t pos;
|
|
||||||
friend class OAHashMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
Iterator iter() const {
|
|
||||||
Iterator it;
|
|
||||||
|
|
||||||
it.valid = true;
|
|
||||||
it.pos = 0;
|
|
||||||
|
|
||||||
return next_iter(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator next_iter(const Iterator &p_iter) const {
|
|
||||||
if (!p_iter.valid) {
|
|
||||||
return p_iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator it;
|
|
||||||
it.valid = false;
|
|
||||||
it.pos = p_iter.pos;
|
|
||||||
it.key = nullptr;
|
|
||||||
it.value = nullptr;
|
|
||||||
|
|
||||||
for (uint32_t i = it.pos; i < capacity; i++) {
|
|
||||||
it.pos = i + 1;
|
|
||||||
|
|
||||||
if (hashes[i] == EMPTY_HASH) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
it.valid = true;
|
|
||||||
it.key = &keys[i];
|
|
||||||
it.value = &values[i];
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
OAHashMap(std::initializer_list<KeyValue<TKey, TValue>> p_init) {
|
|
||||||
reserve(p_init.size());
|
|
||||||
for (const KeyValue<TKey, TValue> &E : p_init) {
|
|
||||||
set(E.key, E.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OAHashMap(const OAHashMap &p_other) {
|
|
||||||
(*this) = p_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const OAHashMap &p_other) {
|
|
||||||
if (capacity != 0) {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
_resize_and_rehash(p_other.capacity);
|
|
||||||
|
|
||||||
for (Iterator it = p_other.iter(); it.valid; it = p_other.next_iter(it)) {
|
|
||||||
set(*it.key, *it.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OAHashMap(uint32_t p_initial_capacity = 64) {
|
|
||||||
// Capacity can't be 0.
|
|
||||||
capacity = MAX(1u, p_initial_capacity);
|
|
||||||
|
|
||||||
keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
|
|
||||||
values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
|
|
||||||
static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
|
|
||||||
hashes = static_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
~OAHashMap() {
|
|
||||||
for (uint32_t i = 0; i < capacity; i++) {
|
|
||||||
if (hashes[i] == EMPTY_HASH) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
values[i].~TValue();
|
|
||||||
keys[i].~TKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory::free_static(keys);
|
|
||||||
Memory::free_static(values);
|
|
||||||
Memory::free_static(hashes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
|
||||||
|
|
||||||
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
|
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
|
||||||
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
|
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
|
||||||
@@ -1264,7 +1264,7 @@ struct VariantBuiltInMethodInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
|
typedef AHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
|
||||||
static BuiltinMethodMap *builtin_method_info;
|
static BuiltinMethodMap *builtin_method_info;
|
||||||
static List<StringName> *builtin_method_names;
|
static List<StringName> *builtin_method_names;
|
||||||
|
|
||||||
@@ -1318,7 +1318,7 @@ void Variant::callp(const StringName &p_method, const Variant **p_args, int p_ar
|
|||||||
} else {
|
} else {
|
||||||
r_error.error = Callable::CallError::CALL_OK;
|
r_error.error = Callable::CallError::CALL_OK;
|
||||||
|
|
||||||
const VariantBuiltInMethodInfo *imf = builtin_method_info[type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *imf = builtin_method_info[type].getptr(p_method);
|
||||||
|
|
||||||
if (!imf) {
|
if (!imf) {
|
||||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
@@ -1350,7 +1350,7 @@ void Variant::call_const(const StringName &p_method, const Variant **p_args, int
|
|||||||
} else {
|
} else {
|
||||||
r_error.error = Callable::CallError::CALL_OK;
|
r_error.error = Callable::CallError::CALL_OK;
|
||||||
|
|
||||||
const VariantBuiltInMethodInfo *imf = builtin_method_info[type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *imf = builtin_method_info[type].getptr(p_method);
|
||||||
|
|
||||||
if (!imf) {
|
if (!imf) {
|
||||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
@@ -1369,7 +1369,7 @@ void Variant::call_const(const StringName &p_method, const Variant **p_args, int
|
|||||||
void Variant::call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
|
void Variant::call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
|
||||||
r_error.error = Callable::CallError::CALL_OK;
|
r_error.error = Callable::CallError::CALL_OK;
|
||||||
|
|
||||||
const VariantBuiltInMethodInfo *imf = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *imf = builtin_method_info[p_type].getptr(p_method);
|
||||||
|
|
||||||
if (!imf) {
|
if (!imf) {
|
||||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
@@ -1404,35 +1404,35 @@ bool Variant::has_builtin_method(Variant::Type p_type, const StringName &p_metho
|
|||||||
|
|
||||||
Variant::ValidatedBuiltInMethod Variant::get_validated_builtin_method(Variant::Type p_type, const StringName &p_method) {
|
Variant::ValidatedBuiltInMethod Variant::get_validated_builtin_method(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, nullptr);
|
ERR_FAIL_NULL_V(method, nullptr);
|
||||||
return method->validated_call;
|
return method->validated_call;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method) {
|
Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, nullptr);
|
ERR_FAIL_NULL_V(method, nullptr);
|
||||||
return method->ptrcall;
|
return method->ptrcall;
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodInfo Variant::get_builtin_method_info(Variant::Type p_type, const StringName &p_method) {
|
MethodInfo Variant::get_builtin_method_info(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, MethodInfo());
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, MethodInfo());
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, MethodInfo());
|
ERR_FAIL_NULL_V(method, MethodInfo());
|
||||||
return method->get_method_info(p_method);
|
return method->get_method_info(p_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) {
|
int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, 0);
|
ERR_FAIL_NULL_V(method, 0);
|
||||||
return method->argument_count;
|
return method->argument_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument) {
|
Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, Variant::NIL);
|
ERR_FAIL_NULL_V(method, Variant::NIL);
|
||||||
ERR_FAIL_INDEX_V(p_argument, method->argument_count, Variant::NIL);
|
ERR_FAIL_INDEX_V(p_argument, method->argument_count, Variant::NIL);
|
||||||
return method->get_argument_type(p_argument);
|
return method->get_argument_type(p_argument);
|
||||||
@@ -1440,7 +1440,7 @@ Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, co
|
|||||||
|
|
||||||
String Variant::get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument) {
|
String Variant::get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String());
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String());
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, String());
|
ERR_FAIL_NULL_V(method, String());
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
ERR_FAIL_INDEX_V(p_argument, method->argument_count, String());
|
ERR_FAIL_INDEX_V(p_argument, method->argument_count, String());
|
||||||
@@ -1452,14 +1452,14 @@ String Variant::get_builtin_method_argument_name(Variant::Type p_type, const Str
|
|||||||
|
|
||||||
Vector<Variant> Variant::get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method) {
|
Vector<Variant> Variant::get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Vector<Variant>());
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Vector<Variant>());
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, Vector<Variant>());
|
ERR_FAIL_NULL_V(method, Vector<Variant>());
|
||||||
return method->default_arguments;
|
return method->default_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method) {
|
bool Variant::has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, false);
|
ERR_FAIL_NULL_V(method, false);
|
||||||
return method->has_return_type;
|
return method->has_return_type;
|
||||||
}
|
}
|
||||||
@@ -1478,35 +1478,35 @@ int Variant::get_builtin_method_count(Variant::Type p_type) {
|
|||||||
|
|
||||||
Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) {
|
Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, Variant::NIL);
|
ERR_FAIL_NULL_V(method, Variant::NIL);
|
||||||
return method->return_type;
|
return method->return_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_method) {
|
bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, false);
|
ERR_FAIL_NULL_V(method, false);
|
||||||
return method->is_const;
|
return method->is_const;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::is_builtin_method_static(Variant::Type p_type, const StringName &p_method) {
|
bool Variant::is_builtin_method_static(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, false);
|
ERR_FAIL_NULL_V(method, false);
|
||||||
return method->is_static;
|
return method->is_static;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) {
|
bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, false);
|
ERR_FAIL_NULL_V(method, false);
|
||||||
return method->is_vararg;
|
return method->is_vararg;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Variant::get_builtin_method_hash(Variant::Type p_type, const StringName &p_method) {
|
uint32_t Variant::get_builtin_method_hash(Variant::Type p_type, const StringName &p_method) {
|
||||||
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
|
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].getptr(p_method);
|
||||||
ERR_FAIL_NULL_V(method, 0);
|
ERR_FAIL_NULL_V(method, 0);
|
||||||
uint32_t hash = hash_murmur3_one_32(method->is_const);
|
uint32_t hash = hash_murmur3_one_32(method->is_const);
|
||||||
hash = hash_murmur3_one_32(method->is_static, hash);
|
hash = hash_murmur3_one_32(method->is_static, hash);
|
||||||
@@ -1531,7 +1531,7 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const StringName &E : builtin_method_names[type]) {
|
for (const StringName &E : builtin_method_names[type]) {
|
||||||
const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E);
|
const VariantBuiltInMethodInfo *method = builtin_method_info[type].getptr(E);
|
||||||
ERR_CONTINUE(!method);
|
ERR_CONTINUE(!method);
|
||||||
p_list->push_back(method->get_method_info(E));
|
p_list->push_back(method->get_method_info(E));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@
|
|||||||
#include "core/io/compression.h"
|
#include "core/io/compression.h"
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct PtrConstruct {};
|
struct PtrConstruct {};
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/rid.h"
|
#include "core/templates/rid.h"
|
||||||
#include "core/templates/rid_owner.h"
|
#include "core/templates/rid_owner.h"
|
||||||
#include "core/variant/binder_common.h"
|
#include "core/variant/binder_common.h"
|
||||||
@@ -1596,7 +1596,7 @@ struct VariantUtilityFunctionInfo {
|
|||||||
Variant::UtilityFunctionType type;
|
Variant::UtilityFunctionType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
static OAHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table;
|
static AHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table;
|
||||||
static List<StringName> utility_function_name_table;
|
static List<StringName> utility_function_name_table;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -1788,7 +1788,7 @@ void Variant::_unregister_variant_utility_functions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
r_error.argument = 0;
|
r_error.argument = 0;
|
||||||
@@ -1816,7 +1816,7 @@ bool Variant::has_utility_function(const StringName &p_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant::ValidatedUtilityFunction Variant::get_validated_utility_function(const StringName &p_name) {
|
Variant::ValidatedUtilityFunction Variant::get_validated_utility_function(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1825,7 +1825,7 @@ Variant::ValidatedUtilityFunction Variant::get_validated_utility_function(const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant::PTRUtilityFunction Variant::get_ptr_utility_function(const StringName &p_name) {
|
Variant::PTRUtilityFunction Variant::get_ptr_utility_function(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1834,7 +1834,7 @@ Variant::PTRUtilityFunction Variant::get_ptr_utility_function(const StringName &
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName &p_name) {
|
Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return Variant::UTILITY_FUNC_TYPE_MATH;
|
return Variant::UTILITY_FUNC_TYPE_MATH;
|
||||||
}
|
}
|
||||||
@@ -1844,7 +1844,7 @@ Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName
|
|||||||
|
|
||||||
MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
|
MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
|
||||||
MethodInfo info;
|
MethodInfo info;
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (bfi) {
|
if (bfi) {
|
||||||
info.name = p_name;
|
info.name = p_name;
|
||||||
if (bfi->returns_value && bfi->return_type == Variant::NIL) {
|
if (bfi->returns_value && bfi->return_type == Variant::NIL) {
|
||||||
@@ -1865,7 +1865,7 @@ MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Variant::get_utility_function_argument_count(const StringName &p_name) {
|
int Variant::get_utility_function_argument_count(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1874,7 +1874,7 @@ int Variant::get_utility_function_argument_count(const StringName &p_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant::Type Variant::get_utility_function_argument_type(const StringName &p_name, int p_arg) {
|
Variant::Type Variant::get_utility_function_argument_type(const StringName &p_name, int p_arg) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return Variant::NIL;
|
return Variant::NIL;
|
||||||
}
|
}
|
||||||
@@ -1883,7 +1883,7 @@ Variant::Type Variant::get_utility_function_argument_type(const StringName &p_na
|
|||||||
}
|
}
|
||||||
|
|
||||||
String Variant::get_utility_function_argument_name(const StringName &p_name, int p_arg) {
|
String Variant::get_utility_function_argument_name(const StringName &p_name, int p_arg) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
@@ -1893,7 +1893,7 @@ String Variant::get_utility_function_argument_name(const StringName &p_name, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::has_utility_function_return_value(const StringName &p_name) {
|
bool Variant::has_utility_function_return_value(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1901,7 +1901,7 @@ bool Variant::has_utility_function_return_value(const StringName &p_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant::Type Variant::get_utility_function_return_type(const StringName &p_name) {
|
Variant::Type Variant::get_utility_function_return_type(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return Variant::NIL;
|
return Variant::NIL;
|
||||||
}
|
}
|
||||||
@@ -1910,7 +1910,7 @@ Variant::Type Variant::get_utility_function_return_type(const StringName &p_name
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::is_utility_function_vararg(const StringName &p_name) {
|
bool Variant::is_utility_function_vararg(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
if (!bfi) {
|
if (!bfi) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1919,7 +1919,7 @@ bool Variant::is_utility_function_vararg(const StringName &p_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
|
uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
|
||||||
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
|
const VariantUtilityFunctionInfo *bfi = utility_function_table.getptr(p_name);
|
||||||
ERR_FAIL_NULL_V(bfi, 0);
|
ERR_FAIL_NULL_V(bfi, 0);
|
||||||
|
|
||||||
uint32_t hash = hash_murmur3_one_32(bfi->is_vararg);
|
uint32_t hash = hash_murmur3_one_32(bfi->is_vararg);
|
||||||
|
|||||||
@@ -570,10 +570,10 @@ bool ShaderGLES3::_load_from_cache(Version *p_version) {
|
|||||||
int cache_variant_count = static_cast<int>(f->get_32());
|
int cache_variant_count = static_cast<int>(f->get_32());
|
||||||
ERR_FAIL_COND_V_MSG(cache_variant_count != variant_count, false, "shader cache variant count mismatch, expected " + itos(variant_count) + " got " + itos(cache_variant_count)); //should not happen but check
|
ERR_FAIL_COND_V_MSG(cache_variant_count != variant_count, false, "shader cache variant count mismatch, expected " + itos(variant_count) + " got " + itos(cache_variant_count)); //should not happen but check
|
||||||
|
|
||||||
LocalVector<OAHashMap<uint64_t, Version::Specialization>> variants;
|
LocalVector<AHashMap<uint64_t, Version::Specialization>> variants;
|
||||||
for (int i = 0; i < cache_variant_count; i++) {
|
for (int i = 0; i < cache_variant_count; i++) {
|
||||||
uint32_t cache_specialization_count = f->get_32();
|
uint32_t cache_specialization_count = f->get_32();
|
||||||
OAHashMap<uint64_t, Version::Specialization> variant;
|
AHashMap<uint64_t, Version::Specialization> variant;
|
||||||
for (uint32_t j = 0; j < cache_specialization_count; j++) {
|
for (uint32_t j = 0; j < cache_specialization_count; j++) {
|
||||||
uint64_t specialization_key = f->get_64();
|
uint64_t specialization_key = f->get_64();
|
||||||
uint32_t variant_size = f->get_32();
|
uint32_t variant_size = f->get_32();
|
||||||
@@ -648,18 +648,14 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
|
|||||||
f->store_32(variant_count);
|
f->store_32(variant_count);
|
||||||
|
|
||||||
for (int i = 0; i < variant_count; i++) {
|
for (int i = 0; i < variant_count; i++) {
|
||||||
int cache_specialization_count = p_version->variants[i].get_num_elements();
|
int cache_specialization_count = p_version->variants[i].size();
|
||||||
f->store_32(cache_specialization_count);
|
f->store_32(cache_specialization_count);
|
||||||
|
|
||||||
for (OAHashMap<uint64_t, ShaderGLES3::Version::Specialization>::Iterator it = p_version->variants[i].iter(); it.valid; it = p_version->variants[i].next_iter(it)) {
|
for (KeyValue<uint64_t, ShaderGLES3::Version::Specialization> &kv : p_version->variants[i]) {
|
||||||
const uint64_t specialization_key = *it.key;
|
const uint64_t specialization_key = kv.key;
|
||||||
f->store_64(specialization_key);
|
f->store_64(specialization_key);
|
||||||
|
|
||||||
const Version::Specialization *specialization = it.value;
|
const Version::Specialization *specialization = &kv.value;
|
||||||
if (specialization == nullptr) {
|
|
||||||
f->store_32(0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
GLint program_size = 0;
|
GLint program_size = 0;
|
||||||
glGetProgramiv(specialization->id, GL_PROGRAM_BINARY_LENGTH, &program_size);
|
glGetProgramiv(specialization->id, GL_PROGRAM_BINARY_LENGTH, &program_size);
|
||||||
if (program_size == 0) {
|
if (program_size == 0) {
|
||||||
@@ -689,11 +685,11 @@ void ShaderGLES3::_clear_version(Version *p_version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < variant_count; i++) {
|
for (int i = 0; i < variant_count; i++) {
|
||||||
for (OAHashMap<uint64_t, Version::Specialization>::Iterator it = p_version->variants[i].iter(); it.valid; it = p_version->variants[i].next_iter(it)) {
|
for (KeyValue<uint64_t, Version::Specialization> &kv : p_version->variants[i]) {
|
||||||
if (it.value->id != 0) {
|
if (kv.value.id != 0) {
|
||||||
glDeleteShader(it.value->vert_id);
|
glDeleteShader(kv.value.vert_id);
|
||||||
glDeleteShader(it.value->frag_id);
|
glDeleteShader(kv.value.frag_id);
|
||||||
glDeleteProgram(it.value->id);
|
glDeleteProgram(kv.value.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -709,7 +705,7 @@ void ShaderGLES3::_initialize_version(Version *p_version) {
|
|||||||
}
|
}
|
||||||
p_version->variants.reserve(variant_count);
|
p_version->variants.reserve(variant_count);
|
||||||
for (int i = 0; i < variant_count; i++) {
|
for (int i = 0; i < variant_count; i++) {
|
||||||
OAHashMap<uint64_t, Version::Specialization> variant;
|
AHashMap<uint64_t, Version::Specialization> variant;
|
||||||
p_version->variants.push_back(variant);
|
p_version->variants.push_back(variant);
|
||||||
Version::Specialization spec;
|
Version::Specialization spec;
|
||||||
_compile_specialization(spec, i, p_version, specialization_default_mask);
|
_compile_specialization(spec, i, p_version, specialization_default_mask);
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LocalVector<OAHashMap<uint64_t, Specialization>> variants;
|
LocalVector<AHashMap<uint64_t, Specialization>> variants;
|
||||||
};
|
};
|
||||||
|
|
||||||
Mutex variant_set_mutex;
|
Mutex variant_set_mutex;
|
||||||
@@ -192,25 +192,25 @@ protected:
|
|||||||
_initialize_version(version); //may lack initialization
|
_initialize_version(version); //may lack initialization
|
||||||
}
|
}
|
||||||
|
|
||||||
Version::Specialization *spec = version->variants[p_variant].lookup_ptr(p_specialization);
|
Version::Specialization *spec = version->variants[p_variant].getptr(p_specialization);
|
||||||
if (!spec) {
|
if (!spec) {
|
||||||
if (false) {
|
if (false) {
|
||||||
// Queue load this specialization and use defaults in the meantime (TODO)
|
// Queue load this specialization and use defaults in the meantime (TODO)
|
||||||
|
|
||||||
spec = version->variants[p_variant].lookup_ptr(specialization_default_mask);
|
spec = version->variants[p_variant].getptr(specialization_default_mask);
|
||||||
} else {
|
} else {
|
||||||
// Compile on the spot
|
// Compile on the spot
|
||||||
Version::Specialization s;
|
Version::Specialization s;
|
||||||
_compile_specialization(s, p_variant, version, p_specialization);
|
_compile_specialization(s, p_variant, version, p_specialization);
|
||||||
version->variants[p_variant].insert(p_specialization, s);
|
version->variants[p_variant].insert(p_specialization, s);
|
||||||
spec = version->variants[p_variant].lookup_ptr(p_specialization);
|
spec = version->variants[p_variant].getptr(p_specialization);
|
||||||
if (shader_cache_dir_valid) {
|
if (shader_cache_dir_valid) {
|
||||||
_save_to_cache(version);
|
_save_to_cache(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (spec->build_queued) {
|
} else if (spec->build_queued) {
|
||||||
// Still queued, wait
|
// Still queued, wait
|
||||||
spec = version->variants[p_variant].lookup_ptr(specialization_default_mask);
|
spec = version->variants[p_variant].getptr(specialization_default_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spec || !spec->ok) {
|
if (!spec || !spec->ok) {
|
||||||
@@ -228,7 +228,7 @@ protected:
|
|||||||
Version *version = version_owner.get_or_null(p_version);
|
Version *version = version_owner.get_or_null(p_version);
|
||||||
ERR_FAIL_NULL_V(version, -1);
|
ERR_FAIL_NULL_V(version, -1);
|
||||||
ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1);
|
ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1);
|
||||||
Version::Specialization *spec = version->variants[p_variant].lookup_ptr(p_specialization);
|
Version::Specialization *spec = version->variants[p_variant].getptr(p_specialization);
|
||||||
ERR_FAIL_NULL_V(spec, -1);
|
ERR_FAIL_NULL_V(spec, -1);
|
||||||
ERR_FAIL_INDEX_V(p_which, int(spec->uniform_location.size()), -1);
|
ERR_FAIL_INDEX_V(p_which, int(spec->uniform_location.size()), -1);
|
||||||
return spec->uniform_location[p_which];
|
return spec->uniform_location[p_which];
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ void QuickOpenResultContainer::set_query_and_update(const String &p_query) {
|
|||||||
|
|
||||||
Vector<QuickOpenResultCandidate> *QuickOpenResultContainer::_get_history() {
|
Vector<QuickOpenResultCandidate> *QuickOpenResultContainer::_get_history() {
|
||||||
if (base_types.size() == 1) {
|
if (base_types.size() == 1) {
|
||||||
return selected_history.lookup_ptr(base_types[0]);
|
return selected_history.getptr(base_types[0]);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_cand
|
|||||||
p_candidate.result = nullptr;
|
p_candidate.result = nullptr;
|
||||||
StringName actual_type;
|
StringName actual_type;
|
||||||
{
|
{
|
||||||
StringName *actual_type_ptr = filetypes.lookup_ptr(p_filepath);
|
StringName *actual_type_ptr = filetypes.getptr(p_filepath);
|
||||||
if (actual_type_ptr) {
|
if (actual_type_ptr) {
|
||||||
actual_type = *actual_type_ptr;
|
actual_type = *actual_type_ptr;
|
||||||
} else {
|
} else {
|
||||||
@@ -496,12 +496,12 @@ void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_cand
|
|||||||
if (item.preview.is_valid()) {
|
if (item.preview.is_valid()) {
|
||||||
p_candidate.thumbnail = item.preview;
|
p_candidate.thumbnail = item.preview;
|
||||||
} else if (file_type_icons.has(actual_type)) {
|
} else if (file_type_icons.has(actual_type)) {
|
||||||
p_candidate.thumbnail = *file_type_icons.lookup_ptr(actual_type);
|
p_candidate.thumbnail = *file_type_icons.getptr(actual_type);
|
||||||
} else if (has_theme_icon(actual_type, EditorStringName(EditorIcons))) {
|
} else if (has_theme_icon(actual_type, EditorStringName(EditorIcons))) {
|
||||||
p_candidate.thumbnail = get_editor_theme_icon(actual_type);
|
p_candidate.thumbnail = get_editor_theme_icon(actual_type);
|
||||||
file_type_icons.insert(actual_type, p_candidate.thumbnail);
|
file_type_icons.insert(actual_type, p_candidate.thumbnail);
|
||||||
} else {
|
} else {
|
||||||
p_candidate.thumbnail = *file_type_icons.lookup_ptr(SNAME("__default_icon"));
|
p_candidate.thumbnail = *file_type_icons.getptr(SNAME("__default_icon"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,11 +820,11 @@ void QuickOpenResultContainer::save_selected_item() {
|
|||||||
|
|
||||||
const StringName &base_type = base_types[0];
|
const StringName &base_type = base_types[0];
|
||||||
QuickOpenResultCandidate &selected = candidates.write[selection_index];
|
QuickOpenResultCandidate &selected = candidates.write[selection_index];
|
||||||
Vector<QuickOpenResultCandidate> *type_history = selected_history.lookup_ptr(base_type);
|
Vector<QuickOpenResultCandidate> *type_history = selected_history.getptr(base_type);
|
||||||
|
|
||||||
if (!type_history) {
|
if (!type_history) {
|
||||||
selected_history.insert(base_type, Vector<QuickOpenResultCandidate>());
|
selected_history.insert(base_type, Vector<QuickOpenResultCandidate>());
|
||||||
type_history = selected_history.lookup_ptr(base_type);
|
type_history = selected_history.getptr(base_type);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < type_history->size(); i++) {
|
for (int i = 0; i < type_history->size(); i++) {
|
||||||
if (selected.file_path == type_history->get(i).file_path) {
|
if (selected.file_path == type_history->get(i).file_path) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/templates/oa_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "scene/gui/dialogs.h"
|
#include "scene/gui/dialogs.h"
|
||||||
#include "scene/gui/margin_container.h"
|
#include "scene/gui/margin_container.h"
|
||||||
|
|
||||||
@@ -111,10 +111,10 @@ private:
|
|||||||
Vector<FuzzySearchResult> search_results;
|
Vector<FuzzySearchResult> search_results;
|
||||||
Vector<StringName> base_types;
|
Vector<StringName> base_types;
|
||||||
Vector<String> filepaths;
|
Vector<String> filepaths;
|
||||||
OAHashMap<String, StringName> filetypes;
|
AHashMap<String, StringName> filetypes;
|
||||||
Vector<QuickOpenResultCandidate> candidates;
|
Vector<QuickOpenResultCandidate> candidates;
|
||||||
|
|
||||||
OAHashMap<StringName, Vector<QuickOpenResultCandidate>> selected_history;
|
AHashMap<StringName, Vector<QuickOpenResultCandidate>> selected_history;
|
||||||
HashSet<String> history_set;
|
HashSet<String> history_set;
|
||||||
|
|
||||||
String query;
|
String query;
|
||||||
@@ -142,7 +142,7 @@ private:
|
|||||||
CheckButton *include_addons_toggle = nullptr;
|
CheckButton *include_addons_toggle = nullptr;
|
||||||
CheckButton *fuzzy_search_toggle = nullptr;
|
CheckButton *fuzzy_search_toggle = nullptr;
|
||||||
|
|
||||||
OAHashMap<StringName, Ref<Texture2D>> file_type_icons;
|
AHashMap<StringName, Ref<Texture2D>> file_type_icons;
|
||||||
|
|
||||||
static QuickOpenDisplayMode get_adaptive_display_mode(const Vector<StringName> &p_base_types);
|
static QuickOpenDisplayMode get_adaptive_display_mode(const Vector<StringName> &p_base_types);
|
||||||
|
|
||||||
|
|||||||
@@ -576,7 +576,7 @@ void CSGShape3D::update_shape() {
|
|||||||
CSGBrush *n = _get_brush();
|
CSGBrush *n = _get_brush();
|
||||||
ERR_FAIL_NULL_MSG(n, "Cannot get CSGBrush.");
|
ERR_FAIL_NULL_MSG(n, "Cannot get CSGBrush.");
|
||||||
|
|
||||||
OAHashMap<Vector3, Vector3> vec_map;
|
AHashMap<Vector3, Vector3> vec_map;
|
||||||
|
|
||||||
Vector<int> face_count;
|
Vector<int> face_count;
|
||||||
face_count.resize(n->materials.size() + 1);
|
face_count.resize(n->materials.size() + 1);
|
||||||
@@ -594,13 +594,12 @@ void CSGShape3D::update_shape() {
|
|||||||
|
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
Vector3 v = n->faces[i].vertices[j];
|
Vector3 v = n->faces[i].vertices[j];
|
||||||
Vector3 add;
|
Vector3 *vec = vec_map.getptr(v);
|
||||||
if (vec_map.lookup(v, add)) {
|
if (vec) {
|
||||||
add += p.normal;
|
*vec += p.normal;
|
||||||
} else {
|
} else {
|
||||||
add = p.normal;
|
vec_map.insert(v, p.normal);
|
||||||
}
|
}
|
||||||
vec_map.set(v, add);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,8 +654,11 @@ void CSGShape3D::update_shape() {
|
|||||||
|
|
||||||
Vector3 normal = p.normal;
|
Vector3 normal = p.normal;
|
||||||
|
|
||||||
if (n->faces[i].smooth && vec_map.lookup(v, normal)) {
|
if (n->faces[i].smooth) {
|
||||||
normal.normalize();
|
Vector3 *ptr = vec_map.getptr(v);
|
||||||
|
if (ptr) {
|
||||||
|
normal = ptr->normalized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->faces[i].invert) {
|
if (n->faces[i].invert) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/object/object.h"
|
#include "core/object/object.h"
|
||||||
#include "core/templates/oa_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
#include "core/variant/typed_array.h"
|
#include "core/variant/typed_array.h"
|
||||||
|
|
||||||
@@ -514,7 +514,7 @@ struct GDScriptUtilityFunctionInfo {
|
|||||||
bool is_constant = false;
|
bool is_constant = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static OAHashMap<StringName, GDScriptUtilityFunctionInfo> utility_function_table;
|
static AHashMap<StringName, GDScriptUtilityFunctionInfo> utility_function_table;
|
||||||
static List<StringName> utility_function_name_table;
|
static List<StringName> utility_function_name_table;
|
||||||
|
|
||||||
static void _register_function(const StringName &p_name, const MethodInfo &p_method_info, GDScriptUtilityFunctions::FunctionPtr p_function, bool p_is_const) {
|
static void _register_function(const StringName &p_name, const MethodInfo &p_method_info, GDScriptUtilityFunctions::FunctionPtr p_function, bool p_is_const) {
|
||||||
@@ -598,50 +598,50 @@ void GDScriptUtilityFunctions::unregister_functions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GDScriptUtilityFunctions::FunctionPtr GDScriptUtilityFunctions::get_function(const StringName &p_function) {
|
GDScriptUtilityFunctions::FunctionPtr GDScriptUtilityFunctions::get_function(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, nullptr);
|
ERR_FAIL_NULL_V(info, nullptr);
|
||||||
return info->function;
|
return info->function;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDScriptUtilityFunctions::has_function_return_value(const StringName &p_function) {
|
bool GDScriptUtilityFunctions::has_function_return_value(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, false);
|
ERR_FAIL_NULL_V(info, false);
|
||||||
return info->info.return_val.type != Variant::NIL || bool(info->info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
|
return info->info.return_val.type != Variant::NIL || bool(info->info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::Type GDScriptUtilityFunctions::get_function_return_type(const StringName &p_function) {
|
Variant::Type GDScriptUtilityFunctions::get_function_return_type(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, Variant::NIL);
|
ERR_FAIL_NULL_V(info, Variant::NIL);
|
||||||
return info->info.return_val.type;
|
return info->info.return_val.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringName GDScriptUtilityFunctions::get_function_return_class(const StringName &p_function) {
|
StringName GDScriptUtilityFunctions::get_function_return_class(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, StringName());
|
ERR_FAIL_NULL_V(info, StringName());
|
||||||
return info->info.return_val.class_name;
|
return info->info.return_val.class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringName &p_function, int p_arg) {
|
Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringName &p_function, int p_arg) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, Variant::NIL);
|
ERR_FAIL_NULL_V(info, Variant::NIL);
|
||||||
ERR_FAIL_INDEX_V(p_arg, info->info.arguments.size(), Variant::NIL);
|
ERR_FAIL_INDEX_V(p_arg, info->info.arguments.size(), Variant::NIL);
|
||||||
return info->info.arguments[p_arg].type;
|
return info->info.arguments[p_arg].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) {
|
int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, 0);
|
ERR_FAIL_NULL_V(info, 0);
|
||||||
return info->info.arguments.size();
|
return info->info.arguments.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDScriptUtilityFunctions::is_function_vararg(const StringName &p_function) {
|
bool GDScriptUtilityFunctions::is_function_vararg(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, false);
|
ERR_FAIL_NULL_V(info, false);
|
||||||
return (bool)(info->info.flags & METHOD_FLAG_VARARG);
|
return (bool)(info->info.flags & METHOD_FLAG_VARARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDScriptUtilityFunctions::is_function_constant(const StringName &p_function) {
|
bool GDScriptUtilityFunctions::is_function_constant(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, false);
|
ERR_FAIL_NULL_V(info, false);
|
||||||
return info->is_constant;
|
return info->is_constant;
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ void GDScriptUtilityFunctions::get_function_list(List<StringName> *r_functions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MethodInfo GDScriptUtilityFunctions::get_function_info(const StringName &p_function) {
|
MethodInfo GDScriptUtilityFunctions::get_function_info(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.getptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, MethodInfo());
|
ERR_FAIL_NULL_V(info, MethodInfo());
|
||||||
return info->info;
|
return info->info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
/**************************************************************************/
|
|
||||||
/* test_oa_hash_map.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/templates/oa_hash_map.h"
|
|
||||||
#include "scene/resources/texture.h"
|
|
||||||
|
|
||||||
#include "tests/test_macros.h"
|
|
||||||
|
|
||||||
namespace TestOAHashMap {
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] List initialization") {
|
|
||||||
OAHashMap<int, String> map{ { 0, "A" }, { 1, "B" }, { 2, "C" }, { 3, "D" }, { 4, "E" } };
|
|
||||||
|
|
||||||
CHECK(map.get_num_elements() == 5);
|
|
||||||
String value;
|
|
||||||
CHECK(map.lookup(0, value));
|
|
||||||
CHECK(value == "A");
|
|
||||||
CHECK(map.lookup(1, value));
|
|
||||||
CHECK(value == "B");
|
|
||||||
CHECK(map.lookup(2, value));
|
|
||||||
CHECK(value == "C");
|
|
||||||
CHECK(map.lookup(3, value));
|
|
||||||
CHECK(value == "D");
|
|
||||||
CHECK(map.lookup(4, value));
|
|
||||||
CHECK(value == "E");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] List initialization with existing elements") {
|
|
||||||
OAHashMap<int, String> map{ { 0, "A" }, { 0, "B" }, { 0, "C" }, { 0, "D" }, { 0, "E" } };
|
|
||||||
|
|
||||||
CHECK(map.get_num_elements() == 1);
|
|
||||||
String value;
|
|
||||||
CHECK(map.lookup(0, value));
|
|
||||||
CHECK(value == "E");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Insert element") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.insert(42, 84);
|
|
||||||
int data = 0;
|
|
||||||
bool lookup_res = map.lookup(42, data);
|
|
||||||
int value = *map.lookup_ptr(42);
|
|
||||||
CHECK(lookup_res);
|
|
||||||
CHECK(value == 84);
|
|
||||||
CHECK(data == 84);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Set element") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.set(42, 84);
|
|
||||||
int data = 0;
|
|
||||||
bool lookup_res = map.lookup(42, data);
|
|
||||||
int value = *map.lookup_ptr(42);
|
|
||||||
CHECK(lookup_res);
|
|
||||||
CHECK(value == 84);
|
|
||||||
CHECK(data == 84);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Overwrite element") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.set(42, 84);
|
|
||||||
map.set(42, 1234);
|
|
||||||
int result = *map.lookup_ptr(42);
|
|
||||||
CHECK(result == 1234);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Remove element") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.insert(42, 84);
|
|
||||||
map.remove(42);
|
|
||||||
CHECK(!map.has(42));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Get Num_Elements") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.set(42, 84);
|
|
||||||
map.set(123, 84);
|
|
||||||
map.set(123, 84);
|
|
||||||
map.set(0, 84);
|
|
||||||
map.set(123485, 84);
|
|
||||||
|
|
||||||
CHECK(map.get_num_elements() == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Iteration") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.insert(42, 84);
|
|
||||||
map.insert(123, 12385);
|
|
||||||
map.insert(0, 12934);
|
|
||||||
map.insert(123485, 1238888);
|
|
||||||
map.set(123, 111111);
|
|
||||||
|
|
||||||
Vector<Pair<int, int>> expected;
|
|
||||||
expected.push_back(Pair<int, int>(42, 84));
|
|
||||||
expected.push_back(Pair<int, int>(123, 111111));
|
|
||||||
expected.push_back(Pair<int, int>(0, 12934));
|
|
||||||
expected.push_back(Pair<int, int>(123485, 1238888));
|
|
||||||
|
|
||||||
for (OAHashMap<int, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) {
|
|
||||||
int64_t result = expected.find(Pair<int, int>(*it.key, *it.value));
|
|
||||||
CHECK(result >= 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Insert, iterate, remove many strings") {
|
|
||||||
uint64_t pre_mem = Memory::get_mem_usage();
|
|
||||||
{
|
|
||||||
const int elem_max = 40;
|
|
||||||
OAHashMap<String, int> map;
|
|
||||||
for (int i = 0; i < elem_max; i++) {
|
|
||||||
map.insert(itos(i), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<String> elems_still_valid;
|
|
||||||
|
|
||||||
for (int i = 0; i < elem_max; i++) {
|
|
||||||
if ((i % 5) == 0) {
|
|
||||||
map.remove(itos(i));
|
|
||||||
} else {
|
|
||||||
elems_still_valid.push_back(itos(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(elems_still_valid.size() == map.get_num_elements());
|
|
||||||
|
|
||||||
for (int i = 0; i < elems_still_valid.size(); i++) {
|
|
||||||
CHECK(map.has(elems_still_valid[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(Memory::get_mem_usage() == pre_mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Clear") {
|
|
||||||
OAHashMap<int, int> map;
|
|
||||||
map.insert(42, 84);
|
|
||||||
map.insert(0, 1234);
|
|
||||||
map.clear();
|
|
||||||
CHECK(!map.has(42));
|
|
||||||
CHECK(!map.has(0));
|
|
||||||
CHECK(map.is_empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Copy constructor") {
|
|
||||||
uint64_t pre_mem = Memory::get_mem_usage();
|
|
||||||
{
|
|
||||||
OAHashMap<int, int> map0;
|
|
||||||
const uint32_t count = 5;
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
map0.insert(i, i);
|
|
||||||
}
|
|
||||||
OAHashMap<int, int> map1(map0);
|
|
||||||
CHECK(map0.get_num_elements() == map1.get_num_elements());
|
|
||||||
CHECK(map0.get_capacity() == map1.get_capacity());
|
|
||||||
CHECK(*map0.lookup_ptr(0) == *map1.lookup_ptr(0));
|
|
||||||
}
|
|
||||||
CHECK(Memory::get_mem_usage() == pre_mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Operator =") {
|
|
||||||
uint64_t pre_mem = Memory::get_mem_usage();
|
|
||||||
{
|
|
||||||
OAHashMap<int, int> map0;
|
|
||||||
OAHashMap<int, int> map1;
|
|
||||||
const uint32_t count = 5;
|
|
||||||
map1.insert(1234, 1234);
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
map0.insert(i, i);
|
|
||||||
}
|
|
||||||
map1 = map0;
|
|
||||||
CHECK(map0.get_num_elements() == map1.get_num_elements());
|
|
||||||
CHECK(map0.get_capacity() == map1.get_capacity());
|
|
||||||
CHECK(*map0.lookup_ptr(0) == *map1.lookup_ptr(0));
|
|
||||||
}
|
|
||||||
CHECK(Memory::get_mem_usage() == pre_mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("[OAHashMap] Non-trivial types") {
|
|
||||||
uint64_t pre_mem = Memory::get_mem_usage();
|
|
||||||
{
|
|
||||||
OAHashMap<String, Ref<Texture2D>> map1;
|
|
||||||
const uint32_t count = 10;
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
String string = "qwerty";
|
|
||||||
string += itos(i);
|
|
||||||
Ref<Texture2D> ref_texture_2d;
|
|
||||||
|
|
||||||
map1.set(string, ref_texture_2d);
|
|
||||||
Ref<Texture2D> map_vec = *map1.lookup_ptr(string);
|
|
||||||
CHECK(map_vec == ref_texture_2d);
|
|
||||||
}
|
|
||||||
OAHashMap<String, Ref<Texture2D>> map1copy(map1);
|
|
||||||
CHECK(map1copy.has(String("qwerty0")));
|
|
||||||
map1copy = map1;
|
|
||||||
CHECK(map1copy.has(String("qwerty2")));
|
|
||||||
|
|
||||||
OAHashMap<int64_t, Vector4 *> map2;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
Vector4 *vec = memnew(Vector4);
|
|
||||||
vec->x = 10;
|
|
||||||
vec->y = 12;
|
|
||||||
vec->z = 151;
|
|
||||||
vec->w = -13;
|
|
||||||
map2.set(i, vec);
|
|
||||||
Vector4 *p = nullptr;
|
|
||||||
map2.lookup(i, p);
|
|
||||||
CHECK(*p == *vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
OAHashMap<int64_t, Vector4 *> map3(map2);
|
|
||||||
for (OAHashMap<int64_t, Vector4 *>::Iterator it = map2.iter(); it.valid; it = map2.next_iter(it)) {
|
|
||||||
memdelete(*(it.value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CHECK(Memory::get_mem_usage() == pre_mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace TestOAHashMap
|
|
||||||
@@ -103,7 +103,6 @@
|
|||||||
#include "tests/core/templates/test_list.h"
|
#include "tests/core/templates/test_list.h"
|
||||||
#include "tests/core/templates/test_local_vector.h"
|
#include "tests/core/templates/test_local_vector.h"
|
||||||
#include "tests/core/templates/test_lru.h"
|
#include "tests/core/templates/test_lru.h"
|
||||||
#include "tests/core/templates/test_oa_hash_map.h"
|
|
||||||
#include "tests/core/templates/test_paged_array.h"
|
#include "tests/core/templates/test_paged_array.h"
|
||||||
#include "tests/core/templates/test_rid.h"
|
#include "tests/core/templates/test_rid.h"
|
||||||
#include "tests/core/templates/test_self_list.h"
|
#include "tests/core/templates/test_self_list.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user