mirror of https://github.com/AxioDL/metaforce.git
CSortedLists: Use std::array where applicable
Prevents implicit array to pointer decay and allows us to simplify a bit of the code.
This commit is contained in:
parent
f5d486f0ca
commit
a5ab077dc3
|
@ -1,20 +1,32 @@
|
||||||
#include "CSortedLists.hpp"
|
#include "Runtime/CSortedLists.hpp"
|
||||||
#include "World/CActor.hpp"
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include "Runtime/World/CActor.hpp"
|
||||||
|
|
||||||
namespace urde {
|
namespace urde {
|
||||||
|
namespace {
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
static std::remove_reference_t<decltype(std::declval<T>()[0])>& AccessElement(T& arr, S idx) {
|
auto AccessElement(T& arr, S idx) -> typename T::reference {
|
||||||
assert(std::extent<T>::value > idx && idx >= 0);
|
assert(std::size(arr) > static_cast<size_t>(idx) && idx >= 0);
|
||||||
return arr[idx];
|
return arr[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
auto AccessElement(const T& arr, S idx) -> typename T::const_reference {
|
||||||
|
assert(std::size(arr) > static_cast<size_t>(idx) && idx >= 0);
|
||||||
|
return arr[idx];
|
||||||
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
CSortedListManager::CSortedListManager() { Reset(); }
|
CSortedListManager::CSortedListManager() { Reset(); }
|
||||||
|
|
||||||
void CSortedListManager::Reset() {
|
void CSortedListManager::Reset() {
|
||||||
std::fill(std::begin(x0_nodes), std::end(x0_nodes), SNode());
|
x0_nodes.fill(SNode{});
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
xb000_sortedLists[i].Reset();
|
for (auto& list : xb000_sortedLists) {
|
||||||
|
list.Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) const {
|
void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) const {
|
||||||
|
@ -33,32 +45,39 @@ void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) c
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) {
|
void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) {
|
||||||
SSortedList& sl = xb000_sortedLists[u32(list)];
|
const auto listIndex = static_cast<size_t>(list);
|
||||||
|
SSortedList& sl = xb000_sortedLists[listIndex];
|
||||||
|
|
||||||
while (idx < sl.x800_size - 1) {
|
while (idx < sl.x800_size - 1) {
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx;
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[listIndex] = idx;
|
||||||
AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1);
|
AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1);
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
--sl.x800_size;
|
--sl.x800_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSortedListManager::MoveInList(ESortedList list, s16 idx) {
|
void CSortedListManager::MoveInList(ESortedList list, s16 idx) {
|
||||||
SSortedList& sl = xb000_sortedLists[int(list)];
|
const auto listIndex = static_cast<size_t>(list);
|
||||||
|
SSortedList& sl = xb000_sortedLists[listIndex];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (idx > 0 && AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x4_box[int(list)] >
|
if (idx > 0 && AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x4_box[listIndex] >
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) {
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[listIndex]) {
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[int(list)] = idx;
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[listIndex] = idx;
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx - 1;
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[listIndex] = idx - 1;
|
||||||
std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1));
|
std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1));
|
||||||
--idx;
|
--idx;
|
||||||
} else {
|
} else {
|
||||||
if (idx >= sl.x800_size - 1)
|
if (idx >= sl.x800_size - 1) {
|
||||||
return;
|
return;
|
||||||
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x4_box[int(list)] >=
|
}
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)])
|
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x4_box[listIndex] >=
|
||||||
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[listIndex]) {
|
||||||
return;
|
return;
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx;
|
}
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx + 1;
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[listIndex] = idx;
|
||||||
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[listIndex] = idx + 1;
|
||||||
std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1));
|
std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1));
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
@ -66,11 +85,13 @@ void CSortedListManager::MoveInList(ESortedList list, s16 idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSortedListManager::InsertInList(ESortedList list, SNode& node) {
|
void CSortedListManager::InsertInList(ESortedList list, SNode& node) {
|
||||||
SSortedList& sl = xb000_sortedLists[int(list)];
|
const auto listIndex = static_cast<size_t>(list);
|
||||||
|
SSortedList& sl = xb000_sortedLists[listIndex];
|
||||||
int insIdx = 0;
|
int insIdx = 0;
|
||||||
|
|
||||||
for (int i = sl.x800_size; i > 0;) {
|
for (int i = sl.x800_size; i > 0;) {
|
||||||
/* Binary search cycle to find insert index */
|
/* Binary search cycle to find insert index */
|
||||||
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, insIdx + i / 2)).x4_box[int(list)] < node.x4_box[int(list)]) {
|
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, insIdx + i / 2)).x4_box[listIndex] < node.x4_box[listIndex]) {
|
||||||
/* Upper */
|
/* Upper */
|
||||||
insIdx = insIdx + i / 2 + 1;
|
insIdx = insIdx + i / 2 + 1;
|
||||||
i = i - i / 2 - 1;
|
i = i - i / 2 - 1;
|
||||||
|
@ -82,22 +103,24 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node) {
|
||||||
|
|
||||||
/* Shift ids for insert */
|
/* Shift ids for insert */
|
||||||
for (int i = sl.x800_size; i > insIdx; --i) {
|
for (int i = sl.x800_size; i > insIdx; --i) {
|
||||||
AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[int(list)] = i;
|
AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[listIndex] = i;
|
||||||
AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1);
|
AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do insert */
|
/* Do insert */
|
||||||
AccessElement(sl.x0_ids, insIdx) = node.x0_actor->GetUniqueId().Value();
|
AccessElement(sl.x0_ids, insIdx) = node.x0_actor->GetUniqueId().Value();
|
||||||
node.x1c_selfIdxs[int(list)] = s16(insIdx);
|
node.x1c_selfIdxs[listIndex] = s16(insIdx);
|
||||||
++sl.x800_size;
|
++sl.x800_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const {
|
s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const {
|
||||||
const SSortedList& sl = xb000_sortedLists[int(list)];
|
const auto listIndex = static_cast<size_t>(list);
|
||||||
|
const SSortedList& sl = xb000_sortedLists[listIndex];
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
for (int i = sl.x800_size; i > 0;) {
|
for (int i = sl.x800_size; i > 0;) {
|
||||||
/* Binary search cycle to find index */
|
/* Binary search cycle to find index */
|
||||||
if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)])) {
|
if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex])) {
|
||||||
/* Upper */
|
/* Upper */
|
||||||
idx = idx + i / 2 + 1;
|
idx = idx + i / 2 + 1;
|
||||||
i = i - i / 2 - 1;
|
i = i - i / 2 - 1;
|
||||||
|
@ -106,15 +129,18 @@ s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const {
|
||||||
i /= 2;
|
i /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 CSortedListManager::FindInListLower(ESortedList list, float val) const {
|
s16 CSortedListManager::FindInListLower(ESortedList list, float val) const {
|
||||||
const SSortedList& sl = xb000_sortedLists[int(list)];
|
const auto listIndex = static_cast<size_t>(list);
|
||||||
|
const SSortedList& sl = xb000_sortedLists[listIndex];
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
for (int i = sl.x800_size; i > 0;) {
|
for (int i = sl.x800_size; i > 0;) {
|
||||||
/* Binary search cycle to find index */
|
/* Binary search cycle to find index */
|
||||||
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)] < val) {
|
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex] < val) {
|
||||||
/* Upper */
|
/* Upper */
|
||||||
idx = idx + i / 2 + 1;
|
idx = idx + i / 2 + 1;
|
||||||
i = i - i / 2 - 1;
|
i = i - i / 2 - 1;
|
||||||
|
@ -123,27 +149,28 @@ s16 CSortedListManager::FindInListLower(ESortedList list, float val) const {
|
||||||
i /= 2;
|
i /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) {
|
s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) {
|
||||||
int minXa = FindInListLower(ESortedList::MinX, aabb.min.x());
|
const int minXa = FindInListLower(ESortedList::MinX, aabb.min.x());
|
||||||
int maxXa = FindInListUpper(ESortedList::MinX, aabb.max.x());
|
const int maxXa = FindInListUpper(ESortedList::MinX, aabb.max.x());
|
||||||
int minXb = FindInListLower(ESortedList::MaxX, aabb.min.x());
|
const int minXb = FindInListLower(ESortedList::MaxX, aabb.min.x());
|
||||||
int maxXb = FindInListUpper(ESortedList::MaxX, aabb.max.x());
|
const int maxXb = FindInListUpper(ESortedList::MaxX, aabb.max.x());
|
||||||
int xEnd = std::min(int(xb000_sortedLists[3].x800_size) - maxXb, minXa) + (maxXb + (maxXa - minXa) - minXb) / 2;
|
const int xEnd = std::min(int(xb000_sortedLists[3].x800_size) - maxXb, minXa) + (maxXb + (maxXa - minXa) - minXb) / 2;
|
||||||
|
|
||||||
int minYa = FindInListLower(ESortedList::MinY, aabb.min.y());
|
const int minYa = FindInListLower(ESortedList::MinY, aabb.min.y());
|
||||||
int maxYa = FindInListUpper(ESortedList::MinY, aabb.max.y());
|
const int maxYa = FindInListUpper(ESortedList::MinY, aabb.max.y());
|
||||||
int minYb = FindInListLower(ESortedList::MaxY, aabb.min.y());
|
const int minYb = FindInListLower(ESortedList::MaxY, aabb.min.y());
|
||||||
int maxYb = FindInListUpper(ESortedList::MaxY, aabb.max.y());
|
const int maxYb = FindInListUpper(ESortedList::MaxY, aabb.max.y());
|
||||||
int yEnd = std::min(int(xb000_sortedLists[4].x800_size) - maxYb, minYa) + (maxYb + (maxYa - minYa) - minYb) / 2;
|
const int yEnd = std::min(int(xb000_sortedLists[4].x800_size) - maxYb, minYa) + (maxYb + (maxYa - minYa) - minYb) / 2;
|
||||||
|
|
||||||
int minZa = FindInListLower(ESortedList::MinZ, aabb.min.z());
|
const int minZa = FindInListLower(ESortedList::MinZ, aabb.min.z());
|
||||||
int maxZa = FindInListUpper(ESortedList::MinZ, aabb.max.z());
|
const int maxZa = FindInListUpper(ESortedList::MinZ, aabb.max.z());
|
||||||
int minZb = FindInListLower(ESortedList::MaxZ, aabb.min.z());
|
const int minZb = FindInListLower(ESortedList::MaxZ, aabb.min.z());
|
||||||
int maxZb = FindInListUpper(ESortedList::MaxZ, aabb.max.z());
|
const int maxZb = FindInListUpper(ESortedList::MaxZ, aabb.max.z());
|
||||||
int zEnd = std::min(int(xb000_sortedLists[5].x800_size) - maxZb, minZa) + (maxZb + (maxZa - minZa) - minZb) / 2;
|
const int zEnd = std::min(int(xb000_sortedLists[5].x800_size) - maxZb, minZa) + (maxZb + (maxZa - minZa) - minZb) / 2;
|
||||||
|
|
||||||
if (xEnd < yEnd && xEnd < zEnd) {
|
if (xEnd < yEnd && xEnd < zEnd) {
|
||||||
return CalculateIntersections(ESortedList::MinX, ESortedList::MaxX, minXa, maxXa, minXb, maxXb, ESortedList::MinY,
|
return CalculateIntersections(ESortedList::MinX, ESortedList::MaxX, minXa, maxXa, minXb, maxXb, ESortedList::MinY,
|
||||||
|
@ -160,31 +187,38 @@ s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) {
|
||||||
s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d,
|
s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d,
|
||||||
ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD,
|
ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD,
|
||||||
const zeus::CAABox& aabb) {
|
const zeus::CAABox& aabb) {
|
||||||
|
const auto listAIndex = static_cast<size_t>(la);
|
||||||
|
const auto listBIndex = static_cast<size_t>(lb);
|
||||||
|
|
||||||
s16 headId = -1;
|
s16 headId = -1;
|
||||||
s16 tailId = -1;
|
s16 tailId = -1;
|
||||||
for (int i = a; i < b; ++i)
|
for (int i = a; i < b; ++i) {
|
||||||
AddToLinkedList(AccessElement(xb000_sortedLists[int(la)].x0_ids, i), headId, tailId);
|
AddToLinkedList(AccessElement(xb000_sortedLists[listAIndex].x0_ids, i), headId, tailId);
|
||||||
for (int i = c; i < d; ++i)
|
}
|
||||||
AddToLinkedList(AccessElement(xb000_sortedLists[int(lb)].x0_ids, i), headId, tailId);
|
for (int i = c; i < d; ++i) {
|
||||||
|
AddToLinkedList(AccessElement(xb000_sortedLists[listBIndex].x0_ids, i), headId, tailId);
|
||||||
|
}
|
||||||
|
|
||||||
if (a < xb000_sortedLists[int(lb)].x800_size - d) {
|
if (a < xb000_sortedLists[listBIndex].x800_size - d) {
|
||||||
for (int i = 0; i < a; ++i) {
|
for (int i = 0; i < a; ++i) {
|
||||||
s16 id = AccessElement(xb000_sortedLists[int(la)].x0_ids, i);
|
const s16 id = AccessElement(xb000_sortedLists[listAIndex].x0_ids, i);
|
||||||
if (AccessElement(x0_nodes, id).x4_box[int(lb)] > aabb[int(lb)])
|
if (AccessElement(x0_nodes, id).x4_box[listBIndex] > aabb[listBIndex]) {
|
||||||
AddToLinkedList(id, headId, tailId);
|
AddToLinkedList(id, headId, tailId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = d; i < xb000_sortedLists[int(lb)].x800_size; ++i) {
|
for (int i = d; i < xb000_sortedLists[listBIndex].x800_size; ++i) {
|
||||||
s16 id = AccessElement(xb000_sortedLists[int(lb)].x0_ids, i);
|
const s16 id = AccessElement(xb000_sortedLists[listBIndex].x0_ids, i);
|
||||||
if (AccessElement(x0_nodes, id).x4_box[int(la)] < aabb[int(la)])
|
if (AccessElement(x0_nodes, id).x4_box[listAIndex] < aabb[listAIndex]) {
|
||||||
AddToLinkedList(id, headId, tailId);
|
AddToLinkedList(id, headId, tailId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s16* id = &headId; *id != -1;) {
|
for (s16* id = &headId; *id != -1;) {
|
||||||
SNode& node = AccessElement(x0_nodes, *id);
|
SNode& node = AccessElement(x0_nodes, *id);
|
||||||
if (node.x4_box[int(slA)] > aabb[int(slB)] || node.x4_box[int(slB)] < aabb[int(slA)] ||
|
if (node.x4_box[size_t(slA)] > aabb[size_t(slB)] || node.x4_box[size_t(slB)] < aabb[size_t(slA)] ||
|
||||||
node.x4_box[int(slC)] > aabb[int(slD)] || node.x4_box[int(slD)] < aabb[int(slC)]) {
|
node.x4_box[size_t(slC)] > aabb[size_t(slD)] || node.x4_box[size_t(slD)] < aabb[size_t(slC)]) {
|
||||||
/* Not intersecting; remove from chain */
|
/* Not intersecting; remove from chain */
|
||||||
*id = node.x28_next;
|
*id = node.x28_next;
|
||||||
node.x28_next = -1;
|
node.x28_next = -1;
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RetroTypes.hpp"
|
#include <array>
|
||||||
#include "zeus/CAABox.hpp"
|
|
||||||
#include "Collision/CMaterialFilter.hpp"
|
#include "Runtime/RetroTypes.hpp"
|
||||||
|
#include "Runtime/Collision/CMaterialFilter.hpp"
|
||||||
|
|
||||||
|
#include <zeus/CAABox.hpp>
|
||||||
|
|
||||||
namespace urde {
|
namespace urde {
|
||||||
enum class ESortedList { MinX, MinY, MinZ, MaxX, MaxY, MaxZ };
|
enum class ESortedList { MinX, MinY, MinZ, MaxX, MaxY, MaxZ };
|
||||||
|
|
||||||
struct SSortedList {
|
struct SSortedList {
|
||||||
s16 x0_ids[1024];
|
std::array<s16, 1024> x0_ids;
|
||||||
u32 x800_size = 0;
|
u32 x800_size = 0;
|
||||||
void Reset() { std::fill(std::begin(x0_ids), std::end(x0_ids), -1); }
|
void Reset() { x0_ids.fill(-1); }
|
||||||
SSortedList() { Reset(); }
|
SSortedList() { Reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,14 +22,14 @@ class CSortedListManager {
|
||||||
struct SNode {
|
struct SNode {
|
||||||
const CActor* x0_actor = nullptr;
|
const CActor* x0_actor = nullptr;
|
||||||
zeus::CAABox x4_box = zeus::skNullBox;
|
zeus::CAABox x4_box = zeus::skNullBox;
|
||||||
s16 x1c_selfIdxs[6] = {-1, -1, -1, -1, -1, -1};
|
std::array<s16, 6> x1c_selfIdxs{-1, -1, -1, -1, -1, -1};
|
||||||
s16 x28_next = -1;
|
s16 x28_next = -1;
|
||||||
bool x2a_populated = false;
|
bool x2a_populated = false;
|
||||||
SNode() = default;
|
SNode() = default;
|
||||||
SNode(const CActor* act, const zeus::CAABox& aabb) : x0_actor(act), x4_box(aabb), x2a_populated(true) {}
|
SNode(const CActor* act, const zeus::CAABox& aabb) : x0_actor(act), x4_box(aabb), x2a_populated(true) {}
|
||||||
};
|
};
|
||||||
SNode x0_nodes[1024];
|
std::array<SNode, 1024> x0_nodes;
|
||||||
SSortedList xb000_sortedLists[6];
|
std::array<SSortedList, 6> xb000_sortedLists;
|
||||||
void Reset();
|
void Reset();
|
||||||
void AddToLinkedList(s16 a, s16& b, s16& c) const;
|
void AddToLinkedList(s16 a, s16& b, s16& c) const;
|
||||||
void RemoveFromList(ESortedList, s16);
|
void RemoveFromList(ESortedList, s16);
|
||||||
|
|
Loading…
Reference in New Issue