Merge pull request #355 from nem0/optimizations

Associative array
This commit is contained in:
Mikulas Florek 2014-11-22 00:45:57 +01:00
commit b7d09a8268
22 changed files with 680 additions and 570 deletions

View file

@ -151,6 +151,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\core\aabb.h" />
<ClInclude Include="..\..\..\src\core\binary_array.h" />
<ClInclude Include="..\..\..\src\core\iallocator.h" />
<ClInclude Include="..\..\..\src\core\array.h" />
<ClInclude Include="..\..\..\src\core\blob.h" />
@ -176,7 +177,6 @@
<ClInclude Include="..\..\..\src\core\json_serializer.h" />
<ClInclude Include="..\..\..\src\core\log.h" />
<ClInclude Include="..\..\..\src\core\lumix.h" />
<ClInclude Include="..\..\..\src\core\map.h" />
<ClInclude Include="..\..\..\src\core\math_utils.h" />
<ClInclude Include="..\..\..\src\core\matrix.h" />
<ClInclude Include="..\..\..\src\core\mtjd\base_entry.h" />
@ -211,6 +211,7 @@
<ClInclude Include="..\..\..\src\core\resource.h" />
<ClInclude Include="..\..\..\src\core\resource_manager.h" />
<ClInclude Include="..\..\..\src\core\resource_manager_base.h" />
<ClInclude Include="..\..\..\src\core\associative_array.h" />
<ClInclude Include="..\..\..\src\core\sphere.h" />
<ClInclude Include="..\..\..\src\core\stack_allocator.h" />
<ClInclude Include="..\..\..\src\core\static_array.h" />
@ -223,6 +224,7 @@
<ClInclude Include="..\..\..\src\debug\stack_tree.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\core\binary_array.cpp" />
<ClCompile Include="..\..\..\src\core\blob.cpp" />
<ClCompile Include="..\..\..\src\core\crc32.cpp" />
<ClCompile Include="..\..\..\src\core\default_allocator.cpp" />

View file

@ -13,7 +13,6 @@
<ClInclude Include="..\..\..\src\core\iserializer.h" />
<ClInclude Include="..\..\..\src\core\json_serializer.h" />
<ClInclude Include="..\..\..\src\core\log.h" />
<ClInclude Include="..\..\..\src\core\map.h" />
<ClInclude Include="..\..\..\src\core\math_utils.h" />
<ClInclude Include="..\..\..\src\core\matrix.h" />
<ClInclude Include="..\..\..\src\core\pod_hash_map.h" />
@ -140,6 +139,8 @@
<ClInclude Include="..\..\..\src\core\MTJD\generic_job.h">
<Filter>mtjd</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\core\associative_array.h" />
<ClInclude Include="..\..\..\src\core\binary_array.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\core\blob.cpp" />
@ -238,6 +239,7 @@
<ClCompile Include="..\..\..\src\debug\pc\stack_tree.cpp">
<Filter>debug</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\core\binary_array.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="fs">

View file

@ -19,6 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\unit_tests\core\ut_binary_array.cpp" />
<ClCompile Include="..\..\..\src\unit_tests\core\ut_file_system.cpp" />
<ClCompile Include="..\..\..\src\unit_tests\core\ut_fixed_lock_free_queue.cpp" />
<ClCompile Include="..\..\..\src\unit_tests\core\ut_hash_map.cpp">

View file

@ -38,6 +38,9 @@
<ClCompile Include="..\..\..\src\unit_tests\core\ut_fixed_lock_free_queue.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\unit_tests\core\ut_binary_array.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\unit_tests\suite\unit_test.h">

View file

@ -6,7 +6,6 @@
#include <QVector>
#include "core/array.h"
#include "core/delegate_list.h"
#include "core/map.h"
#include "core/path.h"
#include "core/string.h"

View file

@ -104,6 +104,19 @@ class Array<T, false>
}
}
void insert(int index, const T& value)
{
if (m_size == m_capacity)
{
grow();
}
memmove(m_data + index + 1, m_data + index, sizeof(T) * (m_size - index));
new (&m_data[index]) T(value);
++m_size;
}
void erase(int index)
{
if(index >= 0 && index < m_size)
@ -374,7 +387,7 @@ public:
{
grow();
}
memmove(m_data + index + 1, m_data + index, m_size - index);
memmove(m_data + index + 1, m_data + index, sizeof(T) * (m_size - index));
m_data[index] = value;
++m_size;
}

View file

