<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::SAVE, InputHandler::KEYBOARD, GLFW_KEY_S);
    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);
    Input()->AssignButton(InputHandler::ZOOM, InputHandler::KEYBOARD, GLFW_KEY_Z);
    Input()->AssignButton(InputHandler::FOCUS, InputHandler::KEYBOARD, GLFW_KEY_F);

    // 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);

    savePromptAnswered = false;
    close = false;

}

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

void Editor::Show(float deltaTime) {

    if (close) {

        if (Hymn().GetPath() != "") {

            savePromtWindow.SetVisible(true);
            savePromtWindow.Show();

            switch (savePromtWindow.GetDecision()) {
            case 0:
                Save();
                savePromptAnswered = true;
                break;

            case 1:
                savePromptAnswered = true;
                break;

            default:
                break;
            }

        }
        else {

            savePromptAnswered = true;

        }

    }
    else {

        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();

                if (Hymn().GetPath() != "") {

                    if (ImGui::MenuItem("Save Hymn", "CTRL+S"))
                        Save();

                }

                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();
                }

                if (Input()->Triggered(InputHandler::ZOOM)) {
                    if (resourceList.GetScene().entityEditor.GetEntity() != nullptr) {
                        const glm::vec3 tempPos = resourceList.GetScene().entityEditor.GetEntity()->GetWorldPosition();
                        cameraEntity->position = tempPos + glm::vec3(0, 7, 7);
                        cameraEntity->rotation = glm::vec3(0, 45, 1);
                    }
                }

                // Editor Camera Coordinates
                ImGui::SameLine(size.x - 280); ImGui::Text("X: %f, Y: %f, Z: %f", cameraEntity->GetWorldPosition().x, cameraEntity->GetWorldPosition().y, cameraEntity->GetWorldPosition().z);
            }

            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]);

            //Move speed scaling.
            float speed = 10.0f * deltaTime * (glm::abs(cameraEntity->position.y) / 10.0f);
            float constantSpeed = 10.0f * deltaTime;

            if (cameraEntity->position.y > 10.0f || cameraEntity->position.y < -10.0f) {
                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));
            }
            else {
                cameraEntity->position += constantSpeed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
                cameraEntity->position += constantSpeed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
            }
        }

        // Move camera position and rotation to fixate on selected object.
        if (Input()->Triggered(InputHandler::FOCUS)) {

            // When mousepicking is added, change this vec3(0,0,0) to object pivot.
            glm::vec3 backward = glm::normalize(cameraEntity->position - glm::vec3(0, 0, 0));

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) > 10) {
                cameraEntity->position -= backward;
            }

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) < 10) {
                cameraEntity->position += backward;
            }
            // When mousepicking is added, change this vec3(0,0,0) to object pivot. NOTE Does this do the same as 'backward' ?
            glm::vec3 camDirection = glm::vec3(0, 0, 0) - cameraEntity->position;
            glm::normalize(camDirection);

            float yaw = std::atan2(camDirection.x, -camDirection.z);
            cameraEntity->rotation.x = glm::degrees(yaw);

            float xz = std::sqrt(camDirection.x * camDirection.x + camDirection.z * camDirection.z);
            float pitch = std::atan2(-camDirection.y, xz);
            cameraEntity->rotation.y = glm::degrees(pitch);
        }

        //Scroll zoom.
        if (Input()->GetScrollDown()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * 10.0f;
            }
        }
        if (Input()->GetScrollUp()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * -10.0f;
            }
        }

        if (Input()->Triggered(InputHandler::PLAYTEST) && Hymn().GetPath() != "")
            play = true;

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

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

        if (Hymn().GetPath() != "" && Input()->Triggered(InputHandler::SAVE) && Input()->Pressed(InputHandler::CONTROL))
            Save();

        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::ReadyToClose() const {
    return savePromptAnswered;
}

void Editor::Close() {
    close = true;
}

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

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

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

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

void Editor::LoadEditorState() {
    Hymn().FromJson(editorState);
}

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>Fixed newline<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::SAVE, InputHandler::KEYBOARD, GLFW_KEY_S);
    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);
    Input()->AssignButton(InputHandler::ZOOM, InputHandler::KEYBOARD, GLFW_KEY_Z);
    Input()->AssignButton(InputHandler::FOCUS, InputHandler::KEYBOARD, GLFW_KEY_F);

    // 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);

    savePromptAnswered = false;
    close = false;

}

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

void Editor::Show(float deltaTime) {

    if (close) {

        if (Hymn().GetPath() != "") {

            savePromtWindow.SetVisible(true);
            savePromtWindow.Show();

            switch (savePromtWindow.GetDecision()) {
            case 0:
                Save();
                savePromptAnswered = true;
                break;

            case 1:
                savePromptAnswered = true;
                break;

            default:
                break;
            }

        } else {

            savePromptAnswered = true;
        }

    } else {

        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();

                if (Hymn().GetPath() != "") {

                    if (ImGui::MenuItem("Save Hymn", "CTRL+S"))
                        Save();

                }

                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();
                }

                if (Input()->Triggered(InputHandler::ZOOM)) {
                    if (resourceList.GetScene().entityEditor.GetEntity() != nullptr) {
                        const glm::vec3 tempPos = resourceList.GetScene().entityEditor.GetEntity()->GetWorldPosition();
                        cameraEntity->position = tempPos + glm::vec3(0, 7, 7);
                        cameraEntity->rotation = glm::vec3(0, 45, 1);
                    }
                }

                // Editor Camera Coordinates
                ImGui::SameLine(size.x - 280); ImGui::Text("X: %f, Y: %f, Z: %f", cameraEntity->GetWorldPosition().x, cameraEntity->GetWorldPosition().y, cameraEntity->GetWorldPosition().z);
            }

            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]);

            //Move speed scaling.
            float speed = 10.0f * deltaTime * (glm::abs(cameraEntity->position.y) / 10.0f);
            float constantSpeed = 10.0f * deltaTime;

            if (cameraEntity->position.y > 10.0f || cameraEntity->position.y < -10.0f) {
                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));
            } else {
                cameraEntity->position += constantSpeed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
                cameraEntity->position += constantSpeed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
            }
        }

        // Move camera position and rotation to fixate on selected object.
        if (Input()->Triggered(InputHandler::FOCUS)) {

            // When mousepicking is added, change this vec3(0,0,0) to object pivot.
            glm::vec3 backward = glm::normalize(cameraEntity->position - glm::vec3(0, 0, 0));

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) > 10) {
                cameraEntity->position -= backward;
            }

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) < 10) {
                cameraEntity->position += backward;
            }
            // When mousepicking is added, change this vec3(0,0,0) to object pivot. NOTE Does this do the same as 'backward' ?
            glm::vec3 camDirection = glm::vec3(0, 0, 0) - cameraEntity->position;
            glm::normalize(camDirection);

            float yaw = std::atan2(camDirection.x, -camDirection.z);
            cameraEntity->rotation.x = glm::degrees(yaw);

            float xz = std::sqrt(camDirection.x * camDirection.x + camDirection.z * camDirection.z);
            float pitch = std::atan2(-camDirection.y, xz);
            cameraEntity->rotation.y = glm::degrees(pitch);
        }

        //Scroll zoom.
        if (Input()->GetScrollDown()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * 10.0f;
            }
        }
        if (Input()->GetScrollUp()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * -10.0f;
            }
        }

        if (Input()->Triggered(InputHandler::PLAYTEST) && Hymn().GetPath() != "")
            play = true;

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

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

        if (Hymn().GetPath() != "" && Input()->Triggered(InputHandler::SAVE) && Input()->Pressed(InputHandler::CONTROL))
            Save();

        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::ReadyToClose() const {
    return savePromptAnswered;
}

