瀏覽代碼

WIP: swap/sort functionalities

Michele Caini 8 年之前
父節點
當前提交
b35737b5d7
共有 2 個文件被更改,包括 79 次插入1 次删除
  1. 17 0
      src/registry.hpp
  2. 62 1
      src/sparse_set.hpp

+ 17 - 0
src/registry.hpp

@@ -368,6 +368,23 @@ public:
         (void)accumulator;
     }
 
+    template<typename Comp>
+    void swap(entity_type lhs, entity_type rhs) {
+        std::get<ident<Component...>.template get<Comp>()>(pool).swap(lhs, rhs);
+    }
+
+    template<typename Comp, typename Compare>
+    void sort(Compare compare) {
+        std::get<ident<Component...>.template get<Comp>()>(pool).sort(std::move(compare));
+    }
+
+    template<typename To, typename From, typename Compare>
+    void sort() {
+        auto &&to = std::get<ident<Component...>.template get<To>()>(pool);
+        auto &&from = std::get<ident<Component...>.template get<From>()>(pool);
+        to.sort(from);
+    }
+
     template<typename Comp>
     void reset(entity_type entity) {
         assert(valid(entity));

+ 62 - 1
src/sparse_set.hpp

@@ -2,6 +2,7 @@
 #define ENTT_COMPONENT_POOL_HPP
 
 
+#include <algorithm>
 #include <utility>
 #include <vector>
 #include <cstddef>
@@ -69,7 +70,7 @@ public:
     SparseSet(const SparseSet &) = delete;
     SparseSet(SparseSet &&) = default;
 
-    virtual ~SparseSet() noexcept {
+    ~SparseSet() noexcept {
         assert(empty());
     }
 
@@ -132,6 +133,14 @@ public:
         return pos;
     }
 
+    void swap(index_type lhs, index_type rhs) {
+        assert(valid(lhs));
+        assert(valid(rhs));
+
+        std::swap(direct[reverse[lhs]], direct[reverse[rhs]]);
+        std::swap(reverse[lhs], reverse[rhs]);
+    }
+
     void reset() {
         reverse.resize(0);
         direct.clear();
@@ -145,6 +154,22 @@ private:
 
 template<typename Index, typename Type>
 class SparseSet<Index, Type> final: public SparseSet<Index> {
+    template<typename Compare>
+    void arrange(Compare compare) {
+        const auto *data = SparseSet<Index>::data();
+        const auto size = SparseSet<Index>::size();
+        std::vector<pos_type> copy(size);
+        pos_type pos = 0;
+
+        std::generate(copy.begin(), copy.end(), [&pos]() { return pos++; });
+        std::sort(copy.begin(), copy.end(), compare);
+
+        for(pos_type i = 0; i < copy.size(); ++i) {
+            SparseSet<Index>::swap(data + copy[i], data + i);
+            std::swap(instances[copy[i]], instances[i]);
+        }
+    }
+
 public:
     using type = Type;
     using index_type = typename SparseSet<Index>::index_type;
@@ -189,6 +214,42 @@ public:
         instances.pop_back();
     }
 
+    void swap(index_type lhs, index_type rhs) {
+        std::swap(SparseSet<Index>::get(lhs), SparseSet<Index>::get(rhs));
+        SparseSet<Index>::swap(lhs, rhs);
+    }
+
+    template<typename Compare>
+    void sort(Compare compare) {
+        arrange([this, compare = std::move(compare)](auto lhs, auto rhs) {
+            return !compare(instances[lhs], instances[rhs]);
+        });
+    }
+
+    template<typename Idx>
+    void sort(const SparseSet<Index> &other) {
+        const auto *data = SparseSet<Index>::data();
+
+        arrange([data, &other](auto lhs, auto rhs) {
+            auto eLhs = data + lhs;
+            auto eRhs = data + rhs;
+
+            bool bLhs = other.has(eLhs);
+            bool bRhs = other.has(eRhs);
+            bool compare = false;
+
+            if(bLhs && bRhs) {
+                compare = other.get(eLhs) < other.get(eRhs);
+            } else if(!bLhs && !bRhs) {
+                compare = eLhs < eRhs;
+            } else {
+                compare = bLhs;
+            }
+
+            return !compare;
+        });
+    }
+
     void reset() {
         SparseSet<Index>::reset();
         instances.clear();