mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-15 06:52:34 +02:00
Add clone methods to Clump, Atomic and ModelFrame to permit copying
This commit is contained in:
parent
0a0be3c52a
commit
ac8d6733cb
@ -1,5 +1,6 @@
|
||||
#include "data/Clump.hpp"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
@ -35,7 +36,7 @@ void ModelFrame::updateHierarchyTransform() {
|
||||
}
|
||||
}
|
||||
|
||||
void ModelFrame::addChild(ModelFramePtr& child) {
|
||||
void ModelFrame::addChild(ModelFramePtr child) {
|
||||
// Make sure the child is an orphan
|
||||
if (child->getParent()) {
|
||||
auto& other_children = child->getParent()->children_;
|
||||
@ -62,6 +63,26 @@ ModelFrame* ModelFrame::findDescendant(const std::string& name) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ModelFramePtr ModelFrame::cloneHierarchy() const {
|
||||
auto self = std::make_shared<ModelFrame>(getIndex(), getDefaultRotation(),
|
||||
getDefaultTranslation());
|
||||
self->setName(getName());
|
||||
for (const auto& child : getChildren()) {
|
||||
auto childclone = child->cloneHierarchy();
|
||||
self->addChild(childclone);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
AtomicPtr Atomic::clone() const {
|
||||
auto newatomic = std::make_shared<Atomic>();
|
||||
newatomic->setGeometry(getGeometry());
|
||||
newatomic->setFrame(getFrame());
|
||||
newatomic->setFlags(getFlags());
|
||||
return newatomic;
|
||||
}
|
||||
|
||||
ModelFrame* Clump::findFrame(const std::string& name) const {
|
||||
if (rootframe_->getName() == name) {
|
||||
return rootframe_.get();
|
||||
@ -85,3 +106,40 @@ void Clump::recalculateMetrics() {
|
||||
glm::length(bounds.center) + bounds.radius);
|
||||
}
|
||||
}
|
||||
|
||||
Clump* Clump::clone() const {
|
||||
// Clone frame hierarchy
|
||||
auto newroot = rootframe_->cloneHierarchy();
|
||||
auto clump = new Clump;
|
||||
clump->setFrame(newroot);
|
||||
|
||||
// This isn't the most optimal implementation, but this code is likely
|
||||
// to be replaced soon.
|
||||
auto find_new_frame = [&](const ModelFramePtr& old) -> ModelFramePtr {
|
||||
std::queue<ModelFramePtr> open;
|
||||
open.push(newroot);
|
||||
while (!open.empty()) {
|
||||
auto frame = open.front();
|
||||
open.pop();
|
||||
if (frame->getIndex() == old->getIndex()) {
|
||||
return frame;
|
||||
}
|
||||
for (const auto& child : frame->getChildren()) {
|
||||
open.push(child);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
// Generate new atomics
|
||||
for (const auto& atomic : getAtomics()) {
|
||||
auto newatomic = atomic->clone();
|
||||
// Replace the original frame with the cloned frame
|
||||
if (atomic->getFrame()) {
|
||||
newatomic->setFrame(find_new_frame(atomic->getFrame()));
|
||||
}
|
||||
clump->addAtomic(newatomic);
|
||||
}
|
||||
|
||||
return clump;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
return parent_;
|
||||
}
|
||||
|
||||
void addChild(ModelFramePtr& child);
|
||||
void addChild(ModelFramePtr child);
|
||||
|
||||
const std::vector<ModelFramePtr>& getChildren() const {
|
||||
return children_;
|
||||
@ -108,6 +108,8 @@ public:
|
||||
}
|
||||
|
||||
ModelFrame* findDescendant(const std::string& name) const;
|
||||
|
||||
ModelFramePtr cloneHierarchy() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -203,7 +205,7 @@ public:
|
||||
return frame_;
|
||||
}
|
||||
|
||||
void setGeometry(GeometryPtr& geom) {
|
||||
void setGeometry(GeometryPtr geom) {
|
||||
geometry_ = geom;
|
||||
}
|
||||
|
||||
@ -227,6 +229,8 @@ public:
|
||||
flags_ &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
AtomicPtr clone() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -265,6 +269,11 @@ public:
|
||||
return rootframe_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A Copy of the frames and atomics in this clump
|
||||
*/
|
||||
Clump* clone() const;
|
||||
|
||||
private:
|
||||
float boundingRadius;
|
||||
AtomicList atomics_;
|
||||
|
@ -29,4 +29,44 @@ BOOST_AUTO_TEST_CASE(test_load_dff) {
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_clump_clone) {
|
||||
{
|
||||
auto frame1 = std::make_shared<ModelFrame>(0);
|
||||
frame1->setName("Frame1");
|
||||
auto frame2 = std::make_shared<ModelFrame>(1);
|
||||
frame2->setName("Frame2");
|
||||
|
||||
frame1->addChild(frame2);
|
||||
|
||||
auto geometry = std::make_shared<Geometry>();
|
||||
|
||||
auto atomic = std::make_shared<Atomic>();
|
||||
atomic->setFrame(frame2);
|
||||
atomic->setGeometry(geometry);
|
||||
|
||||
auto clump = std::make_shared<Clump>();
|
||||
clump->addAtomic(atomic);
|
||||
clump->setFrame(frame1);
|
||||
|
||||
// Now clone and verify that:
|
||||
// The hierarchy has the same data but different objects
|
||||
// The atomics have the same data but different objects
|
||||
// Suspected correct behaviour:
|
||||
// The geometry is the same for each atomic
|
||||
|
||||
auto newclump = std::shared_ptr<Clump>(clump->clone());
|
||||
BOOST_REQUIRE(newclump);
|
||||
|
||||
BOOST_CHECK_NE(newclump, clump);
|
||||
|
||||
BOOST_REQUIRE(newclump->getFrame());
|
||||
BOOST_CHECK_NE(newclump->getFrame(), clump->getFrame());
|
||||
BOOST_CHECK_EQUAL(newclump->getFrame()->getChildren().size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(newclump->getAtomics().size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(frame1->getName(), newclump->getFrame()->getName());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user