~ubuntu-branches/ubuntu/vivid/meshlab/vivid

« back to all changes in this revision

Viewing changes to meshlab/src/fgt/render_rfx/rfx_dialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-10-08 16:40:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20091008164041-0c2ealqv8b8uc20c
Tags: 1.2.2-1
* New upstream version
* Do not build filter_isoparametrization because liblevmar dependency
  is not (yet) in Debian
* Fix compilation with gcc-4.4, thanks to Jonathan Liu for the patch
  (closes: #539544)
* rules: Add compiler variables to the qmake call (for testing with new
  GCC versions)
* io_3ds.pro: Make LIBS and INCLUDEPATH point to Debian version of lib3ds
* io_epoch.pro: Make LIBS point to Debian version of libbz2
* control:
  - Move Homepage URL to the source package section
  - Update to standards-version 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
* MeshLab                                                           o o     *
3
 
* A versatile mesh processing toolbox                             o     o   *
4
 
*                                                                _   O  _   *
5
 
* Copyright(C) 2005-2008                                           \/)\/    *
6
 
* Visual Computing Lab                                            /\/|      *
7
 
* ISTI - Italian National Research Council                           |      *
8
 
*                                                                    \      *
9
 
* All rights reserved.                                                      *
10
 
*                                                                           *
11
 
* This program is free software; you can redistribute it and/or modify      *
12
 
* it under the terms of the GNU General Public License as published by      *
13
 
* the Free Software Foundation; either version 2 of the License, or         *
14
 
* (at your option) any later version.                                       *
15
 
*                                                                           *
16
 
* This program is distributed in the hope that it will be useful,           *
17
 
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18
 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19
 
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20
 
* for more details.                                                         *
21
 
*                                                                           *
22
 
****************************************************************************/
23
 
 
24
 
#include "rfx_dialog.h"
25
 
 
26
 
const float DECTOINT = 10000.0f;
27
 
const float INTTODEC = 0.0001f;
28
 
 
29
 
RfxDialog::RfxDialog(RfxShader *s, QAction *a, QGLWidget *parent)
30
 
        : QDockWidget(parent)
31
 
{
32
 
        shader = s;
33
 
        mGLWin = parent;
34
 
 
35
 
        ui.setupUi(this);
36
 
        setWindowTitle("RenderRfx [" + a->text() + "]");
37
 
 
38
 
        setWidget(ui.RfxDockContents);
39
 
        setFeatures(QDockWidget::AllDockWidgetFeatures);
40
 
        setAllowedAreas(Qt::LeftDockWidgetArea);
41
 
        setFloating(true);
42
 
 
43
 
        /* Passes */
44
 
        QListIterator<RfxGLPass*> pit = s->PassesIterator();
45
 
        while (pit.hasNext()) {
46
 
                RfxGLPass *pass = pit.next();
47
 
                ui.comboPasses->addItem("Pass #" +
48
 
                                                                QString().setNum(pass->GetPassIndex()) +
49
 
                                                                " " + pass->GetPassName() + " ");
50
 
        }
51
 
        // start from first pass
52
 
        connect(ui.comboPasses, SIGNAL(currentIndexChanged(int)), this,
53
 
                        SLOT(PassSelected(int)));
54
 
        selPass = 0;
55
 
        ui.comboPasses->setCurrentIndex(0);
56
 
 
57
 
        QFont fixedfont;
58
 
        fixedfont.setFamily("Courier");
59
 
        fixedfont.setFixedPitch(true);
60
 
        fixedfont.setPointSize(10);
61
 
        ui.textVert->setFont(fixedfont);
62
 
        ui.textFrag->setFont(fixedfont);
63
 
 
64
 
        vertHL = new GLSLSynHlighter(ui.textVert->document());
65
 
        fragHL = new GLSLSynHlighter(ui.textFrag->document());
66
 
 
67
 
        // fill log once for dialog, since it reports status for all passes
68
 
        ui.textLog->setPlainText(s->GetCompilationLog().join("\n"));
69
 
 
70
 
 
71
 
        // uniform tab will contain every uniform from every pass
72
 
        /* Uniforms */
73
 
        pit = s->PassesIterator();
74
 
        while (pit.hasNext()) {
75
 
                RfxGLPass *pass = pit.next();
76
 
 
77
 
                QListIterator<RfxUniform*> it = pass->UniformsIterator();
78
 
                int unifCount = -1; // keep track of uniform index
79
 
                while (it.hasNext()) {
80
 
                        unifCount++;
81
 
                        RfxUniform *uni = it.next();
82
 
                        if (uni->isTexture())
83
 
                                continue;
84
 
 
85
 
                        AddUniformBox(uni, unifCount);
86
 
                }
87
 
 
88
 
                ++selPass;
89
 
        }
90
 
        selPass = 0;
91
 
 
92
 
        setupTabs();
93
 
}
94
 
 
95
 
void RfxDialog::setupTabs()
96
 
{
97
 
        /* Textures */
98
 
        ui.comboTextures->clear();
99
 
        ui.comboTextures->setEnabled(true);
100
 
        disconnect(ui.comboTextures, 0, 0, 0);
101
 
 
102
 
        QListIterator<RfxUniform*> it = shader->GetPass(selPass)->UniformsIterator();
103
 
        int unifCount = -1;
104
 
        while (it.hasNext()) {
105
 
                unifCount++;
106
 
                RfxUniform *uni = it.next();
107
 
                if (!uni->isTexture())
108
 
                        continue;
109
 
                ui.comboTextures->addItem("[" +
110
 
                                                                  RfxUniform::GetTypeString(uni->GetType()) +
111
 
                                                                  "] " +
112
 
                                                                  ((uni->isRenderable())? " (RT) " : "") +
113
 
                                                                  uni->GetName(),
114
 
                                                                  unifCount);
115
 
        }
116
 
 
117
 
        if (ui.comboTextures->count() == 0) {
118
 
                ui.comboTextures->addItem("No textures");
119
 
                ui.comboTextures->setDisabled(true);
120
 
        } else {
121
 
                ui.comboTextures->insertItem(0, "Select...");
122
 
                ui.comboTextures->setCurrentIndex(0);
123
 
                connect(ui.comboTextures, SIGNAL(currentIndexChanged(int)), this,
124
 
                                SLOT(TextureSelected(int)));
125
 
        }
126
 
 
127
 
        disconnect(ui.btnChangeTexture, 0, 0, 0);
128
 
        ui.BoxTextureProps->setTitle("");
129
 
        ui.EditTexFile->clear();
130
 
        ui.TexStatesTable->clear();
131
 
        ui.TexStatesTable->setRowCount(0);
132
 
        ui.TexStatesTable->setColumnCount(2);
133
 
        ui.TexStatesTable->horizontalHeader()->setStretchLastSection(true);
134
 
        ui.TexStatesTable->horizontalHeader()->hide();
135
 
        ui.TexStatesTable->verticalHeader()->hide();
136
 
        ui.lblPreview->clear();
137
 
 
138
 
 
139
 
        /* States */
140
 
        ui.glStatesTable->clear();
141
 
        ui.glStatesTable->setRowCount(0);
142
 
        ui.glStatesTable->setColumnCount(2);
143
 
        ui.glStatesTable->horizontalHeader()->setStretchLastSection(true);
144
 
        ui.glStatesTable->horizontalHeader()->hide();
145
 
        ui.glStatesTable->verticalHeader()->hide();
146
 
        QListIterator<RfxState*> sit = shader->GetPass(selPass)->StatesIterator();
147
 
        int rowidx = 0;
148
 
        while (sit.hasNext()) {
149
 
                RfxState *r = sit.next();
150
 
 
151
 
                // QTableWidget will take ownership of objects, do not delete them.
152
 
                QTableWidgetItem *c0 = new QTableWidgetItem(r->GetRenderState());
153
 
                c0->setFlags(Qt::ItemIsSelectable);
154
 
                QTableWidgetItem *c1 = new QTableWidgetItem(r->GetRenderValue());
155
 
                c1->setFlags(Qt::ItemIsSelectable);
156
 
 
157
 
                ui.glStatesTable->insertRow(rowidx);
158
 
                ui.glStatesTable->setItem(rowidx, 0, c0);
159
 
                ui.glStatesTable->setItem(rowidx, 1, c1);
160
 
                ui.glStatesTable->resizeRowToContents(rowidx);
161
 
                ++rowidx;
162
 
        }
163
 
        ui.glStatesTable->resizeColumnToContents(0);
164
 
        ui.glStatesTable->resizeColumnToContents(1);
165
 
 
166
 
 
167
 
        /* Vertex/Fragment source view */
168
 
        ui.textVert->setPlainText(shader->GetPass(selPass)->GetVertexSource());
169
 
        ui.textFrag->setPlainText(shader->GetPass(selPass)->GetFragmentSource());
170
 
}
171
 
 
172
 
RfxDialog::~RfxDialog()
173
 
{
174
 
        delete vertHL;
175
 
        delete fragHL;
176
 
 
177
 
        CleanTab(ALL_TABS);
178
 
}
179
 
 
180
 
void RfxDialog::PassSelected(int idx)
181
 
{
182
 
        selPass = idx;
183
 
        CleanTab(ALL_TABS);
184
 
        setupTabs();
185
 
}
186
 
 
187
 
void RfxDialog::AddUniformBox(RfxUniform *uni, int uniIndex)
188
 
