From c40c2bc79ec202abc65520d72c1bb679049cc296 Mon Sep 17 00:00:00 2001 From: Anselme Date: Fri, 20 Oct 2017 15:17:22 +0200 Subject: [PATCH] more stability in container nodes, editor now has a trackball camera --- src/editor.cpp | 40 ++++++++++++ src/editor.h | 2 + src/editor/objecteditor.cpp | 4 +- src/scene/containernode.cpp | 46 ++++++++----- src/scene/containernode.h | 4 ++ src/scene/gibgeneratornode.cpp | 4 +- src/scene/graphicalcontainernode.cpp | 50 ++++++++------ src/scene/graphicalcontainernode.h | 3 + src/scene/gui/textinputnode.cpp | 2 +- src/scene/playercharacternode.cpp | 18 ++--- src/scene/scenenode.cpp | 9 ++- src/scene/scenenode.h | 18 +++-- src/scene/scenetree.cpp | 9 +-- src/scene/scenetree.h | 8 +-- src/sparrowshell/shellbuffer.cpp | 2 +- src/test/main.cpp | 98 ++-------------------------- 16 files changed, 158 insertions(+), 159 deletions(-) diff --git a/src/editor.cpp b/src/editor.cpp index 77b4eca..c173d65 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -4,12 +4,17 @@ #include "tools/scenepicker.h" #include "scene/scenetree.h" #include "tools/resourcepack.h" +#include "editor/objecteditor.h" +#include "sparrowshell/sparrowshell.h" #include #include #include #include +#include + +#include #include @@ -17,10 +22,12 @@ Editor::Editor() : m_pickerNode(new ScenePicker()), m_selectedMesh(nullptr), m_editedResourcePack(nullptr), + m_objectEditor(nullptr), m_pickerEnabled(false), m_materialEditorEnabled(false), m_editorEnabled(false) { + m_objectEditor = new ObjectEditor(); addChild(m_pickerNode); m_pickerNode->setVisible(false); } @@ -125,7 +132,40 @@ void Editor::materialGui() void Editor::toggleEditor() { + static Camera* backupCamera = nullptr; + static bool backupMouseGrabbedState = false; + static std::string backupInputContext = ""; + m_editorEnabled = !m_editorEnabled; + if(m_editorEnabled) + { + // input context + if(getEngine().getShell()->isEnabled()) + getEngine().getShell()->toggleShell(); + backupInputContext = getEngine().getInput()->getCurrentContext(); + getEngine().getInput()->setCurrentContext("editor"); + + // mouse grab + backupMouseGrabbedState = getEngine().isMouseGrabbed(); + if(getEngine().isMouseGrabbed()) + getEngine().toggleMouseVisibility(); + + // camera controller + backupCamera = getEngine().getScene()->getCamera(); + getEngine().getScene()->setMainCamera(m_objectEditor->getCamera()); + getEngine().getScene()->getRootObject()->addChild(m_objectEditor); + } + else + { + // restore all previous states + if(getEngine().isMouseGrabbed() != backupMouseGrabbedState) + getEngine().toggleMouseVisibility(); + getEngine().getScene()->setMainCamera(backupCamera); + getEngine().getScene()->getRootObject()->removeChild(m_objectEditor); + if(getEngine().getShell()->isEnabled()) + getEngine().getShell()->toggleShell(); + getEngine().getInput()->setCurrentContext(backupInputContext); + } } void Editor::togglePicker() diff --git a/src/editor.h b/src/editor.h index ce4afb6..87242a2 100644 --- a/src/editor.h +++ b/src/editor.h @@ -6,6 +6,7 @@ class Engine; class ScenePicker; class ResourcePack; +class ObjectEditor; class Mesh; class Editor : public ContainerNode @@ -13,6 +14,7 @@ class Editor : public ContainerNode ScenePicker* m_pickerNode; Mesh* m_selectedMesh; ResourcePack* m_editedResourcePack; + ObjectEditor* m_objectEditor; bool m_pickerEnabled; bool m_materialEditorEnabled; bool m_editorEnabled; diff --git a/src/editor/objecteditor.cpp b/src/editor/objecteditor.cpp index 02f2162..25917c1 100644 --- a/src/editor/objecteditor.cpp +++ b/src/editor/objecteditor.cpp @@ -20,9 +20,9 @@ void ObjectEditor::update() for(Action action : input->getActions()) { if(action.action == DefaultKeysMap::MAIN_ACTION_HOLD) - m_camera->moveCamera(diff.x, diff.y); - else if(action.action == DefaultKeysMap::SECONDARY_ACTION_HOLD) m_camera->rotateCamera(diff.x, diff.y); + else if(action.action == DefaultKeysMap::SECONDARY_ACTION_HOLD) + m_camera->moveCamera(diff.x, diff.y); } m_camera->zoom(input->getDeltaVerticalScroll()*120.f); } diff --git a/src/scene/containernode.cpp b/src/scene/containernode.cpp index ca3fbac..3966939 100644 --- a/src/scene/containernode.cpp +++ b/src/scene/containernode.cpp @@ -1,6 +1,10 @@ #include "containernode.h" #include +ContainerNode::ContainerNode() +{ +} + ContainerNode::~ContainerNode() { for(SceneNode *child : m_children) @@ -10,6 +14,28 @@ ContainerNode::~ContainerNode() // Container Node void ContainerNode::update() { + for(SceneNode* node : m_nodesToRemove) + { + for(auto it = m_children.begin(); it != m_children.end();) + { + if(*it == node) + it = m_children.erase(it); + else + ++it; + } + node->setSceneTree(nullptr); + node->setParent(nullptr); + } + m_nodesToRemove.clear(); + + for(SceneNode* node : m_nodesToAdd) + { + m_children.push_back(node); + node->setSceneTree(m_scene); + node->setParent(this); + } + m_nodesToAdd.clear(); + for(SceneNode* sn : m_children) sn->update(); } @@ -17,29 +43,13 @@ void ContainerNode::update() void ContainerNode::addChild(SceneNode* node) { if(node != nullptr) - { - node->setSceneTree(m_scene); - m_children.push_back(node); - node->m_parent = this; - } + m_nodesToAdd.push_back(node); } void ContainerNode::removeChild(SceneNode* node) { if(node != nullptr) - { - for(auto it = m_children.begin(); it != m_children.end();) - { - if(*it == node) - { - it = m_children.erase(it); - node->m_parent = nullptr; - node->setSceneTree(nullptr); - } - else - ++it; - } - } + m_nodesToRemove.push_back(node); } void ContainerNode::setSceneTree(SceneTree *tree) diff --git a/src/scene/containernode.h b/src/scene/containernode.h index adfecee..52db47f 100644 --- a/src/scene/containernode.h +++ b/src/scene/containernode.h @@ -9,7 +9,11 @@ */ class ContainerNode : public SceneNode { + std::vector m_nodesToRemove; + std::vector m_nodesToAdd; + public: + ContainerNode(); virtual ~ContainerNode(); virtual void update(); diff --git a/src/scene/gibgeneratornode.cpp b/src/scene/gibgeneratornode.cpp index 8084932..28f3185 100644 --- a/src/scene/gibgeneratornode.cpp +++ b/src/scene/gibgeneratornode.cpp @@ -47,7 +47,5 @@ void GibGeneratorNode::update() ++it; } - // use ContainerNode::update() here instead? - for(SceneNode* child : m_children) - child->update(); + ContainerNode::update(); } diff --git a/src/scene/graphicalcontainernode.cpp b/src/scene/graphicalcontainernode.cpp index 1239c3e..882b62b 100644 --- a/src/scene/graphicalcontainernode.cpp +++ b/src/scene/graphicalcontainernode.cpp @@ -10,6 +10,33 @@ GraphicalContainerNode::~GraphicalContainerNode() void GraphicalContainerNode::update() { + for(GraphicalNode* node : m_nodesToRemove) + { + for(auto it = m_children.begin(); it != m_children.end();) + { + if(*it == node) + { + it = m_children.erase(it); + node->setSceneTree(nullptr); + node->setParent(nullptr); + } + else + ++it; + } + } + m_nodesToRemove.clear(); + + for(GraphicalNode* node : m_nodesToAdd) + { + if(m_scene != nullptr) + node->setSceneTree(m_scene); + m_children.push_back(node); + node->setParent(this); + node->setParentTransform(m_transform); + node->setParentVisible(isVisible()); + } + m_nodesToAdd.clear(); + if(m_transformChanged) m_combinedTransform = m_transform * m_parentTransform; for(GraphicalNode* child : m_children) @@ -30,32 +57,13 @@ void GraphicalContainerNode::setSceneTree(SceneTree* tree) void GraphicalContainerNode::addChild(GraphicalNode *node) { if(node != nullptr) - { - if(m_scene != nullptr) - node->setSceneTree(m_scene); - m_children.push_back(node); - node->m_parent = this; - node->setParentTransform(m_transform); - node->setParentVisible(isVisible()); - } + m_nodesToAdd.push_back(node); } void GraphicalContainerNode::removeChild(GraphicalNode *node) { if(node != nullptr) - { - for(auto it = m_children.begin(); it != m_children.end();) - { - if(*it == node) - { - it = m_children.erase(it); - node->m_parent = nullptr; - node->setSceneTree(nullptr); - } - else - ++it; - } - } + m_nodesToRemove.push_back(node); } void GraphicalContainerNode::updateVisibility(bool visible) diff --git a/src/scene/graphicalcontainernode.h b/src/scene/graphicalcontainernode.h index 5b58d78..b5b8660 100644 --- a/src/scene/graphicalcontainernode.h +++ b/src/scene/graphicalcontainernode.h @@ -8,6 +8,9 @@ class GraphicalContainerNode : public GraphicalNode { + std::vector m_nodesToRemove; + std::vector m_nodesToAdd; + protected: std::vector m_children; glm::mat4 m_combinedTransform; diff --git a/src/scene/gui/textinputnode.cpp b/src/scene/gui/textinputnode.cpp index 33f2121..4cc1f7b 100644 --- a/src/scene/gui/textinputnode.cpp +++ b/src/scene/gui/textinputnode.cpp @@ -144,7 +144,7 @@ void TextInputNode::updateTextMesh(){ Font *shellfont = RESOURCE_GET(Font,"shellfont"); if(m_text_mesh){ this->removeChild(m_text_mesh); - delete(m_text_mesh); + m_text_mesh->destroyWhenOrphan(); } m_text_mesh = shellfont->getTextNode(m_text,m_text_color,m_font_size,false); if(m_text_mesh){ diff --git a/src/scene/playercharacternode.cpp b/src/scene/playercharacternode.cpp index 1ec24eb..1823727 100644 --- a/src/scene/playercharacternode.cpp +++ b/src/scene/playercharacternode.cpp @@ -72,9 +72,9 @@ PlayerCharacterNode::PlayerCharacterNode(bool noClip) : m_noclipMode(noClip), m_inputActions({NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION, NO_ACTION}) { - m_playerLight = new PointLight(glm::vec3(150, 10, 30), 10, glm::vec3(0.18f, 0.16f, 0.096f)*2.f); - m_playerLightNode = new LightNode(m_playerLight); - m_playerLightNode->m_parent = this; + // m_playerLight = new PointLight(glm::vec3(150, 10, 30), 10, glm::vec3(0.18f, 0.16f, 0.096f)*2.f); + // m_playerLightNode = new LightNode(m_playerLight); + // m_playerLightNode->setParent(this); // Create the shape btCollisionShape *shape = new btCapsuleShape(TORSO_RADIUS, TORSO_HEIGHT); @@ -93,9 +93,9 @@ PlayerCharacterNode::PlayerCharacterNode(bool noClip) : PlayerCharacterNode::~PlayerCharacterNode() { - m_playerLightNode->setSceneTree(nullptr); - delete m_playerLightNode; - delete m_playerLight; + // m_playerLightNode->setSceneTree(nullptr); + // delete m_playerLightNode; + // delete m_playerLight; } void PlayerCharacterNode::setInputs(int forward, int backward, int strafeLeft, int strafeRight, int jump, int run, int toggleNoClip) @@ -173,7 +173,7 @@ void PlayerCharacterNode::update() // update camera position btVector3 pos = m_rigidBody->getCenterOfMassPosition(); - m_playerLight->setPos(glm::vec3(pos.x(), pos.y()+TORSO_HEIGHT/2.f, pos.z())); + // m_playerLight->setPos(glm::vec3(pos.x(), pos.y()+TORSO_HEIGHT/2.f, pos.z())); m_fpsCamera.moveTo(glm::vec3(pos.x(), pos.y()+EYES_OFFSET, pos.z())); // update body movement @@ -297,7 +297,7 @@ void PlayerCharacterNode::update() } m_rigidBody->setLinearVelocity(newVelocity); } - m_playerLightNode->update(); + // m_playerLightNode->update(); glm::vec3 p = this->getEyePosition(); sf::Listener::setPosition(p.x,p.y,p.z); glm::vec3 d = getDirection(); @@ -313,5 +313,5 @@ void PlayerCharacterNode::toggleNoClip() void PlayerCharacterNode::setSceneTree(SceneTree* tree) { m_scene = tree; - m_playerLightNode->setSceneTree(tree); + // m_playerLightNode->setSceneTree(tree); } diff --git a/src/scene/scenenode.cpp b/src/scene/scenenode.cpp index 81c6636..38f7235 100644 --- a/src/scene/scenenode.cpp +++ b/src/scene/scenenode.cpp @@ -1,8 +1,15 @@ #include "scenenode.h" #include "scenetree.h" -const Engine& SceneNode::getEngine() +Engine &SceneNode::getEngine() { return m_scene->getEngine(); } +void SceneNode::setParent(SceneNode* parent) +{ + if(m_toDestroy && parent == nullptr) + delete this; + else + m_parent = parent; +} diff --git a/src/scene/scenenode.h b/src/scene/scenenode.h index f193400..396b52b 100644 --- a/src/scene/scenenode.h +++ b/src/scene/scenenode.h @@ -8,19 +8,29 @@ class Engine; class SceneNode { -protected: - const Engine& getEngine(); -public: - SceneNode() : m_parent(nullptr), m_scene(nullptr) {} + bool m_toDestroy; +protected: + Engine& getEngine(); SceneNode* m_parent; SceneTree* m_scene; + +public: + SceneNode() : m_toDestroy(false), m_parent(nullptr), m_scene(nullptr) {} + // bool m_enabled; virtual void update() = 0; virtual Light* getLight() {return nullptr;} virtual GeometryNode* getGeometryNode() {return nullptr;} virtual void setSceneTree(SceneTree* tree) {m_scene = tree;} + virtual void setParent(SceneNode* parent); + virtual SceneNode* getParent() { return m_parent; } // virtual void toggleNode(){m_enabled = !m_enabled;} + + /** + * @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; } }; #endif // SCENENODE_H diff --git a/src/scene/scenetree.cpp b/src/scene/scenetree.cpp index 86385e7..15b0fe0 100644 --- a/src/scene/scenetree.cpp +++ b/src/scene/scenetree.cpp @@ -12,7 +12,7 @@ #include -SceneTree::SceneTree(const Engine &engine) : +SceneTree::SceneTree(Engine &engine) : Scene(), m_engine(engine), m_shaderRefreshRequired(false), @@ -30,12 +30,13 @@ SceneTree::~SceneTree() delete m_world; } -void SceneTree::setMainCamera(CameraNode *camNode) +void SceneTree::setMainCamera(Camera *camera) { - m_camera = camNode->getCamera(); + m_camera = camera; ((DeferredPipeline*)m_pipeline)->setCamera(m_camera); sf::Vector2u size = getEngine().getWindow()->getSize(); - m_camera->resize(size.x, size.y); + if(m_camera != nullptr) + m_camera->resize(size.x, size.y); } SceneIterator* SceneTree::getLights() diff --git a/src/scene/scenetree.h b/src/scene/scenetree.h index 84016d6..cfbab18 100644 --- a/src/scene/scenetree.h +++ b/src/scene/scenetree.h @@ -29,7 +29,7 @@ public: void update(); - void setMainCamera(CameraNode *camNode); + void setMainCamera(Camera *camera); Camera* getCamera() const { return m_camera; } ContainerNode* getRootObject(){return &m_root;} @@ -41,15 +41,15 @@ public: void removeFromIndex(SceneNode *node); void updateShaders(); - const Engine& getEngine() { return m_engine; } + Engine& getEngine() { return m_engine; } private: // A SceneTree can only be constructed by the engine by using Engine::createScene() //friend SceneTree* Engine::createScene(); friend void Engine::createScene(std::string scene_name); - SceneTree(const Engine &engine); + SceneTree(Engine &engine); - const Engine &m_engine; + Engine &m_engine; ContainerNode m_root; btDiscreteDynamicsWorld* m_world; std::vector m_lights; diff --git a/src/sparrowshell/shellbuffer.cpp b/src/sparrowshell/shellbuffer.cpp index 8f8bc9e..b62990e 100644 --- a/src/sparrowshell/shellbuffer.cpp +++ b/src/sparrowshell/shellbuffer.cpp @@ -42,7 +42,7 @@ void ShellBuffer::push(TextNode* tnode){ m_zero_offset %= m_max_size; }else m_children.push_back(tnode); - tnode->m_parent = this; + tnode->setParent(this); tnode->setParentTransform(m_transform); tnode->setParentVisible(isVisible()); m_buffer_modified = true; diff --git a/src/test/main.cpp b/src/test/main.cpp index 6ff733a..c4feb7b 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -196,7 +196,7 @@ public: m_player->setInputs(DefaultKeysMap::MOVE_FORWARD, DefaultKeysMap::MOVE_BACKWARD, DefaultKeysMap::STRAFE_LEFT, DefaultKeysMap::STRAFE_RIGHT, DefaultKeysMap::JUMP, DefaultKeysMap::RUN, DefaultKeysMap::TOGGLE_NOCLIP); SceneTree* scene = RESOURCE_GET(SceneTree, m_demo_scene); scene->getRootObject()->addChild(m_player); - scene->setMainCamera(m_player); + scene->setMainCamera(m_player->getCamera()); //potator Potator *potator = new Potator(m_player, DefaultKeysMap::MAIN_ACTION, DefaultKeysMap::SECONDARY_ACTION, DefaultKeysMap::TERTIARY_ACTION); @@ -268,7 +268,6 @@ public: m_demo->initScene(); m_engine->setScene(m_demo->getScene()); m_engine->getInput()->setCurrentContext("default"); - m_engine->getInput()->setMouseGrabbed(true); m_engine->getScene()->getPhysics()->addRigidBody(m_demo->getPlayer()->getRigidbody()); m_engine->toggleMouseVisibility(); } @@ -363,24 +362,26 @@ int main(){ // SceneTree *scene = engine.createScene(); // engine.setScene(scene); - // settin gup SparrowInput + // setting up SparrowInput Input* input = engine.getInput(); input->setKeysMap(DefaultKeysMap()); input->addContext(Context("default", DefaultKeysMap::getDefaultContext())); - input->setCurrentContext("default"); input->updateKeyBindings(); engine.setTogglePhysicsDebugAction(DefaultKeysMap::TOGGLE_PHYSICS_DEBUG); engine.setToggleShellAction(DefaultKeysMap::TOGGLE_CONSOLE); engine.setExitGameAction(DefaultKeysMap::EXIT_GAME); engine.setShowMouseAction(DefaultKeysMap::TOGGLE_MOUSE_CURSOR); - //c'est un goup SparrowShell + // setting up SparrowShell SparrowShell* shell = engine.getShell(); shell->setInputs(DefaultKeysMap::MOVE_CURSOR_LEFT,DefaultKeysMap::MOVE_CURSOR_RIGHT,DefaultKeysMap::HISTORY_UP,DefaultKeysMap::HISTORY_DOWN); input->addContext(Context("shell",DefaultKeysMap::getShellContext())); input->updateKeyBindings(); - //setup menu + // setup editor + input->addContext(Context("editor",DefaultKeysMap::getObjectEditorContext())); + + // setup menu Menu* menu = new Menu(&engine,config); Demo* demo = new Demo(&engine,config); menu->setLeftClickAction(DefaultKeysMap::LEFT_CLICK); @@ -393,90 +394,5 @@ int main(){ engine.setScene(menu->getScene()); engine.getInput()->setMouseGrabbed(false); - /* - // trackball camera - TrackBallCameraNode *trackBallCam = new TrackBallCameraNode(engine.getInput()); - trackBallCam->setInputs(myKeysMap::SECONDARY_HOLD, myKeysMap::MAIN_HOLD); - scene.getRootObject()->addChild(trackBallCam); - scene.setMainCamera(trackBallCam); - - // first person player controller - PlayerCharacterNode *player = new PlayerCharacterNode(false); - player->setInputs(DefaultKeysMap::MOVE_FORWARD, DefaultKeysMap::MOVE_BACKWARD, DefaultKeysMap::STRAFE_LEFT, DefaultKeysMap::STRAFE_RIGHT, DefaultKeysMap::JUMP, DefaultKeysMap::TOGGLE_NOCLIP); - scene->getRootObject()->addChild(player); - scene->setMainCamera(player); - engine.getPhysics()->addRigidBody(player->getRigidbody()); - - // throw cubes and spheres with mouse clicks - Potator *potator = new Potator(player, DefaultKeysMap::MAIN_ACTION, DefaultKeysMap::SECONDARY_ACTION, DefaultKeysMap::TERTIARY_ACTION); - scene->getRootObject()->addChild(potator); - - // lighting - LightNode *ambientLight = new LightNode(new AmbientLight(glm::vec3(0.05f))); - - DirectionnalLight* sun = new DirectionnalLight(glm::vec3(5, 8, -2), glm::vec3(0.9f)); - LightNode *sunLight = new LightNode(sun); - - scene->getRootObject()->addChild(ambientLight); - scene->getRootObject()->addChild(sunLight); -*/ - // scene - - /* if(config.scene == "sponza") - { - sun->initShadowMap(4096); - generateSponza(scene, engine.getPhysics()); - scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-3.5, 2, 1.8), 15, glm::vec3(0.35f)))); - scene->getRootObject()->addChild(new LightNode(new PointLight(glm::vec3(-5, 6, 2), 15, glm::vec3(0.35f)))); - player->setPosition(0.f, 2.f, 0.f); - sun->setShadowView(glm::vec3(30, 30, 50)); - } - else if(config->scene == "terrain") - { - sun->initShadowMap(4096); - generateTerrain(scene, engine.getPhysics()); - player->setPosition(0.f, 15.f, 0.f); - sun->setShadowView(glm::vec3(130, 130, 70)); - }*/ - - // shell output tests -// engine.getShell()->out("Hello World!"); -// engine.getShell()->out("Starting test :"); - - // preparing shaders and launching the engine engine.start(); - - // pathfinding tests -/* GraphNode n1 = GraphNode(); - n1.setValue(1); - GraphNode n2 = GraphNode(); - n2.setValue(2); - GraphNode n3 = GraphNode(); - n3.setValue(3); - GraphNode n4 = GraphNode(); - n4.setValue(4); - GraphNode n5 = GraphNode(); - n5.setValue(5); - - n1.addNeighbours(&n2); - n1.addNeighbours(&n3); - n2.addNeighbours(&n4); - n3.addNeighbours(&n4); - n3.addNeighbours(&n2); - n3.addNeighbours(&n5); - - std::vector path = PathFinder::a_star(&n1,&n4,true); - std::cout << "Path Size: " << path.size() << std::endl; - for(GraphNode* gn: path){ - std::cout << gn->getValue() << std::endl; - } - - // loaders tests - Loader::setObjDirectory("data/"); - Loader::setMtlDirectory("data/"); - Loader::setTexDirectory("data/"); - std::vector meshes = Loader::loadMesh("sword.obj"); -*/ - - }