void Editor::Close() {
    close = true;
}

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

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

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

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

void Editor::LoadEditorState() {
    Hymn().FromJson(editorState);
}

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>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "dcgf.h"
#include <fstream>
#include "BRegistry.h"
#include "PathUtil.h"
#include "StringUtil.h"
#include "tinyxml.h"

//////////////////////////////////////////////////////////////////////////
CBRegistry::CBRegistry(CBGame* inGame):CBBase(inGame)
{
	m_IniName = NULL;

	SetIniName("./wme.ini");
	LoadValues(true);
}

//////////////////////////////////////////////////////////////////////////
CBRegistry::~CBRegistry()
{
	SaveValues();
	SAFE_DELETE_ARRAY(m_IniName);
}

//////////////////////////////////////////////////////////////////////////
AnsiString CBRegistry::ReadString(const AnsiString& subKey, const AnsiString& key, const AnsiString& init)
{
	AnsiString ret = "";

#ifdef __WIN32__
	// check ini file first (so what we can use project files on windows)
	char buffer[32768];
	GetPrivateProfileString(subKey.c_str(), key.c_str(), init.c_str(), buffer, 32768, m_IniName);
	ret = AnsiString(buffer);

	if (buffer != init) return ret;
#endif

	bool found = false;
	ret = GetValue(m_LocalValues, subKey, key, found);
	if (!found) ret = GetValue(m_Values, subKey, key, found);
	if (!found) ret = init;

	return ret;
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteString(const AnsiString& subKey, const AnsiString& key, const AnsiString& value)
{
	m_Values[subKey][key] = value;
	return true;
}

//////////////////////////////////////////////////////////////////////////
int CBRegistry::ReadInt(const AnsiString& subKey, const AnsiString& key, int init)
{
#ifdef __WIN32__
	int ret = GetPrivateProfileInt(subKey.c_str(), key.c_str(), init, m_IniName);
	if(ret != init) return ret;
#endif

	AnsiString val = ReadString(subKey, key, "");
	if (val.empty()) return init;
	else return atoi(val.c_str());
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteInt(const AnsiString& subKey, const AnsiString& key, int value)
{
	WriteString(subKey, key, StringUtil::ToString(value));
	return true;
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::ReadBool(const AnsiString& subKey, const AnsiString& key, bool init)
{
	return (ReadInt(subKey, key, (int)init) != 0);
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteBool(const AnsiString& subKey, const AnsiString& key, bool value)
{
	return WriteInt(subKey, key, (int)value);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SetIniName(char* Name)
{
	SAFE_DELETE_ARRAY(m_IniName);

	if (strchr(Name, '\\') == NULL && strchr(Name, '/') == NULL)
	{
		m_IniName = new char [strlen(Name)+3];
		sprintf(m_IniName, "./%s", Name);
	}
	else
	{
		m_IniName = new char [strlen(Name)+1];
		strcpy(m_IniName, Name);
	}
}

//////////////////////////////////////////////////////////////////////////
char* CBRegistry::GetIniName()
{
	return m_IniName;
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::LoadValues(bool local)
{
	if (local) LoadXml("settings.xml", m_LocalValues);
	else LoadXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SaveValues()
{
	SaveXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SetBasePath(const char* basePath)
{
	m_BasePath = PathUtil::GetFileNameWithoutExtension(basePath);

	LoadValues(false);
}

//////////////////////////////////////////////////////////////////////////
AnsiString CBRegistry::GetValue(PathValueMap& values, const AnsiString path, const AnsiString& key, bool& found)
{
	found = false;
	PathValueMap::iterator it = values.find(path);
	if (it == values.end()) return "";

	KeyValuePair pairs = (*it).second;
	KeyValuePair::iterator keyIt = pairs.find(key);
	if (keyIt == pairs.end()) return "";
	else
	{
		found = true;
		return (*keyIt).second;
	}
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::LoadXml(const AnsiString fileName, PathValueMap& values)
{
	TiXmlDocument doc(fileName);
	if (!doc.LoadFile()) return;

	TiXmlElement* rootElem = doc.RootElement();
	if (!rootElem || rootElem->ValueStr() != "Settings") return;

	for (TiXmlElement* pathElem = rootElem->FirstChildElement(); pathElem != NULL; pathElem = pathElem->NextSiblingElement())
	{
		for (TiXmlElement* keyElem = pathElem->FirstChildElement(); keyElem != NULL; keyElem = keyElem->NextSiblingElement())
		{
			values[pathElem->ValueStr()][keyElem->ValueStr()] = keyElem->GetText();
		}
	}
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SaveXml(const AnsiString fileName, PathValueMap& values)
{
	CBUtils::CreatePath(fileName.c_str());

	TiXmlDocument doc;
	doc.LinkEndChild(new TiXmlDeclaration( "1.0", "utf-8", ""));

	TiXmlElement* root = new TiXmlElement("Settings");
	doc.LinkEndChild(root);

	PathValueMap::iterator pathIt;
	for (pathIt = m_Values.begin(); pathIt != m_Values.end(); ++pathIt)
	{
		TiXmlElement* pathElem = new TiXmlElement((*pathIt).first);
		root->LinkEndChild(pathElem);

		KeyValuePair pairs = (*pathIt).second;
		KeyValuePair::iterator keyIt;
		for (keyIt = pairs.begin(); keyIt != pairs.end(); ++keyIt)
		{
			TiXmlElement* keyElem = new TiXmlElement((*keyIt).first);
			pathElem->LinkEndChild(keyElem);

			keyElem->LinkEndChild(new TiXmlText((*keyIt).second));
		}
	}

	TiXmlPrinter printer;
	doc.Accept(&printer);

	std::ofstream stream;
	stream.open(fileName.c_str());

	if (!stream.is_open()) return;
	else
	{
		stream << printer.Str();
		stream.close();
	}
}
<commit_msg>iOS: Save settings.xml on every settings change<commit_after>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "dcgf.h"
#include <fstream>
#include "BRegistry.h"
#include "PathUtil.h"
#include "StringUtil.h"
#include "tinyxml.h"

//////////////////////////////////////////////////////////////////////////
CBRegistry::CBRegistry(CBGame* inGame):CBBase(inGame)
{
	m_IniName = NULL;

	SetIniName("./wme.ini");
	LoadValues(true);
}

//////////////////////////////////////////////////////////////////////////
CBRegistry::~CBRegistry()
{
	SaveValues();
	SAFE_DELETE_ARRAY(m_IniName);
}

//////////////////////////////////////////////////////////////////////////
AnsiString CBRegistry::ReadString(const AnsiString& subKey, const AnsiString& key, const AnsiString& init)
{
	AnsiString ret = "";

#ifdef __WIN32__
	// check ini file first (so what we can use project files on windows)
	char buffer[32768];
	GetPrivateProfileString(subKey.c_str(), key.c_str(), init.c_str(), buffer, 32768, m_IniName);
	ret = AnsiString(buffer);

	if (buffer != init) return ret;
#endif

	bool found = false;
	ret = GetValue(m_LocalValues, subKey, key, found);
	if (!found) ret = GetValue(m_Values, subKey, key, found);
	if (!found) ret = init;

	return ret;
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteString(const AnsiString& subKey, const AnsiString& key, const AnsiString& value)
{
	m_Values[subKey][key] = value;

#ifdef __IPHONEOS__
	SaveValues();
#endif
	return true;
}

//////////////////////////////////////////////////////////////////////////
int CBRegistry::ReadInt(const AnsiString& subKey, const AnsiString& key, int init)
{
#ifdef __WIN32__
	int ret = GetPrivateProfileInt(subKey.c_str(), key.c_str(), init, m_IniName);
	if(ret != init) return ret;
#endif

	AnsiString val = ReadString(subKey, key, "");
	if (val.empty()) return init;
	else return atoi(val.c_str());
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteInt(const AnsiString& subKey, const AnsiString& key, int value)
{
	WriteString(subKey, key, StringUtil::ToString(value));
	return true;
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::ReadBool(const AnsiString& subKey, const AnsiString& key, bool init)
{
	return (ReadInt(subKey, key, (int)init) != 0);
}

//////////////////////////////////////////////////////////////////////////
bool CBRegistry::WriteBool(const AnsiString& subKey, const AnsiString& key, bool value)
{
	return WriteInt(subKey, key, (int)value);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SetIniName(char* Name)
{
	SAFE_DELETE_ARRAY(m_IniName);

	if (strchr(Name, '\\') == NULL && strchr(Name, '/') == NULL)
	{
		m_IniName = new char [strlen(Name)+3];
		sprintf(m_IniName, "./%s", Name);
	}
	else
	{
		m_IniName = new char [strlen(Name)+1];
		strcpy(m_IniName, Name);
	}
}

//////////////////////////////////////////////////////////////////////////
char* CBRegistry::GetIniName()
{
	return m_IniName;
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::LoadValues(bool local)
{
	if (local) LoadXml("settings.xml", m_LocalValues);
	else LoadXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SaveValues()
{
	SaveXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values);
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SetBasePath(const char* basePath)
{
	m_BasePath = PathUtil::GetFileNameWithoutExtension(basePath);

	LoadValues(false);
}

//////////////////////////////////////////////////////////////////////////
AnsiString CBRegistry::GetValue(PathValueMap& values, const AnsiString path, const AnsiString& key, bool& found)
{
	found = false;
	PathValueMap::iterator it = values.find(path);
	if (it == values.end()) return "";

	KeyValuePair pairs = (*it).second;
	KeyValuePair::iterator keyIt = pairs.find(key);
	if (keyIt == pairs.end()) return "";
	else
	{
		found = true;
		return (*keyIt).second;
	}
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::LoadXml(const AnsiString fileName, PathValueMap& values)
{
	TiXmlDocument doc(fileName);
	if (!doc.LoadFile()) return;

	TiXmlElement* rootElem = doc.RootElement();
	if (!rootElem || rootElem->ValueStr() != "Settings") return;

	for (TiXmlElement* pathElem = rootElem->FirstChildElement(); pathElem != NULL; pathElem = pathElem->NextSiblingElement())
	{
		for (TiXmlElement* keyElem = pathElem->FirstChildElement(); keyElem != NULL; keyElem = keyElem->NextSiblingElement())
		{
			values[pathElem->ValueStr()][keyElem->ValueStr()] = keyElem->GetText();
		}
	}
}

//////////////////////////////////////////////////////////////////////////
void CBRegistry::SaveXml(const AnsiString fileName, PathValueMap& values)
{
	CBUtils::CreatePath(fileName.c_str());

	TiXmlDocument doc;
	doc.LinkEndChild(new TiXmlDeclaration( "1.0", "utf-8", ""));

	TiXmlElement* root = new TiXmlElement("Settings");
	doc.LinkEndChild(root);

	PathValueMap::iterator pathIt;
	for (pathIt = m_Values.begin(); pathIt != m_Values.end(); ++pathIt)
	{
		TiXmlElement* pathElem = new TiXmlElement((*pathIt).first);
		root->LinkEndChild(pathElem);

		KeyValuePair pairs = (*pathIt).second;
		KeyValuePair::iterator keyIt;
		for (keyIt = pairs.begin(); keyIt != pairs.end(); ++keyIt)
		{
			TiXmlElement* keyElem = new TiXmlElement((*keyIt).first);
			pathElem->LinkEndChild(keyElem);

			keyElem->LinkEndChild(new TiXmlText((*keyIt).second));
		}
	}

	TiXmlPrinter printer;
	doc.Accept(&printer);

	std::ofstream stream;
	stream.open(fileName.c_str());

	if (!stream.is_open()) return;
	else
	{
		stream << printer.Str();
		stream.close();
	}
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_FFI
#define REALM_FFI

#include <string>

namespace realm {

enum class RealmErrorType {
    unknown = 0,
    system = 1
};

struct RealmError {
    RealmErrorType type;
    std::string message;
};

}

#endif // REALM_FFI<commit_msg>add _HPP to include guard<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_FFI_HPP
#define REALM_FFI_HPP

#include <string>

namespace realm {

enum class RealmErrorType {
    unknown = 0,
    system = 1
};

struct RealmError {
    RealmErrorType type;
    std::string message;
};

}

#endif // REALM_FFI_HPP<|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::SAVE, InputHandler::KEYBOARD, GLFW_KEY_S);
    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);
    Input()->AssignButton(InputHandler::ZOOM, InputHandler::KEYBOARD, GLFW_KEY_Z);
    Input()->AssignButton(InputHandler::FOCUS, InputHandler::KEYBOARD, GLFW_KEY_F);

    // 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);

    savePromptAnswered = false;
    close = false;

}

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

void Editor::Show(float deltaTime) {

    if (close) {

        if (Hymn().GetPath() != "") {

            savePromtWindow.SetVisible(true);
            savePromtWindow.Show();

            switch (savePromtWindow.GetDecision()) {
            case 0:
                Save();
                savePromptAnswered = true;
                break;

            case 1:
                savePromptAnswered = true;
                break;

            default:
                break;
            }

        } else {

            savePromptAnswered = true;
        }

    } else {

        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();

                if (Hymn().GetPath() != "") {

                    if (ImGui::MenuItem("Save Hymn", "CTRL+S"))
                        Save();

                }

                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();
                }

                if (Input()->Triggered(InputHandler::ZOOM)) {
                    if (resourceView.GetScene().entityEditor.GetEntity() != nullptr) {
                        const glm::vec3 tempPos = resourceView.GetScene().entityEditor.GetEntity()->GetWorldPosition();
                        cameraEntity->position = tempPos + glm::vec3(0, 7, 7);
                        cameraEntity->rotation = glm::vec3(0, 45, 1);
                    }
                }

                // Editor Camera Coordinates
                ImGui::SameLine(size.x - 280); ImGui::Text("X: %f, Y: %f, Z: %f", cameraEntity->GetWorldPosition().x, cameraEntity->GetWorldPosition().y, cameraEntity->GetWorldPosition().z);
            }

            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 (resourceView.IsVisible())
            resourceView.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]);

            //Move speed scaling.
            float speed = 10.0f * deltaTime * (glm::abs(cameraEntity->position.y) / 10.0f);
            float constantSpeed = 10.0f * deltaTime;

            if (cameraEntity->position.y > 10.0f || cameraEntity->position.y < -10.0f) {
                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));
            } else {
                cameraEntity->position += constantSpeed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
                cameraEntity->position += constantSpeed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
            }
        }

        // Move camera position and rotation to fixate on selected object.
        if (Input()->Triggered(InputHandler::FOCUS)) {

            // When mousepicking is added, change this vec3(0,0,0) to object pivot.
            glm::vec3 backward = glm::normalize(cameraEntity->position - glm::vec3(0, 0, 0));

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) > 10) {
                cameraEntity->position -= backward;
            }

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) < 10) {
                cameraEntity->position += backward;
            }
            // When mousepicking is added, change this vec3(0,0,0) to object pivot. NOTE Does this do the same as 'backward' ?
            glm::vec3 camDirection = glm::vec3(0, 0, 0) - cameraEntity->position;
            glm::normalize(camDirection);

            float yaw = std::atan2(camDirection.x, -camDirection.z);
            cameraEntity->rotation.x = glm::degrees(yaw);

            float xz = std::sqrt(camDirection.x * camDirection.x + camDirection.z * camDirection.z);
            float pitch = std::atan2(-camDirection.y, xz);
            cameraEntity->rotation.y = glm::degrees(pitch);
        }

        //Scroll zoom.
        if (Input()->GetScrollDown()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * 10.0f;
            }
        }
        if (Input()->GetScrollUp()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * -10.0f;
            }
        }

        if (Input()->Triggered(InputHandler::PLAYTEST) && Hymn().GetPath() != "")
            play = true;

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

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

        if (Hymn().GetPath() != "" && Input()->Triggered(InputHandler::SAVE) && Input()->Pressed(InputHandler::CONTROL))
            Save();

        if (play)
            Play();

    }

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

}

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

bool Editor::ReadyToClose() const {
    return savePromptAnswered;
}

void Editor::Close() {
    close = true;
}

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

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

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

void Editor::Play() {
    editorState = Hymn().ToJson();
    SetVisible(false);
    resourceView.HideEditors();
    resourceView.ResetScene();
    Managers().scriptManager->RegisterInput();
    Managers().scriptManager->BuildAllScripts();
}

void Editor::LoadEditorState() {
    Hymn().FromJson(editorState);
}

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()) {
        resourceView.ResetScene();
        Hymn().Clear();
        Hymn().world.CreateRoot();
        Hymn().SetPath(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER + hymn);
        resourceView.SetVisible(true);

        // Default scene.
        /// @todo Fix creating 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()) {
        resourceView.ResetScene();
        Hymn().Load(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER + hymn);
        resourceView.SetVisible(true);
    }

    selectHymnWindow.SetVisible(false);
}
<commit_msg>Save, load and clear resources<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 "Resources.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::SAVE, InputHandler::KEYBOARD, GLFW_KEY_S);
    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);
    Input()->AssignButton(InputHandler::ZOOM, InputHandler::KEYBOARD, GLFW_KEY_Z);
    Input()->AssignButton(InputHandler::FOCUS, InputHandler::KEYBOARD, GLFW_KEY_F);

    // 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);

    savePromptAnswered = false;
    close = false;
}

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

