#include "engine.h" #include #include #include #include #include #include #include #include "resourcemanager.h" #include "scene/scenetree.h" #include "sparrowshell/sparrowshell.h" #include "scene/physicsdebugnode.h" #include "imgui/imgui.h" Engine::Engine() : m_window(nullptr), m_input(nullptr), m_world(nullptr), m_physicsDebugNode(nullptr), m_togglePhysicsDebugAction(NO_ACTION), m_toggleShellAction(NO_ACTION), m_exitGameAction(NO_ACTION), m_showMouseAction(NO_ACTION), m_mouseVisible(true) { m_clock = new sf::Clock(); m_clock->restart(); m_renderer = new SparrowRenderer(); } Engine::~Engine() { delete m_clock; delete m_renderer; if(m_window != NULL) { m_window->close(); delete m_window; delete m_input; } if(m_world != NULL) delete m_world; } void Engine::createWindow(std::string title, unsigned int w, unsigned int h, const std::string &mode) { sf::Uint32 style = sf::Style::Close; if(mode == "fullscreen") style = sf::Style::Fullscreen; else if(mode == "borderless") style = sf::Style::None; m_window = new sf::Window(sf::VideoMode(w, h), title, style, sf::ContextSettings(24, 8, 0, 3, 3, sf::ContextSettings::Attribute::Core)); m_window->setFramerateLimit(60); m_input = new Input(m_window); m_renderer->initGL(w, h); m_sparrowshell = new SparrowShell(m_window); } void Engine::initPhysics() { btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration(); btBroadphaseInterface *broadPhase = new btAxisSweep3(btVector3(-1000, -1000, -1000), btVector3(1000, 1000, 1000)); btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration); btSequentialImpulseConstraintSolver *solver = new btSequentialImpulseConstraintSolver(); m_world = new btDiscreteDynamicsWorld(dispatcher, broadPhase, solver, collisionConfiguration); m_world->setGravity(btVector3(0, -9.81f, 0)); } void Engine::update() { // update delta time m_lastTimeStamp = m_timeStamp; m_timeStamp = (unsigned int) m_clock->getElapsedTime().asMilliseconds(); // update Events m_input->updateEvents(); checkSpecialInputs(); // initialize imgui frame ImGuiIO& io = ImGui::GetIO(); io.DeltaTime = float(getDeltaTime()) / 1000.; ImGui::NewFrame(); // test gui { static bool testGuiOpen = true; if(testGuiOpen) { ImGui::Begin("Test imgui Window", &testGuiOpen); ImGui::Text("Hello, world!"); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); bool physicsDebugEnabled = (m_physicsDebugNode != nullptr); if(ImGui::Checkbox("Toggle physics debug", &physicsDebugEnabled)) { if(physicsDebugEnabled) enablePhysicsDebug(); else disablePhysicsDebug(); } bool isMouseVisible = m_mouseVisible; if(ImGui::Checkbox("Mouse cursor ( shortcut : [M] )", &isMouseVisible)) toggleMouseVisibility(); if(ImGui::Button("EXIT GAME")) stop(); float gravity = - m_world->getGravity().y(); if(ImGui::SliderFloat("Gravity", &gravity, 0.f, 100.f)) m_world->setGravity(btVector3(0, -gravity, 0)); ImGui::End(); } } // update Physics if(m_world != nullptr) { m_world->stepSimulation(1000.f*(float)getDeltaTime()); if(m_physicsDebugNode != nullptr) { m_physicsDebugNode->clearBuffers(); m_world->debugDrawWorld(); } } // update Scene getScene()->update(); // update Display if(m_input->isResized()) m_renderer->resizeGL(m_window->getSize().x, m_window->getSize().y); m_renderer->renderGL(); m_window->display(); } void Engine::start() { m_running = true; while(!m_input->isCloseRequested() && m_running) update(); } void Engine::stop() { m_running = false; } unsigned int Engine::getTime() const { return m_timeStamp; } unsigned int Engine::getDeltaTime() const { return m_timeStamp - m_lastTimeStamp; } //void Engine::setScene(SceneTree *scene) void Engine::setScene(std::string scene) { if(m_current_scene.empty()){ m_current_scene = scene; } SceneTree* previous_scene = RESOURCE_GET(SceneTree,m_current_scene); SceneTree* new_scene = RESOURCE_GET(SceneTree,scene); m_current_scene = scene; if(m_physicsDebugNode != nullptr) { previous_scene->removeFromIndex(m_physicsDebugNode); new_scene->addToIndex(m_physicsDebugNode); } previous_scene->getRootObject()->removeChild(m_sparrowshell); m_renderer->setScene(new_scene); m_renderer->resizeGL(m_window->getSize().x, m_window->getSize().y); new_scene->getRootObject()->addChild(m_sparrowshell); new_scene->updateShaders(); } void Engine::enablePhysicsDebug() { if(m_world != nullptr && m_physicsDebugNode == nullptr) { m_physicsDebugNode = new PhysicsDebugNode(); getScene()->addToIndex(m_physicsDebugNode); m_world->setDebugDrawer(m_physicsDebugNode); m_world->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe); getScene()->updateShaders(); } } void Engine::disablePhysicsDebug() { if(m_world != nullptr && m_physicsDebugNode != nullptr) { m_world->setDebugDrawer(nullptr); getScene()->removeFromIndex(m_physicsDebugNode); delete m_physicsDebugNode; m_physicsDebugNode = nullptr; } } void Engine::toggleMouseVisibility() { m_mouseVisible = !m_mouseVisible; m_window->setMouseCursorVisible(m_mouseVisible); m_input->setMouseGrabbed(!m_mouseVisible); } void Engine::setTogglePhysicsDebugAction(int action) { m_togglePhysicsDebugAction = action; } void Engine::setToggleShellAction(int action) { m_toggleShellAction = action; } void Engine::setExitGameAction(int action) { m_exitGameAction = action; } void Engine::setShowMouseAction(int action) { m_showMouseAction = action; } void Engine::checkSpecialInputs() { for(Action action : m_input->getActions()) { if(action.action == NO_ACTION) continue; if(action.action == m_togglePhysicsDebugAction) { if(m_physicsDebugNode == nullptr) enablePhysicsDebug(); else disablePhysicsDebug(); } else if(action.action == m_toggleShellAction) m_sparrowshell->toggleShell(); else if(action.action == m_exitGameAction) { if(m_sparrowshell->isVisible()) m_sparrowshell->toggleShell(); else m_running = false; } else if(action.action == m_showMouseAction) toggleMouseVisibility(); } } void Engine::createScene(std::string scene_name) { RESOURCE_ADD(new SceneTree(*this),SceneTree,scene_name); //return new SceneTree(*this); } SceneTree* Engine::getScene() const { return RESOURCE_GET(SceneTree,m_current_scene); }