refactor(instance): implemented GetDescendant and replaced GetChildren in renderer and simulation with it
This commit is contained in:
parent
215f8ed500
commit
4de2b97c2d
4 changed files with 89 additions and 4 deletions
|
@ -108,6 +108,15 @@ std::optional<std::shared_ptr<Instance>> Instance::GetParent() {
|
|||
return parent.value().lock();
|
||||
}
|
||||
|
||||
static std::shared_ptr<Instance> DUMMY_INSTANCE;
|
||||
DescendantsIterator Instance::GetDescendantsStart() {
|
||||
return DescendantsIterator(GetChildren().size() > 0 ? GetChildren()[0] : DUMMY_INSTANCE);
|
||||
}
|
||||
|
||||
DescendantsIterator Instance::GetDescendantsEnd() {
|
||||
return DescendantsIterator(DUMMY_INSTANCE);
|
||||
}
|
||||
|
||||
bool Instance::IsParentLocked() {
|
||||
return this->parentLocked;
|
||||
}
|
||||
|
@ -232,3 +241,48 @@ InstanceRef Instance::Deserialize(pugi::xml_node* node) {
|
|||
|
||||
return object;
|
||||
}
|
||||
|
||||
// DescendantsIterator
|
||||
|
||||
DescendantsIterator::DescendantsIterator(std::shared_ptr<Instance> current) : current(current), root(current == DUMMY_INSTANCE ? DUMMY_INSTANCE : current->GetParent()), siblingIndex { 0 } { }
|
||||
|
||||
DescendantsIterator::self_type DescendantsIterator::operator++(int _) {
|
||||
// If the current item is dummy, an error has occurred, this is not supposed to happen.
|
||||
if (current == DUMMY_INSTANCE) {
|
||||
Logger::fatalError("Attempt to increment a descendant iterator past its end\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
// If the current item has children, enter it
|
||||
if (current->GetChildren().size() > 0) {
|
||||
siblingIndex.push_back(0);
|
||||
current = current->GetChildren()[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Otherwise, we move to the next sibling, if applicable.
|
||||
|
||||
// But not if one up is null or the root element
|
||||
if (!current->GetParent() || current == root) {
|
||||
current = DUMMY_INSTANCE;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we've hit the end of this item's children, move one up
|
||||
while (current->GetParent() && current->GetParent().value()->GetChildren().size() <= (siblingIndex.back() + 1)) {
|
||||
siblingIndex.pop_back();
|
||||
current = current->GetParent().value();
|
||||
|
||||
// But not if one up is null or the root element
|
||||
if (!current->GetParent() || current == root) {
|
||||
current = DUMMY_INSTANCE;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
// Now move to the next sibling
|
||||
siblingIndex.back()++;
|
||||
current = current->GetParent().value()->GetChildren()[siblingIndex.back()];
|
||||
|
||||
return *this;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
@ -30,6 +31,8 @@ struct InstanceType {
|
|||
std::string explorerIcon = "";
|
||||
};
|
||||
|
||||
class DescendantsIterator;
|
||||
|
||||
// Base class for all instances in the data model
|
||||
// Note: enable_shared_from_this HAS to be public or else its field will not be populated
|
||||
// Maybe this could be replaced with a friendship? But that seems unnecessary.
|
||||
|
@ -70,6 +73,8 @@ public:
|
|||
bool IsParentLocked();
|
||||
inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; }
|
||||
|
||||
DescendantsIterator GetDescendantsStart();
|
||||
DescendantsIterator GetDescendantsEnd();
|
||||
// Utility functions
|
||||
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
||||
|
||||
|
@ -88,3 +93,27 @@ public:
|
|||
|
||||
typedef std::shared_ptr<Instance> InstanceRef;
|
||||
typedef std::weak_ptr<Instance> InstanceRefWeak;
|
||||
|
||||
// https://gist.github.com/jeetsukumaran/307264
|
||||
class DescendantsIterator {
|
||||
public:
|
||||
typedef DescendantsIterator self_type;
|
||||
typedef std::shared_ptr<Instance> value_type;
|
||||
typedef std::shared_ptr<Instance>& reference;
|
||||
typedef std::shared_ptr<Instance> pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
|
||||
DescendantsIterator(std::shared_ptr<Instance> current);
|
||||
inline self_type operator++() { self_type i = *this; ++*this; return i; }
|
||||
inline std::shared_ptr<Instance> operator*() { return current; }
|
||||
inline std::shared_ptr<Instance> operator->() { return current; }
|
||||
inline bool operator==(const self_type& rhs) { return current == rhs.current; }
|
||||
inline bool operator!=(const self_type& rhs) { return current != rhs.current; }
|
||||
|
||||
self_type operator++(int _);
|
||||
private:
|
||||
std::optional<std::shared_ptr<Instance>> root;
|
||||
std::shared_ptr<Instance> current;
|
||||
std::vector<int> siblingIndex;
|
||||
};
|
|
@ -77,7 +77,8 @@ void physicsStep(float deltaTime) {
|
|||
|
||||
// Naive implementation. Parts are only considered so if they are just under Workspace
|
||||
// TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance
|
||||
for (InstanceRef obj : gWorkspace()->GetChildren()) {
|
||||
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
|
||||
InstanceRef obj = *it;
|
||||
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
|
||||
const rp::Transform& transform = part->rigidBody->getTransform();
|
||||
|
|
|
@ -125,7 +125,8 @@ void renderParts() {
|
|||
|
||||
// Sort by nearest
|
||||
std::map<float, std::shared_ptr<Part>> sorted;
|
||||
for (InstanceRef inst : gWorkspace()->GetChildren()) {
|
||||
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
|
||||
InstanceRef inst = *it;
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
if (part->transparency > 0.00001) {
|
||||
|
|
Loading…
Add table
Reference in a new issue