@ -0,0 +1,259 @@
#pragma once
#include "core/array.h"
namespace Lumix
{
template <typename T>
class SortedArray
{
public:
SortedArray(IAllocator& allocator)
: m_data(allocator)
{}
int size() const { return m_data.size(); }
T& operator[](int index)
{
return m_data[index];
}
const T& operator[](int index) const
{
return m_data[index];
}
int insert(const T& value)
{
if (m_data.empty())
{
m_data.push(value);
return 0;
}
else
{
int i = index(value);
if (i >= 0 && ((i < m_data.size() && m_data[i] != value) || i == m_data.size()))
{
m_data.insert(i, value);
return i;
}
}
return -1;
}
bool contains(const T& value)
{
int i = index(value);
return i < m_data.size() && m_data[i] == value;
}
void clear()
{
m_data.clear();
}
void reserve(int capacity)
{
m_data.reserve(capacity);
}
void erase(int index)
{
m_data.erase(index);
}
private:
int index(const T& value) const
{
int l = 0;
int h = m_data.size() - 1;
while (l < h)
{
int mid = (l + h) >> 1;
if (m_data[mid] < value)
{
l = mid + 1;
}
else
{
h = mid;
}
}
if (l + 1 == m_data.size() && m_data[l] < value)
{
return l + 1;
}
return l;
}
private:
Array<T> m_data;
};
template <typename Key, typename Value>
class AssociativeArray
{
public:
AssociativeArray(IAllocator& allocator)
: m_data(allocator)
{}
void insert(const Key& key, const Value& value)
{
m_data.insert(Pair(key, value));
}
bool find(const Key& key, Value& value) const
{
int i = find(key);
if (i < 0)
{
return false;
}
value = m_data[i].m_value;
return true;
}
int find(const Key& key) const
{
int l = 0;
int h = m_data.size() - 1;
while (l < h)
{
int mid = (l + h) >> 1;
if (m_data[mid].m_key < key)
{
l = mid + 1;
}
else
{
h = mid;
}
}
if (l == h && m_data[l].m_key == key)
{
return l;
}
return -1;
}
const Value& operator [](const Key& key) const
{
int index = find(key);
if (index >= 0)
{
return m_data[index].m_value;
}
else
{
return m_data[m_data.insert(Pair(key, Value()))].m_value;
}
}
Value& operator [](const Key& key)
{
int index = find(key);
if (index >= 0)
{
return m_data[index].m_value;
}
else
{
return m_data[m_data.insert(Pair(key, Value()))].m_value;
}
}
int size()
{
return m_data.size();
}
Value& get(const Key& key)
{
int index = find(key);
ASSERT(index >= 0);
return m_data[index].m_value;
}
Value& at(int index)
{
return m_data[index].m_value;
}
void clear()
{
m_data.clear();
}
void reserve(int capacity)
{
m_data.reserve(capacity);
}
const Key& getKey(int index)
{
return m_data[index].m_key;
}
void eraseAt(int index)
{
m_data.erase(index);
}
void erase(const Key& key)
{
int i = find(key);
if (i >= 0)
{
eraseAt(i);
}
}
private:
struct Pair
{
Pair() {}
Pair(const Key& key, const Value& value) : m_key(key), m_value(value) {}
bool operator <(const Pair& rhs) const { return m_key < rhs.m_key; }
bool operator >(const Pair& rhs) const { return m_key > rhs.m_key; }
bool operator ==(const Pair& rhs) const { return m_key == rhs.m_key; }
bool operator !=(const Pair& rhs) const { return m_key != rhs.m_key; }
Key m_key;
Value m_value;
};
private:
SortedArray<Pair> m_data;
};
} // namespace Lumix

163
src/core/binary_array.cpp Normal file
View file

@ -0,0 +1,163 @@
#include "binary_array.h"
namespace Lumix
{
BinaryArray::StoreType BinaryArray::BINARY_MASK[32];
BinaryArray::StoreType BinaryArray::INDEX_BIT[32];
BinaryArray::Accessor::Accessor(BinaryArray& array, int index)
: m_array(array)
, m_index(index)
{}
BinaryArray::BinaryArray(IAllocator& allocator)
: m_allocator(allocator)
, m_data(NULL)
, m_size(0)
, m_capacity(0)
{
static bool init = false;
if (!init)
{
init = true;
for (int i = 31; i >= 0; --i)
{
BINARY_MASK[i] = i == 31 ? 0xffffFFFF : BINARY_MASK[i + 1] << 1;
INDEX_BIT[i] = 1 << (31 - i);
}
}
}
BinaryArray::~BinaryArray()
{
m_allocator.deallocate(m_data);
}
void BinaryArray::erase(int index)
{
if (0 <= index && index < m_size)
{
int major = index >> 5;
const int last_major = (m_size - 1) >> 5;
m_data[major] = (index & 31 == 0 ? 0 : (m_data[major] & BINARY_MASK[(index & 31) - 1])) | ((m_data[major] & ~BINARY_MASK[index & 31]) << 1);
if (major < last_major)
{
m_data[major] |= (m_data[major + 1] & 0x80000000) >> 31;
}
for (int i = major + 1; i <= last_major; ++i)
{
m_data[i] <<= 1;
if (i < (m_size >> 5))
{
m_data[i] |= (m_data[i + 1] & 0x80000000) >> 31;
}
}
m_data[last_major] <<= 1;
}
}
void BinaryArray::clear()
{
m_size = 0;
}
void BinaryArray::push(bool value)
{
if (m_capacity == m_size)
{
grow(m_capacity > 0 ? (m_capacity << 1) : 32);
}
if (value)
{
m_data[m_size >> 5] |= INDEX_BIT[m_size & 31];
}
else
{
m_data[m_size >> 5] &= ~INDEX_BIT[m_size & 31];
}
++m_size;
}
void BinaryArray::pop()
{
ASSERT(m_size > 0);
--m_size;
}
bool BinaryArray::operator[](int index) const
{
ASSERT(index < m_size);
return (m_data[index >> 5] | INDEX_BIT[index & 31]) > 0;
}
BinaryArray::Accessor BinaryArray::operator[](int index)
{
return Accessor(*this, index);
}
bool BinaryArray::back() const
{
ASSERT(m_size > 0);
return (*this)[m_size - 1];
}
BinaryArray::Accessor BinaryArray::back()
{
ASSERT(m_size > 0);
return (*this)[m_size - 1];
}
int BinaryArray::size() const
{
return m_size;
}
void BinaryArray::reserve(int capacity)
{
if ((m_capacity >> 5) < (capacity >> 5))
{
grow(capacity);
}
}
BinaryArray::StoreType* BinaryArray::getRaw()
{
return m_data;
}
int BinaryArray::getRawSize() const
{
return (m_size + 31) >> 5;
}
void BinaryArray::grow(int capacity)
{
StoreType* new_data = static_cast<StoreType*>(m_allocator.allocate(capacity >> 3));
if (m_data)
{
memcpy(new_data, m_data, sizeof(StoreType) * (m_size + 31) >> 5);
m_allocator.deallocate(m_data);
}
m_data = new_data;
m_capacity = capacity;
}
} // namespace Lumix

