ImGui ya funciona, a medio camino de la actividad 3

parent 0e1e76a6
//
// Created by pete on 18/09/25.
//
#include "BackgroundWindow.h"
#include <glm/vec3.hpp>
BackgroundWindow::BackgroundWindow() {
color_fondo = glm::vec3(0.6f, 0.6f, 0.6f);
}
void BackgroundWindow::warnListeners() {
glm::vec3 aux = color_fondo;
for(int i = 0; i<listeners.size(); i++) {
listeners[i]->wakeUp(WindowType::Background, &(aux[0]));
}
}
void BackgroundWindow::render() {
// TODO: Implementar
}
//
// Created by pete on 18/09/25.
//
#ifndef BACKGROUNDWINDOW_H
#define BACKGROUNDWINDOW_H
#include <glm/vec3.hpp>
#include "GuiElement.h"
class BackgroundWindow: public GuiElement {
glm::vec3 color_fondo;
public:
BackgroundWindow();
virtual ~BackgroundWindow() = default;
void warnListeners() override;
void render() override;
};
#endif //BACKGROUNDWINDOW_H
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <imgui_impl_opengl3.h> #include <imgui_impl_opengl3.h>
PAG::GUI* PAG::GUI::instancia = nullptr; PAG::GUI* PAG::GUI::instancia = nullptr;
ImVec4 PAG::GUI::color_fondo = ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
PAG::GUI::GUI() { } PAG::GUI::GUI() { }
...@@ -59,15 +60,14 @@ void PAG::GUI::prepararNuevoFrame() { ...@@ -59,15 +60,14 @@ void PAG::GUI::prepararNuevoFrame() {
// Aquí van las instrucciones de dibujado de ventanas // Aquí van las instrucciones de dibujado de ventanas
ImGui::SetNextWindowPos( ImVec2(10, 10), ImGuiCond_Once ); ImGui::SetNextWindowPos( ImVec2(10, 10), ImGuiCond_Once );
if( ImGui::Begin("Mensajes") ) { if( ImGui::Begin("Selector de color") ) {
// La ventana está desplegada // La ventana está desplegada
ImGui::SetWindowFontScale ( 1.0f ); // Escalamos el texto si fuera necesario ImGui::SetWindowFontScale ( 1.0f ); // Escalamos el texto si fuera necesario
// Pintamos los controles // Pintamos los controles
ImGui::ColorPicker3("Selector de color", (float*)&color_fondo, ImGuiColorEditFlags_PickerHueWheel);
} }
// Si la ventana no está desplegada, Begin devuelve false // Si la ventana no está desplegada, Begin devuelve false
ImGui::End (); ImGui::End ();
} }
/** /**
......
...@@ -23,6 +23,7 @@ namespace PAG { ...@@ -23,6 +23,7 @@ namespace PAG {
*/ */
class GUI { class GUI {
static GUI* instancia; static GUI* instancia;
static ImVec4 color_fondo;
GUI(); GUI();
public: public:
......
//
// Created by pete on 18/09/25.
//
#include "GuiElement.h"
GuiElement::GuiElement() {
listeners = std::vector<Listener*>();
}
void GuiElement::addListener(Listener *listener) {
listeners.push_back(listener);
}
//
// Created by pete on 18/09/25.
//
#ifndef GUIELEMENT_H
#define GUIELEMENT_H
#include <vector>
#include "Listener.h"
class GuiElement {
protected:
std::vector<Listener*> listeners;
public:
GuiElement();
virtual ~GuiElement() = default;
void addListener(Listener* listener);
virtual void warnListeners() = 0;
virtual void render() = 0;
};
#endif //GUIELEMENT_H
//
// Created by pete on 18/09/25.
//
#ifndef LISTENER_H
#define LISTENER_H
// TODO: Cuando el profesor añada el showAxis, cambiar Background a 2
enum WindowType {
Background = 1
};
class Listener {
public:
Listener() = default;
virtual ~Listener() = default;
virtual void wakeUp(WindowType t, ...) = 0;
};
#endif //LISTENER_H
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
#include <GL/gl.h> #include <GL/gl.h>
#include "Renderer.h" #include "Renderer.h"
#include <cstdarg>
PAG::Renderer* PAG::Renderer::instancia = nullptr; PAG::Renderer* PAG::Renderer::instancia = nullptr;
double PAG::Renderer::yPos = 0.6;
PAG::Renderer::Renderer() { } PAG::Renderer::Renderer() { }
...@@ -28,6 +30,21 @@ PAG::Renderer& PAG::Renderer::getInstancia() { ...@@ -28,6 +30,21 @@ PAG::Renderer& PAG::Renderer::getInstancia() {
} }
/** /**
* @brief Función a llamar cuando se inicia la aplicación.
*
* Inicializa el color de fondo y activa el Depth Test.
*/
void PAG::Renderer::inicializar() {
// - Establecemos un gris medio como color con el que se borrará el frame buffer.
// No tiene por qué ejecutarse en cada paso por el ciclo de eventos.
glClearColor ( yPos, yPos, yPos, 1.0 );
// - Le decimos a OpenGL que tenga en cuenta la profundidad a la hora de dibujar.
// No tiene por qué ejecutarse en cada paso por el ciclo de eventos.
glEnable ( GL_DEPTH_TEST );
}
/**
* @brief Función a llamar cuando se necesite refrescar la ventana. * @brief Función a llamar cuando se necesite refrescar la ventana.
* *
* Esta función limpia los buffers de color y de profundidad de * Esta función limpia los buffers de color y de profundidad de
...@@ -35,6 +52,7 @@ PAG::Renderer& PAG::Renderer::getInstancia() { ...@@ -35,6 +52,7 @@ PAG::Renderer& PAG::Renderer::getInstancia() {
*/ */
void PAG::Renderer::refrescar() { void PAG::Renderer::refrescar() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} }
/** /**
...@@ -45,3 +63,31 @@ void PAG::Renderer::refrescar() { ...@@ -45,3 +63,31 @@ void PAG::Renderer::refrescar() {
void PAG::Renderer::refrescar_tamanio_framebuffer(int width, int height) { void PAG::Renderer::refrescar_tamanio_framebuffer(int width, int height) {
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
} }
/**
* @brief Función a llamar cuando se realiza scroll con la rueda del ratón.
*
* Modifica el color de fondo. NO REFRESCA LA PANTALLA.
*
* @param yoffset
*/
void PAG::Renderer::scroll_callback(double yoffset) {
yPos += yoffset*0.1;
if(yPos > 1) yPos = 1;
else if(yPos < 0) yPos = 0;
glClearColor(yPos, yPos, yPos, 1.0);
}
void PAG::Renderer::wakeUp(WindowType t, ...) {
switch (t) {
case Background: {
std::va_list args;
va_start(args, t);
color_fondo = *(va_arg(args, glm::vec3*));
va_end(args);
break;
}
}
}
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
#ifndef PAG_P1_RENDERER_H #ifndef PAG_P1_RENDERER_H
#define PAG_P1_RENDERER_H #define PAG_P1_RENDERER_H
#include "Listener.h"
#include <glm/vec3.hpp>
/** /**
* Espacio de nombres para las prácticas de Programación de Aplicaciones * Espacio de nombres para las prácticas de Programación de Aplicaciones
...@@ -24,16 +25,21 @@ namespace PAG { ...@@ -24,16 +25,21 @@ namespace PAG {
* aplicando el patrón de diseño Singleton. Está pensada para que las * aplicando el patrón de diseño Singleton. Está pensada para que las
* funciones callback hagan llamadas a sus métodos. * funciones callback hagan llamadas a sus métodos.
*/ */
class Renderer { class Renderer: public Listener {
static Renderer* instancia; static Renderer* instancia;
static glm::vec3 color_fondo;
Renderer(); Renderer();
public: public:
virtual ~Renderer(); virtual ~Renderer();
static Renderer& getInstancia(); static Renderer& getInstancia();
void inicializar();
void refrescar(); void refrescar();
void refrescar_tamanio_framebuffer(int width, int height); void refrescar_tamanio_framebuffer(int width, int height);
void scroll_callback(double yoffset);
void wakeUp(WindowType t, ...) override;
}; };
} }
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#include "GUI.h" #include "GUI.h"
#include "Renderer.h" #include "Renderer.h"
//TODO: Cambiar yPos por un atributo de Renderer
double* yPos = nullptr;
// - Esta función callback será llamada cuando GLFW produzca algún error // - Esta función callback será llamada cuando GLFW produzca algún error
void error_callback(int errno, const char* desc) { void error_callback(int errno, const char* desc) {
std::string aux(desc); std::string aux(desc);
...@@ -20,11 +17,6 @@ void refresh_window_callback(GLFWwindow *window) { ...@@ -20,11 +17,6 @@ void refresh_window_callback(GLFWwindow *window) {
// Llamada al método refrescar del Renderer // Llamada al método refrescar del Renderer
PAG::Renderer::getInstancia().refrescar(); PAG::Renderer::getInstancia().refrescar();
// - GLFW usa un doble buffer para que no haya parpadeo. Esta orden
// intercambia el buffer back (en el que se ha estado dibujando) por el
// que se mostraba hasta ahora (front).
glfwSwapBuffers(window);
std::cout << "Refresh callback called" << std::endl; std::cout << "Refresh callback called" << std::endl;
} }
...@@ -60,13 +52,8 @@ void mouse_button_callback(GLFWwindow *window, int button, int action, int mods) ...@@ -60,13 +52,8 @@ void mouse_button_callback(GLFWwindow *window, int button, int action, int mods)
// - Esta función callback será llamada cada vez que se mueva la rueda // - Esta función callback será llamada cada vez que se mueva la rueda
// del ratón sobre el área de dibujo OpenGL. // del ratón sobre el área de dibujo OpenGL.
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) {
if (yPos) { PAG::Renderer::getInstancia().scroll_callback(yoffset);
if(((*yPos)+yoffset*0.1) >= 0 && ((*yPos)+yoffset*0.1) <= 1) {
(*yPos) += yoffset*0.1;
}
glClearColor((*yPos), (*yPos), (*yPos), 1.0);
refresh_window_callback(window); refresh_window_callback(window);
}
std::cout << "Movida la rueda del ratón " << xoffset std::cout << "Movida la rueda del ratón " << xoffset
<< " unidades en horizontal y " << yoffset << " unidades en horizontal y " << yoffset
...@@ -132,26 +119,21 @@ int main() { ...@@ -132,26 +119,21 @@ int main() {
glfwSetMouseButtonCallback(window, mouse_button_callback); glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
// - Establecemos un gris medio como color con el que se borrará el frame buffer. // Inicializamos el renderizado
// No tiene por qué ejecutarse en cada paso por el ciclo de eventos. PAG::Renderer::getInstancia().inicializar();
glClearColor ( 0.6, 0.6, 0.6, 1.0 );
// - Le decimos a OpenGL que tenga en cuenta la profundidad a la hora de dibujar.
// No tiene por qué ejecutarse en cada paso por el ciclo de eventos.
glEnable ( GL_DEPTH_TEST );
// Inicializamos la GUI a través de ImGui // Inicializamos la GUI a través de ImGui
PAG::GUI::getInstancia().inicializarGUI(window); PAG::GUI::getInstancia().inicializarGUI(window);
// Inicializamos la variable yPos que controla la posición actual de la rueda del
// ratón para mostrar el color correspondiente
yPos = new double;
(*yPos) = 0.6;
// - Ciclo de eventos de la aplicación. La condición de parada es que la // - Ciclo de eventos de la aplicación. La condición de parada es que la
// ventana principal deba cerrarse. Por ejemplo, si el usuario pulsa el // ventana principal deba cerrarse. Por ejemplo, si el usuario pulsa el
// botón de cerrar la ventana (la X). // botón de cerrar la ventana (la X).
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
// - GLFW usa un doble buffer para que no haya parpadeo. Esta orden
// intercambia el buffer back (en el que se ha estado dibujando) por el
// que se mostraba hasta ahora (front).
glfwSwapBuffers(window);
PAG::GUI::getInstancia().prepararNuevoFrame(); PAG::GUI::getInstancia().prepararNuevoFrame();
// Renderizado de figuras OpenGL // Renderizado de figuras OpenGL
PAG::GUI::getInstancia().renderizarNuevoFrame(); PAG::GUI::getInstancia().renderizarNuevoFrame();
...@@ -165,12 +147,6 @@ int main() { ...@@ -165,12 +147,6 @@ int main() {
// - Una vez terminado el ciclo de eventos, liberar recursos, etc. // - Una vez terminado el ciclo de eventos, liberar recursos, etc.
std::cout << "Finishing application pag prueba" << std::endl; std::cout << "Finishing application pag prueba" << std::endl;
// Liberamos el puntero yPos
if (yPos) {
delete yPos;
yPos = nullptr;
}
PAG::GUI::getInstancia().destruirGUI(); // - Cerramos y destruimos la interfaz de usuario. PAG::GUI::getInstancia().destruirGUI(); // - Cerramos y destruimos la interfaz de usuario.
glfwDestroyWindow ( window ); // - Cerramos y destruimos la ventana de la aplicación. glfwDestroyWindow ( window ); // - Cerramos y destruimos la ventana de la aplicación.
window = nullptr; window = nullptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment