1 /*
2  * Copyright (C) 2014-2018 Christopho, Solarus - http://www.solarus-games.org
3  *
4  * Solarus Quest Editor is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Solarus Quest Editor is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #ifndef SOLARUSEDITOR_SHADER_PREVIEWER_H
18 #define SOLARUSEDITOR_SHADER_PREVIEWER_H
19 
20 #include "shader_preview_mode.h"
21 
22 // WORKAROUND Avoid QOpenGL headers to redefine glad symbols when including GL/glext.h on macOS
23 #include "solarus/core/Common.h"
24 #ifdef SOLARUS_OSX
25 #  define GL_GLEXT_FUNCTION_POINTERS
26 #endif
27 
28 #include <QFileSystemWatcher>
29 #include <QMatrix4x4>
30 #include <QOpenGLBuffer>
31 #include <QOpenGLDebugLogger>
32 #include <QOpenGLFramebufferObject>
33 #include <QOpenGLShader>
34 #include <QOpenGLShaderProgram>
35 #include <QOpenGLTexture>
36 #include <QOpenGLVertexArrayObject>
37 #include <QOpenGLWidget>
38 #include <QPointer>
39 #include <QTimer>
40 #include <QWidget>
41 
42 // #define SOLARUSEDITOR_DEBUG_GL
43 
44 namespace SolarusEditor {
45 
46 class ShaderModel;
47 class ViewSettings;
48 
49 /**
50  * @brief A widget to preview shaders.
51  */
52 class ShaderPreviewer : public QOpenGLWidget {
53   Q_OBJECT
54 
55 public:
56 
57   ShaderPreviewer(QWidget* parent = nullptr);
58 
59   void set_model(ShaderModel* model);
60   void set_view_settings(ViewSettings& view_settings);
61 
62   ShaderPreviewMode get_preview_mode() const;
63   void set_preview_mode(ShaderPreviewMode preview_mode);
64   void setup_framebuffers(const QSize& output_size);
65 
66   void zoom_in();
67   void zoom_out();
68 
69   /// Mouse events
70   void mouseMoveEvent(QMouseEvent* event) override;
71   void mousePressEvent(QMouseEvent* event) override;
72   void mouseReleaseEvent(QMouseEvent* event) override;
73   void wheelEvent(QWheelEvent* event) override;
74 
75   void set_preview_image(QImage image);
76 
77   /// Opengl events
78   virtual void paintGL() override;
79   virtual void initializeGL() override;
80   virtual void resizeGL(int w, int h) override;
81 
82 signals:
83   void shader_compilation_started(const QString& shader_id);
84   void shader_compilation_finished(const QString& shader_id);
85   void shader_error(const QString& message);
86   void shader_warning(const QString& message);
87 
88 public slots:
89  void on_source_changed();
90  void on_scaling_factor_changed(double factor);
91 
92 private:
93   using Textures = std::vector<std::pair<const char*,GLuint>>;
94 
95   /// Render utils
96   void render_quad(QOpenGLShaderProgram& shader, const Textures& textures);
97   void render_fbs();
98   void render_swipe(float factor);
99   void render_sbs();
100   void compile_program();
101   void build_preview_texture();
102 
103   QVector2D to_frame_center(const QPoint& mouse_position) const;
104   float pixelFactor() const;
105 
106   void update_zoom();
107   QSize get_letter_box(const QSize& qsize, const QSize& basesize) const;
108 
109   QString sanitizeShaderCode(const QString& code) const;
110 
111   bool should_recompile = true;
112   QImage preview_image;
113   QPointer<ViewSettings>
114       view_settings;                            /**< How the view is displayed. */
115 
116   /// Move
117   bool grabbing = false;                        /**< grab state */
118   float zoom = 1.f;                             /**< zoom factor */
119   QPointF last_mouse_pos;                       /**< last registered mouse position */
120   QVector2D translation;                        /**< Translation vector */
121   QCursor grab_cursor;                          /**< Cursor displayedd while grabbing */
122   QCursor hover_cursor;                         /**< Cursor displayed while hovering */
123 
124   /// Opengl
125   QOpenGLFramebufferObject* input_fb = nullptr; /**< Framebuffer to chich the input is drawn */
126   QOpenGLFramebufferObject* output_fb = nullptr;/**< Framebuffer to which the output is drawn */
127   QOpenGLBuffer* vertex_buffer = nullptr;       /**< quad buffer */
128   QOpenGLVertexArrayObject* vao = nullptr;      /**< Empty vertex array for core profiles*/
129   QOpenGLShaderProgram program;                 /**< shader program*/
130   QOpenGLTexture* input_texture = nullptr;      /**< Texture of the input*/
131   QPointer<ShaderModel> model;                  /**< The shader model. */
132   ShaderPreviewMode preview_mode;               /**< Display mode of the preview. */
133   QOpenGLShaderProgram simple_program;          /**< simple default shader for bliting*/
134   QOpenGLShaderProgram swipe_program;           /**< swipe shader to draw two textures */
135 
136   QTimer fps_timer;                             /**< timer to update output periodically */
137 
138   QString glsl_version;
139 #ifdef SOLARUSEDITOR_DEBUG_GL
140   QOpenGLDebugLogger gl_logger;                 /**< Logger to track opengl error in debug mode*/
141 private slots:
142   void on_gl_log(const QOpenGLDebugMessage& message);
143 #endif
144 };
145 
146 }
147 
148 #endif
149