{
189
 
        assert(uni);
190
 
 
191
 
        QLabel *lblUni = new QLabel();
192
 
        QString lblText;
193
 
 
194
 
        lblText.append(QString("(Pass #%1) ").arg(selPass));
195
 
        lblText.append(uni->GetName());
196
 
 
197
 
        if (!uni->GetSemantic().isNull()) {
198
 
                lblText.append("<span style=\"color:darkgreen;\"><br/> [P: ");
199
 
                lblText.append(uni->GetSemantic());
200
 
                lblText.append("]</span>");
201
 
        }
202
 
 
203
 
        lblUni->setText(lblText);
204
 
 
205
 
        QGridLayout *gridUni = new QGridLayout();
206
 
 
207
 
        switch (uni->GetType()) {
208
 
        case RfxUniform::INT:
209
 
        case RfxUniform::FLOAT:
210
 
        case RfxUniform::BOOL:
211
 
                DrawIFace(gridUni, uni, uniIndex, 1, 1);
212
 
                break;
213
 
 
214
 
        case RfxUniform::VEC2:
215
 
        case RfxUniform::IVEC2:
216
 
        case RfxUniform::BVEC2:
217
 
                DrawIFace(gridUni, uni, uniIndex, 1, 2);
218
 
                break;
219
 
 
220
 
        case RfxUniform::VEC3:
221
 
        case RfxUniform::IVEC3:
222
 
        case RfxUniform::BVEC3:
223
 
                DrawIFace(gridUni, uni, uniIndex, 1, 3);
224
 
                break;
225
 
 
226
 
        case RfxUniform::VEC4:
227
 
        case RfxUniform::IVEC4:
228
 
        case RfxUniform::BVEC4:
229
 
                DrawIFace(gridUni, uni, uniIndex, 1, 4);
230
 
                break;
231
 
 
232
 
        case RfxUniform::MAT2:
233
 
                DrawIFace(gridUni, uni, uniIndex, 2, 2);
234
 
                break;
235
 
 
236
 
        case RfxUniform::MAT3:
237
 
                DrawIFace(gridUni, uni, uniIndex, 3, 3);
238
 
                break;
239
 
 
240
 
        case RfxUniform::MAT4:
241
 
                DrawIFace(gridUni, uni, uniIndex, 4, 4);
242
 
                break;
243
 
 
244
 
        default:
245
 
                return;
246
 
        }
247
 
 
248
 
        QHBoxLayout *boxContent = new QHBoxLayout();
249
 
        boxContent->addWidget(lblUni);
250
 
        boxContent->addLayout(gridUni);
251
 
 
252
 
        ((QVBoxLayout*)ui.scrollUniformsContents->layout())->addLayout(boxContent);
253
 
}
254
 
 
255
 
void RfxDialog::DrawIFace(QGridLayout *parent, RfxUniform *u, int uidx, int rows, int columns)
256
 
{
257
 
        enum controlType { INT_CTRL, FLOAT_CTRL, BOOL_CTRL };
258
 
        float *val = u->GetValue();
259
 
        controlType ctrl;
260
 
        QWidget **controls = new QWidget*[rows * columns];
261
 
        QGridLayout *uniLayout = parent;
262
 
        QHBoxLayout *sliderEditLayout = NULL;
263
 
        bool multipleControls = false;
264
 
        QSignalMapper *valMapper = new QSignalMapper(this);
265
 
 
266
 
        switch (u->GetType()) {
267
 
        case RfxUniform::INT:
268
 
        case RfxUniform::IVEC2:
269
 
        case RfxUniform::IVEC3:
270
 
        case RfxUniform::IVEC4:
271
 
                ctrl = INT_CTRL;
272
 
                break;
273
 
 
274
 
        case RfxUniform::FLOAT:
275
 
        case RfxUniform::VEC2:
276
 
        case RfxUniform::VEC3:
277
 
        case RfxUniform::VEC4:
278
 
        case RfxUniform::MAT2:
279
 
        case RfxUniform::MAT3:
280
 
        case RfxUniform::MAT4:
281
 
                ctrl = FLOAT_CTRL;
282
 
                break;
283
 
 
284
 
        case RfxUniform::BOOL:
285
 
        case RfxUniform::BVEC2:
286
 
        case RfxUniform::BVEC3:
287
 
        case RfxUniform::BVEC4:
288
 
                ctrl = BOOL_CTRL;
289
 
                break;
290
 
 
291
 
        default:
292
 
                return;
293
 
        }
294
 
 
295
 
        // controls in a grid layout
296
 
        for (int i = 0; i < rows; ++i) {
297
 
                for (int j = 0; j < columns; ++j) {
298
 
                        int arrayIdx = j + (i * rows);
299
 
                        switch (ctrl) {
300
 
                        case INT_CTRL:
301
 
                                controls[arrayIdx] = new QSpinBox(this);
302
 
                                ((QSpinBox*)controls[arrayIdx])->setRange(-99, 99);
303
 
                                ((QSpinBox*)controls[arrayIdx])->setValue((int)val[arrayIdx]);
304
 
                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)),
305
 
                                        valMapper, SLOT(map()));
306
 
                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)), this,
307
 
                                        SLOT(extendRange(int)));
308
 
                                break;
309
 
                        case FLOAT_CTRL:
310
 
                                if (u->HasMinMax()) {
311
 
                                        controls[arrayIdx] = new QSlider(this);
312
 
                                        ((QSlider*)controls[arrayIdx])->setTickPosition(QSlider::NoTicks);
313
 
                                        ((QSlider*)controls[arrayIdx])->setOrientation(Qt::Horizontal);
314
 
 
315
 
                                        // since qslider only deals with integers, do a little conversion
316
 
                                        // of values
317
 
                                        // keep as much as 5 decimal values, others will be lost in conversion
318
 
                                        int valAsInt = (int)(val[arrayIdx] * DECTOINT);
319
 
                                        int tickAsInt = (int)(((u->GetMaxRange() - u->GetMinRange()) * 0.01) * DECTOINT);
320
 
 
321
 
                                        ((QSlider*)controls[arrayIdx])->setTickInterval(tickAsInt);
322
 
                                        ((QSlider*)controls[arrayIdx])->setRange((int)(u->GetMinRange() * DECTOINT),
323
 
                                                                                 (int)(u->GetMaxRange() * DECTOINT));
324
 
                                        ((QSlider*)controls[arrayIdx])->setValue(valAsInt);
325
 
                                        ((QSlider*)controls[arrayIdx])->setToolTip(QString().setNum(val[arrayIdx]));
326
 
 
327
 
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(int)), valMapper, SLOT(map()));
328
 
 
329
 
                                        // as per request, if value is a single float, also show a qlineedit to allow
330
 
                                        // more accurate settings.
331
 
                                        if (u->GetType() == RfxUniform::FLOAT) {
332
 
 
333
 
                                                QLineEdit *slideValue = new QLineEdit();
334
 
                                                slideValue->setAlignment(Qt::AlignRight);
335
 
                                                slideValue->setText(QString().setNum(val[arrayIdx]));
336
 
 
337
 
                                                QSignalMapper *yaMapper = new QSignalMapper();
338
 
                                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)), yaMapper, SLOT(map()));
339
 
                                                connect(slideValue, SIGNAL(editingFinished()), yaMapper, SLOT(map()));
340
 
                                                yaMapper->setMapping(controls[arrayIdx], slideValue);
341
 
                                                yaMapper->setMapping(slideValue, controls[arrayIdx]);
342
 
                                                connect(yaMapper, SIGNAL(mapped(QWidget*)), this, SLOT(mapSliderLineEdit(QWidget*)));
343
 
 
344
 
                                                if (!u->GetSemantic().isNull())
345
 
                                                        slideValue->setDisabled(true);
346
 
 
347
 
                                                multipleControls = true;
348
 
                                                sliderEditLayout = new QHBoxLayout();
349
 
                                                sliderEditLayout->addWidget(controls[arrayIdx]);
350
 
                                                sliderEditLayout->addWidget(slideValue);
351
 
                                        }
352
 
 
353
 
                                } else {
354
 
                                        controls[arrayIdx] = new QDoubleSpinBox(this);
355
 
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setRange(-99.0, 99.0);
356
 
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setValue(val[arrayIdx]);
357
 
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setDecimals(4);
358
 
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setSingleStep(0.01);
359
 
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(double)),
360
 
                                                        valMapper, SLOT(map()));
361
 
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(double)), this,
362
 
                                                        SLOT(extendRange(double)));
363
 
                                }
364
 
                                break;
365
 
                        case BOOL_CTRL:
366
 
                                controls[arrayIdx] = new QComboBox(this);
367
 
                                ((QComboBox*)controls[arrayIdx])->addItem("FALSE");
368
 
                                ((QComboBox*)controls[arrayIdx])->addItem("TRUE");
369
 
                                if (!val[arrayIdx])
370
 
                                        ((QComboBox*)controls[arrayIdx])->setCurrentIndex(0);
371
 
                                connect(controls[arrayIdx], SIGNAL(currentIndexChanged(int)),
372
 
                                                valMapper, SLOT(map()));
373
 
                                break;
374
 
                        }
375
 
 
376
 
                        valMapper->setMapping(controls[arrayIdx],
377
 
                                              QString().setNum(uidx) + '-' +
378
 
                                              QString().setNum(arrayIdx)  + '-' +
379
 
                                              QString().setNum(selPass));
380
 
 
381
 
                        if (!u->GetSemantic().isNull())
382
 
                                controls[arrayIdx]->setDisabled(true);
383
 
 
384
 
                        if (multipleControls)
385
 
                                uniLayout->addLayout(sliderEditLayout, i, j);
386
 
                        else
387
 
                                uniLayout->addWidget(controls[arrayIdx], i, j);
388
 
                        multipleControls = false;
389
 
                }
390
 
        }
391
 
 
392
 
        connect(valMapper, SIGNAL(mapped(const QString&)), this,
393
 
                SLOT(ChangeValue(const QString&)));
394
 
}
395
 
 
396
 
void RfxDialog::mapSliderLineEdit(QWidget *w)
397
 