void Editor::Show(float deltaTime) {
    if (close) {
        // Ask the user whether they wish to save.
        if (Hymn().GetPath() != "") {
            savePromtWindow.SetVisible(true);
            savePromtWindow.Show();

            switch (savePromtWindow.GetDecision()) {
            case 0:
                Save();
                savePromptAnswered = true;
                break;

            case 1:
                savePromptAnswered = true;
                break;

            default:
                break;
            }
        } else {
            savePromptAnswered = true;
        }
    } else {
        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();

                if (Hymn().GetPath() != "") {
                    if (ImGui::MenuItem("Save Hymn", "CTRL+S"))
                        Save();
                }

                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();
                }

                if (Input()->Triggered(InputHandler::ZOOM)) {
                    if (resourceView.GetScene().entityEditor.GetEntity() != nullptr) {
                        const glm::vec3 tempPos = resourceView.GetScene().entityEditor.GetEntity()->GetWorldPosition();
                        cameraEntity->position = tempPos + glm::vec3(0, 7, 7);
                        cameraEntity->rotation = glm::vec3(0, 45, 1);
                    }
                }

                // Editor Camera Coordinates
                ImGui::SameLine(size.x - 280); ImGui::Text("X: %f, Y: %f, Z: %f", cameraEntity->GetWorldPosition().x, cameraEntity->GetWorldPosition().y, cameraEntity->GetWorldPosition().z);
            }

            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 (resourceView.IsVisible())
            resourceView.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]);

            // Move speed scaling.
            float speed = 10.0f * deltaTime * (glm::abs(cameraEntity->position.y) / 10.0f);
            float constantSpeed = 10.0f * deltaTime;

            if (cameraEntity->position.y > 10.0f || cameraEntity->position.y < -10.0f) {
                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));
            } else {
                cameraEntity->position += constantSpeed * backward * static_cast<float>(Input()->Pressed(InputHandler::BACKWARD) - Input()->Pressed(InputHandler::FORWARD));
                cameraEntity->position += constantSpeed * right * static_cast<float>(Input()->Pressed(InputHandler::RIGHT) - Input()->Pressed(InputHandler::LEFT));
            }
        }

        // Move camera position and rotation to fixate on selected object.
        if (Input()->Triggered(InputHandler::FOCUS)) {

            // When mousepicking is added, change this vec3(0,0,0) to object pivot.
            glm::vec3 backward = glm::normalize(cameraEntity->position - glm::vec3(0, 0, 0));

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) > 10) {
                cameraEntity->position -= backward;
            }

            while (glm::length(glm::vec3(0, 0, 0) - cameraEntity->position) < 10) {
                cameraEntity->position += backward;
            }
            // When mousepicking is added, change this vec3(0,0,0) to object pivot. NOTE Does this do the same as 'backward' ?
            glm::vec3 camDirection = glm::vec3(0, 0, 0) - cameraEntity->position;
            glm::normalize(camDirection);

            float yaw = std::atan2(camDirection.x, -camDirection.z);
            cameraEntity->rotation.x = glm::degrees(yaw);

            float xz = std::sqrt(camDirection.x * camDirection.x + camDirection.z * camDirection.z);
            float pitch = std::atan2(-camDirection.y, xz);
            cameraEntity->rotation.y = glm::degrees(pitch);
        }

        // Scroll zoom.
        if (Input()->GetScrollDown()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * 10.0f;
            }
        }
        if (Input()->GetScrollUp()) {
            if (!ImGui::IsMouseHoveringAnyWindow()) {
                glm::mat4 orientation = cameraEntity->GetCameraOrientation();
                glm::vec3 backward(orientation[0][2], orientation[1][2], orientation[2][2]);
                float speed = 10.0f * deltaTime * (glm::length(cameraEntity->position) / 10.0f);
                cameraEntity->position += speed * backward * -10.0f;
            }
        }

        if (Input()->Triggered(InputHandler::PLAYTEST) && Hymn().GetPath() != "")
            play = true;

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

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

        if (Hymn().GetPath() != "" && Input()->Triggered(InputHandler::SAVE) && Input()->Pressed(InputHandler::CONTROL))
            Save();

        if (play)
            Play();

    }

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

}

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

