| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Scene/Components/SceneComponent.h>
- #include <AnKi/Util/Hierarchy.h>
- #include <AnKi/Util/BitMask.h>
- #include <AnKi/Util/BitSet.h>
- #include <AnKi/Util/List.h>
- #include <AnKi/Util/Enum.h>
- namespace anki {
- /// @addtogroup scene
- /// @{
- /// Interface class backbone of scene
- class SceneNode : public SceneHierarchy<SceneNode>, public IntrusiveListEnabled<SceneNode>
- {
- friend class SceneComponent;
- public:
- using Base = SceneHierarchy<SceneNode>;
- /// The one and only constructor.
- /// @param scene The owner scene.
- /// @param name The unique name of the node. If it's empty the the node is not searchable.
- SceneNode(CString name);
- /// Unregister node
- virtual ~SceneNode();
- /// A dummy init for those scene nodes that don't need it.
- Error init()
- {
- return Error::kNone;
- }
- /// Return the name. It may be empty for nodes that we don't want to track.
- CString getName() const
- {
- return (!m_name.isEmpty()) ? m_name.toCString() : CString();
- }
- U32 getUuid() const
- {
- return m_uuid;
- }
- Bool getMarkedForDeletion() const
- {
- return m_markedForDeletion;
- }
- void setMarkedForDeletion();
- Timestamp getComponentMaxTimestamp() const
- {
- return m_maxComponentTimestamp;
- }
- void setComponentMaxTimestamp(Timestamp maxComponentTimestamp)
- {
- ANKI_ASSERT(maxComponentTimestamp > 0);
- m_maxComponentTimestamp = maxComponentTimestamp;
- }
- void addChild(SceneNode* obj)
- {
- Base::addChild(obj);
- }
- void setParent(SceneNode* obj)
- {
- Base::setParent(obj);
- }
- /// This is called by the scenegraph every frame after all component updates. By default it does nothing.
- /// @param prevUpdateTime Timestamp of the previous update
- /// @param crntTime Timestamp of this update
- virtual Error frameUpdate([[maybe_unused]] Second prevUpdateTime, [[maybe_unused]] Second crntTime)
- {
- return Error::kNone;
- }
- /// Iterate all components.
- template<typename TFunct>
- void iterateComponents(TFunct func) const
- {
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- func(*m_components[i]);
- }
- }
- /// Iterate all components.
- template<typename TFunct>
- void iterateComponents(TFunct func)
- {
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- func(*m_components[i]);
- }
- }
- /// Iterate all components of a specific type
- template<typename TComponent, typename TFunct>
- void iterateComponentsOfType(TFunct func) const
- {
- if(hasComponent<TComponent>())
- {
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- if(m_components[i]->getType() == TComponent::kClassType)
- {
- func(static_cast<const TComponent&>(*m_components[i]));
- }
- }
- }
- }
- /// Iterate all components of a specific type
- template<typename TComponent, typename TFunct>
- void iterateComponentsOfType(TFunct func)
- {
- if(hasComponent<TComponent>())
- {
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- if(m_components[i]->getType() == TComponent::kClassType)
- {
- func(static_cast<TComponent&>(*m_components[i]));
- }
- }
- }
- }
- /// Try geting a pointer to the first component of the requested type
- template<typename TComponent>
- const TComponent* tryGetFirstComponentOfType() const
- {
- if(hasComponent<TComponent>())
- {
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- if(m_components[i]->getType() == TComponent::kClassType)
- {
- return static_cast<const TComponent*>(m_components[i]);
- }
- }
- }
- return nullptr;
- }
- /// Try geting a pointer to the first component of the requested type
- template<typename TComponent>
- TComponent* tryGetFirstComponentOfType()
- {
- const TComponent* c = static_cast<const SceneNode*>(this)->tryGetFirstComponentOfType<TComponent>();
- return const_cast<TComponent*>(c);
- }
- /// Get a pointer to the first component of the requested type
- template<typename TComponent>
- const TComponent& getFirstComponentOfType() const
- {
- const TComponent* out = tryGetFirstComponentOfType<TComponent>();
- ANKI_ASSERT(out != nullptr);
- return *out;
- }
- /// Get a pointer to the first component of the requested type
- template<typename TComponent>
- TComponent& getFirstComponentOfType()
- {
- const TComponent& c = static_cast<const SceneNode*>(this)->getFirstComponentOfType<TComponent>();
- return const_cast<TComponent&>(c);
- }
- /// Try geting a pointer to the nth component of the requested type.
- template<typename TComponent>
- const TComponent* tryGetNthComponentOfType(U32 nth) const
- {
- if(hasComponent<TComponent>())
- {
- I32 inth = I32(nth);
- for(U32 i = 0; i < m_components.getSize(); ++i)
- {
- if(m_components[i]->getType() == TComponent::kClassType && inth-- == 0)
- {
- return static_cast<const TComponent*>(m_components[i]);
- }
- }
- }
- return nullptr;
- }
- /// Try geting a pointer to the nth component of the requested type.
- template<typename TComponent>
- TComponent* tryGetNthComponentOfType(U32 nth)
- {
- const TComponent* c = static_cast<const SceneNode*>(this)->tryGetNthComponentOfType<TComponent>(nth);
- return const_cast<TComponent*>(c);
- }
- template<typename TComponent>
- const TComponent& getNthComponentOfType(U32 nth) const
- {
- const TComponent* out = tryGetNthComponentOfType<TComponent>(nth);
- ANKI_ASSERT(out);
- return *out;
- }
- template<typename TComponent>
- TComponent& getNthComponentOfType(U32 nth)
- {
- TComponent* out = tryGetNthComponentOfType<TComponent>(nth);
- ANKI_ASSERT(out);
- return *out;
- }
- /// Get the nth component.
- template<typename TComponent>
- TComponent& getComponentAt(U32 idx)
- {
- ANKI_ASSERT(m_components[idx]->getType() == TComponent::kClassType);
- SceneComponent* c = m_components[idx];
- return *static_cast<TComponent*>(c);
- }
- /// Get the nth component.
- template<typename TComponent>
- const TComponent& getComponentAt(U32 idx) const
- {
- ANKI_ASSERT(m_components[idx]->getType() == TComponent::kClassType);
- const SceneComponent* c = m_components[idx];
- return *static_cast<const TComponent*>(c);
- }
- U32 getComponentCount() const
- {
- return m_components.getSize();
- }
- template<typename TComponent>
- U32 countComponentsOfType() const
- {
- U32 count = 0;
- iterateComponentsOfType<TComponent>([&]([[maybe_unused]] const TComponent& c) {
- ++count;
- });
- return count;
- }
- /// Ignore parent nodes's transform.
- void setIgnoreParentTransform(Bool ignore)
- {
- m_ignoreParentNodeTransform = ignore;
- }
- const Transform& getLocalTransform() const
- {
- return m_ltrf;
- }
- void setLocalTransform(const Transform& x)
- {
- m_ltrf = x;
- m_localTransformDirty = true;
- }
- void setLocalOrigin(const Vec4& x)
- {
- m_ltrf.setOrigin(x);
- m_localTransformDirty = true;
- }
- const Vec4& getLocalOrigin() const
- {
- return m_ltrf.getOrigin();
- }
- void setLocalRotation(const Mat3x4& x)
- {
- m_ltrf.setRotation(x);
- m_localTransformDirty = true;
- }
- const Mat3x4& getLocalRotation() const
- {
- return m_ltrf.getRotation();
- }
- void setLocalScale(const Vec4& x)
- {
- m_ltrf.setScale(x);
- m_localTransformDirty = true;
- }
- const Vec4& getLocalScale() const
- {
- return m_ltrf.getScale();
- }
- const Transform& getWorldTransform() const
- {
- return m_wtrf;
- }
- const Transform& getPreviousWorldTransform() const
- {
- return m_prevWTrf;
- }
- /// @name Mess with the local transform
- /// @{
- void rotateLocalX(F32 angleRad)
- {
- Mat3x4 r = m_ltrf.getRotation();
- r.rotateXAxis(angleRad);
- m_ltrf.setRotation(r);
- m_localTransformDirty = true;
- }
- void rotateLocalY(F32 angleRad)
- {
- Mat3x4 r = m_ltrf.getRotation();
- r.rotateYAxis(angleRad);
- m_ltrf.setRotation(r);
- m_localTransformDirty = true;
- }
- void rotateLocalZ(F32 angleRad)
- {
- Mat3x4 r = m_ltrf.getRotation();
- r.rotateZAxis(angleRad);
- m_ltrf.setRotation(r);
- m_localTransformDirty = true;
- }
- void moveLocalX(F32 distance)
- {
- Vec3 x_axis = m_ltrf.getRotation().getColumn(0);
- m_ltrf.setOrigin(m_ltrf.getOrigin() + Vec4(x_axis, 0.0f) * distance);
- m_localTransformDirty = true;
- }
- void moveLocalY(F32 distance)
- {
- Vec3 y_axis = m_ltrf.getRotation().getColumn(1);
- m_ltrf.setOrigin(m_ltrf.getOrigin() + Vec4(y_axis, 0.0) * distance);
- m_localTransformDirty = true;
- }
- void moveLocalZ(F32 distance)
- {
- Vec3 z_axis = m_ltrf.getRotation().getColumn(2);
- m_ltrf.setOrigin(m_ltrf.getOrigin() + Vec4(z_axis, 0.0) * distance);
- m_localTransformDirty = true;
- }
- void scale(F32 s)
- {
- m_ltrf.setScale(m_ltrf.getScale() * s);
- m_localTransformDirty = true;
- }
- void lookAtPoint(const Vec4& point)
- {
- m_ltrf.lookAt(point, Vec4(0.0f, 1.0f, 0.0f, 0.0f));
- m_localTransformDirty = true;
- }
- /// @}
- Bool movedThisFrame() const
- {
- return m_transformUpdatedThisFrame;
- }
- ANKI_INTERNAL Bool updateTransform();
- /// Create and append a component to the components container. The SceneNode has the ownership.
- template<typename TComponent>
- TComponent* newComponent();
- template<typename TComponent>
- Bool hasComponent() const
- {
- return !!((1u << SceneComponentTypeMask(TComponent::kClassType)) & m_componentTypeMask);
- }
- private:
- SceneString m_name; ///< A unique name.
- U32 m_uuid;
- SceneComponentTypeMask m_componentTypeMask = SceneComponentTypeMask::kNone;
- GrDynamicArray<SceneComponent*> m_components;
- Timestamp m_maxComponentTimestamp = 0;
- /// The transformation in local space.
- Transform m_ltrf = Transform::getIdentity();
- /// The transformation in world space (local combined with parent's transformation).
- Transform m_wtrf = Transform::getIdentity();
- /// Keep the previous transformation for checking if it moved.
- Transform m_prevWTrf = Transform::getIdentity();
- // Flags
- Bool m_markedForDeletion : 1 = false;
- Bool m_localTransformDirty : 1 = true;
- Bool m_ignoreParentNodeTransform : 1 = false;
- Bool m_transformUpdatedThisFrame : 1 = true;
- void newComponentInternal(SceneComponent* newc);
- };
- /// @}
- } // end namespace anki
|