{
398
 
        QObject *theSender = ((QSignalMapper*)QObject::sender())->mapping(w);
399
 
 
400
 
        QSlider *qslide = dynamic_cast<QSlider*>(theSender);
401
 
        if (qslide != NULL) {
402
 
                ((QLineEdit*)w)->setText(QString().setNum((float)(qslide->value()) * INTTODEC));
403
 
        } else {
404
 
                // we assume it's a QLineEdit (avoid a costly and useless dynamic_cast)
405
 
                // let's do some more checks since qlineedit input is not limited in range
406
 
                bool res = false;
407
 
                float val = ((QLineEdit*)theSender)->text().toFloat(&res);
408
 
                qslide = ((QSlider*)w);
409
 
 
410
 
                // we only accept float values
411
 
                if (!res)
412
 
                        return;
413
 
 
414
 
                // if value is beyond min or max, just set min/max
415
 
                if (val > qslide->maximum() * INTTODEC)
416
 
                        qslide->setValue(qslide->maximum());
417
 
                else if (val < qslide->minimum() * INTTODEC)
418
 
                        qslide->setValue(qslide->minimum());
419
 
                else
420
 
                        qslide->setValue((int)(val * DECTOINT));
421
 
        }
422
 
}
423
 
 
424
 
void RfxDialog::CleanTab(int tabIdx)
425
 
{
426
 
        // deletes all widgets from specified tab or, if tabIdx == -1
427
 
        // removes all widgets from all tabs
428
 
        // (this applies to *dynamically created* widgets only)
429
 
 
430
 
        if (tabIdx == ALL_TABS) {
431
 
                QMapIterator<int, QWidget*> it(widgetsByTab);
432
 
                while (it.hasNext()) {
433
 
                        QWidget *toDelete = it.next().value();
434
 
                        toDelete->close();
435
 
                        delete toDelete;
436
 
                }
437
 
                widgetsByTab.clear();
438
 
 
439
 
        } else {
440
 
                QList<QWidget*> toDelete = widgetsByTab.values(tabIdx);
441
 
                for (int i = 0; i < toDelete.size(); ++i) {
442
 
                        toDelete.at(i)->close();
443
 
                        delete toDelete.at(i);
444
 
                }
445
 
                widgetsByTab.remove(tabIdx);
446
 
        }
447
 
}
448
 
 
449
 
void RfxDialog::extendRange(double newVal)
450
 
{
451
 
        QDoubleSpinBox *sender = (QDoubleSpinBox*)QObject::sender();
452
 
        if (newVal == sender->minimum() || newVal == sender->maximum()) {
453
 
                if (newVal == sender->minimum())
454
 
                        sender->setMinimum(newVal - 50);
455
 
                else
456
 
                        sender->setMaximum(newVal + 50);
457
 
        }
458
 
}
459
 
 
460
 
void RfxDialog::extendRange(int newVal)
461
 
{
462
 
        QSpinBox *sender = (QSpinBox*)QObject::sender();
463
 
        if (newVal == sender->minimum() || newVal == sender->maximum()) {
464
 
                if (newVal == sender->minimum())
465
 
                        sender->setMinimum(newVal - 50);
466
 
                else
467
 
                        sender->setMaximum(newVal + 50);
468
 
        }
469
 
}
470
 
 
471
 
void RfxDialog::ChangeTexture(int unifIdx)
472
 
{
473
 
        int uniIndex = ui.comboTextures->itemData(unifIdx).toInt();
474
 
        RfxUniform *uni = shader->GetPass(selPass)->getUniform(uniIndex);
475
 
        assert(uni);
476
 
 
477
 
        QString fname = QFileDialog::getOpenFileName(this,
478
 
                                                     tr("Choose Texture"),
479
 
                                                     uni->GetTextureFName());
480
 
        if (!fname.isEmpty()) {
481
 
                uni->SetValue(QDir::fromNativeSeparators(fname));
482
 
                uni->LoadTexture();
483
 
                uni->PassToShader();
484
 
                mGLWin->updateGL();
485
 
 
486
 
                // generate a currentIndexChanged event
487
 
                ui.comboTextures->setCurrentIndex(0);
488
 
                ui.comboTextures->setCurrentIndex(unifIdx);
489
 
        }
490
 
}
491
 
 
492
 
void RfxDialog::ChangeValue(const QString& val)
493
 
{
494
 
        QStringList unif = val.split('-');
495
 
        RfxUniform *uni = shader->GetPass(unif[2].toInt())->getUniform(unif[0].toInt());
496
 
        float *oldVal = uni->GetValue();
497
 
        float newVal = 0.0f;
498
 
 
499
 
        QObject *sender = ((QSignalMapper*)QObject::sender())->mapping(val);
500
 
        assert(sender);
501
 
 
502
 
        QComboBox *cbox = dynamic_cast<QComboBox*>(sender);
503
 
        if (cbox != NULL) {
504
 
                newVal = cbox->currentIndex();
505
 
        } else {
506
 
                QSpinBox *sbox = dynamic_cast<QSpinBox*>(sender);
507
 
                if (sbox != NULL) {
508
 
                        newVal = sbox->value();
509
 
                } else {
510
 
                        QDoubleSpinBox *dsbox = dynamic_cast<QDoubleSpinBox*>(sender);
511
 
                        if (dsbox != NULL) {
512
 
                                newVal = dsbox->value();
513
 
                        } else {
514
 
                                QSlider *qslide = dynamic_cast<QSlider*>(sender);
515
 
                                if (qslide != NULL) {
516
 
                                        newVal = qslide->value() * INTTODEC;
517
 
                                        qslide->setToolTip(QString().setNum(newVal));
518
 
                                } else {
519
 
                                        return;
520
 
                                }
521
 
                        }
522
 
                }
523
 
        }
524
 
 
525
 
        oldVal[unif[1].toInt()] = newVal;
526
 
        uni->PassToShader();
527
 
        mGLWin->updateGL();
528
 
}
529
 
 
530
 
void RfxDialog::TextureSelected(int idx)
531
 
{
532
 
        disconnect(ui.btnChangeTexture, 0, 0, 0);
533
 
 
534
 
        if (idx <= 0)
535
 
                return;
536
 
 
537
 
        int uniIndex = ui.comboTextures->itemData(idx).toInt();
538
 
        RfxUniform *uni = shader->GetPass(selPass)->getUniform(uniIndex);
539
 
        assert(uni);
540
 
 
541
 
        // connect Change Texture button
542
 
        QSignalMapper *sigMap = new QSignalMapper(this);
543
 
        connect(ui.btnChangeTexture, SIGNAL(clicked()), sigMap, SLOT(map()));
544
 
        sigMap->setMapping(ui.btnChangeTexture, idx);
545
 
        connect(sigMap, SIGNAL(mapped(int)), this, SLOT(ChangeTexture(int)));
546
 
 
547
 
        ui.BoxTextureProps->setTitle(uni->GetName());
548
 
 
549
 
        // clean and initialize table
550
 
        ui.TexStatesTable->clear();
551
 
        ui.TexStatesTable->setRowCount(0);
552
 
        ui.TexStatesTable->setColumnCount(2);
553
 
        ui.TexStatesTable->horizontalHeader()->setStretchLastSection(true);
554
 
        ui.TexStatesTable->horizontalHeader()->hide();
555
 
        ui.TexStatesTable->verticalHeader()->hide();
556
 
 
557
 
        // delete any existing preview
558
 
        ui.lblPreview->clear();
559
 
 
560
 
        CleanTab(TEXTURE_TAB);
561
 
 
562
 
        if (uni->isRenderable())
563
 
                ui.EditTexFile->clear();
564
 
        else
565
 
                ui.EditTexFile->setText(uni->GetTextureFName());
566
 
 
567
 
        QLabel *fname = new QLabel();
568
 
        ui.infoTexLayout->addWidget(fname);
569
 
        widgetsByTab.insert(TEXTURE_TAB, fname);
570
 
        if (!uni->isTextureFound() || !uni->isTextureLoaded()) {
571
 
                if (!uni->isTextureFound())
572
 
                        fname->setText("<span style=\"color:darkred;\">Texture file not found</span>");
573
 
                else
574
 
                        fname->setText("<span style=\"color:darkred;\">Texture binding failed</span>");
575
 
        } else {
576
 
                fname->setText("<span style=\"color:darkgreen;\">Texture loaded</span>");
577
 
 
578
 
                ImageInfo ii;
579
 
                bool loaded;
580
 
                if (uni->isRenderable()) {
581
 
                        ii.preview = uni->GetRTTexture();
582
 
                        ii.texType = "Render Target";
583
 
                        ii.width = (ii.preview.isNull())? 0 : ii.preview.width();
584
 
                        ii.height = (ii.preview.isNull())? 0 : ii.preview.height();
585
 
                        ii.depth = 1;
586
 
                        ii.format = "";
587
 
                } else {
588
 
                        ii = RfxTextureLoader::LoadAsQImage(uni->GetTextureFName());
589
 
                }
590
 
                loaded = !ii.preview.isNull();
591
 
 
592
 
                if (loaded) {
593
 
                        QLabel *tSize = new QLabel();
594
 
                        tSize->setText("Dimensions: " +
595
 
                                               QString().setNum(ii.width) + " x " +
596
 
                                       QString().setNum(ii.height) +
597
 
                                       ((ii.depth > 1)? " x " + QString().setNum(ii.depth) : ""));
598
 
                        ui.infoTexLayout->addWidget(tSize);
599
 
                        widgetsByTab.insert(TEXTURE_TAB, tSize);
600
 
 
601
 
                        QLabel *tType = new QLabel();
602
 
                        tType->setText("Type: " + ii.texType);
603
 
                        ui.infoTexLayout->addWidget(tType);
604
 
                        widgetsByTab.insert(TEXTURE_TAB, tType);
605
 
 
606
 
                        QLabel *tFormat = new QLabel();
607
 
                        tFormat->setText("Format: " + ii.format);
608
 
                        ui.infoTexLayout->addWidget(tFormat);
609
 
                        widgetsByTab.insert(TEXTURE_TAB, tFormat);
610
 
 
611
 
                        // try to get a preview
612
 
                        QPixmap prvw = QPixmap::fromImage(ii.preview);
613
 
                        if (!prvw.isNull()) {
614
 
                                QSize scaledSize(120, 120);
615
 
                                if (ii.texType == "Cubemap Texture")
616
 
                                        scaledSize.setWidth(200);
617
 
 
618
 
                                ui.lblPreview->setPixmap(prvw.scaled(scaledSize,
619
 
                                                                     Qt::KeepAspectRatio));
620
 
                        }
621
 
                }
622
 
 
623
 
                QLabel *tunit = new QLabel();
624
 
                tunit->setText("Texture Unit: " + QString().setNum(uni->GetTU()));
625
 
                ui.infoTexLayout->addWidget(tunit);
626
 
                widgetsByTab.insert(TEXTURE_TAB, tunit);
627
 
        }
628
 
 
629
 
        QListIterator<RfxState*> it = uni->StatesIterator();
630
 
        int rowidx = 0;
631
 
        while (it.hasNext()) {
632
 
                RfxState *r = it.next();
633
 
 
634
 
                // QTableWidget will take ownership of objects, do not delete them.
635
 
                QTableWidgetItem *c0 = new QTableWidgetItem(r->GetTextureState());
636
 
                c0->setFlags(Qt::ItemIsSelectable);
637
 
                QTableWidgetItem *c1 = new QTableWidgetItem(r->GetTextureValue());
638
 
                c1->setFlags(Qt::ItemIsSelectable);
639
 
 
640
 
                ui.TexStatesTable->insertRow(rowidx);
641
 
                ui.TexStatesTable->setItem(rowidx, 0, c0);
642
 
                ui.TexStatesTable->setItem(rowidx, 1, c1);
643
 
                ui.TexStatesTable->resizeRowToContents(rowidx);
644
 
                ++rowidx;
645
 
        }
646
 
        ui.TexStatesTable->resizeColumnToContents(0);
647
 
        ui.TexStatesTable->resizeColumnToContents(1);
648
 
}
649
 
 
650
 
 
651
 
 
652
 