bool Editor::ReadyToClose() const {
    return savePromptAnswered;
}

void Editor::Close() {
    close = true;
}

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

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

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

void Editor::Play() {
    editorState = Hymn().ToJson();
    SetVisible(false);
    resourceView.HideEditors();
    resourceView.ResetScene();
    Managers().scriptManager->RegisterInput();
    Managers().scriptManager->BuildAllScripts();
}

void Editor::LoadEditorState() {
    Hymn().FromJson(editorState);
}

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()) {
        resourceView.ResetScene();
        Hymn().Clear();
        Resources().Clear();
        Hymn().world.CreateRoot();
        Hymn().SetPath(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER + hymn);
        resourceView.SetVisible(true);

        // Default scene.
        /// @todo Fix creating 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()) {
        resourceView.ResetScene();
        Hymn().Load(FileSystem::DataPath("Hymn to Beauty") + FileSystem::DELIMITER + "Hymns" + FileSystem::DELIMITER + hymn);
        Resources().Load();
        resourceView.SetVisible(true);
    }

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


<commit_before>#include "EffectMattias.h"
#include "lib/noise.h"
#include "lib/color.h"

// --- PerlinRainbow ---
PerlinRainbow::PerlinRainbow() :
	mCycle(0),
	mSaturation(0),
	mVerticalOffset(0)
{}

