123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /*********************************************************************
- * Software License Agreement (AGPL-3 License)
- *
- * OpenViBE Designer
- * Based on OpenViBE V1.1.0, Copyright (C) Inria, 2006-2015
- * Copyright (C) Inria, 2015-2017,V1.0
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.
- * If not, see <http://www.gnu.org/licenses/>.
- */
- #pragma once
-
- #include "m_defines.hpp"
- #include "m_VisualizationTools.hpp"
- #include "m_GtkGL.hpp"
-
- #include <openvibe/ov_all.h>
- #include <visualization-toolkit/ovviz_all.h>
-
- #if defined TARGET_OS_Windows
- #include <Windows.h>
- #endif
-
- #include <gtk/gtk.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
-
- #include <string>
-
- // #define __DIRECT_RENDER__
-
- namespace OpenViBE {
- namespace AdvancedVisualization {
- template <class TBox>
- class TGtkGLWidget
- {
- public:
-
- TGtkGLWidget() : m_box(nullptr) { }
-
- virtual ~TGtkGLWidget()
- {
- if (m_widget)
- {
- if (m_textureId)
- {
- GtkGL::preRender(m_widget);
- glDeleteTextures(1, &m_textureId);
- GtkGL::postRender(m_widget);
- }
- if (m_timeoutSrc) { g_source_destroy(m_timeoutSrc); }
- GtkGL::uninitialize(m_widget);
- }
- }
-
- virtual void initialize(TBox& box, GtkWidget* widget, GtkWidget* left, GtkWidget* right, GtkWidget* bottom)
- {
- GtkGL::initialize(widget);
- {
- m_box = &box;
- m_widget = widget;
- m_left = left;
- m_right = right;
- m_bottom = bottom;
-
- ::g_signal_connect(widget, "configure-event", G_CALLBACK(TGtkGLWidget<TBox>::configureCB), m_box);
- ::g_signal_connect(widget, "expose-event", G_CALLBACK(TGtkGLWidget<TBox>::exposeCB), m_box);
- ::g_signal_connect(widget, "button-press-event", G_CALLBACK(TGtkGLWidget<TBox>::mouseButtonCB), m_box);
- ::g_signal_connect(widget, "button-release-event", G_CALLBACK(TGtkGLWidget<TBox>::mouseButtonCB), m_box);
- ::g_signal_connect(widget, "motion-notify-event", G_CALLBACK(TGtkGLWidget<TBox>::motionNotifyCB), m_box);
- ::g_signal_connect(widget, "enter-notify-event", G_CALLBACK(TGtkGLWidget<TBox>::enterNotifyCB), m_box);
- ::g_signal_connect(gtk_widget_get_parent(widget), "key-press-event", G_CALLBACK(TGtkGLWidget<TBox>::keyPressCB), m_box);
- ::g_signal_connect(gtk_widget_get_parent(widget), "key-release-event", G_CALLBACK(TGtkGLWidget<TBox>::keyReleaseCB), m_box);
-
- ::g_signal_connect_after(left, "expose-event", G_CALLBACK(TGtkGLWidget<TBox>::exposeLeftCB), m_box);
- ::g_signal_connect_after(right, "expose-event", G_CALLBACK(TGtkGLWidget<TBox>::exposeRightCB), m_box);
- ::g_signal_connect_after(bottom, "expose-event", G_CALLBACK(TGtkGLWidget<TBox>::exposeBottomCB), m_box);
-
- m_timeoutSrc = g_timeout_source_new(250); // timeouts every 50 ms
- g_source_set_priority(m_timeoutSrc, G_PRIORITY_LOW);
- g_source_set_callback(m_timeoutSrc, GSourceFunc(timeoutRedrawCB), m_box, nullptr);
- g_source_attach(m_timeoutSrc, nullptr);
-
- gtk_widget_queue_resize(widget);
- }
- }
-
- virtual void redrawTopLevelWindow(const bool immediate = false)
- {
- GtkWidget* top = gtk_widget_get_toplevel(m_widget);
- if (top != nullptr)
- {
- if (immediate)
- {
- gdk_window_process_updates(top->window, false);
- gtk_widget_queue_draw(top);
- }
- else { gdk_window_invalidate_rect(top->window, nullptr, true); }
- }
- }
-
- virtual void redraw(const bool immediate = false)
- {
- if (immediate)
- {
- gdk_window_process_updates(m_widget->window, false);
- gtk_widget_queue_draw(m_widget);
- }
- else { gdk_window_invalidate_rect(m_widget->window, nullptr, true); }
- }
-
- virtual void redrawLeft(const bool immediate = false)
- {
- if (immediate)
- {
- gdk_window_process_updates(m_left->window, false);
- gtk_widget_queue_draw(m_left);
- }
- else { gdk_window_invalidate_rect(m_left->window, nullptr, true); }
- }
-
- virtual void redrawRight(const bool immediate = false)
- {
- if (immediate)
- {
- gdk_window_process_updates(m_right->window, false);
- gtk_widget_queue_draw(m_right);
- }
- else { gdk_window_invalidate_rect(m_right->window, nullptr, true); }
- }
-
- virtual void redrawBottom(const bool immediate = false)
- {
- if (immediate)
- {
- gdk_window_process_updates(m_bottom->window, false);
- gtk_widget_queue_draw(m_bottom);
- }
- else { gdk_window_invalidate_rect(m_bottom->window, nullptr, true); }
- }
-
- virtual void setPointSmoothingActive(const bool active = false)
- {
- if (active) { glEnable(GL_POINT_SMOOTH); }
- else { glDisable(GL_POINT_SMOOTH); }
- }
-
- virtual uint32_t createTexture(const std::string& value)
- {
- #define M_GRADIENT_SIZE 128
-
- if (m_textureId == 0)
- {
- const std::string str = (value.empty() ? "0:0,0,100; 25:0,100,100; 50:0,49,0; 75:100,100,0; 100:100,0,0" : value);
-
- CMatrix gradientBase, gradient;
- VisualizationToolkit::ColorGradient::parse(gradientBase, str.c_str());
- VisualizationToolkit::ColorGradient::interpolate(gradient, gradientBase, M_GRADIENT_SIZE);
-
- float texture[M_GRADIENT_SIZE][3];
- for (size_t i = 0; i < M_GRADIENT_SIZE; ++i)
- {
- texture[i][0] = float(gradient[i * 4 + 1] * .01);
- texture[i][1] = float(gradient[i * 4 + 2] * .01);
- texture[i][2] = float(gradient[i * 4 + 3] * .01);
- }
-
- glGenTextures(1, &m_textureId);
- glBindTexture(GL_TEXTURE_1D, m_textureId);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // GL_LINEAR);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- //glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, __SIZE__, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
- gluBuild1DMipmaps(GL_TEXTURE_1D, GL_RGB, M_GRADIENT_SIZE, GL_RGB, GL_FLOAT, texture);
- }
-
- #undef M_GRADIENT_SIZE
-
- return m_textureId;
- }
-
- protected:
-
- GtkWidget* m_widget = nullptr;
- GtkWidget* m_left = nullptr;
- GtkWidget* m_right = nullptr;
- GtkWidget* m_bottom = nullptr;
- GSource* m_timeoutSrc = nullptr;
-
- TBox* m_box = nullptr;
-
- uint32_t m_textureId = 0;
-
- private:
-
-
- static gboolean timeoutRedrawCB(TBox* box)
- {
- box->redraw();
- return TRUE;
- }
-
- static gboolean configureCB(GtkWidget* widget, GdkEventConfigure* /*event*/, TBox* box)
- {
- GtkGL::preRender(widget);
- glViewport(0, 0, widget->allocation.width, widget->allocation.height);
- box->reshape(widget->allocation.width, widget->allocation.height);
- GtkGL::postRender(widget);
- return TRUE;
- }
-
- static gboolean exposeCB(GtkWidget* widget, GdkEventExpose* /*event*/, TBox* box)
- {
- const float d = 1.F;
- const float dx = d / (widget->allocation.width - d);
- const float dy = d / (widget->allocation.height - d);
-
- GtkGL::preRender(widget);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glTranslatef(0.5, 0, 0);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0 - dx, 1 + dx, 0 - dy, 1 + dy);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.0, 1.0);
-
- glEnable(GL_LINE_SMOOTH);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- glLineWidth(1);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-
- glEnable(GL_TEXTURE_1D);
-
- glDisable(GL_DEPTH_TEST);
- glClearDepth(100);
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glColor3f(1, 1, 1);
-
- // Lighting
- const float fAmbient = 0.0F;
- const float fDiffuse = 1.0F;
- const float fSpecular = 1.0F;
- GLfloat ambient[] = { fAmbient, fAmbient, fAmbient, 1 };
- GLfloat diffuse[] = { fDiffuse, fDiffuse, fDiffuse, 1 };
- GLfloat specular[] = { fSpecular, fSpecular, fSpecular, 1 };
- GLfloat position0[] = { 3, 1, 2, 1 };
- GLfloat position1[] = { -3, 0, -2, 1 };
- glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
- glLightfv(GL_LIGHT0, GL_POSITION, position0);
- glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
- glLightfv(GL_LIGHT1, GL_POSITION, position1);
- glShadeModel(GL_SMOOTH);
- glEnable(GL_LIGHT0);
- glEnable(GL_LIGHT1);
- glEnable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
-
- box->draw();
-
- GtkGL::postRender(widget);
-
- return TRUE;
- }
-
- static gboolean enterNotifyCB(GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, TBox* box)
- {
- box->redraw();
- //box->request();
- //box->m_redrawNeeded = true;
- return TRUE;
- }
-
- static gboolean exposeLeftCB(GtkWidget* /*widget*/, GdkEventExpose* /*event*/, TBox* box)
- {
- box->drawLeft();
- return TRUE;
- }
-
- static gboolean exposeRightCB(GtkWidget* /*widget*/, GdkEventExpose* /*event*/, TBox* box)
- {
- box->drawRight();
- return TRUE;
- }
-
- static gboolean exposeBottomCB(GtkWidget* /*widget*/, GdkEventExpose* /*event*/, TBox* box)
- {
- box->drawBottom();
- return TRUE;
- }
-
- static gboolean mouseButtonCB(GtkWidget* /*widget*/, GdkEventButton* event, TBox* box)
- {
- int status = 0;
- switch (event->type)
- {
- case GDK_BUTTON_PRESS: status = 1;
- break;
- case GDK_2BUTTON_PRESS: status = 2;
- break;
- case GDK_3BUTTON_PRESS: status = 3;
- break;
- default: break;
- }
- box->mouseButton(int(event->x), int(event->y), event->button, status);
- box->draw();
- return TRUE;
- }
-
- static gboolean motionNotifyCB(GtkWidget* /*widget*/, GdkEventMotion* event, TBox* box)
- {
- box->mouseMotion(int(event->x), int(event->y));
- return TRUE;
- }
-
- static gboolean keyPressCB(GtkWidget* /*widget*/, GdkEventKey* event, TBox* box)
- {
- box->keyboard(0, 0, /*event->x, event->y,*/ event->keyval, true);
- return TRUE;
- }
-
- static gboolean keyReleaseCB(GtkWidget* /*widget*/, GdkEventKey* event, TBox* box)
- {
- box->keyboard(0, 0, /*event->x, event->y,*/ event->keyval, false);
- return TRUE;
- }
- };
- } // namespace AdvancedVisualization
- } // namespace OpenViBE
|