/*********************************
653
 
 * GLSL Syntax Highlighter Class *
654
 
 *********************************/
655
 
 
656
 
GLSLSynHlighter::GLSLSynHlighter(QTextDocument *parent)
657
 
        : QSyntaxHighlighter(parent)
658
 
{
659
 
        HighlightingRule rule;
660
 
 
661
 
        kwordsFormat.setForeground(Qt::blue);
662
 
        QStringList keywords;
663
 
        keywords << "uniform" << "int" << "float" << "bool" << "inout"
664
 
                         << "vec2" << "vec3" << "vec4" << "ivec2" << "out"
665
 
                         << "ivec3" << "ivec4" << "bvec2" << "bvec3" << "in"
666
 
                         << "bvec4" << "mat2" << "mat3" << "mat4" << "attribute"
667
 
                         << "sampler1D" << "sampler2D" << "sampler3D"
668
 
                         << "samplerCube" << "sampler1DShadow" << "void"
669
 
                         << "sampler2DShadow" << "varying" << "const";
670
 
 
671
 
        foreach (QString pattern, keywords) {
672
 
                rule.pattern = QRegExp("\\b" + pattern + "\\b");
673
 
                rule.format = kwordsFormat;
674
 
                highlightingRules.append(rule);
675
 
        }
676
 
 
677
 
        builtinsFormat.setForeground(Qt::magenta);
678
 
        QStringList builtins;
679
 
        builtins << "gl_Position" << "gl_ClipSize" << "gl_ClipVertex"
680
 
                 << "gl_Vertex" << "gl_Normal" << "gl_Color" << "gl_FragColor"
681
 
                 << "gl_SecondaryColor" << "gl_FogCoord" << "gl_MultiTexCoord[0-7]"
682
 
                 << "gl_FrontColor" << "gl_BackColor" << "gl_FrontSecondaryColor"
683
 
                 << "gl_BackSecondaryColor" << "gl_TexCoord" << "gl_FogFragCoord"
684
 
                 << "gl_FragData" << "gl_FrontFacing" << "gl_FragCoord"
685
 
                 << "gl_FragDepth" << "gl_ModelViewMatrix" << "gl_ProjectionMatrix"
686
 
                 << "gl_ModelViewProjectionMatrix" << "gl_ModelViewMatrixInverse"
687
 
                 << "gl_ModelViewProjectionMatrixInverse" << "gl_NormalMatrix"
688
 
                 << "gl_NormalScale" << "gl_DepthRange" << "gl_Point"
689
 
                 << "gl_ModelViewMatrixInverseTranspose" << "gl_LightSource"
690
 
                 << "gl_ModelViewMatrixTranspose" << "gl_ProjectionMatrixTranspose"
691
 
                 << "gl_ModelViewProjectionMatrixInverseTranspose" << "gl_Fog"
692
 
                 << "gl_ClipPlane" << "gl_(Eye|Object)Plane[STRQ]"
693
 
                 << "gl_(Front|Back)Material" << "gl_(Front|Back)LightProduct";
694
 
 
695
 
        foreach (QString pattern, builtins) {
696
 
                        rule.pattern = QRegExp("\\b" + pattern + "\\b");
697
 
                        rule.format = builtinsFormat;
698
 
                        highlightingRules.append(rule);
699
 
        }
700
 
 
701
 
        functionFormat.setForeground(QColor::fromRgb(255, 0, 141));
702
 
        QStringList functions;
703
 
        functions << "sin" << "cos" << "tan" << "asin" << "acos" << "atan"
704
 
                  << "radians" << "degrees" << "pow" << "exp" << "log"
705
 
                  << "expr2" << "log2" << "sqrt" << "inversesqrt" << "abs"
706
 
                  << "ceil" << "clamp" << "floor" << "fract" << "min" << "mix"
707
 
                  << "max" << "mod" << "sign" << "smoothstep" << "step"
708
 
                  << "ftransform" << "cross" << "distance" << "dot"
709
 
                  << "faceforward" << "length" << "normalize" << "reflect"
710
 
                  << "dFdx" << "dFdy" << "fwidth" << "matrixCompMult" << "all"
711
 
                  << "any" << "equal" << "greaterThan" << "lessThan" << "notEqual"
712
 
                  << "texture1DProj" << "texture2DProj" << "texture3DProj"
713
 
                  << "textureCube" << "noise4" << "texture3D" << "not" << "noise3"
714
 
                  << "texture1D" << "texture2D" << "noise1" << "noise2";
715
 
 
716
 
        foreach (QString pattern, functions) {
717
 
                rule.pattern = QRegExp("\\b" + pattern + "+(?=\\()");
718
 
                rule.format = functionFormat;
719
 
                highlightingRules.append(rule);
720
 
        }
721
 
 
722
 
        singleLineCommentFormat.setForeground(Qt::darkGreen);
723
 
        rule.pattern = QRegExp("//[^\n]*");
724
 
        rule.format = singleLineCommentFormat;
725
 
        highlightingRules.append(rule);
726
 
 
727
 
        multiLineCommentFormat = singleLineCommentFormat;
728
 
        commentStartExpression = QRegExp("/\\*");
729
 
        commentEndExpression = QRegExp("\\*/");
730
 
}
731
 
 
732
 
void GLSLSynHlighter::highlightBlock(const QString &text)
733
 
{
734
 
        foreach (HighlightingRule rule, highlightingRules) {
735
 
                QRegExp expression(rule.pattern);
736
 
                int index = text.indexOf(expression);
737
 
                while (index >= 0) {
738
 
                        int length = expression.matchedLength();
739
 
                        setFormat(index, length, rule.format);
740
 
                        index = text.indexOf(expression, index + length);
741
 
                }
742
 
        }
743
 
 
744
 
        /* multiline comment management */
745
 
        setCurrentBlockState(0);
746
 
 
747
 
        int startIndex = 0;
748
 
        if (previousBlockState() != 1)
749
 
                startIndex = text.indexOf(commentStartExpression);
750
 
 
751
 
         while (startIndex >= 0) {
752
 
                int endIndex = text.indexOf(commentEndExpression, startIndex);
753
 
                int commentLength;
754
 
                if (endIndex == -1) {
755
 
                        setCurrentBlockState(1);
756
 
                        commentLength = text.length() - startIndex;
757
 
                } else {
758
 
                        commentLength = endIndex - startIndex +
759
 
                                                 commentEndExpression.matchedLength();
760
 
                }
761
 
                setFormat(startIndex, commentLength, multiLineCommentFormat);
762
 
                startIndex = text.indexOf(commentStartExpression,
763
 
                                                      startIndex + commentLength);
764
 
        }
765
 
}
 
1
/****************************************************************************
 
2
* MeshLab                                                           o o     *
 
3
* A versatile mesh processing toolbox                             o     o   *
 
4
*                                                                _   O  _   *
 
5
* Copyright(C) 2005-2008                                           \/)\/    *
 
6
* Visual Computing Lab                                            /\/|      *
 
7
* ISTI - Italian National Research Council                           |      *
 
8
*                                                                    \      *
 
9
* All rights reserved.                                                      *
 
10
*                                                                           *
 
11
* This program is free software; you can redistribute it and/or modify      *
 
12
* it under the terms of the GNU General Public License as published by      *
 
13
* the Free Software Foundation; either version 2 of the License, or         *
 
14
* (at your option) any later version.                                       *
 
15
*                                                                           *
 
16
* This program is distributed in the hope that it will be useful,           *
 
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 
19
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
 
20
* for more details.                                                         *
 
21
*                                                                           *
 
22
****************************************************************************/
 