void PerlinRainbow::beginFrame(const FrameInfo& frame)
{
	const float speed2 = Input(Pot1);
	mSaturation = Input(Pot2);
	mCycle = fmodf(mCycle + frame.timeDelta * speed2, 2 * M_PI);
	mVerticalOffset += Input(Pot3) * 2.0f * frame.timeDelta;
}

void PerlinRainbow::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec3 point = pixel.point;
	point[1] += mVerticalOffset;

	float distance = len(pixel.point);
	float perlin3 = noise3(point);
	float wave1 = sinf(0.5 * distance - mCycle) + perlin3;
	float wave2 = sinf(3.0 * distance - mCycle) - perlin3;
	float wave3 = sinf(mCycle);

	hsv2rgb(rgb, wave1, mSaturation * wave3, wave2);
}

// --- ColorFlow ---
ColorFlow::ColorFlow() :
	mPerlinOctaves(1),
	mPosition{0}
{}

void ColorFlow::beginFrame(const FrameInfo& frame)
{
	if (InputClicked(JoyUp))
		mPerlinOctaves = min(5, mPerlinOctaves+1);
	if (InputClicked(JoyDown))
		mPerlinOctaves = max(0, mPerlinOctaves-1);

	for (int index = 0; index < 3; ++index)
		mPosition[index] += frame.timeDelta * (Input(static_cast<EInput>(index)) - 0.5f);
}

void ColorFlow::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	for (int index = 0; index < 3; ++index)
	{
		Vec3 perlinPoint(pixel.point);
		perlinPoint[1] += mPosition[index];
		rgb[index] = fbm_noise3(perlinPoint, mPerlinOctaves);
	}
}

// --- GlitterEffect ---
Glitter::Glitter() :
	mChance(0.5f),
	mCycle(0),
	mBrightness(0)
{}

void Glitter::beginFrame(const FrameInfo& frame)
{
	mChance = Input(Pot1) * RAND_MAX;
	mCycle += frame.timeDelta;
	mBrightness = 2.0f * Input(Pot2) + sin(mCycle) / 2.0f;
}

void Glitter::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	float value = static_cast<uint32_t>(rand()) <= mChance ? mBrightness : mBrightness - 0.2f;
	Vec3 perlinPoint(pixel.point);
	perlinPoint[1] += mCycle;
	rgb.MakeBlock(value * fbm_noise3(perlinPoint, 3));
}

// --- Water ---
Water::Water() :
	mTime(0),
	mIterations(5),
	mSize(0.5f),
	mGain(0.5f),
	mHue(0.5f)
{}

void Water::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	InputJoystick(mIterations, 1, 10);

	mSize = 1.0f + Input(Pot1) * 10.0f;
	mGain = 1.1f + Input(Pot2) / 2.0f;
	mHue =  Input(Pot3);
}

void Water::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Square();
	Vec2 p = location * mSize - Vec2().MakeBlock(2.0f * mSize);
	Vec2 i = p;
	float c = 1.0f;
	float intensity = 0.05f;

	for (int n = 0; n < mIterations; n++)
	{
		float time = mTime * (1.0f - (3.0f / static_cast<float>(n+1)));

		i = p + Vec2(cos(time - i[0]) + sin(time + i[1]),
		             sin(time - i[1]) + cos(time + i[0]));

		c += 1.0f / len(Vec2(p[0] / (sin(time + i[0]) / intensity),
		                     p[1] / (cos(time + i[1]) / intensity)));
	}

	c /= static_cast<float>(mIterations);
	c = mGain - sqrt(c);

	hsv2rgb(rgb, mHue, 0.5f, c*c*c*c);
	rgb += Vec3().MakeBlock(c*c*c*c);
}

// --- Bounce ---
Bounce::Bounce() :
	mTime(0),
	mSpread(0),
	mHue(0),
	mHueRange(0)
{}

void Bounce::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
}

float Ring(float time, const Vec2& pos)
{
	return sin( cos(time/4.0f) + 1.2f * cos(time) * len(pos) * 8.0f);
}

void Bounce::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Radial();

	rgb = Vec3(
		Ring(mTime,  location/1.2f),
		0.5f + Ring(mTime, location/1.3f - Vec2().MakeBlock(0.3f * sin(mTime * 0.9f))),
		0.3f + Ring(mTime, location/1.5f + Vec2().MakeBlock(0.2f * sin(mTime))));
}

// --- Swirl ---
Swirl::Swirl() :
	mTime(0),
	mGrain(0),
	mHue1(0),
	mHue2(0)
{}

