// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace anki { // Specialize newComponent(). Do that first #define ANKI_DEFINE_SCENE_COMPONENT(name, weight, sceneNodeCanHaveMany, icon, serializable) \ template<> \ name##Component* SceneNode::newComponent() \ { \ if(hasComponent() && !kSceneComponentSceneNodeCanHaveMany[SceneComponentType::k##name]) \ { \ ANKI_SCENE_LOGE("Can't have many %s components in scene node %s", kSceneComponentTypeName[SceneComponentType::k##name], \ getName().cstr()); \ return nullptr; \ } \ auto it = SceneGraph::getSingleton().getComponentArrays().get##name##s().emplace(this); \ it->setArrayIndex(it.getArrayIndex()); \ newComponentInternal(&(*it)); \ return &(*it); \ } #include SceneNode::SceneNode(CString name) : m_uuid(SceneGraph::getSingleton().getNewUuid()) { if(name) { m_name = name; } // Add the implicit MoveComponent newComponent(); } SceneNode::~SceneNode() { for(SceneComponent* comp : m_components) { comp->onDestroy(*this); switch(comp->getType()) { #define ANKI_DEFINE_SCENE_COMPONENT(name, weight, sceneNodeCanHaveMany, icon, serializable) \ case SceneComponentType::k##name: \ SceneGraph::getSingleton().getComponentArrays().get##name##s().erase(comp->getArrayIndex()); \ break; #include default: ANKI_ASSERT(0); } } } void SceneNode::markForDeletion() { visitThisAndChildren([](SceneNode& obj) { obj.m_markedForDeletion = true; return FunctorContinue::kContinue; }); } void SceneNode::newComponentInternal(SceneComponent* newc) { m_componentTypeMask |= 1 << SceneComponentTypeMask(newc->getType()); // Inform all other components that some component was added for(SceneComponent* other : m_components) { other->onOtherComponentRemovedOrAdded(newc, true); } // Inform the current component about others for(SceneComponent* other : m_components) { newc->onOtherComponentRemovedOrAdded(other, true); } m_components.emplaceBack(newc); // Sort based on update weight std::sort(m_components.getBegin(), m_components.getEnd(), [](const SceneComponent* a, const SceneComponent* b) { const F32 weightA = SceneComponent::getUpdateOrderWeight(a->getType()); const F32 weightB = SceneComponent::getUpdateOrderWeight(b->getType()); if(weightA != weightB) { return weightA < weightB; } else { return a->getType() < b->getType(); } }); } Bool SceneNode::updateTransform() { const Bool needsUpdate = m_localTransformDirty; m_localTransformDirty = false; const Bool updatedLastFrame = m_transformUpdatedThisFrame; m_transformUpdatedThisFrame = needsUpdate; if(needsUpdate || updatedLastFrame) { m_prevWTrf = m_wtrf; } // Update world transform if(needsUpdate) { const SceneNode* parent = getParent(); if(parent == nullptr || m_ignoreParentNodeTransform) { m_wtrf = m_ltrf; } else { m_wtrf = parent->getWorldTransform().combineTransformations(m_ltrf); } // Make children dirty as well. Don't walk the whole tree because you will re-walk it later visitChildrenMaxDepth(1, [](SceneNode& childNode) { if(!childNode.m_ignoreParentNodeTransform) { childNode.m_localTransformDirty = true; } return FunctorContinue::kContinue; }); } return needsUpdate; } void SceneNode::setName(CString name) { const SceneString oldName = getName(); m_name = name; SceneGraph::getSingleton().sceneNodeChangedName(*this, oldName); } Error SceneNode::serializeCommon(SceneSerializer& serializer) { ANKI_SERIALIZE(m_uuid, 1); ANKI_SERIALIZE(m_name, 1); Vec3 origin = m_ltrf.getOrigin().xyz; ANKI_SERIALIZE(origin, 1); m_ltrf.setOrigin(origin); Mat3 rotation = m_ltrf.getRotation().getRotationPart(); ANKI_SERIALIZE(rotation, 1); m_ltrf.setRotation(rotation); Vec3 scale = m_ltrf.getScale().xyz; ANKI_SERIALIZE(scale, 1); m_ltrf.setScale(scale); U32 componentCount = m_components.getSize(); ANKI_SERIALIZE(componentCount, 1); SceneDynamicArray componentUuids; if(serializer.isInWriteMode()) { for(SceneComponent* comp : m_components) { componentUuids.emplaceBack(comp->getUuid()); } } else { ANKI_ASSERT(!"TODO"); } ANKI_SERIALIZE(componentUuids, 1); // Parent SceneNode* parent = getParent(); U32 parentUuid = (parent) ? parent->getUuid() : 0; ANKI_SERIALIZE(parentUuid, 1); if(serializer.isInReadMode()) { ANKI_ASSERT(!"TODO"); } return Error::kNone; } } // end namespace anki