diff options
-rw-r--r-- | core/class_db.cpp | 2 | ||||
-rw-r--r-- | core/oa_hash_map.h | 617 | ||||
-rw-r--r-- | drivers/windows/file_access_windows.cpp | 2 | ||||
-rw-r--r-- | main/tests/test_oa_hash_map.cpp | 6 | ||||
-rw-r--r-- | modules/csg/csg.cpp | 2 | ||||
-rw-r--r-- | modules/csg/csg.h | 2 | ||||
-rw-r--r-- | modules/csg/csg_shape.cpp | 4 | ||||
-rw-r--r-- | modules/visual_script/register_types.cpp | 2 | ||||
-rw-r--r-- | scene/2d/light_occluder_2d.cpp | 6 | ||||
-rw-r--r-- | scene/2d/light_occluder_2d.h | 2 | ||||
-rw-r--r-- | scene/3d/camera.h | 4 | ||||
-rw-r--r-- | scene/3d/spatial.cpp | 9 | ||||
-rw-r--r-- | scene/3d/spatial.h | 2 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 6 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 12 | ||||
-rw-r--r-- | scene/main/node.h | 2 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 12 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 2 |
19 files changed, 207 insertions, 489 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp index 08c1ade679..59b100e282 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -357,7 +357,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { ClassInfo *t = classes.getptr(E->get()); ERR_FAIL_COND_V(!t, 0); - if (t->api != p_api) + if (t->api != p_api || !t->exposed) continue; hash = hash_djb2_one_64(t->name.hash(), hash); hash = hash_djb2_one_64(t->inherits.hash(), hash); diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 280aea6a14..0b3b40f30c 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -36,176 +36,181 @@ #include "os/copymem.h" #include "os/memory.h" -// uncomment this to disable initial local storage. -#define OA_HASH_MAP_INITIAL_LOCAL_STORAGE - /** - * This class implements a hash map datastructure that uses open addressing with - * local probing. - * - * It can give huge performance improvements over a chained HashMap because of - * the increased data locality. - * - * Because of that locality property it's important to not use "large" value - * types as the "TData" type. If TData values are too big it can cause more - * cache misses then chaining. If larger values are needed then storing those - * in a separate array and using pointers or indices to reference them is the - * better solution. - * - * This hash map also implements real-time incremental rehashing. + * A HashMap implementation that uses open addressing with robinhood hashing. + * Robinhood 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. * + * The entries are stored inplace, so huge keys or values might fill cache lines + * a lot faster. */ -template <class TKey, class TData, - uint16_t INITIAL_NUM_ELEMENTS = 64, +template <class TKey, class TValue, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey> > class OAHashMap { private: -#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE - TData local_data[INITIAL_NUM_ELEMENTS]; - TKey local_keys[INITIAL_NUM_ELEMENTS]; - uint32_t local_hashes[INITIAL_NUM_ELEMENTS]; - uint8_t local_flags[INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)]; -#endif + TValue *values; + TKey *keys; + uint32_t *hashes; - struct { - TData *data; - TKey *keys; - uint32_t *hashes; + uint32_t capacity; - // This is actually an array of bits, 4 bit pairs per octet. - // | ba ba ba ba | ba ba ba ba | .... - // - // if a is set it means that there is an element present. - // if b is set it means that an element was deleted. This is needed for - // the local probing to work without relocating any succeeding and - // colliding entries. - uint8_t *flags; + uint32_t num_elements; - uint32_t capacity; - } table, old_table; + static const uint32_t EMPTY_HASH = 0; + static const uint32_t DELETED_HASH_BIT = 1 << 31; - bool is_rehashing; - uint32_t rehash_position; - uint32_t rehash_amount; + _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) { + uint32_t hash = Hasher::hash(p_key); - uint32_t elements; + if (hash == EMPTY_HASH) { + hash = EMPTY_HASH + 1; + } else if (hash & DELETED_HASH_BIT) { + hash &= ~DELETED_HASH_BIT; + } - /* Methods */ + return hash; + } - // returns true if the value already existed, false if it's a new entry - bool _raw_set_with_hash(uint32_t p_hash, const TKey &p_key, const TData &p_data) { - for (int i = 0; i < table.capacity; i++) { + _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) { + p_hash = p_hash & ~DELETED_HASH_BIT; // we don't care if it was deleted or not - int pos = (p_hash + i) % table.capacity; + uint32_t original_pos = p_hash % capacity; - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; + return p_pos - original_pos; + } - bool is_filled_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset)); - bool is_deleted_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1)); + _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; - if (is_filled_flag) { - if (table.hashes[pos] == p_hash && Comparator::compare(table.keys[pos], p_key)) { - table.data[pos] = p_data; - return true; - } - continue; + num_elements++; + } + + bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) { + uint32_t hash = _hash(p_key); + uint32_t pos = hash % capacity; + uint32_t distance = 0; + + while (42) { + if (hashes[pos] == EMPTY_HASH) { + return false; } - table.keys[pos] = p_key; - table.data[pos] = p_data; - table.hashes[pos] = p_hash; + if (distance > _get_probe_length(pos, hashes[pos])) { + return false; + } - table.flags[flags_pos] |= (1 << (2 * flags_pos_offset)); - table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset + 1)); + if (hashes[pos] == hash && Comparator::compare(keys[pos], p_key)) { + r_pos = pos; + return true; + } - return false; + pos = (pos + 1) % capacity; + distance++; } - return false; } -public: - _FORCE_INLINE_ uint32_t get_capacity() const { return table.capacity; } - _FORCE_INLINE_ uint32_t get_num_elements() const { return elements; } + void _insert_with_hash(uint32_t p_hash, const TKey &p_key, const TValue &p_value) { - void set(const TKey &p_key, const TData &p_data) { + uint32_t hash = p_hash; + uint32_t distance = 0; + uint32_t pos = hash % capacity; - uint32_t hash = Hasher::hash(p_key); + TKey key = p_key; + TValue value = p_value; - // We don't progress the rehashing if the table just got resized - // to keep the cost of this function low. - if (is_rehashing) { + while (42) { + if (hashes[pos] == EMPTY_HASH) { + _construct(pos, hash, p_key, p_value); - // rehash progress + return; + } - for (int i = 0; i <= rehash_amount && rehash_position < old_table.capacity; rehash_position++) { + // 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) { - int flags_pos = rehash_position / 4; - int flags_pos_offset = rehash_position % 4; + if (hashes[pos] & DELETED_HASH_BIT) { + // we found a place where we can fit in! + _construct(pos, hash, p_key, p_value); - bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + return; + } - if (is_filled_flag) { - _raw_set_with_hash(old_table.hashes[rehash_position], old_table.keys[rehash_position], old_table.data[rehash_position]); + SWAP(hash, hashes[pos]); + SWAP(key, keys[pos]); + SWAP(value, values[pos]); + distance = existing_probe_len; + } - old_table.keys[rehash_position].~TKey(); - old_table.data[rehash_position].~TData(); + pos = (pos + 1) % capacity; + distance++; + } + } + void _resize_and_rehash() { - memnew_placement(&old_table.keys[rehash_position], TKey); - memnew_placement(&old_table.data[rehash_position], TData); + TKey *old_keys = keys; + TValue *old_values = values; + uint32_t *old_hashes = hashes; - old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); - old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); - } - } + uint32_t old_capacity = capacity; - if (rehash_position >= old_table.capacity) { + capacity = old_capacity * 2; + num_elements = 0; - // wohooo, we can get rid of the old table. - is_rehashing = false; + keys = memnew_arr(TKey, capacity); + values = memnew_arr(TValue, capacity); + hashes = memnew_arr(uint32_t, capacity); -#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE - if (old_table.data == local_data) { - // Everything is local, so no cleanup :P - } else -#endif - { - memdelete_arr(old_table.data); - memdelete_arr(old_table.keys); - memdelete_arr(old_table.hashes); - memdelete_arr(old_table.flags); - } - } + for (int i = 0; i < capacity; i++) { + hashes[i] = 0; } - // Table is almost full, resize and start rehashing process. - if (elements >= table.capacity * 0.7) { + for (uint32_t i = 0; i < old_capacity; i++) { + if (old_hashes[i] == EMPTY_HASH) { + continue; + } + if (old_hashes[i] & DELETED_HASH_BIT) { + continue; + } - old_table.capacity = table.capacity; - old_table.data = table.data; - old_table.flags = table.flags; - old_table.hashes = table.hashes; - old_table.keys = table.keys; + _insert_with_hash(old_hashes[i], old_keys[i], old_values[i]); + } - table.capacity = old_table.capacity * 2; + memdelete_arr(old_keys); + memdelete_arr(old_values); + memdelete_arr(old_hashes); + } - table.data = memnew_arr(TData, table.capacity); - table.flags = memnew_arr(uint8_t, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); - table.hashes = memnew_arr(uint32_t, table.capacity); - table.keys = memnew_arr(TKey, table.capacity); +public: + _FORCE_INLINE_ uint32_t get_capacity() const { return capacity; } + _FORCE_INLINE_ uint32_t get_num_elements() const { return num_elements; } - zeromem(table.flags, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); + void insert(const TKey &p_key, const TValue &p_value) { - is_rehashing = true; - rehash_position = 0; - rehash_amount = (elements * 2) / (table.capacity * 0.7 - old_table.capacity); + if ((float)num_elements / (float)capacity > 0.9) { + _resize_and_rehash(); } - if (!_raw_set_with_hash(hash, p_key, p_data)) - elements++; + 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].~TValue(); + memnew_placement(&values[pos], TValue(p_data)); + } else { + insert(p_key, p_data); + } } /** @@ -214,380 +219,108 @@ public: * if r_data is not NULL then the value will be written to the object * it points to. */ - bool lookup(const TKey &p_key, TData *r_data) { - - uint32_t hash = Hasher::hash(p_key); - - bool check_old_table = is_rehashing; - bool check_new_table = true; - - // search for the key and return the value associated with it - // - // if we're rehashing we need to check both the old and the - // current table. If we find a value in the old table we still - // need to continue searching in the new table as it might have - // been added after - - TData *value = NULL; - - for (int i = 0; i < table.capacity; i++) { - - if (!check_new_table && !check_old_table) { - - break; - } - - // if we're rehashing check the old table - if (check_old_table && i < old_table.capacity) { - - int pos = (hash + i) % old_table.capacity; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; - - if (is_filled_flag) { - // found our entry? - if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { - value = &old_table.data[pos]; - check_old_table = false; - } - } else if (!is_deleted_flag) { - - // we hit an empty field here, we don't - // need to further check this old table - // because we know it's not in here. + bool lookup(const TKey &p_key, TValue &r_data) { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - check_old_table = false; - } - } - - if (check_new_table) { - - int pos = (hash + i) % table.capacity; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; - - if (is_filled_flag) { - // found our entry? - if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { - if (r_data != NULL) - *r_data = table.data[pos]; - return true; - } - continue; - } else if (is_deleted_flag) { - continue; - } else if (value != NULL) { - - // We found a value in the old table - if (r_data != NULL) - *r_data = *value; - return true; - } else { - check_new_table = false; - } - } - } - - if (value != NULL) { - if (r_data != NULL) - *r_data = *value; + if (exists) { + r_data.~TValue(); + memnew_placement(&r_data, TValue(values[pos])); return true; } + return false; } _FORCE_INLINE_ bool has(const TKey &p_key) { - return lookup(p_key, NULL); + uint32_t _pos = 0; + return _lookup_pos(p_key, _pos); } void remove(const TKey &p_key) { - uint32_t hash = Hasher::hash(p_key); - - bool check_old_table = is_rehashing; - bool check_new_table = true; - - for (int i = 0; i < table.capacity; i++) { - - if (!check_new_table && !check_old_table) { - return; - } - - // if we're rehashing check the old table - if (check_old_table && i < old_table.capacity) { - - int pos = (hash + i) % old_table.capacity; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; - - if (is_filled_flag) { - // found our entry? - if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { - old_table.keys[pos].~TKey(); - old_table.data[pos].~TData(); + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); - memnew_placement(&old_table.keys[pos], TKey); - memnew_placement(&old_table.data[pos], TData); - - old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); - old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); - - elements--; - return; - } - } else if (!is_deleted_flag) { - - // we hit an empty field here, we don't - // need to further check this old table - // because we know it's not in here. - - check_old_table = false; - } - } - - if (check_new_table) { - - int pos = (hash + i) % table.capacity; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; - - if (is_filled_flag) { - // found our entry? - if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { - table.keys[pos].~TKey(); - table.data[pos].~TData(); - - memnew_placement(&table.keys[pos], TKey); - memnew_placement(&table.data[pos], TData); - - table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); - table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); - - // don't return here, this value might still be in the old table - // if it was already relocated. - - elements--; - return; - } - continue; - } else if (is_deleted_flag) { - continue; - } else { - check_new_table = false; - } - } + if (!exists) { + return; } + + hashes[pos] |= DELETED_HASH_BIT; + values[pos].~TValue(); + keys[pos].~TKey(); + num_elements--; } struct Iterator { bool valid; - uint32_t hash; - const TKey *key; - const TData *data; + const TValue *value; private: + uint32_t pos; friend class OAHashMap; - bool was_from_old_table; }; Iterator iter() const { Iterator it; - it.valid = false; - it.was_from_old_table = false; - - bool check_old_table = is_rehashing; - - for (int i = 0; i < table.capacity; i++) { - - // if we're rehashing check the old table first - if (check_old_table && i < old_table.capacity) { - - int pos = i; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - - if (is_filled_flag) { - it.valid = true; - it.hash = old_table.hashes[pos]; - it.data = &old_table.data[pos]; - it.key = &old_table.keys[pos]; - - it.was_from_old_table = true; - - return it; - } - } - - { - - int pos = i; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - - if (is_filled_flag) { - it.valid = true; - it.hash = table.hashes[pos]; - it.data = &table.data[pos]; - it.key = &table.keys[pos]; - - return it; - } - } - } + it.valid = true; + it.pos = 0; - return it; + 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.was_from_old_table = false; - - bool check_old_table = is_rehashing; - - // we use this to skip the first check or not - bool was_from_old_table = p_iter.was_from_old_table; - - int prev_index = (p_iter.data - (p_iter.was_from_old_table ? old_table.data : table.data)); - - if (!was_from_old_table) { - prev_index++; - } + it.pos = p_iter.pos; + it.key = NULL; + it.value = NULL; - for (int i = prev_index; i < table.capacity; i++) { + for (uint32_t i = it.pos; i < capacity; i++) { + it.pos = i + 1; - // if we're rehashing check the old table first - if (check_old_table && i < old_table.capacity && !was_from_old_table) { - - int pos = i; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - - if (is_filled_flag) { - it.valid = true; - it.hash = old_table.hashes[pos]; - it.data = &old_table.data[pos]; - it.key = &old_table.keys[pos]; - - it.was_from_old_table = true; - - return it; - } + if (hashes[i] == EMPTY_HASH) { + continue; } - - was_from_old_table = false; - - { - int pos = i; - - int flags_pos = pos / 4; - int flags_pos_offset = pos % 4; - - bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; - - if (is_filled_flag) { - it.valid = true; - it.hash = table.hashes[pos]; - it.data = &table.data[pos]; - it.key = &table.keys[pos]; - - return it; - } + if (hashes[i] & DELETED_HASH_BIT) { + continue; } + + it.valid = true; + it.key = &keys[i]; + it.value = &values[i]; + return it; } return it; } - OAHashMap(uint32_t p_initial_capacity = INITIAL_NUM_ELEMENTS) { + OAHashMap(uint32_t p_initial_capacity = 64) { -#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + capacity = p_initial_capacity; + num_elements = 0; - if (p_initial_capacity <= INITIAL_NUM_ELEMENTS) { - table.data = local_data; - table.keys = local_keys; - table.hashes = local_hashes; - table.flags = local_flags; + keys = memnew_arr(TKey, p_initial_capacity); + values = memnew_arr(TValue, p_initial_capacity); + hashes = memnew_arr(uint32_t, p_initial_capacity); - zeromem(table.flags, INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)); - - table.capacity = INITIAL_NUM_ELEMENTS; - elements = 0; - } else -#endif - { - table.data = memnew_arr(TData, p_initial_capacity); - table.keys = memnew_arr(TKey, p_initial_capacity); - table.hashes = memnew_arr(uint32_t, p_initial_capacity); - table.flags = memnew_arr(uint8_t, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); - - zeromem(table.flags, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); - - table.capacity = p_initial_capacity; - elements = 0; + for (int i = 0; i < p_initial_capacity; i++) { + hashes[i] = 0; } - - is_rehashing = false; - rehash_position = 0; } ~OAHashMap() { -#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE - if (table.capacity <= INITIAL_NUM_ELEMENTS) { - return; // Everything is local, so no cleanup :P - } -#endif - if (is_rehashing) { - -#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE - if (old_table.data == local_data) { - // Everything is local, so no cleanup :P - } else -#endif - { - memdelete_arr(old_table.data); - memdelete_arr(old_table.keys); - memdelete_arr(old_table.hashes); - memdelete_arr(old_table.flags); - } - } - memdelete_arr(table.data); - memdelete_arr(table.keys); - memdelete_arr(table.hashes); - memdelete_arr(table.flags); + memdelete_arr(keys); + memdelete_arr(values); + memdelete(hashes); } }; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 88ed8b27b4..aa0fd34e0a 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -162,7 +162,7 @@ void FileAccessWindows::close() { } if (rename_error) { attempts--; - OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again + OS::get_singleton()->delay_usec(100000); // wait 100msec and try again } } diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp index ac65fdf19c..0e34faace7 100644 --- a/main/tests/test_oa_hash_map.cpp +++ b/main/tests/test_oa_hash_map.cpp @@ -49,7 +49,7 @@ MainLoop *test() { map.set(42, 11880); int value; - map.lookup(42, &value); + map.lookup(42, value); OS::get_singleton()->print("capacity %d\n", map.get_capacity()); OS::get_singleton()->print("elements %d\n", map.get_num_elements()); @@ -72,7 +72,7 @@ MainLoop *test() { uint32_t num_elems = 0; for (int i = 0; i < 500; i++) { int tmp; - if (map.lookup(i, &tmp)) + if (map.lookup(i, tmp) && tmp == i * 2) num_elems++; } @@ -88,7 +88,7 @@ MainLoop *test() { map.set("Godot rocks", 42); for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) { - OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.data); + OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.value); } } diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 9752defa79..c1fe11d6aa 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -1255,7 +1255,7 @@ void CSGBrushOperation::MeshMerge::add_face(const Vector3 &p_a, const Vector3 &p vk.z = int((double(src_points[i].z) + double(vertex_snap) * 0.31234) / double(vertex_snap)); int res; - if (snap_cache.lookup(vk, &res)) { + if (snap_cache.lookup(vk, res)) { indices[i] = res; } else { indices[i] = points.size(); diff --git a/modules/csg/csg.h b/modules/csg/csg.h index d89e542b5e..bb67e1fb36 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -108,7 +108,7 @@ struct CSGBrushOperation { } }; - OAHashMap<VertexKey, int, 64, VertexKeyHash> snap_cache; + OAHashMap<VertexKey, int, VertexKeyHash> snap_cache; Vector<Vector3> points; diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 279edbcec5..1f2f12f54d 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -157,7 +157,7 @@ void CSGShape::_update_shape() { for (int j = 0; j < 3; j++) { Vector3 v = n->faces[i].vertices[j]; Vector3 add; - if (vec_map.lookup(v, &add)) { + if (vec_map.lookup(v, add)) { add += p.normal; } else { add = p.normal; @@ -233,7 +233,7 @@ void CSGShape::_update_shape() { Vector3 normal = p.normal; - if (n->faces[i].smooth && vec_map.lookup(v, &normal)) { + if (n->faces[i].smooth && vec_map.lookup(v, normal)) { normal.normalize(); } diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 2809cff362..11401c0460 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -112,7 +112,9 @@ void register_visual_script_types() { register_visual_script_expression_node(); #ifdef TOOLS_ENABLED + ClassDB::set_current_api(ClassDB::API_EDITOR); ClassDB::register_class<_VisualScriptEditor>(); + ClassDB::set_current_api(ClassDB::API_CORE); vs_editor_singleton = memnew(_VisualScriptEditor); Engine::get_singleton()->add_singleton(Engine::Singleton("VisualScriptEditor", _VisualScriptEditor::get_singleton())); diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index d4481583fb..c9e5d0f1bc 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -107,12 +107,12 @@ OccluderPolygon2D::~OccluderPolygon2D() { VS::get_singleton()->free(occ_polygon); } -#ifdef DEBUG_ENABLED void LightOccluder2D::_poly_changed() { +#ifdef DEBUG_ENABLED update(); -} #endif +} void LightOccluder2D::_notification(int p_what) { @@ -221,9 +221,7 @@ void LightOccluder2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask); ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask); -#ifdef DEBUG_ENABLED ClassDB::bind_method("_poly_changed", &LightOccluder2D::_poly_changed); -#endif ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), "set_occluder_polygon", "get_occluder_polygon"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask"); diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index 5e16351a6f..d59c9100b0 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -78,9 +78,7 @@ class LightOccluder2D : public Node2D { int mask; Ref<OccluderPolygon2D> occluder_polygon; -#ifdef DEBUG_ENABLED void _poly_changed(); -#endif protected: void _notification(int p_what); diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 109bf3adc6..1b506e0c4f 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -132,9 +132,9 @@ public: virtual Transform get_camera_transform() const; - Vector3 project_ray_normal(const Point2 &p_pos) const; + virtual Vector3 project_ray_normal(const Point2 &p_pos) const; virtual Vector3 project_ray_origin(const Point2 &p_pos) const; - Vector3 project_local_ray_normal(const Point2 &p_pos) const; + virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const; virtual Point2 unproject_position(const Vector3 &p_pos) const; bool is_position_behind(const Vector3 &p_pos) const; virtual Vector3 project_position(const Point2 &p_point) const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index dab0e573d7..5deeb75c67 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -430,10 +430,9 @@ Ref<SpatialGizmo> Spatial::get_gizmo() const { #endif } -#ifdef TOOLS_ENABLED - void Spatial::_update_gizmo() { +#ifdef TOOLS_ENABLED if (!is_inside_world()) return; data.gizmo_dirty = false; @@ -445,8 +444,10 @@ void Spatial::_update_gizmo() { data.gizmo->clear(); } } +#endif } +#ifdef TOOLS_ENABLED void Spatial::set_disable_gizmo(bool p_enabled) { data.gizmo_disabled = p_enabled; @@ -726,9 +727,7 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel); ClassDB::bind_method(D_METHOD("get_world"), &Spatial::get_world); -#ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); -#endif ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo); ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Spatial::set_gizmo); @@ -790,9 +789,7 @@ void Spatial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); ADD_GROUP("Visibility", ""); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); -#ifdef TOOLS_ENABLED ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo"); -#endif ADD_SIGNAL(MethodInfo("visibility_changed")); } diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 518bba9a51..ca35d85348 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -100,10 +100,8 @@ class Spatial : public Node { #endif } data; -#ifdef TOOLS_ENABLED void _update_gizmo(); -#endif void _notify_dirty(); void _propagate_transform_changed(Spatial *p_origin); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index e3b8baf0c0..1ceb3f0a8b 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1349,12 +1349,12 @@ PopupMenu *LineEdit::get_menu() const { return menu; } -#ifdef TOOLS_ENABLED void LineEdit::_editor_settings_changed() { +#ifdef TOOLS_ENABLED cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false)); cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65)); -} #endif +} void LineEdit::set_expand_to_text_length(bool p_enabled) { @@ -1423,9 +1423,7 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed); ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret); -#ifdef TOOLS_ENABLED ClassDB::bind_method("_editor_settings_changed", &LineEdit::_editor_settings_changed); -#endif ClassDB::bind_method(D_METHOD("set_align", "align"), &LineEdit::set_align); ClassDB::bind_method(D_METHOD("get_align"), &LineEdit::get_align); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 48dde2461e..304faed9bd 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -135,9 +135,7 @@ private: void clear_internal(); void changed_internal(); -#ifdef TOOLS_ENABLED void _editor_settings_changed(); -#endif void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 001b8cfd0b..a1d79e7357 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2581,18 +2581,21 @@ Array Node::_get_children() const { return arr; } -#ifdef TOOLS_ENABLED void Node::set_import_path(const NodePath &p_import_path) { +#ifdef TOOLS_ENABLED data.import_path = p_import_path; +#endif } NodePath Node::get_import_path() const { +#ifdef TOOLS_ENABLED return data.import_path; -} - +#else + return NodePath(); #endif +} static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<String> *r_options) { @@ -2751,13 +2754,10 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config); ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config); -#ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path); ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path); ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path"); -#endif - { MethodInfo mi; diff --git a/scene/main/node.h b/scene/main/node.h index a0b6399486..b5a956116d 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -380,10 +380,8 @@ public: void force_parent_owned() { data.parent_owned = true; } //hack to avoid duplicate nodes -#ifdef TOOLS_ENABLED void set_import_path(const NodePath &p_import_path); //path used when imported, used by scene editors to keep tracking NodePath get_import_path() const; -#endif bool is_owned_by_parent() const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 727807dbcd..011087b487 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1205,16 +1205,20 @@ void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, c _update_root_rect(); } -#ifdef TOOLS_ENABLED void SceneTree::set_edited_scene_root(Node *p_node) { +#ifdef TOOLS_ENABLED edited_scene_root = p_node; +#endif } Node *SceneTree::get_edited_scene_root() const { +#ifdef TOOLS_ENABLED return edited_scene_root; -} +#else + return NULL; #endif +} void SceneTree::set_current_scene(Node *p_scene) { @@ -1745,10 +1749,8 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint); ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint); -#ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root); ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root); -#endif ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); @@ -1823,9 +1825,7 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling"); -#ifdef TOOLS_ENABLED ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root"); -#endif ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root"); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 203c1d9c9c..9c06e4ded3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -390,10 +390,8 @@ public: //void change_scene(const String& p_path); //Node *get_loaded_scene(); -#ifdef TOOLS_ENABLED void set_edited_scene_root(Node *p_node); Node *get_edited_scene_root() const; -#endif void set_current_scene(Node *p_scene); Node *get_current_scene() const; |