void Swirl::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta / 10;
	mGrain = Input(Pot1);
	mHue1 = Input(Pot2);
	mHue2 = Input(Pot3);
}

void Swirl::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Radial();
	float x = len(location) * mGrain;
	float c = pow(2.0f * fabs((x - mTime) - floorf(x - mTime) - 0.5f), 2.0f);
	c = sin(atan2(location[1], location[0]) + c * M_PI * 4.0f);

	if (mHue1 == 0.0f && mHue2 == 0.0f)
		hsv2rgb(rgb, 1.0f, 0.0f, c);
	else if (mHue2 == 0.0f)
		hsv2rgb(rgb, mHue1, 0.5f, c);
	else
		hsv2rgb(rgb, mix(mHue1, mHue2, c), 0.5f, c + 0.3f);
}

// --- SinusSnake ---
SinusSnake::SinusSnake() :
	mTime(0)
{}

void SinusSnake::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
}

float Band(const Vec2& pos, float amplitude, float frequency, float time)
{
	const float scale = 0.8f;
	float wave = scale * amplitude * sin(1.0f * M_PI * frequency * pos[0] + time) / 5.0f;
	float light = Clip(amplitude * frequency * 0.02f,
	                   0.05f + 0.001f / scale,
			           50.0f) * scale / fabs(wave - pos[1] + 0.5f);
	return light;
}

void SinusSnake::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Square();
	Vec3 color = Vec3(1.1f + cos(mTime), sin(mTime)+1.2, sin(3.14 * mTime));

	const float time = mTime * 0.7f + location[0] * 10.0f;
	float spectrum = Band(location, 1.0f * cos(sin(3.14f * time)), sin(cos(3.14f * time)), mTime);

	rgb = color * spectrum;
}

// --- Fire ---
Fire::Fire() :
	mTime(0),
	mScale(0)
{}

void Fire::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	mScale = Input(Pot1) * 10.0f;
	hsv2rgb(mHighLight, Input(Pot2), 1.0f, 0.7f); // Hard left = red
	hsv2rgb(mLowLight,  Input(Pot3) + 1.0f / 6, 1.0f, 1.0f); // Hard left = yellow
}

float Rand(const Vec2& n)
{
	float dummyIntpart;
	float fracPart = abs(modf(cos(dot(n, Vec2(12.9898f, 4.1414f))) * 43758.5453f, &dummyIntpart));

//	cout << LVAL(fracPart) << endl;
	return fracPart;
}

float SmoothStep(float edge0, float edge1, float x)
{
	float t = Clip((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
	float ss =  t * t * (3.0f - 2.0f * t);
//	cout << LVAL(ss) << endl;
	return ss;
}

float Noise(const Vec2& n)
{
	Vec2 b(floor(n[0]), floor(n[1]));
	Vec2 f = n - b;
	f[0] =  SmoothStep(0, 1, f[0]);
	f[1] =  SmoothStep(0, 1, f[1]);

	float noise = Mix(
			Mix(Rand(b),
				Rand(b + vl_x),
				f[0]),
			Mix(Rand(b + vl_y),
				Rand(b + vl_1),
				f[0]),
			f[1]);
//	cout << LVAL(n) << LVAL(b) << LVAL(f) << LVAL(noise) << endl;
	return noise;
}

// Fractional Brownian Amplitude
float Fbm(Vec2 n)
{
	float total = 0.0f;
	float amplitude = 1.0f;
	for (int i = 0; i < 4; i++)
	{
		total += Noise(n) * amplitude;
		n += n;
		amplitude *= 0.5f;
	}
//	cout << LVAL(total) << endl;
	return total;
}

void Fire::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	// Colors
	static const Vec3 c1(0.0, 0.0, 0.1); // Black
//	static const Vec3 c2(0.7, 0.0, 0.0); // Light red
	static const Vec3 c3(0.2, 0.0, 0.0); // Dark red
//	static const Vec3 c4(1.0, 0.9, 0.0); // Yellow
	static const Vec3 c5(0.1, 0.1, 0.1); // Dark gray
	static const Vec3 c6(0.9, 0.9, 0.9); // Light gray

	Vec2 location = JellyPixel(pixel).Square();
	Vec2 pos(location[0] * mScale / 2.0f, location[1] * mScale); // Offset coordinates
	float q =     Fbm(pos + Vec2().MakeBlock(mTime * -0.1f)); // Noise offset for movement
	Vec2 r = Vec2(Fbm(pos + Vec2().MakeBlock(mTime *  0.7f + q - pos[0] - pos[1])),
			      Fbm(pos + Vec2().MakeBlock(mTime * -0.4f + q)));

//	cout << LVAL(location) << LVAL(pos) << LVAL(q) << LVAL(r);

	rgb = Mix(c1, mHighLight, Fbm(pos + r))
		+ Mix(c3, mLowLight, r[0])
		- Mix(c5, c6, r[1]);
//	cout << LVAL(rgb) << endl;

	rgb *= cos(M_PI/2 * location[1]); // Gradient towards dark top
//	cout << LVAL(rgb) << endl;
}

// --- Particles ---
Particles::Particles() :
	mTime(0),
	mCount(3),
	mSize(4),
	mHueRange(0.5f),
	mHueStart(0.5f)
{}

void Particles::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	InputJoystick(mCount, 1, kMaxCount);
	mSize = Input(Pot1) * 8.0f;
	mHueRange = Input(Pot2);
	mHueStart = Input(Pot3);
}

void Particles::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	static float sTimeFactor[kMaxCount] = {1.1, 1.7, 2.1, 2.5, 3.6, 4.2, 4.4};
	Vec2 location = JellyPixel(pixel).Radial() * 2.0f;
	for (int32_t index = 0; index < mCount; ++index)
	{
		Vec3 color;
		hsv2rgb(color, mHueStart + mHueRange / mCount * index, 0.7f, 1.0f);
		rgb += color * ((1.0f + mSize) / 20.0f / len(location - Vec2(
				sin(mTime) + sin(mTime * sTimeFactor[index]),
				cos(mTime) + cos(mTime * sTimeFactor[index]))));
	}
}
<commit_msg>Minor particle effect tweaks<commit_after>#include "EffectMattias.h"
#include "lib/noise.h"
#include "lib/color.h"

// --- PerlinRainbow ---
PerlinRainbow::PerlinRainbow() :
	mCycle(0),
	mSaturation(0),
	mVerticalOffset(0)
{}

void PerlinRainbow::beginFrame(const FrameInfo& frame)
{
	const float speed2 = Input(Pot1);
	mSaturation = Input(Pot2);
	mCycle = fmodf(mCycle + frame.timeDelta * speed2, 2 * M_PI);
	mVerticalOffset += Input(Pot3) * 2.0f * frame.timeDelta;
}

void PerlinRainbow::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec3 point = pixel.point;
	point[1] += mVerticalOffset;

	float distance = len(pixel.point);
	float perlin3 = noise3(point);
	float wave1 = sinf(0.5 * distance - mCycle) + perlin3;
	float wave2 = sinf(3.0 * distance - mCycle) - perlin3;
	float wave3 = sinf(mCycle);

	hsv2rgb(rgb, wave1, mSaturation * wave3, wave2);
}