23
 
 
24
#include "rfx_dialog.h"
 
25
 
 
26
const float RfxDialog::DECTOINT = 10000.0f;
 
27
const float RfxDialog::INTTODEC = 0.0001f;
 
28
 
 
29
RfxDialog::RfxDialog(RfxShader *s, QAction *a, QGLWidget *parent)
 
30
        : QDockWidget(parent)
 
31
{
 
32
        shader = s;
 
33
        mGLWin = parent;
 
34
 
 
35
        ui.setupUi(this);
 
36
        setWindowTitle("RenderRfx [" + a->text() + "]");
 
37
 
 
38
        setWidget(ui.RfxDockContents);
 
39
        setFeatures(QDockWidget::AllDockWidgetFeatures);
 
40
        setAllowedAreas(Qt::LeftDockWidgetArea);
 
41
        setFloating(true);
 
42
 
 
43
        /* Passes */
 
44
        QListIterator<RfxGLPass*> pit = s->PassesIterator();
 
45
        while (pit.hasNext()) {
 
46
                RfxGLPass *pass = pit.next();
 
47
                ui.comboPasses->addItem("Pass #" +
 
48
                                                                QString().setNum(pass->GetPassIndex()) +
 
49
                                                                " " + pass->GetPassName() + " ");
 
50
        }
 
51
        // start from first pass
 
52
        connect(ui.comboPasses, SIGNAL(currentIndexChanged(int)), this,
 
53
                        SLOT(PassSelected(int)));
 
54
        selPass = 0;
 
55
        ui.comboPasses->setCurrentIndex(0);
 
56
 
 
57
        QFont fixedfont;
 
58
        fixedfont.setFamily("Courier");
 
59
        fixedfont.setFixedPitch(true);
 
60
        fixedfont.setPointSize(10);
 
61
        ui.textVert->setFont(fixedfont);
 
62
        ui.textFrag->setFont(fixedfont);
 
63
 
 
64
        vertHL = new GLSLSynHlighter(ui.textVert->document());
 
65
        fragHL = new GLSLSynHlighter(ui.textFrag->document());
 
66
 
 
67
        // fill log once for dialog, since it reports status for all passes
 
68
        ui.textLog->setPlainText(s->GetCompilationLog().join("\n"));
 
69
 
 
70
 
 
71
        // uniform tab will contain every uniform from every pass
 
72
        /* Uniforms */
 
73
        pit = s->PassesIterator();
 
74
        while (pit.hasNext()) {
 
75
                RfxGLPass *pass = pit.next();
 
76
 
 
77
                QListIterator<RfxUniform*> it = pass->UniformsIterator();
 
78
                int unifCount = -1; // keep track of uniform index
 
79
                while (it.hasNext()) {
 
80
                        unifCount++;
 
81
                        RfxUniform *uni = it.next();
 
82
                        if (uni->isTexture())
 
83
                                continue;
 
84
 
 
85
               /* Verifies if the type of the uniform is special or not */
 
86
               using namespace std;
 
87
               const type_info& ti  = typeid(*uni);
 
88
               
 
89
               if(ti != typeid(RfxSpecialUniform))
 
90
                             AddUniformBox(uni, unifCount);
 
91
               else{
 
92
                                   /* If the uniform is a special one, casts it to special uniform */
 
93
                    RfxSpecialUniform* sp = dynamic_cast<RfxSpecialUniform*>(uni);
 
94
                                        /* and initializes its value */
 
95
                    sp->initialize();
 
96
                    sp->PassToShader();
 
97
                           }
 
98
                }
 
99
 
 
100
                ++selPass;
 
101
        }
 
102
        selPass = 0;
 
103
 
 
104
        setupTabs();
 
105
}
 
106
 
 
107
void RfxDialog::setupTabs()
 
108
{
 
109
        /* Textures */
 
110
        ui.comboTextures->clear();
 
111
        ui.comboTextures->setEnabled(true);
 
112
        disconnect(ui.comboTextures, 0, 0, 0);
 
113
 
 
114
        QListIterator<RfxUniform*> it = shader->GetPass(selPass)->UniformsIterator();
 
115
        int unifCount = -1;
 
116
        while (it.hasNext()) {
 
117
                unifCount++;
 
118
                RfxUniform *uni = it.next();
 
119
                if (!uni->isTexture())
 
120
                        continue;
 
121
                ui.comboTextures->addItem("[" +
 
122
                                                                  RfxUniform::GetTypeString(uni->GetType()) +
 
123
                                                                  "] " +
 
124
                                                                  ((uni->isRenderable())? " (RT) " : "") +
 
125
                                                                  uni->GetName(),
 
126
                                                                  unifCount);
 
127
        }
 
128
 
 
129
        if (ui.comboTextures->count() == 0) {
 
130
                ui.comboTextures->addItem("No textures");
 
131
                ui.comboTextures->setDisabled(true);
 
132
        } else {
 
133
                ui.comboTextures->insertItem(0, "Select...");
 
134
                ui.comboTextures->setCurrentIndex(0);
 
135
                connect(ui.comboTextures, SIGNAL(currentIndexChanged(int)), this,
 
136
                                SLOT(TextureSelected(int)));
 
137
        }
 
138
 
 
139
        disconnect(ui.btnChangeTexture, 0, 0, 0);
 
140
        ui.BoxTextureProps->setTitle("");
 
141
        ui.EditTexFile->clear();
 
142
        ui.TexStatesTable->clear();
 
143
        ui.TexStatesTable->setRowCount(0);
 
144
        ui.TexStatesTable->setColumnCount(2);
 
145
        ui.TexStatesTable->horizontalHeader()->setStretchLastSection(true);
 
146
        ui.TexStatesTable->horizontalHeader()->hide();
 
147
        ui.TexStatesTable->verticalHeader()->hide();
 
148
        ui.lblPreview->clear();
 
149
 
 
150
 
 
151
        /* States */
 
152
        ui.glStatesTable->clear();
 
153
        ui.glStatesTable->setRowCount(0);
 
154
        ui.glStatesTable->setColumnCount(2);
 
155
        ui.glStatesTable->horizontalHeader()->setStretchLastSection(true);
 
156
        ui.glStatesTable->horizontalHeader()->hide();
 
157
        ui.glStatesTable->verticalHeader()->hide();
 
158
        QListIterator<RfxState*> sit = shader->GetPass(selPass)->StatesIterator();
 
159
        int rowidx = 0;
 
160
        while (sit.hasNext()) {
 
161
                RfxState *r = sit.next();
 
162
 
 
163
                // QTableWidget will take ownership of objects, do not delete them.
 
164
                QTableWidgetItem *c0 = new QTableWidgetItem(r->GetRenderState());
 
165
                c0->setFlags(Qt::ItemIsSelectable);
 
166
                QTableWidgetItem *c1 = new QTableWidgetItem(r->GetRenderValue());
 
167
                c1->setFlags(Qt::ItemIsSelectable);
 
168
 
 
169
                ui.glStatesTable->insertRow(rowidx);
 
170
                ui.glStatesTable->setItem(rowidx, 0, c0);
 
171
                ui.glStatesTable->setItem(rowidx, 1, c1);
 
172
                ui.glStatesTable->resizeRowToContents(rowidx);
 
173
                ++rowidx;
 
174
        }
 
175
        ui.glStatesTable->resizeColumnToContents(0);
 
176
        ui.glStatesTable->resizeColumnToContents(1);
 
177
 
 
178
 
 
179
        /* Vertex/Fragment source view */
 
180
        ui.textVert->setPlainText(shader->GetPass(selPass)->GetVertexSource());
 
181
        ui.textFrag->setPlainText(shader->GetPass(selPass)->GetFragmentSource());
 
182
}
 
183
 
 
184
RfxDialog::~RfxDialog()
 
185
{
 
186
        delete vertHL;
 
187
        delete fragHL;
 
188
 
 
189
        CleanTab(ALL_TABS);
 
190
}
 
191
 
 
192
void RfxDialog::PassSelected(int idx)
 
193
{
 
194
        selPass = idx;
 
195
        CleanTab(ALL_TABS);
 
196
        setupTabs();
 
197
}
 
198
 
 
199
void RfxDialog::AddUniformBox(RfxUniform *uni, int uniIndex)
 
200
{
 
201
        assert(uni);
 
202
 
 
203
        QLabel *lblUni = new QLabel();
 
204
        QString lblText;
 
205
 
 
206
        lblText.append(QString("(Pass #%1) ").arg(selPass));
 
207
        lblText.append(uni->GetName());
 
208
 
 
209
        if (!uni->GetSemantic().isNull()) {
 
210
                lblText.append("<span style=\"color:darkgreen;\"><br/> [P: ");
 
211
                lblText.append(uni->GetSemantic());
 
212
                lblText.append("]</span>");
 
213
        }
 
214
 
 
215
        lblUni->setText(lblText);
 
216
 
 
217
        QGridLayout *gridUni = new QGridLayout();
 
218
 
 
219
        switch (uni->GetType()) {
 
220
        case RfxUniform::INT:
 
221
        case RfxUniform::FLOAT:
 
222
        case RfxUniform::BOOL:
 
223
                DrawIFace(gridUni, uni, uniIndex, 1, 1);
 
224
                break;
 
225
 
 
226
        case RfxUniform::VEC2:
 
227
        case RfxUniform::IVEC2:
 
228
        case RfxUniform::BVEC2:
 
229
                DrawIFace(gridUni, uni, uniIndex, 1, 2);
 
230
                break;
 
231
 
 
232
        case RfxUniform::VEC3:
 
233
        case RfxUniform::IVEC3:
 
234
        case RfxUniform::BVEC3:
 
235
                DrawIFace(gridUni, uni, uniIndex, 1, 3);
 
236
                break;
 
237
 
 
238
        case RfxUniform::VEC4:
 
239
                if(uni->isRmColorVariable()){
 
240
                        DrawIFace(gridUni, uni, uniIndex, 1, 1);
 
241
                        break;
 
242
                }
 
243
        case RfxUniform::IVEC4:
 
244
        case RfxUniform::BVEC4:
 
245
                DrawIFace(gridUni, uni, uniIndex, 1, 4);
 
246
                break;
 
247
 
 
248
        case RfxUniform::MAT2:
 
249
                DrawIFace(gridUni, uni, uniIndex, 2, 2);
 
250
                break;
 
251
 
 
252
        case RfxUniform::MAT3:
 
253
                DrawIFace(gridUni, uni, uniIndex, 3, 3);
 
254
                break;
 
255
 
 
256
        case RfxUniform::MAT4:
 
257
                DrawIFace(gridUni, uni, uniIndex, 4, 4);
 
258
                break;
 
259
 
 
260
        default:
 
261
                return;
 
262
        }
 
263
 
 
264
        QHBoxLayout *boxContent = new QHBoxLayout();
 
265
        boxContent->addWidget(lblUni);
 
266
        boxContent->addLayout(gridUni);
 
267
 
 
268
        ((QVBoxLayout*)ui.scrollUniformsContents->layout())->addLayout(boxContent);
 
269
}
 