79
src/core/binary_array.h Normal file
View file

@ -0,0 +1,79 @@
#pragma once
#include "core/iallocator.h"
namespace Lumix
{
class LUMIX_CORE_API BinaryArray
{
public:
typedef uint32_t StoreType;
static const size_t ITEM_SIZE = sizeof(StoreType);
class Accessor
{
public:
Accessor(BinaryArray& array, int index);
Accessor& operator =(bool value)
{
if (value)
{
m_array.m_data[m_index >> 5] |= m_array.INDEX_BIT[m_index & 31];
}
else
{
m_array.m_data[m_index >> 5] &= ~m_array.INDEX_BIT[m_index & 31];
}
return *this;
}
operator bool()
{
return (m_array.m_data[m_index >> 5] | (1 << (m_index & 31))) > 0;
}
private:
BinaryArray& m_array;
int m_index;
};
public:
BinaryArray(IAllocator& allocator);
~BinaryArray();
Accessor operator[](int index);
Accessor back();
bool back() const;
bool operator[](int index) const;
void reserve(int capacity);
void erase(int index);
void clear();
void push(bool value);
void pop();
int size() const;
int getRawSize() const;
StoreType* getRaw();
private:
void grow(int capacity);
BinaryArray(const BinaryArray& rhs);
void operator =(const BinaryArray& rhs);
private:
static StoreType BINARY_MASK[sizeof(StoreType) << 3];
static StoreType INDEX_BIT[sizeof(StoreType) << 3];
IAllocator& m_allocator;
StoreType* m_data;
int m_size;
int m_capacity;
};
} // namespace Lumix

View file