// --- ColorFlow ---
ColorFlow::ColorFlow() :
	mPerlinOctaves(1),
	mPosition{0}
{}

void ColorFlow::beginFrame(const FrameInfo& frame)
{
	if (InputClicked(JoyUp))
		mPerlinOctaves = min(5, mPerlinOctaves+1);
	if (InputClicked(JoyDown))
		mPerlinOctaves = max(0, mPerlinOctaves-1);

	for (int index = 0; index < 3; ++index)
		mPosition[index] += frame.timeDelta * (Input(static_cast<EInput>(index)) - 0.5f);
}

void ColorFlow::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	for (int index = 0; index < 3; ++index)
	{
		Vec3 perlinPoint(pixel.point);
		perlinPoint[1] += mPosition[index];
		rgb[index] = fbm_noise3(perlinPoint, mPerlinOctaves);
	}
}

// --- GlitterEffect ---
Glitter::Glitter() :
	mChance(0.5f),
	mCycle(0),
	mBrightness(0)
{}

void Glitter::beginFrame(const FrameInfo& frame)
{
	mChance = Input(Pot1) * RAND_MAX;
	mCycle += frame.timeDelta;
	mBrightness = 2.0f * Input(Pot2) + sin(mCycle) / 2.0f;
}

void Glitter::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	float value = static_cast<uint32_t>(rand()) <= mChance ? mBrightness : mBrightness - 0.2f;
	Vec3 perlinPoint(pixel.point);
	perlinPoint[1] += mCycle;
	rgb.MakeBlock(value * fbm_noise3(perlinPoint, 3));
}

// --- Water ---
Water::Water() :
	mTime(0),
	mIterations(5),
	mSize(0.5f),
	mGain(0.5f),
	mHue(0.5f)
{}

void Water::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	InputJoystick(mIterations, 1, 10);

	mSize = 1.0f + Input(Pot1) * 10.0f;
	mGain = 1.1f + Input(Pot2) / 2.0f;
	mHue =  Input(Pot3);
}

void Water::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Square();
	Vec2 p = location * mSize - Vec2().MakeBlock(2.0f * mSize);
	Vec2 i = p;
	float c = 1.0f;
	float intensity = 0.05f;

	for (int n = 0; n < mIterations; n++)
	{
		float time = mTime * (1.0f - (3.0f / static_cast<float>(n+1)));

		i = p + Vec2(cos(time - i[0]) + sin(time + i[1]),
		             sin(time - i[1]) + cos(time + i[0]));

		c += 1.0f / len(Vec2(p[0] / (sin(time + i[0]) / intensity),
		                     p[1] / (cos(time + i[1]) / intensity)));
	}

	c /= static_cast<float>(mIterations);
	c = mGain - sqrt(c);

	hsv2rgb(rgb, mHue, 0.5f, c*c*c*c);
	rgb += Vec3().MakeBlock(c*c*c*c);
}

// --- Bounce ---
Bounce::Bounce() :
	mTime(0),
	mSpread(0),
	mHue(0),
	mHueRange(0)
{}

void Bounce::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
}

float Ring(float time, const Vec2& pos)
{
	return sin( cos(time/4.0f) + 1.2f * cos(time) * len(pos) * 8.0f);
}

void Bounce::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Radial();

	rgb = Vec3(
		Ring(mTime,  location/1.2f),
		0.5f + Ring(mTime, location/1.3f - Vec2().MakeBlock(0.3f * sin(mTime * 0.9f))),
		0.3f + Ring(mTime, location/1.5f + Vec2().MakeBlock(0.2f * sin(mTime))));
}

// --- Swirl ---
Swirl::Swirl() :
	mTime(0),
	mGrain(0),
	mHue1(0),
	mHue2(0)
{}

void Swirl::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta / 10;
	mGrain = Input(Pot1);
	mHue1 = Input(Pot2);
	mHue2 = Input(Pot3);
}

void Swirl::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Radial();
	float x = len(location) * mGrain;
	float c = pow(2.0f * fabs((x - mTime) - floorf(x - mTime) - 0.5f), 2.0f);
	c = sin(atan2(location[1], location[0]) + c * M_PI * 4.0f);

	if (mHue1 == 0.0f && mHue2 == 0.0f)
		hsv2rgb(rgb, 1.0f, 0.0f, c);
	else if (mHue2 == 0.0f)
		hsv2rgb(rgb, mHue1, 0.5f, c);
	else
		hsv2rgb(rgb, mix(mHue1, mHue2, c), 0.5f, c + 0.3f);
}

// --- SinusSnake ---
SinusSnake::SinusSnake() :
	mTime(0)
{}

void SinusSnake::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
}

float Band(const Vec2& pos, float amplitude, float frequency, float time)
{
	const float scale = 0.8f;
	float wave = scale * amplitude * sin(1.0f * M_PI * frequency * pos[0] + time) / 5.0f;
	float light = Clip(amplitude * frequency * 0.02f,
	                   0.05f + 0.001f / scale,
			           50.0f) * scale / fabs(wave - pos[1] + 0.5f);
	return light;
}

void SinusSnake::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	Vec2 location = JellyPixel(pixel).Square();
	Vec3 color = Vec3(1.1f + cos(mTime), sin(mTime)+1.2, sin(3.14 * mTime));

	const float time = mTime * 0.7f + location[0] * 10.0f;
	float spectrum = Band(location, 1.0f * cos(sin(3.14f * time)), sin(cos(3.14f * time)), mTime);

	rgb = color * spectrum;
}

// --- Fire ---
Fire::Fire() :
	mTime(0),
	mScale(0)
{}

void Fire::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	mScale = Input(Pot1) * 10.0f;
	hsv2rgb(mHighLight, Input(Pot2), 1.0f, 0.7f); // Hard left = red
	hsv2rgb(mLowLight,  Input(Pot3) + 1.0f / 6, 1.0f, 1.0f); // Hard left = yellow
}

float Rand(const Vec2& n)
{
	float dummyIntpart;
	float fracPart = abs(modf(cos(dot(n, Vec2(12.9898f, 4.1414f))) * 43758.5453f, &dummyIntpart));

//	cout << LVAL(fracPart) << endl;
	return fracPart;
}