270
 
 
271
void RfxDialog::DrawIFace(QGridLayout *parent, RfxUniform *u, int uidx, int rows, int columns)
 
272
{
 
273
        enum controlType { INT_CTRL, FLOAT_CTRL, BOOL_CTRL, COLOR_CTRL };
 
274
        enum ColorComponentsType { R, G, B, A };
 
275
        float *val = u->GetValue();
 
276
        controlType ctrl;
 
277
        ColorComponentsType rgba = R;
 
278
        QWidget **controls = new QWidget*[rows * columns];
 
279
        QGridLayout *uniLayout = parent;
 
280
        QHBoxLayout *sliderEditLayout = NULL;
 
281
        bool multipleControls = false;
 
282
        QSignalMapper *valMapper = new QSignalMapper(this);
 
283
 
 
284
        switch (u->GetType()) {
 
285
        case RfxUniform::INT:
 
286
        case RfxUniform::IVEC2:
 
287
        case RfxUniform::IVEC3:
 
288
        case RfxUniform::IVEC4:
 
289
                ctrl = INT_CTRL;
 
290
                break;
 
291
 
 
292
        case RfxUniform::FLOAT:
 
293
        case RfxUniform::VEC2:
 
294
        case RfxUniform::VEC3:
 
295
        case RfxUniform::VEC4:
 
296
                if(u->isRmColorVariable()){
 
297
                        ctrl = COLOR_CTRL;
 
298
                        break;
 
299
                }
 
300
        case RfxUniform::MAT2:
 
301
        case RfxUniform::MAT3:
 
302
        case RfxUniform::MAT4:
 
303
                ctrl = FLOAT_CTRL;
 
304
                break;
 
305
 
 
306
        case RfxUniform::BOOL:
 
307
        case RfxUniform::BVEC2:
 
308
        case RfxUniform::BVEC3:
 
309
        case RfxUniform::BVEC4:
 
310
                ctrl = BOOL_CTRL;
 
311
                break;
 
312
 
 
313
        default:
 
314
                return;
 
315
        }
 
316
        if(ctrl == COLOR_CTRL)
 
317
        {
 
318
                RfxColorBox* mycolorBox = new RfxColorBox(100, 25, QColor(val[0] * 255, val[1] * 255, val[2] * 255, val[3] * 255));
 
319
                uniLayout->addWidget(mycolorBox, 0,0);
 
320
                connect(mycolorBox, SIGNAL(colorChanged()), valMapper, SLOT(map()));
 
321
                valMapper->setMapping(mycolorBox,
 
322
                                              QString().setNum(uidx) + '-' +
 
323
                                              QString().setNum(1)  + '-' +
 
324
                                              QString().setNum(selPass));
 
325
        }
 
326
        else{
 
327
        // controls in a grid layout
 
328
        for (int i = 0; i < rows; ++i) {
 
329
                for (int j = 0; j < columns; ++j) {
 
330
                        int arrayIdx = j + (i * rows);
 
331
                        switch (ctrl) {
 
332
                        case INT_CTRL:
 
333
                                controls[arrayIdx] = new QSpinBox(this);
 
334
                                ((QSpinBox*)controls[arrayIdx])->setRange(-99, 99);
 
335
                                ((QSpinBox*)controls[arrayIdx])->setValue((int)val[arrayIdx]);
 
336
                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)),
 
337
                                        valMapper, SLOT(map()));
 
338
                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)), this,
 
339
                                        SLOT(extendRange(int)));
 
340
                                break;
 
341
                        case FLOAT_CTRL:
 
342
                                if (u->HasMinMax()) {
 
343
                                        controls[arrayIdx] = new QSlider(this);
 
344
                                        ((QSlider*)controls[arrayIdx])->setTickPosition(QSlider::NoTicks);
 
345
                                        ((QSlider*)controls[arrayIdx])->setOrientation(Qt::Horizontal);
 
346
 
 
347
                                        // since qslider only deals with integers, do a little conversion
 
348
                                        // of values
 
349
                                        // keep as much as 5 decimal values, others will be lost in conversion
 
350
                                        int valAsInt = (int)(val[arrayIdx] * DECTOINT);
 
351
                                        int tickAsInt = (int)(((u->GetMaxRange() - u->GetMinRange()) * 0.01) * DECTOINT);
 
352
 
 
353
                                        ((QSlider*)controls[arrayIdx])->setTickInterval(tickAsInt);
 
354
                                        ((QSlider*)controls[arrayIdx])->setRange((int)(u->GetMinRange() * DECTOINT),
 
355
                                                                                 (int)(u->GetMaxRange() * DECTOINT));
 
356
                                        ((QSlider*)controls[arrayIdx])->setValue(valAsInt);
 
357
                                        ((QSlider*)controls[arrayIdx])->setToolTip(QString().setNum(val[arrayIdx]));
 
358
 
 
359
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(int)), valMapper, SLOT(map()));
 
360
 
 
361
                                        // as per request, if value is a single float, also show a qlineedit to allow
 
362
                                        // more accurate settings.
 
363
                                        if (u->GetType() == RfxUniform::FLOAT) {
 
364
 
 
365
                                                QLineEdit *slideValue = new QLineEdit();
 
366
                                                slideValue->setAlignment(Qt::AlignRight);
 
367
                                                slideValue->setText(QString().setNum(val[arrayIdx]));
 
368
 
 
369
                                                QSignalMapper *yaMapper = new QSignalMapper();
 
370
                                                connect(controls[arrayIdx], SIGNAL(valueChanged(int)), yaMapper, SLOT(map()));
 
371
                                                connect(slideValue, SIGNAL(editingFinished()), yaMapper, SLOT(map()));
 
372
                                                yaMapper->setMapping(controls[arrayIdx], slideValue);
 
373
                                                yaMapper->setMapping(slideValue, controls[arrayIdx]);
 
374
                                                connect(yaMapper, SIGNAL(mapped(QWidget*)), this, SLOT(mapSliderLineEdit(QWidget*)));
 
375
 
 
376
                                                if (!u->GetSemantic().isNull())
 
377
                                                        slideValue->setDisabled(true);
 
378
 
 
379
                                                multipleControls = true;
 
380
                                                sliderEditLayout = new QHBoxLayout();
 
381
                                                sliderEditLayout->addWidget(controls[arrayIdx]);
 
382
                                                sliderEditLayout->addWidget(slideValue);
 
383
                                        }
 
384
 
 
385
                                } else {
 
386
                                        controls[arrayIdx] = new QDoubleSpinBox(this);
 
387
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setRange(-99.0, 99.0);
 
388
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setValue(val[arrayIdx]);
 
389
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setDecimals(4);
 
390
                                        ((QDoubleSpinBox*)controls[arrayIdx])->setSingleStep(0.01);
 
391
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(double)),
 
392
                                                        valMapper, SLOT(map()));
 
393
                                        connect(controls[arrayIdx], SIGNAL(valueChanged(double)), this,
 
394
                                                        SLOT(extendRange(double)));
 
395
                                }
 
396
                                break;
 
397
                        case BOOL_CTRL:
 
398
                                controls[arrayIdx] = new QComboBox(this);
 
399
                                ((QComboBox*)controls[arrayIdx])->addItem("FALSE");
 
400
                                ((QComboBox*)controls[arrayIdx])->addItem("TRUE");
 
401
                                if (!val[arrayIdx])
 
402
                                        ((QComboBox*)controls[arrayIdx])->setCurrentIndex(0);
 
403
                                connect(controls[arrayIdx], SIGNAL(currentIndexChanged(int)),
 
404
                                                valMapper, SLOT(map()));
 
405
                                break;
 
406
 
 
407
                                
 
408
                        }
 
409
 
 
410
                        valMapper->setMapping(controls[arrayIdx],
 
411
                                              QString().setNum(uidx) + '-' +
 
412
                                              QString().setNum(arrayIdx)  + '-' +
 
413
                                              QString().setNum(selPass));
 
414
 
 
415
                        if (!u->GetSemantic().isNull())
 
416
                                controls[arrayIdx]->setDisabled(true);
 
417
 
 
418
                        if (multipleControls)
 
419
                                uniLayout->addLayout(sliderEditLayout, i, j);
 
420
                        else
 
421
                                uniLayout->addWidget(controls[arrayIdx], i, j);
 
422
                        multipleControls = false;
 
423
                }
 
424
        }
 
425
}
 
426
        connect(valMapper, SIGNAL(mapped(const QString&)), this,
 
427
                SLOT(ChangeValue(const QString&)));
 