@ -1,469 +0,0 @@
#pragma once
#include <new>
#include "core/default_allocator.h"
#include "core/lumix.h"
#include "core/math_utils.h"
namespace Lumix
{
template <typename Key, typename Value>
class Map
{
private:
struct Node
{
Node(const Key& key, const Value& value) : key(key), value(value) { left = right = NULL; height = 1; }
Key key;
Value value;
Node* left;
Node* right;
Node* parent;
int height;
int getLeftHeight() { return left ? left->height : 0; }
int getRightHeight() { return right ? right->height : 0; }
};
public:
struct iterator
{
iterator(Node* node)
{
this->node = node;
}
Value& value()
{
return node->value;
}
Key& key()
{
return node->key;
}
Value& second()
{
return node->value;
}
Key& first()
{
return node->key;
}
bool operator !=(const iterator& rhs)
{
return node != rhs.node;
}
bool operator ==(const iterator& rhs)
{
return node == rhs.node;
}
void operator ++()
{
if(node->left != 0)
node = node->left;
else if(node->right != 0)
node = node->right;
else if(node->parent != 0)
{
if(node->parent->left == node && node->parent->right != 0)
{
node = node->parent->right;
}
else
{
Node* tmp = node;
do
{
tmp = node;
node = node->parent;
}
while(node && (node->right == 0 || node->right == tmp));
if(node)
{
node = node->right;
}
}
}
else
{
node = 0;
}
}
private:
Node* node;
};
public:
Map(IAllocator& allocator)
: m_allocator(allocator)
{
m_root = NULL;
m_size = 0;
}
~Map()
{
clear();
}
int size()
{
return m_size;
}
void clear()
{
clearNode(m_root);
m_root = 0;
}
iterator begin() const
{
return iterator(m_root);
}
iterator end() const
{
return iterator(0);
}
bool contains(const Key& key)
{
return _find(key) != NULL;
}
iterator find(const Key& key) const
{
Node* node = _find(key);
if(node != NULL && node->key == key)
{
return iterator(node);
}
return iterator(NULL);
}
bool find(const Key& key, Value& value) const
{
Node* node = _find(key);
if(node != 0 && node->key == key)
{
value = node->value;
return true;
}
return false;
}
Value& operator[](const Key& key)
{
Node* node = _find(key);
if(!node || node->key != key)
{
Node* new_node = new (m_allocator.allocate(sizeof(Node))) Node(key, Value());
++m_size;
insert(key, m_root, NULL, new_node);
return new_node->value;
}
return node->value;
}
void insert(const Key& key, const Value& value)
{
Node* new_node = new (static_cast<Node*>(m_allocator.allocate(sizeof(Node)))) Node(key, value);
++m_size;
insert(key, m_root, 0, new_node);
}
void erase(const Key& key)
{
m_root = deleteNode(key, m_root);
}
void erase(iterator& iter)
{
m_root = deleteNode(iter.key(), m_root);
}
private:
void clearNode(Node* node)
{
if(node)
{
clearNode(node->left);
clearNode(node->right);
--m_size;
node->value.~Value();
m_allocator.deallocate(node);
}
}
Node* rotateLeft(Node*& node)
{
Node* rightChild = node->right;
node->right = rightChild->left;
if(node->right)
node->right->parent = node;
rightChild->left = node;
rightChild->parent = node->parent;
if(rightChild->left)
rightChild->left->parent = rightChild;
rightChild->height = Math::maxValue(rightChild->getLeftHeight(), rightChild->getRightHeight()) + 1;
node->height = Math::maxValue(node->getLeftHeight(), node->getRightHeight()) + 1;
node = rightChild;
return node;
}
Node* rotateRight(Node*& node)
{
Node* leftChild = node->left;
node->left = leftChild->right;
if(node->left)
node->left->parent = node;
leftChild->right = node;
leftChild->parent = node->parent;
if(leftChild->right)
leftChild->right->parent = leftChild;
leftChild->height = Math::maxValue(leftChild->getLeftHeight(), leftChild->getRightHeight()) + 1;
node->height = Math::maxValue(node->getLeftHeight(), node->getRightHeight()) + 1;
node = leftChild;
return node;
}
Node* insert(const Key& key, Node*& node, Node* parent, Node* new_node)
{
Node* ret = node;
if(node == 0)
{
node = new_node;
node->parent = parent;
ret = node;
}
else if(key < node->key)
{
node->left = insert(key, node->left, node, new_node);
if(node->getLeftHeight() - node->getRightHeight() == 2)
{
if(key < node->left->key)
{
ret = rotateRight(node);
}
else
{
node->left = rotateLeft(node->left);
ret = rotateRight(node);
}
}
}
else if(node->key < key)
{
node->right = insert(key, node->right, node, new_node);
if(node->getRightHeight() - node->getLeftHeight() == 2)
{
if(node->right->key < key)
{
ret = rotateLeft(node);
}
else
{
node->right = rotateRight(node->right);
ret = rotateLeft(node);
}
}
}
else
{
ASSERT(false); // key == node->key -> key already in tree
}
ret->height = Math::maxValue(node->getLeftHeight(), node->getRightHeight()) + 1;
return ret;
}
Node* _find(const Key& key) const
{
Node* node = m_root;
Node* found = 0;
while(node)
{
if(key < node->key)
{
node = node->left;
}
else
{
found = node;
node = node->right;
}
}
return found;
}
Node* deleteNode(const Key& key, Node* root)
{
if (root == NULL)
return root;
if ( key < root->key )
root->left = deleteNode(key, root->left);
else if( key > root->key )
root->right = deleteNode(key, root->right);
else
{
if( (root->left == NULL) || (root->right == NULL) )
{
Node *temp = root->left ? root->left : root->right;
if(temp == NULL)
{
temp = root;
root = NULL;
}
else
{
temp->parent = root->parent;
if(root->parent)
{
if(root->parent->left == root)
{
root->parent->left = temp;
}
else
{
root->parent->right = temp;
}
}
Node* swap = temp;
temp = root;
root = swap;
}
--m_size;
temp->value.~Value();
m_allocator.deallocate(temp);
}
else
{
Node* temp = getMinValueNode(root->right);
swap(temp, root);
root->right = deleteNode(temp->key, root->right);
}
}
if (root == NULL)
return root;
root->height = Math::maxValue(root->getLeftHeight(), root->getRightHeight()) + 1;
int balance = root->getLeftHeight() - root->getRightHeight();
int left_balance = root->left ? (root->left->getLeftHeight() - root->left->getRightHeight()) : 0;
if (balance > 1 && left_balance >= 0)
return rotateRight(root);
if (balance > 1 && left_balance < 0)
{
root->left = rotateLeft(root->left);
return rotateRight(root);
}
int right_balance = root->right ? (root->right->getLeftHeight() - root->right->getRightHeight()) : 0;
if (balance < -1 && right_balance <= 0)
return rotateLeft(root);
// Right Left Case
if (balance < -1 && right_balance > 0)
{
root->right = rotateRight(root->right);
return rotateLeft(root);
}
return root;
}
void swap(Node*& a, Node*& b)
{
Node* tmp = a->left;
a->left = b->left;
b->left = tmp;
if(a->left)
{
a->left->parent = a;
}
if(b->left)
{
b->left->parent = b;
}
tmp = a->right;
a->right = b->right;
b->right = tmp;
if(a->right)
{
a->right->parent = a;
}
if(b->right)
{
b->right->parent = b;
}
tmp = a->parent;
a->parent = b->parent;
if(b->parent)
{
if(b->parent->left == b)
{
a->parent->left = a;
}
else
{
a->parent->right = a;
}
}
b->parent = tmp;
if(tmp)
{
if(tmp->left == a)
{
tmp->left = b;
}
else
{
tmp->right = b;
}
}
tmp = a;
a = b;
b = tmp;
}
Node* getMinValueNode(Node* node)
{
Node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
private:
Node* m_root;
int m_size;
IAllocator& m_allocator;
};
} // !namespace Lumix

View file

@ -1,5 +1,5 @@
#include "core/input_system.h"
#include "core/map.h"
#include "core/associative_array.h"
#include "core/string.h"
#include <Windows.h>
@ -22,7 +22,7 @@ namespace Lumix
};
IAllocator& m_allocator;
Map<uint32_t, Action> m_actions;
AssociativeArray<uint32_t, Action> m_actions;
float m_mouse_rel_x;
float m_mouse_rel_y;
bool m_is_enabled;

View file

@ -1,6 +1,7 @@
#include "debug/stack_tree.h"
#include "core/lumix.h"
#include "core/MT/atomic.h"
#include "core/string.h"
#include <Windows.h>
#include <cstdio>
#include <Dbghelp.h>
@ -65,6 +66,16 @@ namespace Debug
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
SymFromAddr(process, (DWORD64)(node->m_instruction), 0, symbol);
IMAGEHLP_LINE line;
DWORD offset;
SymGetLineFromAddr(process, (DWORD64)(node->m_instruction), &offset, &line);
OutputDebugString("\t");
OutputDebugString(line.FileName);
OutputDebugString("(");
char tmp[20];
toCString((uint32_t)line.LineNumber, tmp, sizeof(tmp));
OutputDebugString(tmp);
OutputDebugString("):");
OutputDebugString("\t");
OutputDebugString(symbol->Name);
OutputDebugString("\n");

View file

