<commit_before>#ifndef EC_META_SYSTEM_THREADPOOL_HPP
#define EC_META_SYSTEM_THREADPOOL_HPP

#include <atomic>
#include <chrono>
#include <deque>
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <tuple>
#include <vector>

#ifndef NDEBUG
#include <iostream>
#endif

namespace EC {

namespace Internal {
using TPFnType = std::function<void(void *)>;
using TPTupleType = std::tuple<TPFnType, void *>;
using TPQueueType = std::queue<TPTupleType>;
using ThreadPtr = std::unique_ptr<std::thread>;
using ThreadStackType = std::vector<std::tuple<ThreadPtr, std::thread::id>>;
using ThreadStacksType = std::deque<ThreadStackType>;
using ThreadStacksMutexesT = std::deque<std::mutex>;
using ThreadCountersT = std::deque<std::atomic_uint>;
using PtrsHoldT = std::deque<std::atomic_bool>;
using PointersT =
    std::tuple<ThreadStackType *, std::mutex *, std::atomic_uint *, std::atomic_bool *>;
}  // namespace Internal

/*!
    \brief Implementation of a Thread Pool.

    Note that MAXSIZE template parameter determines how many threads are created
    each time that startThreads() (or easyStartAndWait()) is called.
*/
template <unsigned int MAXSIZE>
class ThreadPool {
   public:
    ThreadPool()
        : threadStacks{}, threadStackMutexes{}, fnQueue{}, queueMutex{} {}

    ~ThreadPool() {
        while (!isNotRunning()) {
            std::this_thread::sleep_for(std::chrono::microseconds(30));
        }
    }

    /*!
        \brief Queues a function to be called (doesn't start calling yet).

        To run the queued functions, startThreads() must be called to wake the
        waiting threads which will start pulling functions from the queue to be
        called.

        Note that the easyStartAndWait() calls startThreads() and waits until
        the threads have finished execution.
    */
    void queueFn(std::function<void(void *)> &&fn, void *ud = nullptr) {
        std::lock_guard<std::mutex> lock(queueMutex);
        fnQueue.emplace(std::make_tuple(fn, ud));
    }

    /*!
        \brief Creates MAXSIZE threads that will process queueFn() functions.

        Note that if MAXSIZE < 2, then this function will synchronously execute
        the queued functions and block until the functions have been executed.
        Otherwise, this function may return before the queued functions have
        been executed.
     */
    Internal::PointersT startThreads() {
        if (MAXSIZE >= 2) {
            checkStacks();
            auto pointers = newStackEntry();
            Internal::ThreadStackType *threadStack = std::get<0>(pointers);
            std::mutex *threadStackMutex = std::get<1>(pointers);
            std::atomic_uint *aCounter = std::get<2>(pointers);
            for (unsigned int i = 0; i < MAXSIZE; ++i) {
                std::thread *newThread = new std::thread(
                    [](Internal::ThreadStackType *threadStack,
                       std::mutex *threadStackMutex,
                       Internal::TPQueueType *fnQueue, std::mutex *queueMutex,
                       std::atomic_uint *initCount) {
                        // add id to idStack "call stack"
                        {
                            std::lock_guard<std::mutex> lock(*threadStackMutex);
                            threadStack->push_back(
                                {Internal::ThreadPtr(nullptr),
                                 std::this_thread::get_id()});
                        }

                        ++(*initCount);

                        // fetch queued fns and execute them
                        // fnTuples must live until end of function
                        std::list<Internal::TPTupleType> fnTuples;
                        do {
                            bool fnFound = false;
                            {
                                std::lock_guard<std::mutex> lock(*queueMutex);
                                if (!fnQueue->empty()) {
                                    fnTuples.emplace_back(
                                        std::move(fnQueue->front()));
                                    fnQueue->pop();
                                    fnFound = true;
                                }
                            }
                            if (fnFound) {
                                std::get<0>(fnTuples.back())(
                                    std::get<1>(fnTuples.back()));
                            } else {
                                break;
                            }
                        } while (true);

                        // pop id from idStack "call stack"
                        do {
                            std::this_thread::sleep_for(
                                std::chrono::microseconds(15));
                            if (initCount->load() != MAXSIZE) {
                                continue;
                            }
                            {
                                std::lock_guard<std::mutex> lock(
                                    *threadStackMutex);
                                if (std::get<1>(threadStack->back()) ==
                                    std::this_thread::get_id()) {
                                    if (!std::get<0>(threadStack->back())) {
                                        continue;
                                    }
                                    std::get<0>(threadStack->back())->detach();
                                    threadStack->pop_back();
                                    break;
                                }
                            }
                        } while (true);
                    },
                    threadStack, threadStackMutex, &fnQueue, &queueMutex,
                    aCounter);
                // Wait until thread has pushed to threadStack before setting
                // the handle to it
                while (aCounter->load() != i + 1) {
                    std::this_thread::sleep_for(std::chrono::microseconds(15));
                }
                std::lock_guard<std::mutex> stackLock(*threadStackMutex);
                std::get<0>(threadStack->at(i)).reset(newThread);
            }
            return pointers;
        } else {
            sequentiallyRunTasks();
        }
        return {nullptr, nullptr, nullptr, nullptr};
    }

    /*!
        \brief Returns true if the function queue is empty.
    */
    bool isQueueEmpty() {
        std::lock_guard<std::mutex> lock(queueMutex);
        return fnQueue.empty();
    }

    /*!
        \brief Returns the MAXSIZE count that this class was created with.
     */
    constexpr unsigned int getMaxThreadCount() { return MAXSIZE; }

    /*!
        \brief Calls startThreads() and waits until all threads have finished.

        Regardless of the value set to MAXSIZE, this function will block until
        all previously queued functions have been executed.
     */
    void easyStartAndWait() {
        if (MAXSIZE >= 2) {
            Internal::PointersT pointers = startThreads();
            do {
                std::this_thread::sleep_for(std::chrono::microseconds(30));

                bool isQueueEmpty = false;
                {
                    std::lock_guard<std::mutex> lock(queueMutex);
                    isQueueEmpty = fnQueue.empty();
                }

                if (isQueueEmpty) {
                    break;
                }
            } while (true);
            if (std::get<0>(pointers)) {
                do {
                    {
                        std::lock_guard<std::mutex> lock(*std::get<1>(pointers));
                        if (std::get<0>(pointers)->empty()) {
                            std::get<3>(pointers)->store(false);
                            break;
                        }
                    }
                    std::this_thread::sleep_for(std::chrono::microseconds(15));
                } while (true);
            }
        } else {
            sequentiallyRunTasks();
        }
    }

    /*!
        \brief Checks if any threads are currently running, returning true if
        there are no threads running.
     */
    bool isNotRunning() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        auto tIter = threadStacks.begin();
        auto mIter = threadStackMutexes.begin();
        while (tIter != threadStacks.end() &&
               mIter != threadStackMutexes.end()) {
            {
                std::lock_guard<std::mutex> lock(*mIter);
                if (!tIter->empty()) {
                    return false;
                }
            }
            ++tIter;
            ++mIter;
        }
        return true;
    }

   private:
    Internal::ThreadStacksType threadStacks;
    Internal::ThreadStacksMutexesT threadStackMutexes;
    Internal::TPQueueType fnQueue;
    std::mutex queueMutex;
    Internal::ThreadCountersT threadCounters;
    Internal::PtrsHoldT ptrsHoldBools;
    std::mutex dequesMutex;

    void sequentiallyRunTasks() {
        // pull functions from queue and run them on current thread
        Internal::TPTupleType fnTuple;
        bool hasFn;
        do {
            {
                std::lock_guard<std::mutex> lock(queueMutex);
                if (!fnQueue.empty()) {
                    hasFn = true;
                    fnTuple = fnQueue.front();
                    fnQueue.pop();
                } else {
                    hasFn = false;
                }
            }
            if (hasFn) {
                std::get<0>(fnTuple)(std::get<1>(fnTuple));
            }
        } while (hasFn);
    }

    void checkStacks() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        if (threadStacks.empty()) {
            return;
        }

        bool erased = false;
        do {
            erased = false;
            {
                std::lock_guard<std::mutex> lock(threadStackMutexes.front());
                if (ptrsHoldBools.front().load()) {
                    break;
                } else if (threadStacks.front().empty()) {
                    threadStacks.pop_front();
                    threadCounters.pop_front();
                    ptrsHoldBools.pop_front();
                    erased = true;
                }
            }
            if (erased) {
                threadStackMutexes.pop_front();
            } else {
                break;
            }
        } while (!threadStacks.empty() && !threadStackMutexes.empty() &&
                 !threadCounters.empty() && !ptrsHoldBools.empty());
    }

    Internal::PointersT newStackEntry() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        threadStacks.emplace_back();
        threadStackMutexes.emplace_back();
        threadCounters.emplace_back();
        threadCounters.back().store(0);
        ptrsHoldBools.emplace_back();
        ptrsHoldBools.back().store(true);

        return {&threadStacks.back(), &threadStackMutexes.back(),
                &threadCounters.back(), &ptrsHoldBools.back()};
    }
};

}  // namespace EC

#endif
<commit_msg>clang-format EC/ThreadPool.hpp<commit_after>#ifndef EC_META_SYSTEM_THREADPOOL_HPP
#define EC_META_SYSTEM_THREADPOOL_HPP

#include <atomic>
#include <chrono>
#include <deque>
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <tuple>
#include <vector>

#ifndef NDEBUG
#include <iostream>
#endif

namespace EC {

namespace Internal {
using TPFnType = std::function<void(void *)>;
using TPTupleType = std::tuple<TPFnType, void *>;
using TPQueueType = std::queue<TPTupleType>;
using ThreadPtr = std::unique_ptr<std::thread>;
using ThreadStackType = std::vector<std::tuple<ThreadPtr, std::thread::id>>;
using ThreadStacksType = std::deque<ThreadStackType>;
using ThreadStacksMutexesT = std::deque<std::mutex>;
using ThreadCountersT = std::deque<std::atomic_uint>;
using PtrsHoldT = std::deque<std::atomic_bool>;
using PointersT = std::tuple<ThreadStackType *, std::mutex *,
                             std::atomic_uint *, std::atomic_bool *>;
}  // namespace Internal

/*!
    \brief Implementation of a Thread Pool.

    Note that MAXSIZE template parameter determines how many threads are created
    each time that startThreads() (or easyStartAndWait()) is called.
*/
template <unsigned int MAXSIZE>
class ThreadPool {
   public:
    ThreadPool()
        : threadStacks{}, threadStackMutexes{}, fnQueue{}, queueMutex{} {}

    ~ThreadPool() {
        while (!isNotRunning()) {
            std::this_thread::sleep_for(std::chrono::microseconds(30));
        }
    }

    /*!
        \brief Queues a function to be called (doesn't start calling yet).

        To run the queued functions, startThreads() must be called to wake the
        waiting threads which will start pulling functions from the queue to be
        called.

        Note that the easyStartAndWait() calls startThreads() and waits until
        the threads have finished execution.
    */
    void queueFn(std::function<void(void *)> &&fn, void *ud = nullptr) {
        std::lock_guard<std::mutex> lock(queueMutex);
        fnQueue.emplace(std::make_tuple(fn, ud));
    }

