diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Button.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Button.cpp index a3bf855..41d76e8 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Button.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Button.cpp @@ -3,7 +3,7 @@ using namespace glm; using namespace std; -Button::Button(vec3 color, float x, float y, float width, float height, string str, Mesh* mesh, Shader& shader, Shader& textShader, Engine& engine,function action):DrawableObject(shader,color),textShader(textShader),engine(engine),mesh(mesh),text(nullptr),action(action) { +Button::Button(vec3 color, float x, float y, float width, float height, string str, Mesh* mesh, Engine& engine,function action):DrawableObject(engine.getShader(),color),textShader(engine.getTextShader()),engine(engine),mesh(mesh),text(nullptr),action(action) { setupText(str, x, y, width, height); setLocation(vec3(x, y, 6.1)); setScale(vec3(width, height, 1)); diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Button.h b/SequenceAlignmentVis/SequenceAlignmentVis/Button.h index 851947e..038789e 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Button.h +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Button.h @@ -8,7 +8,7 @@ class Button :public DrawableObject { public: - Button(glm::vec3 color, float x,float y, float width, float height,std::string str,Mesh* mesh, Shader& shader,Shader& textShader, Engine& engine,std::function action); + Button(glm::vec3 color, float x,float y, float width, float height,std::string str,Mesh* mesh,Engine& engine,std::function action); Button(const Button& other); virtual ~Button(); void onClick(); diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Engine.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Engine.cpp index 8120e11..a30febc 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Engine.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Engine.cpp @@ -1,6 +1,8 @@ #include #include "Engine.h" #include "UserInterface.h" +#include "MessageBox.h" + using namespace glm; using namespace std; @@ -38,11 +40,17 @@ void Engine::run() { glReadPixels(mouse.xPos, mouse.yPos, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); int ind = getId(vec3(data[0], data[1], data[2])); DrawableObject* selObj = currScene->getSelectedObj(); - if (selObj != nullptr) { selObj->onRelease(); } if (ind >= 0) { + if (selObj != nullptr && selObj->getId()!=ind) { + printf("ind:%d\nselObj:%d\n", ind, selObj->getId()); + selObj->onRelease(); + } currScene->getObject(ind).onClick(); } else { + if (selObj != nullptr) { + selObj->onRelease(); + } currScene->onClickBackground(); } } @@ -55,6 +63,15 @@ void Engine::run() { } } +void Engine::showAlert(string title, string text) { + if (currScene == nullptr) { return; } + UI::Messagebox m(vec3(0.8f, 0.2f, 0.2f), vec3(0.0f, 0.0f, 0.0f), 6.0f, 8.0f, 1.0f, 1.0f, title, text, *this); + m.setOnDismiss([](Engine& e) {e.cont(); }); + int ind = currScene->addObject(&m); + currScene->setSelectedObj(&(currScene->getObject(ind))); + halt(); +} + void Engine::clearScene() { if (currScene != nullptr) { delete(currScene); @@ -81,6 +98,7 @@ void Engine::clearAdditionalFunctions() { } void Engine::callAdditionalFunctions() { + if (!runAdditionalFunctions) { return; } for (unsigned int i = 0; i < additionalFunctions.size(); ++i) { bool del = !additionalFunctions[i](); if (del) { diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Engine.h b/SequenceAlignmentVis/SequenceAlignmentVis/Engine.h index 56da025..50a5a77 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Engine.h +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Engine.h @@ -14,7 +14,10 @@ class Engine { virtual ~Engine(); void run(); void changeScene(Scene* newScene); + void showAlert(std::string title, std::string text); + inline void halt() { runAdditionalFunctions = false; } + inline void cont() { runAdditionalFunctions = true; } inline void addAdditionalFunction(std::function func) { additionalFunctions.push_back(func); } inline Display& getDisplay() { return d; } inline Shader& getShader() { return *shader; } @@ -25,6 +28,7 @@ class Engine { mutable std::mutex mtx; std::thread::id drawingThread; std::vector> additionalFunctions; + bool runAdditionalFunctions = true; bool isRunning = false; Scene* currScene; Shader* shader; diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.cpp new file mode 100644 index 0000000..707f212 --- /dev/null +++ b/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.cpp @@ -0,0 +1,135 @@ +#include "Messagebox.h" +#include "Engine.h" +#include + +const float Z_COORDINATE = 4.0f; +const float TITLE_SIZE_FACTOR = 1.6f; +const float TEXT_SIZE_FACTOR = 0.8f; +const int LETTERS_PER_LINE = 10; +const float Z_OFFSET = -0.1f; + +using namespace glm; +using namespace std; + +namespace UI { + Messagebox::Messagebox(vec3 color, vec3 textColor, float width, float height, float x, float y, string title, string text, Engine& e) : DrawableObject(e.getShader(), color), textShader(e.getTextShader()), textColor(textColor), width(width), height(height), x(x), y(y),e(e){ + setupText(title, text); + createMesh(); + } + + Messagebox::Messagebox(const Messagebox& other) : DrawableObject(other), textShader(other.textShader), textColor(other.textColor), width(other.width), height(other.height), x(other.x), y(other.y),onDismiss(other.onDismiss),e(other.e){ + copyText(other); + createMesh(); + } + + Messagebox::~Messagebox() { + clear(); + } + + void Messagebox::draw(Shader* shader, mat4 VP) { + if (titleInd == -1) { + titleInd = scn->addObject(title); + } + for (unsigned int i = 0; i < text.size(); ++i) { + if (textInd[i] == -1) { + textInd[i] = scn->addObject(text[i]); + } + } + Shader& s = shader != nullptr ? *shader : defaultShader; + glm::mat4 MVP = VP*modelMatrix; + glm::vec3 id = getIdVec(); + s.Bind(); + s.Update(MVP, modelMatrix); + s.setColor(color, id); + if (mesh != nullptr) { + mesh->Draw(); + } + + } + + DrawableObject* Messagebox::clone() { + return new Messagebox(*this); + } + + void Messagebox::onClick() { + scn->setSelectedObj(this); + } + + void Messagebox::onRelease() { + onDismiss(e); + scn->removeDrawable(getId()); + } + + void Messagebox::onKeyClick(int key) { + + } + + void Messagebox::setupText(string title, string text) { + float titleSize = TITLE_SIZE_FACTOR*(width / title.size()); + float textSize = 2*(width / LETTERS_PER_LINE); + vec3 titleLocation(x+width/2-titleSize, y + height / 2- titleSize /2, Z_COORDINATE); + this->title = new Text(titleLocation, textColor, titleSize, title, textShader); + this->title->setZOffset(Z_OFFSET); + titleInd = -1; + float currY = y + height / 2 - 2 * titleSize; + while (text.size() > 0) { + string prefix = text.substr(0, LETTERS_PER_LINE); + vec3 textLocation(x + width / 2 - textSize, currY, Z_COORDINATE); + this->text.push_back(new Text(textLocation, textColor, textSize, prefix, textShader)); + this->text[this->text.size() - 1]->setZOffset(Z_OFFSET); + this->textInd.push_back(-1); + if (LETTERS_PER_LINE >= text.size()) { + text = ""; + }else { + text = text.substr(LETTERS_PER_LINE, text.size()); + } + currY = currY - textSize; + } + } + + void Messagebox::createMesh() { + Vertex vertices[] = + { + Vertex(glm::vec3(x + width / 2.0f, y - height / 2, Z_COORDINATE), vec2(0,0), glm::vec3(0, 0, -1),color), + Vertex(glm::vec3(x - width / 2.0f, y - height / 2, Z_COORDINATE), vec2(1,0), glm::vec3(0, 0, -1),color), + Vertex(glm::vec3(x - width / 2.0f, y + height / 2, Z_COORDINATE), vec2(1,1), glm::vec3(0, 0, -1),color), + Vertex(glm::vec3(x + width / 2.0f, y + height / 2, Z_COORDINATE), vec2(0,1), glm::vec3(0, 0, -1),color), + }; + + unsigned int indices[] = { 3, 0, 1, + 3, 1, 2 + }; + mesh = new Mesh(vertices, sizeof(vertices) / sizeof(vertices[0]), indices, sizeof(indices) / sizeof(indices[0])); + } + + void Messagebox::copyText(const Messagebox& other) { + this->title = static_cast(other.title->clone()); + titleInd = -1; + for (auto it = other.text.begin(); it != other.text.end(); ++it) { + text.push_back(static_cast((*it)->clone())); + textInd.push_back(-1); + } + } + + void Messagebox::clear() { + if (mesh != nullptr) { + delete(mesh); + mesh = nullptr; + } + if (title != nullptr) { + delete(title); + if (titleInd != -1) { + scn->removeDrawable(titleInd); + } + } + for (unsigned int i = 0; i < text.size(); ++i) { + Text* curr = text[i]; + if (curr != nullptr) { + delete(curr); + if (textInd[i] != -1) { + scn->removeDrawable(textInd[i]); + } + } + } + } +} \ No newline at end of file diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.h b/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.h new file mode 100644 index 0000000..00e6d61 --- /dev/null +++ b/SequenceAlignmentVis/SequenceAlignmentVis/MessageBox.h @@ -0,0 +1,42 @@ +#ifndef MESSAGE_BOX_H_ +#define MESSAGE_BOX_H_ + +#include "Object.h" +#include + +class Text; +class Engine; + +namespace UI { + class Messagebox :public DrawableObject { + public: + Messagebox(glm::vec3 color, glm::vec3 textColor, float width, float height, float x, float y, std::string title, std::string text, Engine& e); + Messagebox(const Messagebox& other); + virtual ~Messagebox(); + + void draw(Shader* shader, glm::mat4 vp); + DrawableObject* clone(); + void onClick(); + void onRelease(); + void onKeyClick(int key); + + void setOnDismiss(std::function callback) { onDismiss = callback; } + private: + void setupText(std::string title, std::string text); + void createMesh(); + void copyText(const Messagebox& other); + void clear(); + float width, height, x, y; + glm::vec3 textColor; + Engine& e; + Shader& textShader; + Mesh* mesh; + Text* title; + int titleInd; + std::vector text; + std::vector textInd; + std::function onDismiss = [](Engine&e) {}; + }; +} + +#endif \ No newline at end of file diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Object.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Object.cpp index bb9ea88..519b507 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Object.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Object.cpp @@ -1,11 +1,12 @@ #include "Object.h" #include "Scene.h" + DrawableObject::DrawableObject(Shader& defaultShader, glm::vec3 color) :id(-1), defaultShader(defaultShader), color(color){ } glm::vec3 DrawableObject::getIdVec() { - int tempId = getId(); + int tempId = getId()+1; int ri = tempId % 256; tempId = tempId / 256; int gi = tempId % 256; diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Object.h b/SequenceAlignmentVis/SequenceAlignmentVis/Object.h index ea9f638..419082b 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Object.h +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Object.h @@ -16,12 +16,16 @@ class DrawableObject { DrawableObject(Shader& defaultShader, glm::vec3 color); DrawableObject(const DrawableObject& other) :defaultShader(other.defaultShader), color(other.color), location(other.location), rotate(other.rotate),scale(other.scale), modelMatrix(other.modelMatrix) { } + virtual ~DrawableObject(){} + virtual void draw(Shader* shader, glm::mat4 vp) = 0; virtual DrawableObject* clone() = 0; virtual void onClick() = 0; virtual void onRelease() = 0; virtual void onKeyClick(int key) = 0; + + inline void setId(int id) { this->id = id; } inline void setLocation(glm::vec3 location) { this->location = location; updateModelMatrix(); } inline void setRotate(glm::vec3 axis, float deg) { this->rotate = glm::rotate(rotate, deg, axis); updateModelMatrix(); } @@ -50,7 +54,7 @@ class Object3D:public DrawableObject { public: Object3D(glm::vec3 color,Mesh* mesh,Shader& shader); Object3D(const Object3D& other); - ~Object3D(); + virtual ~Object3D(); inline void setTexture(Texture* tex) { this->tex = tex; } inline void resetTexture() { this->tex = nullptr; } diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/RadioButton.h b/SequenceAlignmentVis/SequenceAlignmentVis/RadioButton.h index 634641b..3da1e20 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/RadioButton.h +++ b/SequenceAlignmentVis/SequenceAlignmentVis/RadioButton.h @@ -17,7 +17,7 @@ class RadioButton :public DrawableObject { public: RadioButton(float x, float y, std::string str, Shader& shader, T value); RadioButton(const RadioButton& other); - ~RadioButton(); + virtual ~RadioButton(); void draw(Shader* shader, glm::mat4 vp); DrawableObject* clone(); void onClick(); diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Scene.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Scene.cpp index 72892ea..3e2050a 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Scene.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Scene.cpp @@ -133,8 +133,6 @@ void Scene::onClickBackground() { } int Scene::addObject(DrawableObject* object) { - bool shouldLock = lockingThread != std::this_thread::get_id(); - if (shouldLock) { mtx.lock(); } DrawableObject* objectToAdd = object->clone(); objectToAdd->setScene(this); bool text = &object->getDefaultShader() == textShader; @@ -149,9 +147,8 @@ int Scene::addObject(DrawableObject* object) { else { list.push_back(objectToAdd); } - objectToAdd->setId(!text ? (ind+1) : -1); + objectToAdd->setId(!text ? (ind) : -1); int ans = text ? -1 - ind : ind; - if (shouldLock) { mtx.unlock(); } return ans; } @@ -167,18 +164,16 @@ void Scene::clearFontTexture() { } void Scene::removeDrawable(int ind) { - bool shouldLock = lockingThread != std::this_thread::get_id(); - if (shouldLock) { mtx.lock(); } vector& list = ind >= 0 ? objects : textObjects; int corrInd = ind >= 0 ? ind : -ind - 1; vector& freeIndices = ind >= 0 ? freeIndicesObjects : freeIndicesTextObjects; if (corrInd >= (int)list.size()) { return; } if (list[corrInd] != nullptr) { + printf("deleting\n"); delete(list[corrInd]); list[corrInd] = nullptr; freeIndices.push_back(corrInd); } - if (shouldLock) { mtx.unlock(); } } DrawableObject& Scene::getObject(int ind) { @@ -346,6 +341,6 @@ void Menu::addButton(float x, float y, float width, float height, string text, f } void Menu::addButton(vec3 color,float x, float y, float width, float height, string text, function action) { - Button button(color, x, y, width, height, text,cubeMesh,engine.getShader(), engine.getTextShader(), engine, action); + Button button(color, x, y, width, height, text,cubeMesh,engine, action); addObject(&button); } \ No newline at end of file diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj b/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj index 2c25372..6150ce1 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj +++ b/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj @@ -122,6 +122,7 @@ + @@ -143,6 +144,7 @@ + diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj.filters b/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj.filters index 60819cd..c376edc 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj.filters +++ b/SequenceAlignmentVis/SequenceAlignmentVis/SequenceAlignmentVis.vcxproj.filters @@ -90,6 +90,9 @@ Header Files\UI + + Header Files\UI + @@ -149,5 +152,8 @@ Source Files\UI + + Source Files\UI + \ No newline at end of file diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Textbox.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Textbox.cpp index 87e7209..b1e2392 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Textbox.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Textbox.cpp @@ -91,7 +91,6 @@ void TextBox::createMesh() { 3, 1, 2 }; mesh = new Mesh(vertices, sizeof(vertices) / sizeof(vertices[0]), indices, sizeof(indices) / sizeof(indices[0])); - } void TextBox::clearText() { diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.cpp b/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.cpp index 38e228c..121522d 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.cpp +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.cpp @@ -20,6 +20,7 @@ const vec3 GREEN_COLOR = vec3(0.2f, 0.8f, 0.2f); const vec3 BLUE_COLOR = vec3(0.1f, 0.1f, 1.0f); const vec3 BLACK_COLOR = vec3(0.0f, 0.0f, 0.0f); const vec3 GRAY_COLOR = vec3(0.8, 0.8, 0.9); +const vec3 RED_COLOR = vec3(1.0f, 0.0f, 0.0f); const float INIT_X = 5.0f; const float INIT_Y = 5.0f; @@ -125,8 +126,13 @@ bool Visualizer::createScene() { auto func = [this](Engine& e) { stop = !stop; }; - Button b(GREEN_COLOR, 8.0f, 8.0f, 2.0f, 1.0f, "Stop", scene->getCubeMesh(), engine.getShader(), engine.getTextShader(), engine, func); + Button b(GREEN_COLOR, 2.0f, 8.0f, 2.0f, 1.0f, "Stop", scene->getCubeMesh(),engine, func); + Button exit(RED_COLOR, 8.0f, 8.0f, 2.0f, 1.0f, "Exit", scene->getCubeMesh(), engine, [this](Engine& e) { + e.changeScene(prevScene); + delete(this); + }); scene->addObject(&b); + scene->addObject(&exit); if (alignerptr->strings.size() < 2 || alignerptr->strings.size() > 3) { return false; } if (alignerptr->strings.size() == 2) { create2DScene(); diff --git a/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.h b/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.h index 7ac9627..9acd7b8 100644 --- a/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.h +++ b/SequenceAlignmentVis/SequenceAlignmentVis/Visualizer.h @@ -21,7 +21,7 @@ class Visualizer { void globalAlignmentInit(); void freeEndsInit(); void localAlignmentInit(); - + void setPrevScene(Scene* prevScene) { this->prevScene = prevScene; } void step(); private: bool stop = false; @@ -44,6 +44,7 @@ class Visualizer { Aligner* alignerptr; Engine& engine; FullDPTable* sceneTable; + Scene* prevScene; Scene* scene; };