@ -2,7 +2,7 @@
#include "core/array.h"
#include "core/crc32.h"
#include "core/iserializer.h"
#include "core/map.h"
#include "core/math_utils.h"
#include "core/string.h"
#include "editor/ieditor_command.h"
#include "editor/world_editor.h"
@ -42,15 +42,15 @@ namespace Lumix
virtual void execute() override
{
Map<uint32_t, Array<Entity> >::iterator iter = m_entity_system.m_instances.find(m_template_name_hash);
if (iter != m_entity_system.m_instances.end())
int instance_index = m_entity_system.m_instances.find(m_template_name_hash);
if (instance_index >= 0)
{
m_entity = m_entity_system.m_editor.getEngine().getUniverse()->createEntity();
m_entity.setPosition(m_position);
m_entity.setRotation(m_rotation);
iter.second().push(m_entity);
Entity template_entity = iter.second()[0];
m_entity_system.m_instances.at(instance_index).push(m_entity);
Entity template_entity = m_entity_system.m_instances.at(instance_index)[0];
const WorldEditor::ComponentList& template_cmps = m_editor.getComponents(template_entity);
for (int i = 0; i < template_cmps.size(); ++i)
{
@ -163,7 +163,7 @@ namespace Lumix
uint32_t tpl = getTemplate(entity);
if (tpl != 0)
{
Array<Entity>& instances = m_instances.find(tpl).second();
Array<Entity>& instances = m_instances.get(tpl);
instances.eraseItemFast(entity);
if (instances.empty())
{
@ -184,11 +184,11 @@ namespace Lumix
virtual void createTemplateFromEntity(const char* name, const Entity& entity) override
{
uint32_t name_hash = crc32(name);
if (m_instances.find(name_hash) == m_instances.end())
if (m_instances.find(name_hash) >= 0)
{
m_template_names.push(string(name, m_editor.getAllocator()));
m_instances.insert(name_hash, Array<Entity>(m_editor.getAllocator()));
m_instances.find(name_hash).second().push(entity);
m_instances.get(name_hash).push(entity);
m_updated.invoke();
}
else
@ -200,14 +200,14 @@ namespace Lumix
virtual uint32_t getTemplate(const Entity& entity) override
{
for (auto iter = m_instances.begin(), end = m_instances.end(); iter != end; ++iter)
for (int j = 0; j < m_instances.size(); ++j)
{
Array<Entity>& entities = iter.second();
Array<Entity>& entities = m_instances.at(j);
for (int i = 0, c = entities.size(); i < c; ++i)
{
if (entities[i] == entity)
{
return iter.first();
return m_instances.getKey(j);
}
}
}
@ -217,13 +217,13 @@ namespace Lumix
virtual const Array<Entity>& getInstances(uint32_t template_name_hash) override
{
Map<uint32_t, Array<Entity> >::iterator iter = m_instances.find(template_name_hash);
if (iter == m_instances.end())
int instances_index = m_instances.find(template_name_hash);
if (instances_index < 0)
{
m_instances.insert(template_name_hash, Array <Entity>(m_editor.getAllocator()));
iter = m_instances.find(template_name_hash);
instances_index = m_instances.find(template_name_hash);
}
return iter.second();
return m_instances.at(instances_index);
}
@ -246,13 +246,14 @@ namespace Lumix
serializer.endArray();
serializer.serialize("instance_count", (int32_t)m_instances.size());
serializer.beginArray("instances");
for (auto i = m_instances.begin(), end = m_instances.end(); i != end; ++i)
for (int i = 0; i < m_instances.size(); ++i)
{
serializer.serializeArrayItem(i.first());
serializer.serializeArrayItem((int32_t)i.second().size());
for (int j = 0, c = i.second().size(); j < c; ++j)
serializer.serializeArrayItem(m_instances.getKey(i));
Array<Entity>& entities = m_instances.at(i);
serializer.serializeArrayItem((int32_t)entities.size());
for (int j = 0, c = entities.size(); j < c; ++j)
{
serializer.serializeArrayItem(i.second()[j].index);
serializer.serializeArrayItem(entities[j].index);
}
}
serializer.endArray();
@ -284,7 +285,7 @@ namespace Lumix
int32_t instances_per_template;
serializer.deserializeArrayItem(instances_per_template, 0);
m_instances.insert(hash, Array<Entity>(m_editor.getAllocator()));
Array<Entity>& entities = m_instances.find(hash).second();
Array<Entity>& entities = m_instances.get(hash);
for (int j = 0; j < instances_per_template; ++j)
{
int32_t entity_index;
@ -310,7 +311,7 @@ namespace Lumix
private:
Map<uint32_t, Array<Entity> > m_instances;
AssociativeArray<uint32_t, Array<Entity> > m_instances;
Array<string> m_template_names;
Universe* m_universe;
WorldEditor& m_editor;

View file

@ -3,6 +3,7 @@
#include "animation/animation_system.h"
#include "core/aabb.h"
#include "core/array.h"
#include "core/associative_array.h"
#include "core/blob.h"
#include "core/crc32.h"
#include "core/delegate_list.h"
@ -15,7 +16,6 @@
#include "core/input_system.h"
#include "core/json_serializer.h"
#include "core/log.h"
#include "core/map.h"
#include "core/matrix.h"
#include "core/mt/mutex.h"
#include "core/profiler.h"
@ -576,10 +576,10 @@ struct WorldEditorImpl : public WorldEditor
for (int j = cmps.size() - 1; j >= 0; --j)
{
m_old_values.write(cmps[j].type);
Map<uint32_t, Array<IPropertyDescriptor*> >::iterator iter = m_editor.m_component_properties.find(cmps[j].type);
if (iter != m_editor.m_component_properties.end())
int props_index = m_editor.m_component_properties.find(cmps[j].type);
if (props_index >= 0)
{
Array<IPropertyDescriptor*>& props = iter.second();
Array<IPropertyDescriptor*>& props = m_editor.m_component_properties.get(props_index);
for (int k = 0; k < props.size(); ++k)
{
props[k]->get(cmps[j], m_old_values);
@ -623,11 +623,11 @@ struct WorldEditorImpl : public WorldEditor
break;
}
}
Map<uint32_t, Array<IPropertyDescriptor*> >::iterator iter = m_editor.m_component_properties.find(cmp_type);
if (iter != m_editor.m_component_properties.end())
int props_index = m_editor.m_component_properties.find(cmp_type);
if (props_index >= 0)
{
Array<IPropertyDescriptor*>& props = iter.second();
Array<IPropertyDescriptor*>& props = m_editor.m_component_properties.get(props_index);
for (int k = 0; k < props.size(); ++k)
{
@ -678,7 +678,8 @@ struct WorldEditorImpl : public WorldEditor
{
uint32_t template_hash = m_editor.m_template_system->getTemplate(m_component.entity);
const Array<IScene*>& scenes = m_editor.m_engine->getScenes();
Map<uint32_t, Array<IPropertyDescriptor*> >::iterator iter = m_editor.m_component_properties.find(m_component.type);
int props_index = m_editor.m_component_properties.find(m_component.type);
if (template_hash == 0)
{
for (int i = 0; i < scenes.size(); ++i)
@ -691,9 +692,9 @@ struct WorldEditorImpl : public WorldEditor
}
}
m_old_values.rewindForRead();
if (iter != m_editor.m_component_properties.end())
if (props_index >= 0)
{
const Array<IPropertyDescriptor*>& props = iter.second();
const Array<IPropertyDescriptor*>& props = m_editor.m_component_properties.get(props_index);
for (int i = 0; i < props.size(); ++i)
{
props[i]->set(m_component, m_old_values);
@ -711,9 +712,9 @@ struct WorldEditorImpl : public WorldEditor
if (cmp_new.isValid())
{
m_old_values.rewindForRead();
if (iter != m_editor.m_component_properties.end())
if (props_index >= 0)
{
const Array<IPropertyDescriptor*>& props = iter.second();
const Array<IPropertyDescriptor*>& props = m_editor.m_component_properties.get(props_index);
for (int i = 0; i < props.size(); ++i)
{
props[i]->set(cmp_new, m_old_values);
@ -1570,6 +1571,7 @@ struct WorldEditorImpl : public WorldEditor
void load(FS::IFile& file, const char* path)
{
m_components.clear();
m_components.reserve(5000);
g_log_info.log("editor") << "parsing universe...";
JsonSerializer serializer(file, JsonSerializer::READ, path);
m_engine->deserialize(serializer);
@ -1588,13 +1590,13 @@ struct WorldEditorImpl : public WorldEditor
virtual Array<Component>& getComponents(const Entity& entity) override
{
Map<int32_t, Array<Component> >::iterator iter = m_components.find(entity.index);
if (iter == m_components.end())
int cmps_index = m_components.find(entity.index);
if (cmps_index < 0)
{
m_components.insert(entity.index, Array<Component>(m_allocator));
iter = m_components.find(entity.index);
cmps_index = m_components.find(entity.index);
}
return iter.second();
return m_components.at(cmps_index);
}
virtual Component getComponent(const Entity& entity, uint32_t type) override
@ -1717,15 +1719,13 @@ struct WorldEditorImpl : public WorldEditor
{
m_allocator.deleteObject(m_measure_tool);
destroyUndoStack();
auto iter = m_component_properties.begin();
auto end = m_component_properties.end();
while (iter != end)
for (int j = 0; j < m_component_properties.size(); ++j)
{
for (int i = 0, c = iter.second().size(); i < c; ++i)
Array<IPropertyDescriptor*>& props = m_component_properties.at(j);
for (int i = 0, c = props.size(); i < c; ++i)
{
m_allocator.deleteObject(iter.second()[i]);
m_allocator.deleteObject(props[i]);
}
++iter;
}
destroyUniverse();
@ -1815,13 +1815,13 @@ struct WorldEditorImpl : public WorldEditor
virtual Array<IPropertyDescriptor*>& getPropertyDescriptors(uint32_t type) override
{
Map<uint32_t, Array<IPropertyDescriptor*> >::iterator iter = m_component_properties.find(type);
if (iter == m_component_properties.end())
int props_index = m_component_properties.find(type);
if (props_index < 0)
{
m_component_properties.insert(type, Array<IPropertyDescriptor*>(m_allocator));
iter = m_component_properties.find(type);
props_index = m_component_properties.find(type);
}
return iter.second();
return m_component_properties.at(props_index);
}
@ -2175,12 +2175,12 @@ struct WorldEditorImpl : public WorldEditor
MT::Mutex m_universe_mutex;
Gizmo m_gizmo;
Array<Entity> m_selected_entities;
Map<uint32_t, Array<IPropertyDescriptor*> > m_component_properties;
AssociativeArray<uint32_t, Array<IPropertyDescriptor*> > m_component_properties;
MouseMode::Value m_mouse_mode;
float m_mouse_x;
float m_mouse_y;
Array<EditorIcon*> m_editor_icons;
Map<int32_t, Array<Component> > m_components;
AssociativeArray<int32_t, Array<Component> > m_components;
bool m_is_game_mode;
FS::IFile* m_game_mode_file;
Engine* m_engine;

View file

@ -2,6 +2,7 @@
#include "culling_system.h"
#include "core/array.h"
#include "core/binary_array.h"
#include "core/frustum.h"
#include "core/sphere.h"
@ -11,7 +12,7 @@
namespace Lumix
{
typedef Array<bool> VisibilityFlags;
typedef BinaryArray VisibilityFlags;
static const int MIN_ENTITIES_PER_THREAD = 50;
@ -19,7 +20,7 @@ namespace Lumix
int start_index,
const Sphere* LUMIX_RESTRICT start,
const Sphere* LUMIX_RESTRICT end,
const bool* LUMIX_RESTRICT visiblity_flags,
const VisibilityFlags& visiblity_flags,
const Frustum* LUMIX_RESTRICT frustum,
CullingSystem::Subresults& results
)
@ -38,7 +39,7 @@ namespace Lumix
class CullingJob : public MTJD::Job
{
public:
CullingJob(const CullingSystem::InputSpheres& spheres, VisibilityFlags& visibility_flags, CullingSystem::Subresults& results, int start, int end, const Frustum& frustum, MTJD::Manager& manager, IAllocator& allocator)
CullingJob(const CullingSystem::InputSpheres& spheres, const VisibilityFlags& visibility_flags, CullingSystem::Subresults& results, int start, int end, const Frustum& frustum, MTJD::Manager& manager, IAllocator& allocator)
: Job(true, MTJD::Priority::Default, false, manager, allocator)
, m_spheres(spheres)
, m_results(results)
@ -60,14 +61,14 @@ namespace Lumix
virtual void execute() override
{
ASSERT(m_results.empty() && !m_is_executed);
doCulling(m_start, &m_spheres[m_start], &m_spheres[m_end], &m_visibility_flags[0], &m_frustum, m_results);
doCulling(m_start, &m_spheres[m_start], &m_spheres[m_end], m_visibility_flags, &m_frustum, m_results);
m_is_executed = true;
}
private:
const CullingSystem::InputSpheres& m_spheres;
CullingSystem::Subresults& m_results;
VisibilityFlags& m_visibility_flags;
const VisibilityFlags& m_visibility_flags;
int m_start;
int m_end;
const Frustum& m_frustum;
@ -130,7 +131,7 @@ namespace Lumix
{
m_result[i].clear();
}
doCulling(0, &m_spheres[0], &m_spheres.back(), &m_visibility_flags[0], &frustum, m_result[0]);
doCulling(0, &m_spheres[0], &m_spheres.back(), m_visibility_flags, &frustum, m_result[0]);
m_is_async_result = false;
}
@ -188,8 +189,8 @@ namespace Lumix
virtual void addStatic(const Sphere& sphere) override
{
m_spheres.push(sphere);
m_visibility_flags.push(true);
m_spheres.push(sphere);
m_visibility_flags.push(true);
}

View file

@ -1,13 +1,13 @@
#include "graphics/pipeline.h"
#include "graphics/gl_ext.h"
#include "core/array.h"
#include "core/associative_array.h"
#include "core/crc32.h"
#include "core/frustum.h"
#include "core/fs/file_system.h"
#include "core/iserializer.h"
#include "core/json_serializer.h"
#include "core/log.h"
#include "core/map.h"
#include "core/profiler.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
@ -494,10 +494,10 @@ struct PipelineInstanceImpl : public PipelineInstance
void executeCustomCommand(uint32_t name)
{
Map<uint32_t, CustomCommandHandler>::iterator iter = m_custom_commands_handlers.find(name);
if (iter != m_custom_commands_handlers.end())
CustomCommandHandler handler;
if (m_custom_commands_handlers.find(name, handler))
{
iter.second().invoke();
handler.invoke();
}
}
@ -882,7 +882,7 @@ struct PipelineInstanceImpl : public PipelineInstance
Vec4 m_shadowmap_splits;
int m_width;
int m_height;
Map<uint32_t, CustomCommandHandler> m_custom_commands_handlers;
AssociativeArray<uint32_t, CustomCommandHandler> m_custom_commands_handlers;
Component m_active_camera;
Array<TerrainInfo> m_terrain_infos;
Array<GrassInfo> m_grass_infos;

View file

@ -205,9 +205,9 @@ namespace Lumix
{
m_allocator.deleteObject(m_grass_types[i]);
}
for(Map<Component, Array<GrassQuad*> >::iterator iter = m_grass_quads.begin(), end = m_grass_quads.end(); iter != end; ++iter)
for (int j = 0; j < m_grass_quads.size(); ++j)
{
Array<GrassQuad*>& quads = iter.value();
Array<GrassQuad*>& quads = m_grass_quads.at(j);
for (int i = 0; i < quads.size(); ++i)
{
m_allocator.deleteObject(quads[i]);
@ -323,9 +323,9 @@ namespace Lumix
void Terrain::forceGrassUpdate()
{
m_force_grass_update = true;
for(Map<Component, Array<GrassQuad*> >::iterator iter = m_grass_quads.begin(), end = m_grass_quads.end(); iter != end; ++iter)
for (int i = 0; i < m_grass_quads.size(); ++i)
{
Array<GrassQuad*>& quads = iter.value();
Array<GrassQuad*>& quads = m_grass_quads.at(i);
while(!quads.empty())
{
m_free_grass_quads.push(quads.back());
@ -336,13 +336,13 @@ namespace Lumix
Array<Terrain::GrassQuad*>& Terrain::getQuads(const Component& camera)
{
Map<Component, Array<GrassQuad*> >::iterator iter = m_grass_quads.find(camera);
if (iter == m_grass_quads.end())
int quads_index = m_grass_quads.find(camera);
if (quads_index < 0)
{
m_grass_quads.insert(camera, Array<GrassQuad*>(m_allocator));
iter = m_grass_quads.find(camera);
quads_index = m_grass_quads.find(camera);
}
return iter.second();
return m_grass_quads.at(quads_index);
}
@ -516,7 +516,7 @@ namespace Lumix
}
void Terrain::getGrassInfos(const Frustum& frustum, Array<GrassInfo>& infos, const Component& camera)
void Terrain::getGrassInfos(const Frustum&, Array<GrassInfo>& infos, const Component& camera)
{
updateGrass(camera);
Array<GrassQuad*>& quads = getQuads(camera);

View file

@ -2,6 +2,7 @@
#include "core/array.h"
#include "core/associative_array.h"
#include "core/matrix.h"
#include "core/resource.h"
#include "core/vec3.h"
@ -129,8 +130,8 @@ class Terrain
RenderScene& m_scene;
Array<GrassType*> m_grass_types;
Array<GrassQuad*> m_free_grass_quads;
Map<Component, Array<GrassQuad*> > m_grass_quads;
Map<Component, Vec3> m_last_camera_position;
AssociativeArray<Component, Array<GrassQuad*> > m_grass_quads;
AssociativeArray<Component, Vec3> m_last_camera_position;
Vec3 m_brush_position;
float m_brush_size;
bool m_force_grass_update;

View file

@ -0,0 +1,50 @@
#include "unit_tests/suite/lumix_unit_tests.h"
#include "core/binary_array.h"
#include <cstdio>
void UT_binary_array(const char* params)
{
Lumix::DefaultAllocator allocator;
Lumix::BinaryArray array(allocator);
LUMIX_EXPECT_EQ(array.size(), 0);
for (int i = 0; i < 100; ++i)
{
array.push(true);
}
for (int i = 0; i < 100; ++i)
{
LUMIX_EXPECT_TRUE(array[i]);
}
LUMIX_EXPECT_EQ(array.getRaw()[0], 0xffffFFFF);
for (int i = 0; i < 100; ++i)
{
array.push(false);
}
for (int i = 100; i < 200; ++i)
{
LUMIX_EXPECT_TRUE(array[i]);
}
LUMIX_EXPECT_EQ(array.size(), 200);
for (int i = 0; i < 150; ++i)
{
array.pop();
}
LUMIX_EXPECT_EQ(array.size(), 50);
LUMIX_EXPECT_EQ(array.getRawSize(), 2);
LUMIX_EXPECT_EQ(array.getRaw()[0], 0xffffFFFF);
array.clear();
for (int i = 0; i < 100; ++i)
{
array.push(i == 2 || i == 50);
}
array.erase(50);
array.erase(2);
LUMIX_EXPECT_EQ(array.getRaw()[0], 0);
LUMIX_EXPECT_EQ(array.getRaw()[1], 0);
}
REGISTER_TEST("unit_tests/core/binary_array", UT_binary_array, "")

View file

@ -107,18 +107,19 @@ namespace Lumix
const char* Entity::getName() const
{
auto iter = universe->m_id_to_name_map.find(index);
return iter == universe->m_id_to_name_map.end() ? "" : iter.value().c_str();
int name_index = universe->m_id_to_name_map.find(index);
return name_index < 0 ? "" : universe->m_id_to_name_map.at(name_index).c_str();
}
void Entity::setName(const char* name)
{
auto iter = universe->m_id_to_name_map.find(index);
if (iter != universe->m_id_to_name_map.end())
int name_index = universe->m_id_to_name_map.find(index);
if (name_index >= 0)
{
universe->m_name_to_id_map.erase(crc32(iter.value().c_str()));
universe->m_id_to_name_map.erase(iter);
uint32_t hash = crc32(universe->m_id_to_name_map.at(name_index).c_str());
universe->m_name_to_id_map.erase(hash);
universe->m_id_to_name_map.eraseAt(name_index);
}
if (name && name[0] != '\0')

View file

@ -134,10 +134,10 @@ void Universe::serialize(ISerializer& serializer)
serializer.serialize("name_count", m_id_to_name_map.size());
serializer.beginArray("names");
for (auto iter = m_id_to_name_map.begin(), end = m_id_to_name_map.end(); iter != end; ++iter)
for (int i = 0, c = m_id_to_name_map.size(); i < c; ++i)
{
serializer.serializeArrayItem(iter.key());
serializer.serializeArrayItem(iter.value().c_str());
serializer.serializeArrayItem(m_id_to_name_map.getKey(i));
serializer.serializeArrayItem(m_id_to_name_map.get(i).c_str());
}
serializer.endArray();
@ -223,14 +223,7 @@ Component Universe::addComponent(const Entity& entity, uint32_t component_type,
bool Universe::nameExists(const char* name) const
{
for (auto iter = m_id_to_name_map.begin(), end = m_id_to_name_map.end(); iter != end; ++iter)
{
if (iter.value() == name)
{
return true;
}
}
return false;
return m_name_to_id_map.find(crc32(name)) != -1;
}

View file

@ -3,8 +3,8 @@
#include "core/lumix.h"
#include "core/array.h"
#include "core/associative_array.h"
#include "core/delegate_list.h"
#include "core/map.h"
#include "core/quat.h"
#include "core/string.h"
#include "core/vec3.h"
@ -59,8 +59,8 @@ class LUMIX_ENGINE_API Universe final
Array<Vec3> m_positions;
Array<Quat> m_rotations;
Array<int> m_free_slots;
Map<uint32_t, uint32_t> m_name_to_id_map;
Map<uint32_t, string> m_id_to_name_map;
AssociativeArray<uint32_t, uint32_t> m_name_to_id_map;
AssociativeArray<uint32_t, string> m_id_to_name_map;
DelegateList<void(const Entity&)> m_entity_moved;
DelegateList<void(const Entity&)> m_entity_created;
DelegateList<void(const Entity&)> m_entity_destroyed;