428
}
 
429
 
 
430
void RfxDialog::mapSliderLineEdit(QWidget *w)
 
431
{
 
432
        QObject *theSender = ((QSignalMapper*)QObject::sender())->mapping(w);
 
433
 
 
434
        QSlider *qslide = dynamic_cast<QSlider*>(theSender);
 
435
        if (qslide != NULL) {
 
436
                ((QLineEdit*)w)->setText(QString().setNum((float)(qslide->value()) * INTTODEC));
 
437
        } else {
 
438
                // we assume it's a QLineEdit (avoid a costly and useless dynamic_cast)
 
439
                // let's do some more checks since qlineedit input is not limited in range
 
440
                bool res = false;
 
441
                float val = ((QLineEdit*)theSender)->text().toFloat(&res);
 
442
                qslide = ((QSlider*)w);
 
443
 
 
444
                // we only accept float values
 
445
                if (!res)
 
446
                        return;
 
447
 
 
448
                // if value is beyond min or max, just set min/max
 
449
                if (val > qslide->maximum() * INTTODEC)
 
450
                        qslide->setValue(qslide->maximum());
 
451
                else if (val < qslide->minimum() * INTTODEC)
 
452
                        qslide->setValue(qslide->minimum());
 
453
                else
 
454
                        qslide->setValue((int)(val * DECTOINT));
 
455
        }
 
456
}
 
457
 
 
458
void RfxDialog::CleanTab(int tabIdx)
 
459
{
 
460
        // deletes all widgets from specified tab or, if tabIdx == -1
 
461
        // removes all widgets from all tabs
 
462
        // (this applies to *dynamically created* widgets only)
 
463
 
 
464
        if (tabIdx == ALL_TABS) {
 
465
                QMapIterator<int, QWidget*> it(widgetsByTab);
 
466
                while (it.hasNext()) {
 
467
                        QWidget *toDelete = it.next().value();
 
468
                        toDelete->close();
 
469
                        delete toDelete;
 
470
                }
 
471
                widgetsByTab.clear();
 
472
 
 
473
        } else {
 
474
                QList<QWidget*> toDelete = widgetsByTab.values(tabIdx);
 
475
                for (int i = 0; i < toDelete.size(); ++i) {
 
476
                        toDelete.at(i)->close();
 
477
                        delete toDelete.at(i);
 
478
                }
 
479
                widgetsByTab.remove(tabIdx);
 
480
        }
 
481
}
 
482
 
 
483
void RfxDialog::extendRange(double newVal)
 
484
{
 
485
        QDoubleSpinBox *sender = (QDoubleSpinBox*)QObject::sender();
 
486
        if (newVal == sender->minimum() || newVal == sender->maximum()) {
 
487
                if (newVal == sender->minimum())
 
488
                        sender->setMinimum(newVal - 50);
 
489
                else
 
490
                        sender->setMaximum(newVal + 50);
 
491
        }
 
492
}
 
493
 
 
494
void RfxDialog::extendRange(int newVal)
 
495
{
 
496
        QSpinBox *sender = (QSpinBox*)QObject::sender();
 
497
        if (newVal == sender->minimum() || newVal == sender->maximum()) {
 
498
                if (newVal == sender->minimum())
 
499
                        sender->setMinimum(newVal - 50);
 
500
                else
 
501
                        sender->setMaximum(newVal + 50);
 
502
        }
 
503
}
 
504
 
 
505
void RfxDialog::ChangeTexture(int unifIdx)
 
506
{
 
507
        int uniIndex = ui.comboTextures->itemData(unifIdx).toInt();
 
508
        RfxUniform *uni = shader->GetPass(selPass)->getUniform(uniIndex);
 
509
        assert(uni);
 
510
 
 
511
        QString fname = QFileDialog::getOpenFileName(this,
 
512
                                                     tr("Choose Texture"),
 
513
                                                     uni->GetTextureFName());
 
514
        if (!fname.isEmpty()) {
 
515
                uni->SetValue(QDir::fromNativeSeparators(fname));
 
516
                uni->LoadTexture();
 
517
                uni->PassToShader();
 
518
                mGLWin->updateGL();
 
519
 
 
520
                // generate a currentIndexChanged event
 
521
                ui.comboTextures->setCurrentIndex(0);
 
522
                ui.comboTextures->setCurrentIndex(unifIdx);
 
523
        }
 
524
}
 
525
 
 
526
void RfxDialog::ChangeValue(const QString& val)
 
527
{
 
528
        QStringList unif = val.split('-');
 
529
        RfxUniform *uni = shader->GetPass(unif[2].toInt())->getUniform(unif[0].toInt());
 
530
        float *oldVal = uni->GetValue();
 
531
        float newVal = 0.0f;
 
532
 
 
533
        QObject *sender = ((QSignalMapper*)QObject::sender())->mapping(val);
 
534
        assert(sender);
 
535
 
 
536
        QComboBox *cbox = dynamic_cast<QComboBox*>(sender);
 
537
        if (cbox != NULL) {
 
538
                newVal = cbox->currentIndex();
 
539
        } else {
 
540
                QSpinBox *sbox = dynamic_cast<QSpinBox*>(sender);
 
541
                if (sbox != NULL) {
 
542
                        newVal = sbox->value();
 
543
                } else {
 
544
                        QDoubleSpinBox *dsbox = dynamic_cast<QDoubleSpinBox*>(sender);
 
545
                        if (dsbox != NULL) {
 
546
                                newVal = dsbox->value();
 
547
                        } else {
 
548
                                QSlider *qslide = dynamic_cast<QSlider*>(sender);
 
549
                                if (qslide != NULL) {
 
550
                                        newVal = qslide->value() * INTTODEC;
 
551
                                        qslide->setToolTip(QString().setNum(newVal));
 
552
                                } else {
 
553
                                        RfxColorBox *cBox = dynamic_cast<RfxColorBox*>(sender);
 
554
                                        if (cBox != NULL) {
 
555
                                                float* newVal = cBox->getColorf();
 
556
                                                oldVal[0] = newVal[0];
 
557
                                                oldVal[1] = newVal[1];
 
558
                                                oldVal[2] = newVal[2];
 
559
                                                oldVal[3] = newVal[3];
 
560
                                                uni->PassToShader();
 
561
                                                mGLWin->updateGL();
 
562
                                                return;
 
563
                                        } else {
 
564
                                                return;
 
565
                                        }
 
566
                                }
 
567
                        }
 
568
                }
 
569
        }
 
570
 
 
571
        oldVal[unif[1].toInt()] = newVal;
 
572
        uni->PassToShader();
 
573
        mGLWin->updateGL();
 
574
}
 
575
void RfxDialog::TextureSelected(int idx)
 
