#ifndef SCENENODE_H #define SCENENODE_H #include #include "LinearMath/btMotionState.h" #include #include class SceneTree; class Transform; class Engine; class Light; class btRigidBody; class SceneNode { public: class SparrowMotionState : public btMotionState { SceneNode* m_node; public: SparrowMotionState(SceneNode* node) : m_node(node) {} /// bullet physics uses this getter to access the node's transform virtual void getWorldTransform(btTransform& worldTrans ) const; /// bullet physics calls this setter to move objects (only on active rigidbodies) virtual void setWorldTransform(const btTransform& worldTrans); }; class Script { public: virtual void begin(SceneNode* node) {} virtual void update(SceneNode* node) = 0; virtual void end(SceneNode* node) {} }; private: bool m_toDestroy; std::vector m_nodesToRemove; std::vector m_nodesToAdd; std::string m_id; bool m_parentVisible; bool m_visible; bool m_enabled; bool m_transformChanged; SceneNode* m_parent; SceneTree* m_scene; // contains the mesh if this node has one GeometryNode m_geometry; // contains the light source if the node has one Light* m_light; // m_transform is the relative transformation matrix of this node glm::mat4 m_transform; // m_parentTransform is the base transform for this element glm::mat4 m_parentTransform; // m_script allows to add some game logic in a generic way Script* m_script; // bullet physics rigidbody btRigidBody *m_rigidBody; // bullet physics handle for our transformation matrix SparrowMotionState m_motionState; // node's children std::vector m_children; void updateVisibility(bool visible); void setParent(SceneNode* parent); void updateLightSource(); bool m_showInfo; public: // constructor/destructor SceneNode(std::string node_id = "undefined id",Script *script = nullptr); virtual ~SceneNode(); // game logic methods /// @brief update this method is called every tick by the engine virtual void update(); bool isEnabled() { return m_enabled; } void setEnabled(bool isEnabled) { m_enabled = isEnabled; } Script* getScript(); std::string getID(); void setID(std::string id){m_id = id;} // methods called to access the graphic propeties of the node void setMesh(Mesh* mesh) { m_geometry.mesh = mesh; } Mesh* getMesh() { return m_geometry.mesh; } GeometryNode* getGeometryNode() { return &m_geometry; } void setLight(Light* light) { m_light = light; } Light* getLight() { return m_light; } // scene tree structure methods /// @brief setSceneTree this method can be used to change the scene of the node virtual void setSceneTree(SceneTree* tree); /// @brief getScene this method returns the scene this node is in SceneTree* getScene() { return m_scene; } /// @brief addChild this method can be used to add a child to a node void addChild(SceneNode* node); /// @brief removeChild this method can be used to remove a child from a node void removeChild(SceneNode* node); /// @brief getParent returns the parent of this node, or nullptr if this node is the scene tree root virtual SceneNode* getParent() { return m_parent; } /// @brief killWhenOrphan this method can be called if you wish to delete this object as soon as it has no parent. virtual void destroyWhenOrphan() { m_toDestroy = true; } /// @brief getChildren returns a vector containing all this node's children const std::vector getChildren() { return m_children; } // transform methods void setTransform(const Transform& t); void getTransform(Transform& t); void setTransform(const glm::mat4 &transform); const glm::mat4& getTransform() { return m_transform; } void setParentTransform(const glm::mat4 &transform); const glm::mat4& getParentTransform() { return m_parentTransform; } void resetTransform(); // visibility methods bool isVisible() { return m_parentVisible && m_visible; } void toggleVisibility() { setVisible(!m_visible); } void setVisible(bool visible); void setParentVisible(bool visible); // transformation tools : void moveTo(const glm::vec3 &position); void translate(const glm::vec3 &vector); void lookAt(const glm::vec3 &target, const glm::vec3 &upVector = glm::vec3(0, 1, 0)); void rotate(float angle, const glm::vec3 &vector); void scale(const glm::vec3 &scaleFactor); //2D tools: void moveTo2D(const glm::vec2 &position) { setTransform(glm::translate(m_transform,glm::vec3(position.x,position.y,0) - glm::vec3(m_transform[3]))); } void rotate2D(const glm::vec2 ¢er, float angle) { setTransform(glm::rotate(m_transform,angle,glm::vec3(0,0,1))); } void scale2D(const glm::vec2 scaleFactor) { setTransform(glm::scale(m_transform, glm::vec3(scaleFactor.x,scaleFactor.y,1))); } void resize2D(const glm::vec2 oldDimension, glm::vec2 newDimension) { scale2D(glm::vec2(newDimension / oldDimension)); } float getDepth(); void setDepth(float depth); // physics methods /// @brief getMotionState this is used to synchronize a bullet rigidbody's transform with a GraphicalNode transform SparrowMotionState* getMotionState() { return &m_motionState; } /// @brief setRigidBody sets a rigidbody to the node void setRigidBody(btRigidBody* body); btRigidBody* getRigidBody() { return m_rigidBody; } /// the scene node clones itself, with no parent virtual SceneNode* clone(); //serialization methods template void serialize(Archive & archive) { archive(m_transform); } void openInfoWindow(); void gui(); // global engine methods Engine& getEngine(); }; #endif // SCENENODE_H