    /*!
        \brief Creates MAXSIZE threads that will process queueFn() functions.

        Note that if MAXSIZE < 2, then this function will synchronously execute
        the queued functions and block until the functions have been executed.
        Otherwise, this function may return before the queued functions have
        been executed.
     */
    Internal::PointersT startThreads() {
        if (MAXSIZE >= 2) {
            checkStacks();
            auto pointers = newStackEntry();
            Internal::ThreadStackType *threadStack = std::get<0>(pointers);
            std::mutex *threadStackMutex = std::get<1>(pointers);
            std::atomic_uint *aCounter = std::get<2>(pointers);
            for (unsigned int i = 0; i < MAXSIZE; ++i) {
                std::thread *newThread = new std::thread(
                    [](Internal::ThreadStackType *threadStack,
                       std::mutex *threadStackMutex,
                       Internal::TPQueueType *fnQueue, std::mutex *queueMutex,
                       std::atomic_uint *initCount) {
                        // add id to idStack "call stack"
                        {
                            std::lock_guard<std::mutex> lock(*threadStackMutex);
                            threadStack->push_back(
                                {Internal::ThreadPtr(nullptr),
                                 std::this_thread::get_id()});
                        }

                        ++(*initCount);

                        // fetch queued fns and execute them
                        // fnTuples must live until end of function
                        std::list<Internal::TPTupleType> fnTuples;
                        do {
                            bool fnFound = false;
                            {
                                std::lock_guard<std::mutex> lock(*queueMutex);
                                if (!fnQueue->empty()) {
                                    fnTuples.emplace_back(
                                        std::move(fnQueue->front()));
                                    fnQueue->pop();
                                    fnFound = true;
                                }
                            }
                            if (fnFound) {
                                std::get<0>(fnTuples.back())(
                                    std::get<1>(fnTuples.back()));
                            } else {
                                break;
                            }
                        } while (true);

                        // pop id from idStack "call stack"
                        do {
                            std::this_thread::sleep_for(
                                std::chrono::microseconds(15));
                            if (initCount->load() != MAXSIZE) {
                                continue;
                            }
                            {
                                std::lock_guard<std::mutex> lock(
                                    *threadStackMutex);
                                if (std::get<1>(threadStack->back()) ==
                                    std::this_thread::get_id()) {
                                    if (!std::get<0>(threadStack->back())) {
                                        continue;
                                    }
                                    std::get<0>(threadStack->back())->detach();
                                    threadStack->pop_back();
                                    break;
                                }
                            }
                        } while (true);
                    },
                    threadStack, threadStackMutex, &fnQueue, &queueMutex,
                    aCounter);
                // Wait until thread has pushed to threadStack before setting
                // the handle to it
                while (aCounter->load() != i + 1) {
                    std::this_thread::sleep_for(std::chrono::microseconds(15));
                }
                std::lock_guard<std::mutex> stackLock(*threadStackMutex);
                std::get<0>(threadStack->at(i)).reset(newThread);
            }
            return pointers;
        } else {
            sequentiallyRunTasks();
        }
        return {nullptr, nullptr, nullptr, nullptr};
    }

    /*!
        \brief Returns true if the function queue is empty.
    */
    bool isQueueEmpty() {
        std::lock_guard<std::mutex> lock(queueMutex);
        return fnQueue.empty();
    }

    /*!
        \brief Returns the MAXSIZE count that this class was created with.
     */
    constexpr unsigned int getMaxThreadCount() { return MAXSIZE; }

    /*!
        \brief Calls startThreads() and waits until all threads have finished.

        Regardless of the value set to MAXSIZE, this function will block until
        all previously queued functions have been executed.
     */
    void easyStartAndWait() {
        if (MAXSIZE >= 2) {
            Internal::PointersT pointers = startThreads();
            do {
                std::this_thread::sleep_for(std::chrono::microseconds(30));

                bool isQueueEmpty = false;
                {
                    std::lock_guard<std::mutex> lock(queueMutex);
                    isQueueEmpty = fnQueue.empty();
                }

                if (isQueueEmpty) {
                    break;
                }
            } while (true);
            if (std::get<0>(pointers)) {
                do {
                    {
                        std::lock_guard<std::mutex> lock(
                            *std::get<1>(pointers));
                        if (std::get<0>(pointers)->empty()) {
                            std::get<3>(pointers)->store(false);
                            break;
                        }
                    }
                    std::this_thread::sleep_for(std::chrono::microseconds(15));
                } while (true);
            }
        } else {
            sequentiallyRunTasks();
        }
    }

    /*!
        \brief Checks if any threads are currently running, returning true if
        there are no threads running.
     */
    bool isNotRunning() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        auto tIter = threadStacks.begin();
        auto mIter = threadStackMutexes.begin();
        while (tIter != threadStacks.end() &&
               mIter != threadStackMutexes.end()) {
            {
                std::lock_guard<std::mutex> lock(*mIter);
                if (!tIter->empty()) {
                    return false;
                }
            }
            ++tIter;
            ++mIter;
        }
        return true;
    }

   private:
    Internal::ThreadStacksType threadStacks;
    Internal::ThreadStacksMutexesT threadStackMutexes;
    Internal::TPQueueType fnQueue;
    std::mutex queueMutex;
    Internal::ThreadCountersT threadCounters;
    Internal::PtrsHoldT ptrsHoldBools;
    std::mutex dequesMutex;

    void sequentiallyRunTasks() {
        // pull functions from queue and run them on current thread
        Internal::TPTupleType fnTuple;
        bool hasFn;
        do {
            {
                std::lock_guard<std::mutex> lock(queueMutex);
                if (!fnQueue.empty()) {
                    hasFn = true;
                    fnTuple = fnQueue.front();
                    fnQueue.pop();
                } else {
                    hasFn = false;
                }
            }
            if (hasFn) {
                std::get<0>(fnTuple)(std::get<1>(fnTuple));
            }
        } while (hasFn);
    }

    void checkStacks() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        if (threadStacks.empty()) {
            return;
        }

        bool erased = false;
        do {
            erased = false;
            {
                std::lock_guard<std::mutex> lock(threadStackMutexes.front());
                if (ptrsHoldBools.front().load()) {
                    break;
                } else if (threadStacks.front().empty()) {
                    threadStacks.pop_front();
                    threadCounters.pop_front();
                    ptrsHoldBools.pop_front();
                    erased = true;
                }
            }
            if (erased) {
                threadStackMutexes.pop_front();
            } else {
                break;
            }
        } while (!threadStacks.empty() && !threadStackMutexes.empty() &&
                 !threadCounters.empty() && !ptrsHoldBools.empty());
    }

    Internal::PointersT newStackEntry() {
        std::lock_guard<std::mutex> lock(dequesMutex);
        threadStacks.emplace_back();
        threadStackMutexes.emplace_back();
        threadCounters.emplace_back();
        threadCounters.back().store(0);
        ptrsHoldBools.emplace_back();
        ptrsHoldBools.back().store(true);

        return {&threadStacks.back(), &threadStackMutexes.back(),
                &threadCounters.back(), &ptrsHoldBools.back()};
    }
};

}  // namespace EC

#endif
<|endoftext|>


<commit_before>#include "Editor.hpp"

#include "Util/EditorSettings.hpp"
#undef CreateDirectory

#include <Engine/Util/Input.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/ScriptManager.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/MainWindow.hpp>
#include <Engine/Component/DirectionalLight.hpp>
#include <Engine/Component/Lens.hpp>
#include <Engine/Component/Listener.hpp>
#include "ImGui/Theme.hpp"

#include <imgui.h>
#include <GLFW/glfw3.h>