float SmoothStep(float edge0, float edge1, float x)
{
	float t = Clip((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
	float ss =  t * t * (3.0f - 2.0f * t);
//	cout << LVAL(ss) << endl;
	return ss;
}

float Noise(const Vec2& n)
{
	Vec2 b(floor(n[0]), floor(n[1]));
	Vec2 f = n - b;
	f[0] =  SmoothStep(0, 1, f[0]);
	f[1] =  SmoothStep(0, 1, f[1]);

	float noise = Mix(
			Mix(Rand(b),
				Rand(b + vl_x),
				f[0]),
			Mix(Rand(b + vl_y),
				Rand(b + vl_1),
				f[0]),
			f[1]);
//	cout << LVAL(n) << LVAL(b) << LVAL(f) << LVAL(noise) << endl;
	return noise;
}

// Fractional Brownian Amplitude
float Fbm(Vec2 n)
{
	float total = 0.0f;
	float amplitude = 1.0f;
	for (int i = 0; i < 4; i++)
	{
		total += Noise(n) * amplitude;
		n += n;
		amplitude *= 0.5f;
	}
//	cout << LVAL(total) << endl;
	return total;
}

void Fire::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	// Colors
	static const Vec3 c1(0.0, 0.0, 0.1); // Black
//	static const Vec3 c2(0.7, 0.0, 0.0); // Light red
	static const Vec3 c3(0.2, 0.0, 0.0); // Dark red
//	static const Vec3 c4(1.0, 0.9, 0.0); // Yellow
	static const Vec3 c5(0.1, 0.1, 0.1); // Dark gray
	static const Vec3 c6(0.9, 0.9, 0.9); // Light gray

	Vec2 location = JellyPixel(pixel).Square();
	Vec2 pos(location[0] * mScale / 2.0f, location[1] * mScale); // Offset coordinates
	float q =     Fbm(pos + Vec2().MakeBlock(mTime * -0.1f)); // Noise offset for movement
	Vec2 r = Vec2(Fbm(pos + Vec2().MakeBlock(mTime *  0.7f + q - pos[0] - pos[1])),
			      Fbm(pos + Vec2().MakeBlock(mTime * -0.4f + q)));

//	cout << LVAL(location) << LVAL(pos) << LVAL(q) << LVAL(r);

	rgb = Mix(c1, mHighLight, Fbm(pos + r))
		+ Mix(c3, mLowLight, r[0])
		- Mix(c5, c6, r[1]);
//	cout << LVAL(rgb) << endl;

	rgb *= cos(M_PI/2 * location[1]); // Gradient towards dark top
//	cout << LVAL(rgb) << endl;
}

// --- Particles ---
Particles::Particles() :
	mTime(0),
	mCount(3),
	mSize(4),
	mHueRange(0.5f),
	mHueStart(0.5f)
{}

void Particles::beginFrame(const FrameInfo& frame)
{
	mTime += frame.timeDelta;
	InputJoystick(mCount, 1, kMaxCount);
	mSize = Input(Pot1) * 8.0f;
	mHueStart = Input(Pot2);
	mHueRange = Input(Pot3);
}

void Particles::shader(Vec3& rgb, const PixelInfo& pixel) const
{
	static float sTimeFactor[kMaxCount] = {1.1, 1.7, 2.1, 2.5, 3.6, 4.2, 4.4};
	Vec2 location = JellyPixel(pixel).Radial() * 2.1f;
	for (int32_t index = 0; index < mCount; ++index)
	{
		Vec3 color;
		hsv2rgb(color, mHueStart + mHueRange / mCount * index, 0.7f, 1.0f);
		rgb += color * ((1.0f + mSize + index / 10.0f ) / 20.0f / len(location - Vec2(
				sin(mTime) + sin(mTime * sTimeFactor[index]),
				cos(mTime) + cos(mTime * sTimeFactor[index]))));
	}
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include <string>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "LexerModule.h"
#include "Catalogue.h"
#include "ExternalLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerManager *LexerManager::theInstance = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
	fneFactory = fFactory;
	fnFactory = fFactory(index);
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(const char *ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	lib = DynamicLibrary::Load(ModuleName);
	if (lib->IsValid()) {
		m_sModuleName = ModuleName;
		//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
			//ExtLexerFunction fnLexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
			//ExtFoldFunction fnFolder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");
			GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
				Catalogue::AddLexerModule(lex);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here.
				lex->SetExternal(fnFactory, i);
			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
	delete lib;
}

void LexerLibrary::Release() {
	//TODO maintain a list of lexers created, and delete them!
	LexerMinder *lm;
	LexerMinder *lmNext;
	lm = first;
	while (NULL != lm) {
		lmNext = lm->next;
		delete lm->self;
		delete lm;
		lm = lmNext;
	}

	first = NULL;
	last = NULL;
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
	if (!theInstance)
		theInstance = new LexerManager;
	return theInstance;
}

/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
	delete theInstance;
	theInstance = NULL;
}

/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
	first = NULL;
	last = NULL;
}

LexerManager::~LexerManager() {
	Clear();
}

void LexerManager::Load(const char *path) {
	LoadLexerLibrary(path);
}

void LexerManager::LoadLexerLibrary(const char *module) {
	for (LexerLibrary *ll = first; ll; ll= ll->next) {
		if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
			return;
	}
	LexerLibrary *lib = new LexerLibrary(module);
	if (NULL != first) {
		last->next = lib;
		last = lib;
	} else {
		first = lib;
		last = lib;
	}
}

void LexerManager::Clear() {
	if (NULL != first) {
		LexerLibrary *cur = first;
		LexerLibrary *next;
		while (cur) {
			next = cur->next;
			delete cur;
			cur = next;
		}
		first = NULL;
		last = NULL;
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

LMMinder::~LMMinder() {
	LexerManager::DeleteInstance();
}

LMMinder minder;
<commit_msg>Removed dead comments.<commit_after>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include <string>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "LexerModule.h"
#include "Catalogue.h"
#include "ExternalLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerManager *LexerManager::theInstance = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
	fneFactory = fFactory;
	fnFactory = fFactory(index);
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(const char *ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	lib = DynamicLibrary::Load(ModuleName);
	if (lib->IsValid()) {
		m_sModuleName = ModuleName;
		//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
			GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
				Catalogue::AddLexerModule(lex);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here.
				lex->SetExternal(fnFactory, i);
			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
	delete lib;
}

void LexerLibrary::Release() {
	LexerMinder *lm;
	LexerMinder *lmNext;
	lm = first;
	while (NULL != lm) {
		lmNext = lm->next;
		delete lm->self;
		delete lm;
		lm = lmNext;
	}

	first = NULL;
	last = NULL;
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
	if (!theInstance)
		theInstance = new LexerManager;
	return theInstance;
}

/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
	delete theInstance;
	theInstance = NULL;
}

/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
	first = NULL;
	last = NULL;
}

LexerManager::~LexerManager() {
	Clear();
}

void LexerManager::Load(const char *path) {
	LoadLexerLibrary(path);
}

void LexerManager::LoadLexerLibrary(const char *module) {
	for (LexerLibrary *ll = first; ll; ll= ll->next) {
		if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
			return;
	}
	LexerLibrary *lib = new LexerLibrary(module);
	if (NULL != first) {
		last->next = lib;
		last = lib;
	} else {
		first = lib;
		last = lib;
	}
}

void LexerManager::Clear() {
	if (NULL != first) {
		LexerLibrary *cur = first;
		LexerLibrary *next;
		while (cur) {
			next = cur->next;
			delete cur;
			cur = next;
		}
		first = NULL;
		last = NULL;
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

LMMinder::~LMMinder() {
	LexerManager::DeleteInstance();
}

LMMinder minder;
<|endoftext|>