576
{
 
577
        disconnect(ui.btnChangeTexture, 0, 0, 0);
 
578
 
 
579
        if (idx <= 0)
 
580
                return;
 
581
 
 
582
        int uniIndex = ui.comboTextures->itemData(idx).toInt();
 
583
        RfxUniform *uni = shader->GetPass(selPass)->getUniform(uniIndex);
 
584
        assert(uni);
 
585
 
 
586
        // connect Change Texture button
 
587
        QSignalMapper *sigMap = new QSignalMapper(this);
 
588
        connect(ui.btnChangeTexture, SIGNAL(clicked()), sigMap, SLOT(map()));
 
589
        sigMap->setMapping(ui.btnChangeTexture, idx);
 
590
        connect(sigMap, SIGNAL(mapped(int)), this, SLOT(ChangeTexture(int)));
 
591
 
 
592
        ui.BoxTextureProps->setTitle(uni->GetName());
 
593
 
 
594
        // clean and initialize table
 
595
        ui.TexStatesTable->clear();
 
596
        ui.TexStatesTable->setRowCount(0);
 
597
        ui.TexStatesTable->setColumnCount(2);
 
598
        ui.TexStatesTable->horizontalHeader()->setStretchLastSection(true);
 
599
        ui.TexStatesTable->horizontalHeader()->hide();
 
600
        ui.TexStatesTable->verticalHeader()->hide();
 
601
 
 
602
        // delete any existing preview
 
603
        ui.lblPreview->clear();
 
604
 
 
605
        CleanTab(TEXTURE_TAB);
 
606
 
 
607
        if (uni->isRenderable())
 
608
                ui.EditTexFile->clear();
 
609
        else
 
610
                ui.EditTexFile->setText(uni->GetTextureFName());
 
611
 
 
612
        QLabel *fname = new QLabel();
 
613
        ui.infoTexLayout->addWidget(fname);
 
614
        widgetsByTab.insert(TEXTURE_TAB, fname);
 
615
        if (!uni->isTextureFound() || !uni->isTextureLoaded()) {
 
616
                if (!uni->isTextureFound())
 
617
                        fname->setText("<span style=\"color:darkred;\">Texture file not found</span>");
 
618
                else
 
619
                        fname->setText("<span style=\"color:darkred;\">Texture binding failed</span>");
 
620
        } else {
 
621
                fname->setText("<span style=\"color:darkgreen;\">Texture loaded</span>");
 
622
 
 
623
                ImageInfo ii;
 
624
                bool loaded;
 
625
                if (uni->isRenderable()) {
 
626
                        ii.preview = uni->GetRTTexture();
 
627
                        ii.texType = "Render Target";
 
628
                        ii.width = (ii.preview.isNull())? 0 : ii.preview.width();
 
629
                        ii.height = (ii.preview.isNull())? 0 : ii.preview.height();
 
630
                        ii.depth = 1;
 
631
                        ii.format = "";
 
632
                } else {
 
633
                        ii = RfxTextureLoader::LoadAsQImage(uni->GetTextureFName());
 
634
                }
 
635
                loaded = !ii.preview.isNull();
 
636
 
 
637
                if (loaded) {
 
638
                        QLabel *tSize = new QLabel();
 
639
                        tSize->setText("Dimensions: " +
 
640
                                               QString().setNum(ii.width) + " x " +
 
641
                                       QString().setNum(ii.height) +
 
642
                                       ((ii.depth > 1)? " x " + QString().setNum(ii.depth) : ""));
 
643
                        ui.infoTexLayout->addWidget(tSize);
 
644
                        widgetsByTab.insert(TEXTURE_TAB, tSize);
 
645
 
 
646
                        QLabel *tType = new QLabel();
 
647
                        tType->setText("Type: " + ii.texType);
 
648
                        ui.infoTexLayout->addWidget(tType);
 
649
                        widgetsByTab.insert(TEXTURE_TAB, tType);
 
650
 
 
651
                        QLabel *tFormat = new QLabel();
 
652
                        tFormat->setText("Format: " + ii.format);
 
653
                        ui.infoTexLayout->addWidget(tFormat);
 
654
                        widgetsByTab.insert(TEXTURE_TAB, tFormat);
 
655
 
 
656
                        // try to get a preview
 
657
                        QPixmap prvw = QPixmap::fromImage(ii.preview);
 
658
                        if (!prvw.isNull()) {
 
659
                                QSize scaledSize(120, 120);
 
660
                                if (ii.texType == "Cubemap Texture")
 
661
                                        scaledSize.setWidth(200);
 
662
 
 
663
                                ui.lblPreview->setPixmap(prvw.scaled(scaledSize,
 
664
                                                                     Qt::KeepAspectRatio));
 
665
                        }
 
666
                }
 
667
 
 
668
                QLabel *tunit = new QLabel();
 
669
                tunit->setText("Texture Unit: " + QString().setNum(uni->GetTU()));
 
670
                ui.infoTexLayout->addWidget(tunit);
 
671
                widgetsByTab.insert(TEXTURE_TAB, tunit);
 
672
        }
 
673
 
 
674
        QListIterator<RfxState*> it = uni->StatesIterator();
 
675
        int rowidx = 0;
 
676
        while (it.hasNext()) {
 
677
                RfxState *r = it.next();
 
678
 
 
679
                // QTableWidget will take ownership of objects, do not delete them.
 
680
                QTableWidgetItem *c0 = new QTableWidgetItem(r->GetTextureState());
 
681
                c0->setFlags(Qt::ItemIsSelectable);
 
682
                QTableWidgetItem *c1 = new QTableWidgetItem(r->GetTextureValue());
 
683
                c1->setFlags(Qt::ItemIsSelectable);
 
684
 
 
685
                ui.TexStatesTable->insertRow(rowidx);
 
686
                ui.TexStatesTable->setItem(rowidx, 0, c0);
 
687
                ui.TexStatesTable->setItem(rowidx, 1, c1);
 
688
                ui.TexStatesTable->resizeRowToContents(rowidx);
 
689
                ++rowidx;
 
690
        }
 
691
        ui.TexStatesTable->resizeColumnToContents(0);
 
692
        ui.TexStatesTable->resizeColumnToContents(1);
 
693
}
 
694
 
 
695
 
 
696
 
 
697
/*********************************
 
698
 * GLSL Syntax Highlighter Class *
 
699
 *********************************/
 
700
 
 
701
GLSLSynHlighter::GLSLSynHlighter(QTextDocument *parent)
 
702
        : QSyntaxHighlighter(parent)
 
703
{
 
704
        HighlightingRule rule;
 
705
 
 
706
        kwordsFormat.setForeground(Qt::blue);
 
707
        QStringList keywords;
 
708
        keywords << "uniform" << "int" << "float" << "bool" << "inout"
 
709
                         << "vec2" << "vec3" << "vec4" << "ivec2" << "out"
 
710
                         << "ivec3" << "ivec4" << "bvec2" << "bvec3" << "in"
 
711
                         << "bvec4" << "mat2" << "mat3" << "mat4" << "attribute"
 
712
                         << "sampler1D" << "sampler2D" << "sampler3D"
 
713
                         << "samplerCube" << "sampler1DShadow" << "void"
 
714
                         << "sampler2DShadow" << "varying" << "const";
 
715
 
 
716
        foreach (QString pattern, keywords) {
 
717
                rule.pattern = QRegExp("\\b" + pattern + "\\b");
 
718
                rule.format = kwordsFormat;
 
719
                highlightingRules.append(rule);
 
720
        }
 
721
 
 
722
        builtinsFormat.setForeground(Qt::magenta);
 
723
        QStringList builtins;
 
724
        builtins << "gl_Position" << "gl_ClipSize" << "gl_ClipVertex"
 
725
                 << "gl_Vertex" << "gl_Normal" << "gl_Color" << "gl_FragColor"
 
726
                 << "gl_SecondaryColor" << "gl_FogCoord" << "gl_MultiTexCoord[0-7]"
 
727
                 << "gl_FrontColor" << "gl_BackColor" << "gl_FrontSecondaryColor"
 
728
                 << "gl_BackSecondaryColor" << "gl_TexCoord" << "gl_FogFragCoord"
 
729
                 << "gl_FragData" << "gl_FrontFacing" << "gl_FragCoord"
 
730
                 << "gl_FragDepth" << "gl_ModelViewMatrix" << "gl_ProjectionMatrix"
 
731
                 << "gl_ModelViewProjectionMatrix" << "gl_ModelViewMatrixInverse"
 
732
                 << "gl_ModelViewProjectionMatrixInverse" << "gl_NormalMatrix"
 
733
                 << "gl_NormalScale" << "gl_DepthRange" << "gl_Point"
 
734
                 << "gl_ModelViewMatrixInverseTranspose" << "gl_LightSource"
 
735
                 << "gl_ModelViewMatrixTranspose" << "gl_ProjectionMatrixTranspose"
 
736
                 << "gl_ModelViewProjectionMatrixInverseTranspose" << "gl_Fog"
 
737
                 << "gl_ClipPlane" << "gl_(Eye|Object)Plane[STRQ]"
 
738
                 << "gl_(Front|Back)Material" << "gl_(Front|Back)LightProduct";
 
739
 
 
740
        foreach (QString pattern, builtins) {
 
741
                        rule.pattern = QRegExp("\\b" + pattern + "\\b");
 
742
                        rule.format = builtinsFormat;
 
743
                        highlightingRules.append(rule);
 
744
        }
 
745
 
 
746
        functionFormat.setForeground(QColor::fromRgb(255, 0, 141));
 
747
        QStringList functions;
 
748
        functions << "sin" << "cos" << "tan" << "asin" << "acos" << "atan"
 
749
                  << "radians" << "degrees" << "pow" << "exp" << "log"
 
750
                  << "expr2" << "log2" << "sqrt" << "inversesqrt" << "abs"
 
751
                  << "ceil" << "clamp" << "floor" << "fract" << "min" << "mix"
 
752
                  << "max" << "mod" << "sign" << "smoothstep" << "step"
 
753
                  << "ftransform" << "cross" << "distance" << "dot"
 
754
                  << "faceforward" << "length" << "normalize" << "reflect"
 
755
                  << "dFdx" << "dFdy" << "fwidth" << "matrixCompMult" << "all"
 
756
                  << "any" << "equal" << "greaterThan" << "lessThan" << "notEqual"
 
757
                  << "texture1DProj" << "texture2DProj" << "texture3DProj"
 
758
                  << "textureCube" << "noise4" << "texture3D" << "not" << "noise3"
 
759
                  << "texture1D" << "texture2D" << "noise1" << "noise2";
 
760
 
 
761
        foreach (QString pattern, functions) {
 
762
                rule.pattern = QRegExp("\\b" + pattern + "+(?=\\()");
 
763
                rule.format = functionFormat;
 
764
                highlightingRules.append(rule);
 
765
        }
 
766
 
 
767
        singleLineCommentFormat.setForeground(Qt::darkGreen);
 
768
        rule.pattern = QRegExp("//[^\n]*");
 
769
        rule.format = singleLineCommentFormat;
 
770
        highlightingRules.append(rule);
 
771
 
 
772
        multiLineCommentFormat = singleLineCommentFormat;
 
773
        commentStartExpression = QRegExp("/\\*");
 
774
        commentEndExpression = QRegExp("\\*/");
 
775
}
 
776
 
 
777
void GLSLSynHlighter::highlightBlock(const QString &text)
 
778
{
 
779
        foreach (HighlightingRule rule, highlightingRules) {
 
780
                QRegExp expression(rule.pattern);
 
781
                int index = text.indexOf(expression);
 
782
                while (index >= 0) {
 
783
                        int length = expression.matchedLength();
 
784
                        setFormat(index, length, rule.format);
 
785
                        index = text.indexOf(expression, index + length);
 
786
                }
 
787
        }
 
788
 
 
789
        /* multiline comment management */
 
790
        setCurrentBlockState(0);
 
791
 
 
792
        int startIndex = 0;
 
793
        if (previousBlockState() != 1)
 
794
                startIndex = text.indexOf(commentStartExpression);
 
795
 
 
796
         while (startIndex >= 0) {
 
797
                int endIndex = text.indexOf(commentEndExpression, startIndex);
 
798
                int commentLength;
 
799
                if (endIndex == -1) {
 
800
                        setCurrentBlockState(1);
 
801
                        commentLength = text.length() - startIndex;
 
802
                } else {
 
803
                        commentLength = endIndex - startIndex +
 
804
                                                 commentEndExpression.matchedLength();
 
805
                }
 
806
                setFormat(startIndex, commentLength, multiLineCommentFormat);
 
807
                startIndex = text.indexOf(commentStartExpression,
 
808
                                                      startIndex + commentLength);
 
809
        }
 
810
}
 
 
b'\\ No newline at end of file'