Editor::Editor() {
    // Create Hymns directory.
    FileSystem::CreateDirectory((FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns").c_str());

    // Load theme.
    std::string theme = EditorSettings::GetInstance().GetString("Theme");
    if (FileSystem::FileExists((FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Themes" + FileSystem::DELIMITER + theme + ".json").c_str())) {
        ImGui::LoadTheme(theme.c_str());
    } else {
        ImGui::LoadDefaultTheme();
    }

    // Assign controls.
    Input()->AssignButton(InputHandler::PROFILE, InputHandler::KEYBOARD, GLFW_KEY_F2);
    Input()->AssignButton(InputHandler::PLAYTEST, InputHandler::KEYBOARD, GLFW_KEY_F5);
    Input()->AssignButton(InputHandler::CONTROL, InputHandler::KEYBOARD, GLFW_KEY_LEFT_CONTROL);
    Input()->AssignButton(InputHandler::NEW, InputHandler::KEYBOARD, GLFW_KEY_N);
    Input()->AssignButton(InputHandler::OPEN, InputHandler::KEYBOARD, GLFW_KEY_O);
    Input()->AssignButton(InputHandler::CAMERA, InputHandler::MOUSE, GLFW_MOUSE_BUTTON_MIDDLE);
    Input()->AssignButton(InputHandler::FORWARD, InputHandler::KEYBOARD, GLFW_KEY_W);
    Input()->AssignButton(InputHandler::BACKWARD, InputHandler::KEYBOARD, GLFW_KEY_S);
    Input()->AssignButton(InputHandler::LEFT, InputHandler::KEYBOARD, GLFW_KEY_A);
    Input()->AssignButton(InputHandler::RIGHT, InputHandler::KEYBOARD, GLFW_KEY_D);

    // Create editor camera.
    cameraEntity = cameraWorld.CreateEntity("Editor Camera");
    cameraEntity->AddComponent<Component::Lens>();
    cameraEntity->position.z = 10.0f;

    // Create cursors.
    cursors[0] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
    cursors[1] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
    cursors[2] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
    cursors[3] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
    cursors[4] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
}

Editor::~Editor() {
    // Destroy cursors.
    for (int i=0; i < 5; ++i) {
        glfwDestroyCursor(cursors[i]);
    }
}

void Editor::Show(float deltaTime) {
    bool play = false;

    ImVec2 size(MainWindow::GetInstance()->GetSize().x, MainWindow::GetInstance()->GetSize().y);

    // Main menu bar.
    if (ImGui::BeginMainMenuBar()) {

        // File menu.
        if (ImGui::BeginMenu("File")) {
            if (ImGui::MenuItem("New Hymn", "CTRL+N"))
                NewHymn();

            if (ImGui::MenuItem("Open Hymn", "CTRL+O"))
                OpenHymn();

            ImGui::Separator();

            if (ImGui::MenuItem("Settings"))
                settingsWindow.SetVisible(true);

            ImGui::EndMenu();
        }

        // View menu.
        if (ImGui::BeginMenu("View")) {
            static bool soundSources = EditorSettings::GetInstance().GetBool("Sound Source Icons");
            ImGui::MenuItem("Sound Sources", "", &soundSources);
            EditorSettings::GetInstance().SetBool("Sound Source Icons", soundSources);

            static bool particleEmitters = EditorSettings::GetInstance().GetBool("Particle Emitter Icons");
            ImGui::MenuItem("Particle Emitters", "", &particleEmitters);
            EditorSettings::GetInstance().SetBool("Particle Emitter Icons", particleEmitters);

            static bool lightSources = EditorSettings::GetInstance().GetBool("Light Source Icons");
            ImGui::MenuItem("Light Sources", "", &lightSources);
            EditorSettings::GetInstance().SetBool("Light Source Icons", lightSources);

            static bool cameras = EditorSettings::GetInstance().GetBool("Camera Icons");
            ImGui::MenuItem("Cameras", "", &cameras);
            EditorSettings::GetInstance().SetBool("Camera Icons", cameras);

            ImGui::EndMenu();
        }

        // Play
        if (ImGui::BeginMenu("Play")) {
            if (ImGui::MenuItem("Play", "F5"))
                play = true;

            ImGui::EndMenu();
        }

        // Hymn
        if(Hymn().GetPath() != "") {
            if (ImGui::BeginMenu("Hymn")) {
                if (ImGui::MenuItem("Input"))
                    inputWindow.SetVisible(true);

                if (ImGui::MenuItem("Filters"))
                    filtersWindow.SetVisible(true);

                ImGui::EndMenu();
            }
        }

        ImGui::EndMainMenuBar();
    }

    // Show hymn selection window.
    if (selectHymnWindow.IsVisible()) {
        ImGui::SetNextWindowPosCenter();
        selectHymnWindow.Show();
    }

    if (inputWindow.IsVisible())
        inputWindow.Show();

    // Show filters window.
    if (filtersWindow.IsVisible())
        filtersWindow.Show();

    // Show resource list.
    if (resourceList.IsVisible())
        resourceList.Show();

    // Show settings window.
    if (settingsWindow.IsVisible()) {
        settingsWindow.Show();
    }

    // Control the editor camera.
    if (Input()->Pressed(InputHandler::CAMERA)) {
        if (Input()->Triggered(InputHandler::CAMERA)) {
            lastX = Input()->GetCursorX();
            lastY = Input()->GetCursorY();
        }

        float sensitivity = 0.3f;
        cameraEntity->rotation.x += sensitivity * (Input()->GetCursorX() - lastX);
        cameraEntity->rotation.y += sensitivity * (Input()->GetCursorY() - lastY);

        lastX = Input()->GetCursorX();
        lastY = Input()->GetCursorY();

        glm::mat4 orientation = cameraEntity->GetCameraOrientation();
        glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
        glm::vec3 right(orientation[0][0], orientation[1][0], orientation[2][0]);
        float speed = 3.0f * deltaTime;
        cameraEntity->position += speed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
        cameraEntity->position += speed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
    }

    if (Input()->Triggered(InputHandler::PLAYTEST))
        play = true;

    if (Input()->Triggered(InputHandler::NEW) && Input()->Pressed(InputHandler::CONTROL))
        NewHymn();

    if (Input()->Triggered(InputHandler::OPEN) && Input()->Pressed(InputHandler::CONTROL))
        OpenHymn();

    if (play)
        Play();

    // Set cursor.
    if (ImGui::GetMouseCursor() < 5) {
        glfwSetCursor(MainWindow::GetInstance()->GetGLFWWindow(), cursors[ImGui::GetMouseCursor()]);
    }
}

void Editor::Save() const {
    resourceList.SaveScene();
    Hymn().Save();
}

bool Editor::IsVisible() const {
    return visible;
}

void Editor::SetVisible(bool visible) {
    this->visible = visible;
}

Entity* Editor::GetCamera() const {
    return cameraEntity;
}

void Editor::Play() {
    Save();
    SetVisible(false);
    resourceList.HideEditors();
    resourceList.ResetScene();
    Managers().scriptManager->RegisterInput();
    Managers().scriptManager->BuildAllScripts();
}

void Editor::NewHymn() {
    selectHymnWindow.Scan();
    selectHymnWindow.SetClosedCallback(std::bind(&Editor::NewHymnClosed, this, std::placeholders::_1));
    selectHymnWindow.SetTitle("New Hymn");
    selectHymnWindow.SetOpenButtonName("Create");
    selectHymnWindow.SetVisible(true);
}

void Editor::NewHymnClosed(const std::string& hymn) {
    // Create new hymn
    if (!hymn.empty()) {
        resourceList.ResetScene();
        Hymn().Clear();
        Hymn().world.CreateRoot();
        Hymn().SetPath(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER +  hymn);
        resourceList.SetVisible(true);

        // Default scene.
        Hymn().scenes.push_back("Scene #0");

        Entity* player = Hymn().world.GetRoot()->AddChild("Player");
        player->position.z = 10.f;
        player->AddComponent<Component::Lens>();
        player->AddComponent<Component::Listener>();

        Entity* sun = Hymn().world.GetRoot()->AddChild("Sun");
        sun->AddComponent<Component::DirectionalLight>();
    }

    selectHymnWindow.SetVisible(false);
}

void Editor::OpenHymn() {
    selectHymnWindow.Scan();
    selectHymnWindow.SetClosedCallback(std::bind(&Editor::OpenHymnClosed, this, std::placeholders::_1));
    selectHymnWindow.SetTitle("Open Hymn");
    selectHymnWindow.SetOpenButtonName("Open");
    selectHymnWindow.SetVisible(true);
}

void Editor::OpenHymnClosed(const std::string& hymn) {
    // Open hymn.
    if (!hymn.empty()) {
        resourceList.ResetScene();
        Hymn().Load(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER +  hymn);
        resourceList.SetVisible(true);
    }

    selectHymnWindow.SetVisible(false);
}
<commit_msg>Don't show Play when no hymn loaded<commit_after>#include "Editor.hpp"

#include "Util/EditorSettings.hpp"
#undef CreateDirectory

#include <Engine/Util/Input.hpp>
#include <Engine/Hymn.hpp>
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/ScriptManager.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Engine/MainWindow.hpp>
#include <Engine/Component/DirectionalLight.hpp>
#include <Engine/Component/Lens.hpp>
#include <Engine/Component/Listener.hpp>
#include "ImGui/Theme.hpp"

#include <imgui.h>
#include <GLFW/glfw3.h>

Editor::Editor() {
    // Create Hymns directory.
    FileSystem::CreateDirectory((FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns").c_str());

    // Load theme.
    std::string theme = EditorSettings::GetInstance().GetString("Theme");
    if (FileSystem::FileExists((FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Themes" + FileSystem::DELIMITER + theme + ".json").c_str())) {
        ImGui::LoadTheme(theme.c_str());
    } else {
        ImGui::LoadDefaultTheme();
    }

    // Assign controls.
    Input()->AssignButton(InputHandler::PROFILE, InputHandler::KEYBOARD, GLFW_KEY_F2);
    Input()->AssignButton(InputHandler::PLAYTEST, InputHandler::KEYBOARD, GLFW_KEY_F5);
    Input()->AssignButton(InputHandler::CONTROL, InputHandler::KEYBOARD, GLFW_KEY_LEFT_CONTROL);
    Input()->AssignButton(InputHandler::NEW, InputHandler::KEYBOARD, GLFW_KEY_N);
    Input()->AssignButton(InputHandler::OPEN, InputHandler::KEYBOARD, GLFW_KEY_O);
    Input()->AssignButton(InputHandler::CAMERA, InputHandler::MOUSE, GLFW_MOUSE_BUTTON_MIDDLE);
    Input()->AssignButton(InputHandler::FORWARD, InputHandler::KEYBOARD, GLFW_KEY_W);
    Input()->AssignButton(InputHandler::BACKWARD, InputHandler::KEYBOARD, GLFW_KEY_S);
    Input()->AssignButton(InputHandler::LEFT, InputHandler::KEYBOARD, GLFW_KEY_A);
    Input()->AssignButton(InputHandler::RIGHT, InputHandler::KEYBOARD, GLFW_KEY_D);

    // Create editor camera.
    cameraEntity = cameraWorld.CreateEntity("Editor Camera");
    cameraEntity->AddComponent<Component::Lens>();
    cameraEntity->position.z = 10.0f;

    // Create cursors.
    cursors[0] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
    cursors[1] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
    cursors[2] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
    cursors[3] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
    cursors[4] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
}

Editor::~Editor() {
    // Destroy cursors.
    for (int i=0; i < 5; ++i) {
        glfwDestroyCursor(cursors[i]);
    }
}

void Editor::Show(float deltaTime) {
    bool play = false;

    ImVec2 size(MainWindow::GetInstance()->GetSize().x, MainWindow::GetInstance()->GetSize().y);

    // Main menu bar.
    if (ImGui::BeginMainMenuBar()) {

        // File menu.
        if (ImGui::BeginMenu("File")) {
            if (ImGui::MenuItem("New Hymn", "CTRL+N"))
                NewHymn();

            if (ImGui::MenuItem("Open Hymn", "CTRL+O"))
                OpenHymn();

            ImGui::Separator();

            if (ImGui::MenuItem("Settings"))
                settingsWindow.SetVisible(true);

            ImGui::EndMenu();
        }

        // View menu.
        if (ImGui::BeginMenu("View")) {
            static bool soundSources = EditorSettings::GetInstance().GetBool("Sound Source Icons");
            ImGui::MenuItem("Sound Sources", "", &soundSources);
            EditorSettings::GetInstance().SetBool("Sound Source Icons", soundSources);

            static bool particleEmitters = EditorSettings::GetInstance().GetBool("Particle Emitter Icons");
            ImGui::MenuItem("Particle Emitters", "", &particleEmitters);
            EditorSettings::GetInstance().SetBool("Particle Emitter Icons", particleEmitters);

            static bool lightSources = EditorSettings::GetInstance().GetBool("Light Source Icons");
            ImGui::MenuItem("Light Sources", "", &lightSources);
            EditorSettings::GetInstance().SetBool("Light Source Icons", lightSources);

            static bool cameras = EditorSettings::GetInstance().GetBool("Camera Icons");
            ImGui::MenuItem("Cameras", "", &cameras);
            EditorSettings::GetInstance().SetBool("Camera Icons", cameras);

            ImGui::EndMenu();
        }

        if(Hymn().GetPath() != "") {
            // Play
            if (ImGui::BeginMenu("Play")) {
                if (ImGui::MenuItem("Play", "F5"))
                    play = true;

                ImGui::EndMenu();
            }

            // Hymn
            if (ImGui::BeginMenu("Hymn")) {
                if (ImGui::MenuItem("Input"))
                    inputWindow.SetVisible(true);

                if (ImGui::MenuItem("Filters"))
                    filtersWindow.SetVisible(true);

                ImGui::EndMenu();
            }
        }

        ImGui::EndMainMenuBar();
    }

    // Show hymn selection window.
    if (selectHymnWindow.IsVisible()) {
        ImGui::SetNextWindowPosCenter();
        selectHymnWindow.Show();
    }

    if (inputWindow.IsVisible())
        inputWindow.Show();

    // Show filters window.
    if (filtersWindow.IsVisible())
        filtersWindow.Show();

    // Show resource list.
    if (resourceList.IsVisible())
        resourceList.Show();

    // Show settings window.
    if (settingsWindow.IsVisible()) {
        settingsWindow.Show();
    }

    // Control the editor camera.
    if (Input()->Pressed(InputHandler::CAMERA)) {
        if (Input()->Triggered(InputHandler::CAMERA)) {
            lastX = Input()->GetCursorX();
            lastY = Input()->GetCursorY();
        }

        float sensitivity = 0.3f;
        cameraEntity->rotation.x += sensitivity * (Input()->GetCursorX() - lastX);
        cameraEntity->rotation.y += sensitivity * (Input()->GetCursorY() - lastY);

        lastX = Input()->GetCursorX();
        lastY = Input()->GetCursorY();

        glm::mat4 orientation = cameraEntity->GetCameraOrientation();
        glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
        glm::vec3 right(orientation[0][0], orientation[1][0], orientation[2][0]);
        float speed = 3.0f * deltaTime;
        cameraEntity->position += speed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
        cameraEntity->position += speed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
    }

    if (Input()->Triggered(InputHandler::PLAYTEST))
        play = true;

    if (Input()->Triggered(InputHandler::NEW) && Input()->Pressed(InputHandler::CONTROL))
        NewHymn();

    if (Input()->Triggered(InputHandler::OPEN) && Input()->Pressed(InputHandler::CONTROL))
        OpenHymn();

    if (play)
        Play();

    // Set cursor.
    if (ImGui::GetMouseCursor() < 5) {
        glfwSetCursor(MainWindow::GetInstance()->GetGLFWWindow(), cursors[ImGui::GetMouseCursor()]);
    }
}

void Editor::Save() const {
    resourceList.SaveScene();
    Hymn().Save();
}

bool Editor::IsVisible() const {
    return visible;
}

void Editor::SetVisible(bool visible) {
    this->visible = visible;
}

Entity* Editor::GetCamera() const {
    return cameraEntity;
}

void Editor::Play() {
    Save();
    SetVisible(false);
    resourceList.HideEditors();
    resourceList.ResetScene();
    Managers().scriptManager->RegisterInput();
    Managers().scriptManager->BuildAllScripts();
}

void Editor::NewHymn() {
    selectHymnWindow.Scan();
    selectHymnWindow.SetClosedCallback(std::bind(&Editor::NewHymnClosed, this, std::placeholders::_1));
    selectHymnWindow.SetTitle("New Hymn");
    selectHymnWindow.SetOpenButtonName("Create");
    selectHymnWindow.SetVisible(true);
}

void Editor::NewHymnClosed(const std::string& hymn) {
    // Create new hymn
    if (!hymn.empty()) {
        resourceList.ResetScene();
        Hymn().Clear();
        Hymn().world.CreateRoot();
        Hymn().SetPath(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER +  hymn);
        resourceList.SetVisible(true);

        // Default scene.
        Hymn().scenes.push_back("Scene #0");

        Entity* player = Hymn().world.GetRoot()->AddChild("Player");
        player->position.z = 10.f;
        player->AddComponent<Component::Lens>();
        player->AddComponent<Component::Listener>();

        Entity* sun = Hymn().world.GetRoot()->AddChild("Sun");
        sun->AddComponent<Component::DirectionalLight>();
    }

    selectHymnWindow.SetVisible(false);
}

void Editor::OpenHymn() {
    selectHymnWindow.Scan();
    selectHymnWindow.SetClosedCallback(std::bind(&Editor::OpenHymnClosed, this, std::placeholders::_1));
    selectHymnWindow.SetTitle("Open Hymn");
    selectHymnWindow.SetOpenButtonName("Open");
    selectHymnWindow.SetVisible(true);
}

void Editor::OpenHymnClosed(const std::string& hymn) {
    // Open hymn.
    if (!hymn.empty()) {
        resourceList.ResetScene();
        Hymn().Load(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER +  hymn);
        resourceList.SetVisible(true);
    }

    selectHymnWindow.SetVisible(false);
}
<|endoftext|>


<commit_before>/************************************************************************
*
* Flood Project  (2008-201x)
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/

#include "Engine/API.h"
#include "Engine/Engine.h"

#include "Core/Memory.h"
#include "Core/Network/Network.h"
#include "Resources/ResourceManager.h"
#include "Resources/ResourceLoader.h"
#include "Graphics/Texture.h"
#include "Graphics/RenderDevice.h"
#include "Engine/Input/InputManager.h"
#include "Engine/Audio/Device.h"
#include "Engine/Paging/PageManager.h"
#include "Engine/Physics/Physics.h"
#include "Engine/Window/WindowManager.h"
#include "Script/ScriptManager.h"

#ifdef API_ENGINE_DLL_EXPORT
FL_INSTANTIATE_TEMPLATES()
#endif

NAMESPACE_ENGINE_BEGIN

//-----------------------------------//

static Engine* gs_engineInstance;
Engine* GetEngine() { return gs_engineInstance; }

Engine::Engine()
	: log(nullptr)
	, stream(nullptr)
	, taskPool(nullptr)
	, resourceManager(nullptr)
	, renderDevice(nullptr)
	, inputManager(nullptr)
	, audioDevice(nullptr)
	, physicsManager(nullptr)
	, scriptManager(nullptr)
	, windowManager(nullptr)
{
	assert(gs_engineInstance == nullptr);
	gs_engineInstance = this;
}

//-----------------------------------//

Engine::~Engine()
{
	for( size_t i = 0; i < subsystems.size(); i++ )
	{
		Subsystem* system = subsystems[i];
		Deallocate(system);
	}

	Deallocate(physicsManager);
	Deallocate(scriptManager);
	Deallocate(renderDevice);
	Deallocate(windowManager);

#ifdef ENABLE_AUDIO_OPENAL
	Deallocate(audioDevice);
#endif

	Deallocate(resourceManager);

	InputDeinitialize();
	GraphicsDeinitialize();
	ResourcesDeinitialize();

#ifdef ENABLE_NETWORK_ENET
	NetworkDeinitialize();
#endif

	TaskPoolDestroy(taskPool);
	Deallocate(stream);
	LogDestroy(log);
}

//-----------------------------------//

void Engine::addSubsystem( Subsystem* const subsystem )
{
	LogInfo( "Registering new engine subsystem" );

	subsystems.push_back( subsystem );
}

//-----------------------------------//

void Engine::init()
{
	// Sets up the main logger.
	setupLogger();

	// Creates the task system.
	taskPool = TaskPoolCreate( AllocatorGetThis(), 2 );

#ifdef ENABLE_NETWORK_ENET
	NetworkInitialize();
#endif

	ResourcesInitialize();
	InputInitialize();
	GraphicsInitialize();

	// Creates the resource manager.
	resourceManager = AllocateThis(ResourceManager);
	resourceManager->setTaskPool( taskPool );

	// Registers default resource loaders.
	resourceManager->setupResourceLoaders( ResourceLoaderGetType() );

	// Creates the rendering device.
	renderDevice = AllocateThis(RenderDevice);

#ifdef ENABLE_AUDIO_OPENAL
	// Creates the audio device.
	audioDevice = AudioCreateDevice("");

	if( audioDevice )
		audioDevice->createMainContext();
#endif

#ifdef ENABLE_SCRIPTING_LUA
	// Creates the scripting manager.
	scriptManager = AllocateThis(ScriptManager);
#endif
}

//-----------------------------------//

void Engine::setupLogger()
{
	stream = AllocateHeap(FileStream, "Log.html", StreamOpenMode::Write);
	log = LogCreate( AllocatorGetHeap() );
}

//-----------------------------------//

void Engine::update()
{
	for( size_t i = 0; i < subsystems.size(); i++ )
	{
		Subsystem* system = subsystems[i];
		system->update();
	}

	resourceManager->update();

#ifdef ENABLE_SCRIPTING_LUA
	scriptManager->update();
#endif
}

//-----------------------------------//

void Engine::stepFrame()
{
	AllocatorReset( GetFrameAllocator() );
}

//-----------------------------------//

NAMESPACE_ENGINE_END<commit_msg>Update loops to C++11 for ranges.<commit_after>/************************************************************************
*
* Flood Project  (2008-201x)
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/

#include "Engine/API.h"
#include "Engine/Engine.h"

#include "Core/Memory.h"
#include "Core/Network/Network.h"
#include "Resources/ResourceManager.h"
#include "Resources/ResourceLoader.h"
#include "Graphics/Texture.h"
#include "Graphics/RenderDevice.h"
#include "Engine/Input/InputManager.h"
#include "Engine/Audio/Device.h"
#include "Engine/Paging/PageManager.h"
#include "Engine/Physics/Physics.h"
#include "Engine/Window/WindowManager.h"
#include "Script/ScriptManager.h"

#ifdef API_ENGINE_DLL_EXPORT
FL_INSTANTIATE_TEMPLATES()
#endif

NAMESPACE_ENGINE_BEGIN

//-----------------------------------//

static Engine* gs_engineInstance;
Engine* GetEngine() { return gs_engineInstance; }

Engine::Engine()
	: log(nullptr)
	, stream(nullptr)
	, taskPool(nullptr)
	, resourceManager(nullptr)
	, renderDevice(nullptr)
	, inputManager(nullptr)
	, audioDevice(nullptr)
	, physicsManager(nullptr)
	, scriptManager(nullptr)
	, windowManager(nullptr)
{
	assert(gs_engineInstance == nullptr);
	gs_engineInstance = this;
}

//-----------------------------------//

Engine::~Engine()
{
	for(auto& subsystem : subsystems)
    {
		Deallocate(subsystem);
    }

	Deallocate(physicsManager);
	Deallocate(scriptManager);
	Deallocate(renderDevice);
	Deallocate(windowManager);

#ifdef ENABLE_AUDIO_OPENAL
	Deallocate(audioDevice);
#endif

	Deallocate(resourceManager);

	InputDeinitialize();
	GraphicsDeinitialize();
	ResourcesDeinitialize();

#ifdef ENABLE_NETWORK_ENET
	NetworkDeinitialize();
#endif

	TaskPoolDestroy(taskPool);
	Deallocate(stream);
	LogDestroy(log);
}

//-----------------------------------//

void Engine::addSubsystem( Subsystem* const subsystem )
{
	LogInfo( "Registering new engine subsystem" );

	subsystems.push_back( subsystem );
}

//-----------------------------------//

void Engine::init()
{
	// Sets up the main logger.
	setupLogger();

	// Creates the task system.
	taskPool = TaskPoolCreate( AllocatorGetThis(), 2 );

#ifdef ENABLE_NETWORK_ENET
	NetworkInitialize();
#endif

	ResourcesInitialize();
	InputInitialize();
	GraphicsInitialize();

	// Creates the resource manager.
	resourceManager = AllocateThis(ResourceManager);
	resourceManager->setTaskPool( taskPool );

	// Registers default resource loaders.
	resourceManager->setupResourceLoaders( ResourceLoaderGetType() );

	// Creates the rendering device.
	renderDevice = AllocateThis(RenderDevice);

#ifdef ENABLE_AUDIO_OPENAL
	// Creates the audio device.
	audioDevice = AudioCreateDevice("");

	if( audioDevice )
		audioDevice->createMainContext();
#endif

#ifdef ENABLE_SCRIPTING_LUA
	// Creates the scripting manager.
	scriptManager = AllocateThis(ScriptManager);
#endif
}

//-----------------------------------//

void Engine::setupLogger()
{
	stream = AllocateHeap(FileStream, "Log.html", StreamOpenMode::Write);
	log = LogCreate( AllocatorGetHeap() );
}

//-----------------------------------//

void Engine::update()
{
	for(auto& subsystem : subsystems)
		subsystem->update();

	resourceManager->update();

#ifdef ENABLE_SCRIPTING_LUA
	scriptManager->update();
#endif
}

//-----------------------------------//

void Engine::stepFrame()
{
	AllocatorReset( GetFrameAllocator() );
}

//-----------------------------------//

NAMESPACE_ENGINE_END<|endoftext|>


<commit_before>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

#include "GPSManager.h"
#include <QDebug>
#include <cinttypes>

GPSManager::GPSManager(QGCApplication* app)
    : QGCTool(app)
{
    qRegisterMetaType<GPSPositionMessage>();
    qRegisterMetaType<GPSSatelliteMessage>();
}

GPSManager::~GPSManager()
{
    cleanup();
}

void GPSManager::setupGPS(const QString& device)
{
    Q_ASSERT(_toolbox);

    cleanup();
    _requestGpsStop = false;
    _gpsProvider = new GPSProvider(device, true, _requestGpsStop);
    _gpsProvider->start();

    //create RTCM device
    _rtcmMavlink = new RTCMMavlink(*_toolbox);

    connect(_gpsProvider, SIGNAL(RTCMDataUpdate(QByteArray)), _rtcmMavlink,
            SLOT(RTCMDataUpdate(QByteArray)));

    //test: connect to position update
    connect(_gpsProvider, SIGNAL(positionUpdate(GPSPositionMessage)), this,
            SLOT(GPSPositionUpdate(GPSPositionMessage)));
    connect(_gpsProvider, SIGNAL(satelliteInfoUpdate(GPSSatelliteMessage)), this,
            SLOT(GPSSatelliteUpdate(GPSSatelliteMessage)));

}

void GPSManager::GPSPositionUpdate(GPSPositionMessage msg)
{
    qDebug("GPS: got position update: alt=%i, long=%i, lat=%i, time=%" PRIu64,
            msg.position_data.alt, msg.position_data.lon,
            msg.position_data.lat, msg.position_data.time_utc_usec);
}
void GPSManager::GPSSatelliteUpdate(GPSSatelliteMessage msg)
{
    qDebug("GPS: got satellite info update, %i satellites", (int)msg.satellite_data.count);
}

void GPSManager::cleanup()
{
    if (_gpsProvider) {
        _requestGpsStop = true;
        //Note that we need a relatively high timeout to be sure the GPS thread finished.
        if (!_gpsProvider->wait(2000)) {
            qWarning() << "Failed to wait for GPS thread exit. Consider increasing the timeout";
        }
        delete(_gpsProvider);
    }
    if (_rtcmMavlink) {
        delete(_rtcmMavlink);
    }
}
<commit_msg>GPSManager: remove the usage of PRIu64, because of problems under windows<commit_after>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

#include "GPSManager.h"
#include <QDebug>

GPSManager::GPSManager(QGCApplication* app)
    : QGCTool(app)
{
    qRegisterMetaType<GPSPositionMessage>();
    qRegisterMetaType<GPSSatelliteMessage>();
}

GPSManager::~GPSManager()
{
    cleanup();
}

void GPSManager::setupGPS(const QString& device)
{
    Q_ASSERT(_toolbox);

    cleanup();
    _requestGpsStop = false;
    _gpsProvider = new GPSProvider(device, true, _requestGpsStop);
    _gpsProvider->start();

    //create RTCM device
    _rtcmMavlink = new RTCMMavlink(*_toolbox);

    connect(_gpsProvider, SIGNAL(RTCMDataUpdate(QByteArray)), _rtcmMavlink,
            SLOT(RTCMDataUpdate(QByteArray)));

    //test: connect to position update
    connect(_gpsProvider, SIGNAL(positionUpdate(GPSPositionMessage)), this,
            SLOT(GPSPositionUpdate(GPSPositionMessage)));
    connect(_gpsProvider, SIGNAL(satelliteInfoUpdate(GPSSatelliteMessage)), this,
            SLOT(GPSSatelliteUpdate(GPSSatelliteMessage)));

}

void GPSManager::GPSPositionUpdate(GPSPositionMessage msg)
{
    qDebug("GPS: got position update: alt=%i, long=%i, lat=%i",
            msg.position_data.alt, msg.position_data.lon,
            msg.position_data.lat);
}
void GPSManager::GPSSatelliteUpdate(GPSSatelliteMessage msg)
{
    qDebug("GPS: got satellite info update, %i satellites", (int)msg.satellite_data.count);
}

void GPSManager::cleanup()
{
    if (_gpsProvider) {
        _requestGpsStop = true;
        //Note that we need a relatively high timeout to be sure the GPS thread finished.
        if (!_gpsProvider->wait(2000)) {
            qWarning() << "Failed to wait for GPS thread exit. Consider increasing the timeout";
        }
        delete(_gpsProvider);
    }
    if (_rtcmMavlink) {
        delete(_rtcmMavlink);
    }
}
<|endoftext|>


<commit_before>#ifndef AX_INVERSE_MATRIX_H
#define AX_INVERSE_MATRIX_H
#include "Matrix.hpp"

namespace ax
{

// for 2x2 dimentional
template<class L, typename std::enable_if<
             is_MatrixExpression<typename L::value_trait>::value&&
             is_SameSize<L::col, L::row>::value&&
             is_SameSize<L::col, 2>::value
             >::type*& = enabler>
const double determinant(const L& lhs)
{
    return lhs(0,0) * lhs(1,1) - lhs(1,0) * lhs(0,1);
}

// for 3x3 dimentional
template<class L, typename std::enable_if<
             is_MatrixExpression<typename L::value_trait>::value&&
             is_SameSize<L::col, L::row>::value&&
             is_SameSize<L::col, 3>::value
             >::type*& = enabler>
const double determinant(const L& lhs)
{
    return lhs(0,0) * lhs(1,1) * lhs(2,2) +
           lhs(1,0) * lhs(2,1) * lhs(0,2) +
           lhs(2,0) * lhs(0,1) * lhs(1,2) -
           lhs(0,0) * lhs(2,1) * lhs(1,2) -
           lhs(2,0) * lhs(1,1) * lhs(0,2) -
           lhs(1,0) * lhs(0,1) * lhs(2,2);
}

template<class L, typename std::enable_if<
             is_MatrixExpression<typename L::value_trait>::value&&
             is_SameSize<L::col, L::row>::value&&
             is_SameSize<L::col, 2>::value
             >::type*& = enabler>
RealMatrix<L::row, L::col> inverse(const L& lhs)
{
    const double det_inv = 1e0 / determinant(lhs);
    RealMatrix<L::row, L::col> inv;
    inv(0,0) =  det_inv * lhs(1,1);
    inv(1,1) =  det_inv * lhs(0,0);
    inv(0,1) = -det_inv * lhs(0,1);
    inv(1,0) = -det_inv * lhs(1,0);
    return inv;
}

template<class L, typename std::enable_if<
             is_MatrixExpression<typename L::value_trait>::value&&
             is_SameSize<L::col, L::row>::value&&
             is_SameSize<L::col, 3>::value
             >::type*& = enabler>
RealMatrix<L::row, L::col> inverse(const L& lhs_)
{
    const L lhs = lhs_;
    const double det_inv = 1e0 / determinant(lhs);

    RealMatrix<L::row, L::col> inv;
    inv(0,0) = det_inv * (lhs(1,1) * lhs(2,2) - lhs(1,2) * lhs(2,1));
    inv(1,1) = det_inv * (lhs(0,0) * lhs(2,2) - lhs(0,2) * lhs(2,0));
    inv(2,2) = det_inv * (lhs(0,0) * lhs(1,1) - lhs(0,1) * lhs(1,0));

    inv(0,1) = det_inv * (lhs(0,2) * lhs(2,1) - lhs(0,1) * lhs(2,2));
    inv(0,2) = det_inv * (lhs(0,1) * lhs(1,2) - lhs(0,2) * lhs(1,1));
    inv(1,2) = det_inv * (lhs(0,2) * lhs(1,0) - lhs(0,0) * lhs(1,2));

    inv(1,0) = det_inv * (lhs(1,2) * lhs(2,0) - lhs(1,0) * lhs(2,2));
    inv(2,0) = det_inv * (lhs(1,0) * lhs(2,1) - lhs(2,0) * lhs(1,1));
    inv(2,1) = det_inv * (lhs(2,0) * lhs(0,1) - lhs(0,0) * lhs(2,1));
    return inv;
}

}
#endif /* AX_INVERSE_MATRIX_H */
<commit_msg>add InverseMatrix<commit_after>#ifndef AX_INVERSE_MATRIX_H
#define AX_INVERSE_MATRIX_H
#include "Matrix.hpp"

namespace ax
{

// for 2x2 dimentional
template<class T_mat, typename std::enable_if<
    is_matrix_expression<typename T_mat::tag>::value&&
    is_same_dimension<T_mat::dim_col, T_mat::dim_row>::value&&
    is_same_dimension<T_mat::dim_col, 2>::value>::type*& = enabler>
inline typename T_mat::elem_t
determinant(const T_mat& mat)
{
    return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
}

// for 3x3 dimentional
template<class T_mat, typename std::enable_if<
    is_matrix_expression<typename T_mat::tag>::value&&
    is_same_dimension<T_mat::dim_col, T_mat::dim_row>::value&&
    is_same_dimension<T_mat::dim_col, 3>::value>::type*& = enabler>
inline typename T_mat::elem_t
determinant(const T_mat& mat)
{
    return mat(0,0) * mat(1,1) * mat(2,2) +
           mat(1,0) * mat(2,1) * mat(0,2) +
           mat(2,0) * mat(0,1) * mat(1,2) -
           mat(0,0) * mat(2,1) * mat(1,2) -
           mat(2,0) * mat(1,1) * mat(0,2) -
           mat(1,0) * mat(0,1) * mat(2,2);
}

template<class T_mat, typename std::enable_if<
    is_matrix_expression<typename T_mat::tag>::value&&
    is_same_dimension<T_mat::dim_col, T_mat::dim_row>::value&&
    is_same_dimension<T_mat::dim_col, 2>::value>::type*& = enabler>
Matrix<typename T_mat::elem_t, T_mat::dim_row, T_mat::dim_col>
inverse(const T_mat& mat)
{
    const auto det_inv = 1e0 / determinant(mat);
    Matrix<typename T_mat::elem_t, T_mat::dim_row, T_mat::dim_col> inv;
    inv(0,0) =  det_inv * mat(1,1);
    inv(1,1) =  det_inv * mat(0,0);
    inv(0,1) = -det_inv * mat(0,1);
    inv(1,0) = -det_inv * mat(1,0);
    return inv;
}

template<class T_mat, typename std::enable_if<
    is_matrix_expression<typename T_mat::tag>::value&&
    is_same_dimension<T_mat::dim_col, T_mat::dim_row>::value&&
    is_same_dimension<T_mat::dim_col, 3>::value>::type*& = enabler>
Matrix<typename T_mat::elem_t, T_mat::dim_row, T_mat::dim_col>
inverse(const T_mat& mat)
{
    const auto det_inv = 1e0 / determinant(mat);

    Matrix<typename T_mat::elem_t, T_mat::dim_row, T_mat::dim_col> inv;
    inv(0,0) = det_inv * (mat(1,1) * mat(2,2) - mat(1,2) * mat(2,1));
    inv(1,1) = det_inv * (mat(0,0) * mat(2,2) - mat(0,2) * mat(2,0));
    inv(2,2) = det_inv * (mat(0,0) * mat(1,1) - mat(0,1) * mat(1,0));

    inv(0,1) = det_inv * (mat(0,2) * mat(2,1) - mat(0,1) * mat(2,2));
    inv(0,2) = det_inv * (mat(0,1) * mat(1,2) - mat(0,2) * mat(1,1));
    inv(1,2) = det_inv * (mat(0,2) * mat(1,0) - mat(0,0) * mat(1,2));

    inv(1,0) = det_inv * (mat(1,2) * mat(2,0) - mat(1,0) * mat(2,2));
    inv(2,0) = det_inv * (mat(1,0) * mat(2,1) - mat(2,0) * mat(1,1));
    inv(2,1) = det_inv * (mat(2,0) * mat(0,1) - mat(0,0) * mat(2,1));
    return inv;
}

}
#endif /* AX_INVERSE_MATRIX_H */
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/util/util.hpp>

#include <nix/hdf5/DataArrayHDF5.hpp>
#include <nix/hdf5/DataSetHDF5.hpp>
#include <nix/hdf5/DimensionHDF5.hpp>

using namespace std;
using namespace nix::base;

namespace nix {
namespace hdf5 {

DataArrayHDF5::DataArrayHDF5(const std::shared_ptr<base::IFile> &file, const std::shared_ptr<base::IBlock> &block, const Group &group)
        : EntityWithSourcesHDF5(file, block, group) {
    dimension_group = this->group().openOptGroup("dimensions");
}

DataArrayHDF5::DataArrayHDF5(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const Group &group,
                             const string &id, const string &type, const string &name)
        : DataArrayHDF5(file, block, group, id, type, name, util::getTime()) {
}

DataArrayHDF5::DataArrayHDF5(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const Group &group,
                             const string &id, const string &type, const string &name, time_t time)
        : EntityWithSourcesHDF5(file, block, group, id, type, name, time) {
    dimension_group = this->group().openOptGroup("dimensions");
}

//--------------------------------------------------
// Element getters and setters
//--------------------------------------------------

boost::optional<std::string> DataArrayHDF5::label() const {
    boost::optional<std::string> ret;
    string value;
    bool have_attr = group().getAttr("label", value);

    if (have_attr) {
        ret = value;
    }

    return ret;
}

void DataArrayHDF5::label(const string &label) {
    if (label.empty()) {
        throw EmptyString("label");
    }
    else {
        group().setAttr("label", label);
        forceUpdatedAt();
    }
}

void DataArrayHDF5::label(const none_t t) {
    if (group().hasAttr("label")) {
        group().removeAttr("label");
    }
    forceUpdatedAt();
}

boost::optional<std::string> DataArrayHDF5::unit() const {
    boost::optional<std::string> ret;
    string value;
    bool have_attr = group().getAttr("unit", value);
    if (have_attr) {
        ret = value;
    }
    return ret;
}

void DataArrayHDF5::unit(const string &unit) {
    if (unit.empty()) {
        throw EmptyString("unit");
    }
    else {
        group().setAttr("unit", unit);
        forceUpdatedAt();
    }
}

void DataArrayHDF5::unit(const none_t t) {
    if (group().hasAttr("unit")) {
        group().removeAttr("unit");
    }
    forceUpdatedAt();
}

// TODO use defaults
boost::optional<double> DataArrayHDF5::expansionOrigin() const {
    boost::optional<double> ret;
    double expansion_origin;
    bool have_attr = group().getAttr("expansion_origin", expansion_origin);
    if (have_attr) {
        ret = expansion_origin;
    }
    return ret;
}

void DataArrayHDF5::expansionOrigin(double expansion_origin) {
    group().setAttr("expansion_origin", expansion_origin);
    forceUpdatedAt();
}

void DataArrayHDF5::expansionOrigin(const none_t t) {
    if (group().hasAttr("expansion_origin")) {
        group().removeAttr("expansion_origin");
    }
    forceUpdatedAt();
}

// TODO use defaults
vector<double> DataArrayHDF5::polynomCoefficients() const {
    vector<double> polynom_coefficients;

    if (group().hasData("polynom_coefficients")) {
        DataSet ds = group().openData("polynom_coefficients");
        ds.read(polynom_coefficients, true);
    }

    return polynom_coefficients;
}

void DataArrayHDF5::polynomCoefficients(const vector<double> &coefficients) {
    DataSet ds;
    if (group().hasData("polynom_coefficients")) {
        ds = group().openData("polynom_coefficients");
        ds.setExtent({coefficients.size()});
    } else {
        ds = group().createData("polynom_coefficients", DataType::Double, {coefficients.size()});
    }
    ds.write(coefficients);
    forceUpdatedAt();
}

void DataArrayHDF5::polynomCoefficients(const none_t t) {
    if (group().hasData("polynom_coefficients")) {
        group().removeData("polynom_coefficients");
    }
    forceUpdatedAt();
}

//--------------------------------------------------
// Methods concerning dimensions
//--------------------------------------------------

size_t DataArrayHDF5::dimensionCount() const {
    boost::optional<Group> g = dimension_group();
    return g ? g->objectCount() : size_t(0);
}

shared_ptr<IDimension> DataArrayHDF5::getDimension(size_t index) const {
    shared_ptr<IDimension> dim;
    boost::optional<Group> g = dimension_group();

    if (g) {
        string str_id = util::numToStr(index);
        if (g->hasGroup(str_id)) {
            Group group = g->openGroup(str_id, false);
            dim = openDimensionHDF5(group, index);
        }
    }

    return dim;
}

std::shared_ptr<base::ISetDimension> DataArrayHDF5::createSetDimension(size_t index) {
    Group g = createDimensionGroup(index);
    return make_shared<SetDimensionHDF5>(g, index);
}

std::shared_ptr<base::IRangeDimension> DataArrayHDF5::createRangeDimension(size_t index, const std::vector<double> &ticks) {
    Group g = createDimensionGroup(index);
    return make_shared<RangeDimensionHDF5>(g, index, ticks);
}

std::shared_ptr<base::ISampledDimension> DataArrayHDF5::createSampledDimension(size_t index, double sampling_interval) {
    Group g = createDimensionGroup(index);
    return make_shared<SampledDimensionHDF5>(g, index, sampling_interval);
}

Group DataArrayHDF5::createDimensionGroup(size_t index) {
    boost::optional<Group> g = dimension_group(true);

    size_t dim_max = dimensionCount() + 1;
    if (index > dim_max || index <= 0)
        throw new runtime_error("Invalid dimension index: has to be 0 < index <= " + util::numToStr(dim_max));

    string str_id = util::numToStr(index);
    if (g->hasGroup(str_id)) {
        g->removeGroup(str_id);
    }

    return g->openGroup(str_id, true);
}

bool DataArrayHDF5::deleteDimension(size_t index) {
    bool deleted = false;
    size_t dim_count = dimensionCount();
    string str_id = util::numToStr(index);
    boost::optional<Group> g = dimension_group();

    if (g) {
        if (g->hasGroup(str_id)) {
            g->removeGroup(str_id);
            deleted = true;
        }

        if (deleted && index < dim_count) {
            for (size_t old_id = index + 1; old_id <= dim_count; old_id++) {
                string str_old_id = util::numToStr(old_id);
                string str_new_id = util::numToStr(old_id - 1);
                g->renameGroup(str_old_id, str_new_id);
            }
        }
    }

    return deleted;
}

//--------------------------------------------------
// Other methods and functions
//--------------------------------------------------

DataArrayHDF5::~DataArrayHDF5() {
}

void DataArrayHDF5::createData(DataType dtype, const NDSize &size) {
    if (group().hasData("data")) {
        throw new std::runtime_error("DataArray alread exists"); //TODO: FIXME, better exception
    }

    group().createData("data", dtype, size); //FIXME: check if this 2-step creation is needed
    DataSet ds = group().openData("data");
}

bool DataArrayHDF5::hasData() const {
    return group().hasData("data");
}

void DataArrayHDF5::write(DataType dtype, const void *data, const NDSize &count, const NDSize &offset) {
    DataSet ds;

    if (!group().hasData("data")) {
        //FIXME: this case should actually never be possible, replace with exception?
        ds = group().createData("data", dtype, count);
    } else {
        ds = group().openData("data");
    }

    if (offset.size()) {
        Selection fileSel = ds.createSelection();
        fileSel.select(count, offset);
        Selection memSel(DataSpace::create(count, false));

        ds.write(dtype, data, fileSel, memSel);
    } else {
        ds.write(dtype, count, data);
    }
}

void DataArrayHDF5::read(DataType dtype, void *data, const NDSize &count, const NDSize &offset) const {
    if (!group().hasData("data")) {
        return;
    }

    DataSet ds = group().openData("data");

    if (offset.size()) {
        Selection fileSel = ds.createSelection();
        // if count.size() == 0, i.e. we want to read a scalar,
        // we have to supply something that fileSel can make sense of
        fileSel.select(count ? count : NDSize(offset.size(), 1), offset);
        Selection memSel(DataSpace::create(count, false));

        ds.read(dtype, data, fileSel, memSel);
    } else {
        ds.read(dtype, count, data);
    }

}

NDSize DataArrayHDF5::dataExtent(void) const {
    if (!group().hasData("data")) {
        return NDSize{};
    }

    DataSet ds = group().openData("data");
    return ds.size();
}

void DataArrayHDF5::dataExtent(const NDSize &extent) {
    if (!group().hasData("data")) {
        throw runtime_error("Data field not found in DataArray!");
    }

    DataSet ds = group().openData("data");
    ds.setExtent(extent);
}

DataType DataArrayHDF5::dataType(void) const {
    if (!group().hasData("data")) {
        return DataType::Nothing;
    }

    DataSet ds = group().openData("data");
    return ds.dataType();
}

} // ns nix::hdf5
} // ns nix<commit_msg>DataArray: dimensionCount: cast size_t → ndsize_t<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/util/util.hpp>

#include <nix/hdf5/DataArrayHDF5.hpp>
#include <nix/hdf5/DataSetHDF5.hpp>
#include <nix/hdf5/DimensionHDF5.hpp>

using namespace std;
using namespace nix::base;

namespace nix {
namespace hdf5 {

DataArrayHDF5::DataArrayHDF5(const std::shared_ptr<base::IFile> &file, const std::shared_ptr<base::IBlock> &block, const Group &group)
        : EntityWithSourcesHDF5(file, block, group) {
    dimension_group = this->group().openOptGroup("dimensions");
}

DataArrayHDF5::DataArrayHDF5(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const Group &group,
                             const string &id, const string &type, const string &name)
        : DataArrayHDF5(file, block, group, id, type, name, util::getTime()) {
}

DataArrayHDF5::DataArrayHDF5(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const Group &group,
                             const string &id, const string &type, const string &name, time_t time)
        : EntityWithSourcesHDF5(file, block, group, id, type, name, time) {
    dimension_group = this->group().openOptGroup("dimensions");
}

//--------------------------------------------------
// Element getters and setters
//--------------------------------------------------

boost::optional<std::string> DataArrayHDF5::label() const {
    boost::optional<std::string> ret;
    string value;
    bool have_attr = group().getAttr("label", value);

    if (have_attr) {
        ret = value;
    }

    return ret;
}

void DataArrayHDF5::label(const string &label) {
    if (label.empty()) {
        throw EmptyString("label");
    }
    else {
        group().setAttr("label", label);
        forceUpdatedAt();
    }
}

void DataArrayHDF5::label(const none_t t) {
    if (group().hasAttr("label")) {
        group().removeAttr("label");
    }
    forceUpdatedAt();
}

boost::optional<std::string> DataArrayHDF5::unit() const {
    boost::optional<std::string> ret;
    string value;
    bool have_attr = group().getAttr("unit", value);
    if (have_attr) {
        ret = value;
    }
    return ret;
}

void DataArrayHDF5::unit(const string &unit) {
    if (unit.empty()) {
        throw EmptyString("unit");
    }
    else {
        group().setAttr("unit", unit);
        forceUpdatedAt();
    }
}

void DataArrayHDF5::unit(const none_t t) {
    if (group().hasAttr("unit")) {
        group().removeAttr("unit");
    }
    forceUpdatedAt();
}

// TODO use defaults
boost::optional<double> DataArrayHDF5::expansionOrigin() const {
    boost::optional<double> ret;
    double expansion_origin;
    bool have_attr = group().getAttr("expansion_origin", expansion_origin);
    if (have_attr) {
        ret = expansion_origin;
    }
    return ret;
}

void DataArrayHDF5::expansionOrigin(double expansion_origin) {
    group().setAttr("expansion_origin", expansion_origin);
    forceUpdatedAt();
}

void DataArrayHDF5::expansionOrigin(const none_t t) {
    if (group().hasAttr("expansion_origin")) {
        group().removeAttr("expansion_origin");
    }
    forceUpdatedAt();
}

// TODO use defaults
vector<double> DataArrayHDF5::polynomCoefficients() const {
    vector<double> polynom_coefficients;

    if (group().hasData("polynom_coefficients")) {
        DataSet ds = group().openData("polynom_coefficients");
        ds.read(polynom_coefficients, true);
    }

    return polynom_coefficients;
}

void DataArrayHDF5::polynomCoefficients(const vector<double> &coefficients) {
    DataSet ds;
    if (group().hasData("polynom_coefficients")) {
        ds = group().openData("polynom_coefficients");
        ds.setExtent({coefficients.size()});
    } else {
        ds = group().createData("polynom_coefficients", DataType::Double, {coefficients.size()});
    }
    ds.write(coefficients);
    forceUpdatedAt();
}

void DataArrayHDF5::polynomCoefficients(const none_t t) {
    if (group().hasData("polynom_coefficients")) {
        group().removeData("polynom_coefficients");
    }
    forceUpdatedAt();
}

//--------------------------------------------------
// Methods concerning dimensions
//--------------------------------------------------

size_t DataArrayHDF5::dimensionCount() const {
    boost::optional<Group> g = dimension_group();
	size_t count = 0;
	if (g) {
		ndsize_t objs = g->objectCount();
		//FIXME: issue 473
		count = static_cast<size_t>(objs);
	}
    return count;
}

shared_ptr<IDimension> DataArrayHDF5::getDimension(size_t index) const {
    shared_ptr<IDimension> dim;
    boost::optional<Group> g = dimension_group();

    if (g) {
        string str_id = util::numToStr(index);
        if (g->hasGroup(str_id)) {
            Group group = g->openGroup(str_id, false);
            dim = openDimensionHDF5(group, index);
        }
    }

    return dim;
}

std::shared_ptr<base::ISetDimension> DataArrayHDF5::createSetDimension(size_t index) {
    Group g = createDimensionGroup(index);
    return make_shared<SetDimensionHDF5>(g, index);
}

std::shared_ptr<base::IRangeDimension> DataArrayHDF5::createRangeDimension(size_t index, const std::vector<double> &ticks) {
    Group g = createDimensionGroup(index);
    return make_shared<RangeDimensionHDF5>(g, index, ticks);
}

std::shared_ptr<base::ISampledDimension> DataArrayHDF5::createSampledDimension(size_t index, double sampling_interval) {
    Group g = createDimensionGroup(index);
    return make_shared<SampledDimensionHDF5>(g, index, sampling_interval);
}

Group DataArrayHDF5::createDimensionGroup(size_t index) {
    boost::optional<Group> g = dimension_group(true);

    size_t dim_max = dimensionCount() + 1;
    if (index > dim_max || index <= 0)
        throw new runtime_error("Invalid dimension index: has to be 0 < index <= " + util::numToStr(dim_max));

    string str_id = util::numToStr(index);
    if (g->hasGroup(str_id)) {
        g->removeGroup(str_id);
    }

    return g->openGroup(str_id, true);
}

bool DataArrayHDF5::deleteDimension(size_t index) {
    bool deleted = false;
    size_t dim_count = dimensionCount();
    string str_id = util::numToStr(index);
    boost::optional<Group> g = dimension_group();

    if (g) {
        if (g->hasGroup(str_id)) {
            g->removeGroup(str_id);
            deleted = true;
        }

        if (deleted && index < dim_count) {
            for (size_t old_id = index + 1; old_id <= dim_count; old_id++) {
                string str_old_id = util::numToStr(old_id);
                string str_new_id = util::numToStr(old_id - 1);
                g->renameGroup(str_old_id, str_new_id);
            }
        }
    }

    return deleted;
}

//--------------------------------------------------
// Other methods and functions
//--------------------------------------------------

DataArrayHDF5::~DataArrayHDF5() {
}

void DataArrayHDF5::createData(DataType dtype, const NDSize &size) {
    if (group().hasData("data")) {
        throw new std::runtime_error("DataArray alread exists"); //TODO: FIXME, better exception
    }

    group().createData("data", dtype, size); //FIXME: check if this 2-step creation is needed
    DataSet ds = group().openData("data");
}

bool DataArrayHDF5::hasData() const {
    return group().hasData("data");
}

void DataArrayHDF5::write(DataType dtype, const void *data, const NDSize &count, const NDSize &offset) {
    DataSet ds;

    if (!group().hasData("data")) {
        //FIXME: this case should actually never be possible, replace with exception?
        ds = group().createData("data", dtype, count);
    } else {
        ds = group().openData("data");
    }

    if (offset.size()) {
        Selection fileSel = ds.createSelection();
        fileSel.select(count, offset);
        Selection memSel(DataSpace::create(count, false));

        ds.write(dtype, data, fileSel, memSel);
    } else {
        ds.write(dtype, count, data);
    }
}

void DataArrayHDF5::read(DataType dtype, void *data, const NDSize &count, const NDSize &offset) const {
    if (!group().hasData("data")) {
        return;
    }

    DataSet ds = group().openData("data");

    if (offset.size()) {
        Selection fileSel = ds.createSelection();
        // if count.size() == 0, i.e. we want to read a scalar,
        // we have to supply something that fileSel can make sense of
        fileSel.select(count ? count : NDSize(offset.size(), 1), offset);
        Selection memSel(DataSpace::create(count, false));

        ds.read(dtype, data, fileSel, memSel);
    } else {
        ds.read(dtype, count, data);
    }

}

NDSize DataArrayHDF5::dataExtent(void) const {
    if (!group().hasData("data")) {
        return NDSize{};
    }

    DataSet ds = group().openData("data");
    return ds.size();
}

void DataArrayHDF5::dataExtent(const NDSize &extent) {
    if (!group().hasData("data")) {
        throw runtime_error("Data field not found in DataArray!");
    }

    DataSet ds = group().openData("data");
    ds.setExtent(extent);
}

DataType DataArrayHDF5::dataType(void) const {
    if (!group().hasData("data")) {
        return DataType::Nothing;
    }

    DataSet ds = group().openData("data");
    return ds.dataType();
}

} // ns nix::hdf5
} // ns nix<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <qi/log/headfileloghandler.hpp>

#include <boost/function.hpp>
#include <boost/filesystem.hpp>
#include <boost/bind.hpp>

#include <sstream>
#include <iomanip>
#include <string>
#include <qi/log.hpp>
#include "log_p.hpp"
#include <qi/os.hpp>
#include <cstdio>

namespace qi {
  namespace log {
    class PrivateHeadFileLogHandler
    {
    public:
      FILE* _file;
      int   _count;
      int   _max;
    };

    HeadFileLogHandler::HeadFileLogHandler(const std::string& filePath,
                                           int length)
      : _private(new PrivateHeadFileLogHandler)
    {
      _private->_max = length;
      _private->_file = NULL;
      _private->_count = _private->_max + 1;

      boost::filesystem::path fPath(filePath);
      // Create the directory!
      try
      {
        if (!boost::filesystem::exists(fPath.make_preferred().parent_path()))
          boost::filesystem::create_directories(fPath.make_preferred().parent_path());
      }
      catch (boost::filesystem::filesystem_error &e)
      {
        qiLogWarning("qi.log.headfileloghandler") << e.what() << std::endl;
      }
      // Open the file.
      FILE* file = qi::os::fopen(fPath.make_preferred().string().c_str(), "w+");

      if (file)
      {
        _private->_file = file;
        _private->_count = 0;
      }
      else
      {
        qiLogWarning("qi.log.headfileloghandler") << "Cannot open "
                                                  << filePath << std::endl;
      }
    }

    HeadFileLogHandler::~HeadFileLogHandler()
    {
      if (_private->_file != NULL)
        fclose(_private->_file);
      delete _private;
    }

    void HeadFileLogHandler::log(const qi::log::LogLevel verb,
                                 const qi::os::timeval   date,
                                 const char              *category,
                                 const char              *msg,
                                 const char              *file,
                                 const char              *fct,
                                 const int               line)
    {
      if (_private->_count < _private->_max)
      {
        if (verb > qi::log::verbosity() || _private->_file == NULL)
        {
          return;
        }
        else
        {
          std::string logline = qi::detail::logline(date, category, msg, file, fct, line);
          fprintf(_private->_file, "%s %s", logLevelToString(verb), logline.c_str());
          fflush(_private->_file);

          _private->_count++;
        }
      }
      else if (_private->_file != NULL)
      {
        fclose(_private->_file);
        _private->_file = NULL;
      }
    }
  }
}
<commit_msg>Add missing mutex to qi::log HeadFileLogHandler<commit_after>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <qi/log/headfileloghandler.hpp>

#include <boost/function.hpp>
#include <boost/filesystem.hpp>
#include <boost/bind.hpp>

#include <sstream>
#include <iomanip>
#include <string>
#include <qi/log.hpp>
#include "log_p.hpp"
#include <qi/os.hpp>
#include <cstdio>
#include <boost/thread/mutex.hpp>

namespace qi {
  namespace log {
    class PrivateHeadFileLogHandler
    {
    public:
      FILE* _file;
      int   _count;
      int   _max;
      boost::mutex _mutex;
    };

    HeadFileLogHandler::HeadFileLogHandler(const std::string& filePath,
                                           int length)
      : _private(new PrivateHeadFileLogHandler)
    {
      _private->_max = length;
      _private->_file = NULL;
      _private->_count = _private->_max + 1;

      boost::filesystem::path fPath(filePath);
      // Create the directory!
      try
      {
        if (!boost::filesystem::exists(fPath.make_preferred().parent_path()))
          boost::filesystem::create_directories(fPath.make_preferred().parent_path());
      }
      catch (boost::filesystem::filesystem_error &e)
      {
        qiLogWarning("qi.log.headfileloghandler") << e.what() << std::endl;
      }
      // Open the file.
      FILE* file = qi::os::fopen(fPath.make_preferred().string().c_str(), "w+");

      if (file)
      {
        _private->_file = file;
        _private->_count = 0;
      }
      else
      {
        qiLogWarning("qi.log.headfileloghandler") << "Cannot open "
                                                  << filePath << std::endl;
      }
    }

    HeadFileLogHandler::~HeadFileLogHandler()
    {
      if (_private->_file != NULL)
        fclose(_private->_file);
      delete _private;
    }

    void HeadFileLogHandler::log(const qi::log::LogLevel verb,
                                 const qi::os::timeval   date,
                                 const char              *category,
                                 const char              *msg,
                                 const char              *file,
                                 const char              *fct,
                                 const int               line)
    {
      boost::mutex::scoped_lock scopedLock(_private->_mutex);

      if (_private->_count < _private->_max)
      {
        if (verb > qi::log::verbosity() || _private->_file == NULL)
        {
          return;
        }
        else
        {
          std::string logline = qi::detail::logline(date, category, msg, file, fct, line);
          fprintf(_private->_file, "%s %s", logLevelToString(verb), logline.c_str());
          fflush(_private->_file);

          _private->_count++;
        }
      }
      else if (_private->_file != NULL)
      {
        fclose(_private->_file);
        _private->_file = NULL;
      }
    }
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <list>
#include "NeuralNetwork.h"
#include "Sigmoid.h"

NeuralNetwork::NeuralNetwork(NetworkConfiguration * configuration) {
  int inputs = configuration->getInputs();
  int outputs = configuration->getOutputs();
  int hidden = configuration->getHiddenLayers();
  int neuron_hidden = configuration->getNeuronHidden();

  // initialize the hidden layers - the first layer is initialized with
  // as many inputs ad the number of inputs to the network
  // the subsequent layers will be initialized with as many inputs as neurons
  // per hidden layer
  for(int i = 0; i < hidden; i++) {
    list<Neuron *> neurons;
    for(int j = 0; j < neuron_hidden; j++) {
      neurons.push_back(new Neuron(i == 0 ? inputs + 1 : neuron_hidden + 1, true));
    }

    m_hidden.push_back(neurons);
  }

  // Initialize the output layer with as many inputs as the number of neurons
  // per hidden layer
  for(int i = 0; i < outputs; i++) {
    m_output.push_back(new Neuron(neuron_hidden + 1, false));
  }
}

NeuralNetwork::~NeuralNetwork() {
  // destruct all the neuron in the hidden layers
  for(list<list<Neuron *> >::const_iterator it_s = m_hidden.begin(); it_s != m_hidden.end(); it_s++) {
    list<Neuron *>::const_iterator it_in;

    for(it_in = (*it_s).begin(); it_in != (*it_s).end(); it_in++) {
      delete *it_in;
    }
  }

  // destruct all the neuron in the output layer
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++) {
    delete *it;
  }
}

// main update method to the neural network. The input parameter is an array of
// input values, and returns an array of output values
vector<float> NeuralNetwork::feedForward(vector<float> inputs) {
  return evaluateOutputLayer(evaluateHiddenLayers(inputs));
}

// main function to train the network given an input and output vectors
// it uses backpropagation algorithm to update the network weights
// it returns the current error
float NeuralNetwork::train(vector<float> input, vector<float> output) {
  size_t index = 0;
  // feed forward the input to get an output
  feedForward(input);

  // calculate the error of the output layer based on the desired output
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++, index++) {
    Neuron * n = *it;
    n->setError(output[index] - n->getOutput() * Sigmoid::dSigmoid(n->getOutput()));
  }

  //TODO calculate the errors for all the hidden layers

  //TODO update the weights accordingly

  double error = 0.0;
  // return the error
  index = 0;
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++, index++) {
    error += 0.5 * pow(output[index] - (*it)->getOutput(), 2);
  }

  return error;
}

// auxiliary method to import an array of weights to the network neurons
// it is used to recover the state of a previously trained network
void NeuralNetwork::loadWeights(vector<float> weights) {
  int weights_index = 0;

  list<list<Neuron *> >::const_iterator it;

  for(it = m_hidden.begin(); it != m_hidden.end(); it++) {
    list<Neuron *>::const_iterator neuron_it;

    for(neuron_it = (*it).begin(); neuron_it != (*it).end(); neuron_it++) {
      vector<float> weightsVector;
      for(size_t i = 0; i < (*neuron_it)->getWeights().size(); i++) {
        weightsVector.push_back(weights[weights_index++]);
      }
      (*neuron_it)->setWeights(weightsVector);
    }
  }

  list<Neuron *>::const_iterator output_it;

  for(output_it = m_output.begin(); output_it != m_output.end(); output_it++) {
    vector<float> weightsVector;

    for(size_t i = 0; i < (*output_it)->getWeights().size(); i++) {
      weightsVector.push_back(weights[weights_index++]);
    }

    (*output_it)->setWeights(weightsVector);
  }
}

//
// Private methods
//

vector<float> NeuralNetwork::evaluateHiddenLayers(vector<float> inputs) {
  vector<float> hiddenLayerInput = inputs;
  vector<float> hiddenLayerOutput;

  list<list<Neuron *> >::const_iterator it;

  for(it = m_hidden.begin(); it != m_hidden.end(); it++) {
    list<Neuron *>::const_iterator neuron_it;
    for(neuron_it = (*it).begin(); neuron_it != (*it).end(); neuron_it++) {
      Neuron * n = *neuron_it;
      hiddenLayerOutput.push_back(n->evaluate(hiddenLayerInput));
    }

    hiddenLayerInput = hiddenLayerOutput;
  }

  return hiddenLayerOutput;

}

vector<float> NeuralNetwork::evaluateOutputLayer(vector<float> hidden_output) {
  vector<float> outputs;

  list<Neuron *>::const_iterator output_it;

  for(output_it = m_output.begin(); output_it != m_output.end(); output_it++) {
    Neuron * n = *output_it;
    outputs.push_back(n->evaluate(hidden_output));
  }

  return outputs;
}

<commit_msg>bug fix<commit_after>#include <iostream>
#include <list>
#include "NeuralNetwork.h"
#include "Sigmoid.h"

NeuralNetwork::NeuralNetwork(NetworkConfiguration * configuration) {
  int inputs = configuration->getInputs();
  int outputs = configuration->getOutputs();
  int hidden = configuration->getHiddenLayers();
  int neuron_hidden = configuration->getNeuronHidden();

  // initialize the hidden layers - the first layer is initialized with
  // as many inputs ad the number of inputs to the network
  // the subsequent layers will be initialized with as many inputs as neurons
  // per hidden layer
  for(int i = 0; i < hidden; i++) {
    list<Neuron *> neurons;
    for(int j = 0; j < neuron_hidden; j++) {
      neurons.push_back(new Neuron(i == 0 ? inputs + 1 : neuron_hidden + 1, true));
    }

    m_hidden.push_back(neurons);
  }

  // Initialize the output layer with as many inputs as the number of neurons
  // per hidden layer
  for(int i = 0; i < outputs; i++) {
    m_output.push_back(new Neuron(neuron_hidden + 1, false));
  }
}

NeuralNetwork::~NeuralNetwork() {
  // destruct all the neuron in the hidden layers
  for(list<list<Neuron *> >::const_iterator it_s = m_hidden.begin(); it_s != m_hidden.end(); it_s++) {
    list<Neuron *>::const_iterator it_in;

    for(it_in = (*it_s).begin(); it_in != (*it_s).end(); it_in++) {
      delete *it_in;
    }
  }

  // destruct all the neuron in the output layer
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++) {
    delete *it;
  }
}

// main update method to the neural network. The input parameter is an array of
// input values, and returns an array of output values
vector<float> NeuralNetwork::feedForward(vector<float> inputs) {
  return evaluateOutputLayer(evaluateHiddenLayers(inputs));
}

// main function to train the network given an input and output vectors
// it uses backpropagation algorithm to update the network weights
// it returns the current error
float NeuralNetwork::train(vector<float> input, vector<float> output) {
  size_t index = 0;
  // feed forward the input to get an output
  feedForward(input);

  // calculate the error of the output layer based on the desired output
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++, index++) {
    Neuron * n = *it;
    n->setError((output[index] - n->getOutput()) * Sigmoid::dSigmoid(n->getOutput()));
  }

  //TODO calculate the errors for all the hidden layers

  //TODO update the weights accordingly

  double error = 0.0;
  // return the error
  index = 0;
  for(list<Neuron *>::const_iterator it = m_output.begin(); it != m_output.end(); it++, index++) {
    error += 0.5 * pow(output[index] - (*it)->getOutput(), 2);
  }

  return error;
}

// auxiliary method to import an array of weights to the network neurons
// it is used to recover the state of a previously trained network
void NeuralNetwork::loadWeights(vector<float> weights) {
  int weights_index = 0;

  list<list<Neuron *> >::const_iterator it;

  for(it = m_hidden.begin(); it != m_hidden.end(); it++) {
    list<Neuron *>::const_iterator neuron_it;

    for(neuron_it = (*it).begin(); neuron_it != (*it).end(); neuron_it++) {
      vector<float> weightsVector;
      for(size_t i = 0; i < (*neuron_it)->getWeights().size(); i++) {
        weightsVector.push_back(weights[weights_index++]);
      }
      (*neuron_it)->setWeights(weightsVector);
    }
  }

  list<Neuron *>::const_iterator output_it;

  for(output_it = m_output.begin(); output_it != m_output.end(); output_it++) {
    vector<float> weightsVector;

    for(size_t i = 0; i < (*output_it)->getWeights().size(); i++) {
      weightsVector.push_back(weights[weights_index++]);
    }

    (*output_it)->setWeights(weightsVector);
  }
}

//
// Private methods
//

vector<float> NeuralNetwork::evaluateHiddenLayers(vector<float> inputs) {
  vector<float> hiddenLayerInput = inputs;
  vector<float> hiddenLayerOutput;

  list<list<Neuron *> >::const_iterator it;

  for(it = m_hidden.begin(); it != m_hidden.end(); it++) {
    list<Neuron *>::const_iterator neuron_it;
    for(neuron_it = (*it).begin(); neuron_it != (*it).end(); neuron_it++) {
      Neuron * n = *neuron_it;
      hiddenLayerOutput.push_back(n->evaluate(hiddenLayerInput));
    }

    hiddenLayerInput = hiddenLayerOutput;
  }

  return hiddenLayerOutput;

}

vector<float> NeuralNetwork::evaluateOutputLayer(vector<float> hidden_output) {
  vector<float> outputs;

  list<Neuron *>::const_iterator output_it;

  for(output_it = m_output.begin(); output_it != m_output.end(); output_it++) {
    Neuron * n = *output_it;
    outputs.push_back(n->evaluate(hidden_output));
  }

  return outputs;
}

<|endoftext|>