diff --git a/attachable.h b/attachable.h index 97837c0..7ebacba 100644 --- a/attachable.h +++ b/attachable.h @@ -7,13 +7,14 @@ namespace vb01{ class Node; struct Attachable{ - std::string fullName = ""; - Node *node = nullptr; - - Attachable(std::string fullName){this->fullName = fullName;} - Attachable(){} - virtual void onAttached(Node*){} - std::string getFullName(){return fullName;} + public: + Attachable(std::string fullName){this->fullName = fullName;} + Attachable(){} + virtual void onAttached(Node *node){this->node = node;} + std::string getAttachableName(){return fullName;} + protected: + std::string fullName = ""; + Node *node = nullptr; }; } diff --git a/node.cpp b/node.cpp index c61e9d9..c3e5163 100755 --- a/node.cpp +++ b/node.cpp @@ -68,54 +68,65 @@ namespace vb01{ } Node* Node::clone(){ - return cloneNode(true); - } + vector originalDescendants = vector{this}; + getDescendants(originalDescendants); - Node* Node::cloneNode(bool firstIter){ - Node *node = new Node(pos, orientation, scale, name); + int numDescendants = originalDescendants.size(); + vector clonedDescendants; - for(Mesh *mesh : meshes){ - Mesh *m = new Mesh(mesh->getMeshBase()); - m->construct(); - node->attachMesh(m); + for(int i = 0; i < numDescendants; i++){ + Node *original = originalDescendants[i]; + Node *clone = new Node(original->getPosition(), original->getOrientation(), original->getScale(), original->getName()); + + for(int j = 0; j < i; j++) + if(original->getParent() == originalDescendants[j]){ + clonedDescendants[j]->attachChild(clone); + break; + } + + clonedDescendants.push_back(clone); } - for(Skeleton *skel : skeletons){ - vector bones = skel->getBones(); - Skeleton *sk = new Skeleton(skel->getName()); + for(int i = 0; i < numDescendants; i++){ + Node *original = originalDescendants[i]; - for(Bone *bone : bones) - sk->addBone(bone, nullptr); + for(Skeleton *skel : original->getSkeletons()){ + Skeleton *sk = new Skeleton(skel->getAttachableName()); - node->addSkeleton(sk); - } + for(Bone *bone : skel->getBones()) + for(int j = 0; j < numDescendants; j++) + if(bone == originalDescendants[j]){ + sk->addBone((Bone*)clonedDescendants[j], nullptr); + break; + } - for(Node *child : children) - node->attachChild(child->cloneNode(false)); + clonedDescendants[i]->addSkeleton(sk); + } - if(firstIter){ - vector descendants = vector{node}; - node->getDescendants(descendants); - vector meshes; + for(Mesh *mesh : original->getMeshes()){ + Mesh *m = new Mesh(MeshData(mesh->getMeshBase())); - for(Node *desc : descendants) - for(Mesh *mesh : desc->getMeshes()) - meshes.push_back(mesh); + if(mesh->getSkeleton()) + for(int j = 0; j < numDescendants; j++) + for(int k = 0; k < clonedDescendants[j]->getNumSkeletons(); k++) + if( + clonedDescendants[j]->getName() == originalDescendants[j]->getName() && + clonedDescendants[j]->getSkeleton(k)->getAttachableName() == mesh->getSkeleton()->getAttachableName() + ){ + m->setSkeleton(clonedDescendants[j]->getSkeleton(k)); + break; + } - for(Mesh *mesh : meshes){ - int dotId = mesh->getMeshBase().fullSkeletonName.find_first_of("."); - string nodeName = mesh->getMeshBase().fullSkeletonName.substr(0, dotId); - string skelName = mesh->getMeshBase().fullSkeletonName.substr(dotId + 1, string::npos); + clonedDescendants[i]->attachMesh(m); + } - for(Node *desc : descendants) - if(nodeName == desc->getName()) - for(Skeleton *sk : desc->getSkeletons()) - if(sk->getName() == skelName) - mesh->setSkeleton(sk); + for(Driver *driver : original->getDrivers()){ + Driver *dr = new Driver(nullptr, driver->getKeyframeChannel(), driver->getType()); + clonedDescendants[i]->addDriver(dr); } } - return node; + return clonedDescendants[0]; } float Node::getDriverValue(Driver::VariableType type){ @@ -180,7 +191,7 @@ namespace vb01{ void Node::attachMesh(Mesh *mesh){ meshes.push_back(mesh); - mesh->setNode(this); + mesh->onAttached(this); } void Node::addSkeleton(Skeleton *skeleton){ @@ -189,27 +200,26 @@ namespace vb01{ void Node::attachParticleEmitter(ParticleEmitter *emitter){ emitters.push_back(emitter); - emitter->setNode(this); + emitter->onAttached(this); } void Node::addLight(Light *light){ Root::getSingleton()->shiftNumLights(true); lights.push_back(light); - light->setNode(this); + light->onAttached(this); updateShaders(); } void Node::removeLight(int id){ Root::getSingleton()->shiftNumLights(false); Light *light = lights[id]; - light->setNode(nullptr); lights.erase(lights.begin() + id); updateShaders(); } void Node::addText(Text *text){ texts.push_back(text); - text->setNode(this); + text->onAttached(this); } void Node::lookAt(Vector3 newDir, Vector3 newUp){ diff --git a/node.h b/node.h index 9523e70..47c5395 100755 --- a/node.h +++ b/node.h @@ -46,6 +46,7 @@ namespace vb01{ Vector3 localToGlobalScale(Vector3); Vector3 globalToLocalScale(Vector3); inline Skeleton* getSkeleton(int i){return skeletons[i];} + inline int getNumSkeletons(){return skeletons.size();} inline Text* getText(int i){return texts[i];} inline std::vector& getMeshes(){return meshes;} inline std::vector& getSkeletons(){return skeletons;} @@ -67,8 +68,9 @@ namespace vb01{ inline bool isVisible(){return visible;} inline void setVisible(bool v){this->visible = v;} inline void addDriver(Driver *d){drivers.push_back(d);} + inline Driver* getDriver(int i){return drivers[i];} + inline std::vector getDrivers(){return drivers;} private: - Node* cloneNode(bool); void adjustUp(Vector3); void adjustDir(Vector3); void updateShaders(); diff --git a/nodeTest.cpp b/nodeTest.cpp index 503926d..419d6d5 100644 --- a/nodeTest.cpp +++ b/nodeTest.cpp @@ -79,15 +79,12 @@ namespace vb01{ } void NodeTest::testClonedDrivers(){ - vector keyframes = vector{ - KeyframeChannel::createKeyframe(KeyframeInterpolation::LINEAR, 1, 1), - KeyframeChannel::createKeyframe(KeyframeInterpolation::LINEAR, 2, 2), - KeyframeChannel::createKeyframe(KeyframeInterpolation::LINEAR, 3, 3) - }; + vector keyframes; KeyframeChannelType channelType = KeyframeChannelType::POS_X; - KeyframeChannel channel = KeyframeChannel::createKeyframeChannel(channelType, "D", keyframes); + string animName = "D"; + KeyframeChannel channel = KeyframeChannel::createKeyframeChannel(channelType, animName, keyframes); Driver::VariableType driverType = Driver::POS_X; - Driver *driver = new Driver(nullptr, channel, driverType); + Driver *driver = new Driver(originalD, channel, driverType); originalB->addDriver(driver); Node *clonedA = originalA->clone(); @@ -101,7 +98,7 @@ namespace vb01{ clonedB = desc; break; } - else if(desc->getName() == "D"){ + else if(desc->getName() == animName){ clonedD = desc; break; } @@ -110,17 +107,17 @@ namespace vb01{ Driver *driverClone = clonedB->getDriver(0); CPPUNIT_ASSERT(driverClone->getAnimatable() == clonedD); CPPUNIT_ASSERT(driverClone->getKeyframeChannel().type == channelType); + CPPUNIT_ASSERT(driverClone->getKeyframeChannel().animatable == animName); CPPUNIT_ASSERT(driverClone->getType() == driverType); } void NodeTest::testClonedSkeletons(){ Skeleton *skeleton = new Skeleton(); - skeleton->addBone((Bone*)originalC, nullptr); - skeleton->addBone((Bone*)originalD, nullptr); + skeleton->addBone((Bone*)originalC, (Bone*)originalC->getParent()); + skeleton->addBone((Bone*)originalD, (Bone*)originalD->getParent()); originalA->addSkeleton(skeleton); Node *clonedA = originalA->clone(); - CPPUNIT_ASSERT(!empty(clonedA->getSkeletons())); CPPUNIT_ASSERT(clonedA->getSkeleton(0)); Skeleton *clonedSkeleton = originalA->getSkeleton(0); @@ -128,6 +125,29 @@ namespace vb01{ CPPUNIT_ASSERT(clonedSkeleton->getBone(1)->getName() == originalD->getName()); } + void NodeTest::testClonedMeshSkeleton(){ + string name = "skeleton"; + Mesh *mesh = new Mesh(MeshData(nullptr, nullptr, 0)); + Skeleton *skeleton = new Skeleton(name); + mesh->setSkeleton(skeleton); + + originalD->attachMesh(mesh); + originalD->addSkeleton(skeleton); + + Node *clonedA = originalA->clone(); + Node *clonedD = nullptr; + vector clonedDescendands; + clonedA->getDescendants(clonedDescendands); + + for(Node *desc : clonedDescendands) + if(desc->getName() == "D"){ + clonedD = desc; + break; + } + + CPPUNIT_ASSERT(clonedD->getMesh(0)->getSkeleton()->getAttachableName() == name); + } + void NodeTest::testGetAncestors(){ vector ancestors = ancestorD->getAncestors(); CPPUNIT_ASSERT(ancestors[ancestors.size() - 1] == rootNode); diff --git a/nodeTest.h b/nodeTest.h index 989181e..85700c2 100644 --- a/nodeTest.h +++ b/nodeTest.h @@ -12,6 +12,7 @@ namespace vb01{ CPPUNIT_TEST(testClonedMeshes); CPPUNIT_TEST(testClonedDrivers); CPPUNIT_TEST(testClonedSkeletons); + CPPUNIT_TEST(testClonedMeshSkeleton); CPPUNIT_TEST(testGetAncestors); CPPUNIT_TEST(testAdjustDir); CPPUNIT_TEST(testAdjustUp); @@ -30,6 +31,7 @@ namespace vb01{ void testClonedMeshes(); void testClonedDrivers(); void testClonedSkeletons(); + void testClonedMeshSkeleton(); void testAdjustDir(); void testAdjustUp(); void testDetachChild(); diff --git a/skeleton.cpp b/skeleton.cpp index 3a1c374..ab94e93 100644 --- a/skeleton.cpp +++ b/skeleton.cpp @@ -89,8 +89,8 @@ namespace vb01{ if(parent) parent->attachChild(bone); - bone->setSkeleton(this); bones.push_back(bone); + bone->setSkeleton(this); } Bone* Skeleton::getBone(string name){