diff --git a/ChangeLog b/ChangeLog index 08855fe..ad45c9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,7 @@ GUI : * Previews locations and render params are now saved. * Added grid and axis labels to curve editor. * Added camera location to previews. + * Added toggles and choices to configure some previews. Misc : * Version handling in saved files. diff --git a/TODO b/TODO index d907b6a..b590f81 100644 --- a/TODO +++ b/TODO @@ -9,7 +9,6 @@ Technology Preview 2 : - Add layer sorting/naming. - Add logarithmic sliders for some float values. - Improve previews. - => Add a right click menu for toggles and modes => Add user markers on OSD - Add a zone editor dialog for localized textures. - Add a terrain modifier dialog with zones. @@ -39,7 +38,6 @@ Technology Preview 3 : - Mark modified tabs and ask for losing modifications (idem for layers). - Fix potential holes in land rendering. - Progressive final render (increasing resolution, for second pass only). -- Propose several backgrounds for water preview (grid, sinus...). - Water and terrain LOD moves with the camera, fix it like in the wanderer. - Improve 3d explorer => Restore LOD and intelligent poly count (and raise max tessellation) diff --git a/gui_qt/basepreview.cpp b/gui_qt/basepreview.cpp index 20a10c2..bdfd7e9 100644 --- a/gui_qt/basepreview.cpp +++ b/gui_qt/basepreview.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "tools.h" #include "../lib_paysages/system.h" @@ -270,7 +271,7 @@ int PreviewDrawingManager::chunkCount() BasePreview::BasePreview(QWidget* parent) : QWidget(parent) { - this->lock_drawing = new QMutex(); + this->_lock_drawing = new QMutex(); this->conf_scroll_xmin = 0.0; this->conf_scroll_xmax = 0.0; @@ -287,8 +288,8 @@ QWidget(parent) this->scalingbase = 1.0; this->xoffset = 0.0; this->yoffset = 0.0; - this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); - this->pixbuf->fill(0x00000000); + this->_pixbuf = new QImage(this->size(), QImage::Format_ARGB32); + this->_pixbuf->fill(0x00000000); _width = width(); _height = height(); _revision = 0; @@ -314,8 +315,8 @@ BasePreview::~BasePreview() _drawing_manager->removeChunks(this); delete _info; - delete pixbuf; - delete lock_drawing; + delete _pixbuf; + delete _lock_drawing; } void BasePreview::addOsd(QString name) @@ -329,6 +330,8 @@ void BasePreview::savePack(PackStream* stream) packWriteDouble(stream, &this->xoffset); packWriteDouble(stream, &this->yoffset); packWriteDouble(stream, &this->scaling); + + // TODO Save choices and toggles } void BasePreview::loadPack(PackStream* stream) @@ -336,6 +339,9 @@ void BasePreview::loadPack(PackStream* stream) packReadDouble(stream, &this->xoffset); packReadDouble(stream, &this->yoffset); packReadDouble(stream, &this->scaling); + + // TODO Save choices and toggles + emit contentChange(); } @@ -400,6 +406,37 @@ void BasePreview::configScrolling(double xmin, double xmax, double xinit, double redraw(); } +void BasePreview::addChoice(const QString& key, const QString& title, const QStringList& choices, int init_value) +{ + _ContextChoice choice; + choice.title = title; + choice.items << choices; + choice.current = init_value; + + _choices.insert(key, choice); + + choiceChangeEvent(key, init_value); +} + +void BasePreview::choiceChangeEvent(const QString&, int) +{ +} + +void BasePreview::addToggle(const QString& key, const QString& text, bool init_value) +{ + _ContextToggle toggle; + toggle.title = text; + toggle.value = init_value; + + _toggles.insert(key, toggle); + + toggleChangeEvent(key, init_value); +} + +void BasePreview::toggleChangeEvent(QString, bool) +{ +} + void BasePreview::redraw() { emit(redrawRequested()); @@ -408,24 +445,24 @@ void BasePreview::redraw() QImage BasePreview::startChunkTransaction(int x, int y, int w, int h, int* revision) { *revision = _revision; - return pixbuf->copy(x, y, w, h); + return _pixbuf->copy(x, y, w, h); } void BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision) { - lock_drawing->lock(); + _lock_drawing->lock(); if (revision == _revision) { for (int ix = 0; ix < w; ix++) { for (int iy = 0; iy < h; iy++) { - pixbuf->setPixel(x + ix, y + iy, chunk->pixel(ix, iy)); + _pixbuf->setPixel(x + ix, y + iy, chunk->pixel(ix, iy)); } } emit contentChange(); } - lock_drawing->unlock(); + _lock_drawing->unlock(); } QColor BasePreview::getPixelColor(int x, int y) @@ -435,12 +472,41 @@ QColor BasePreview::getPixelColor(int x, int y) void BasePreview::handleRedraw() { - lock_drawing->lock(); + _lock_drawing->lock(); updateData(); invalidatePixbuf(128); - lock_drawing->unlock(); + _lock_drawing->unlock(); +} + +void BasePreview::choiceSelected(QAction* action) +{ + switch (action->property("mode").toInt()) + { + case 1: + { + QString key = action->property("key").toString(); + int value = action->property("value").toInt(); + + _choices[key].current = value; + + choiceChangeEvent(key, value); + break; + } + case 2: + { + QString key = action->property("key").toString(); + bool value = action->property("value").toBool(); + + _toggles[key].value = value; + + toggleChangeEvent(key, value); + break; + } + default: + ; + } } void BasePreview::showEvent(QShowEvent* event) @@ -453,16 +519,16 @@ void BasePreview::resizeEvent(QResizeEvent* event) QImage* image; int added = 0; - this->lock_drawing->lock(); + this->_lock_drawing->lock(); - image = this->pixbuf; + image = this->_pixbuf; _width = event->size().width(); _height = event->size().height(); - this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); + this->_pixbuf = new QImage(this->size(), QImage::Format_ARGB32); - this->pixbuf->fill(0x00000000); + this->_pixbuf->fill(0x00000000); _drawing_manager->removeChunks(this); for (int x = 0; x < _width; x += 32) @@ -477,15 +543,15 @@ void BasePreview::resizeEvent(QResizeEvent* event) delete image; - this->lock_drawing->unlock(); + this->_lock_drawing->unlock(); } void BasePreview::paintEvent(QPaintEvent* event) { QPainter painter(this); - painter.drawImage(0, 0, *this->pixbuf); + painter.drawImage(0, 0, *this->_pixbuf); - QImage osd(pixbuf->size(), pixbuf->format()); + QImage osd(_pixbuf->size(), _pixbuf->format()); osd.fill(0x00000000); for (int i = 0; i < _osd.size(); i++) { @@ -518,16 +584,80 @@ void BasePreview::invalidatePixbuf(int value) { for (int iy = 0; iy < _height; iy++) { - QRgb col = pixbuf->pixel(ix, iy); + QRgb col = _pixbuf->pixel(ix, iy); if (qAlpha(col) == 255) { - pixbuf->setPixel(ix, iy, qRgba(qRed(col), qGreen(col), qBlue(col), value)); + _pixbuf->setPixel(ix, iy, qRgba(qRed(col), qGreen(col), qBlue(col), value)); } } } updateChunks(); } +void BasePreview::contextMenuEvent(QContextMenuEvent* event) +{ + QMenu menu(this); + + // TODO Get menu items from OSDs + + // Fill with choices + QHashIterator iter1(_choices); + while (iter1.hasNext()) + { + if (not menu.isEmpty()) + { + menu.addSeparator(); + } + + iter1.next(); + menu.addAction(QString(" %1 ").arg(iter1.value().title))->setDisabled(true); + + QStringList list = iter1.value().items; + for (int i = 0; i < list.count(); i++) + { + QAction* action = menu.addAction(list[i]); + action->setProperty("mode", 1); + action->setProperty("key", iter1.key()); + action->setProperty("value", i); + if (i == iter1.value().current) + { + action->setIcon(QIcon("images/choice_on.png")); + action->setIconVisibleInMenu(true); + } + } + } + + // Fill with toggles + QHashIterator iter2(_toggles); + while (iter2.hasNext()) + { + if (not menu.isEmpty() and not iter2.hasPrevious()) + { + menu.addSeparator(); + } + + iter2.next(); + + QAction* action = menu.addAction(iter2.value().title); + action->setProperty("mode", 2); + action->setProperty("key", iter2.key()); + action->setProperty("value", not iter2.value().value); + if (iter2.value().value) + { + action->setIcon(QIcon("images/toggle_on.png")); + action->setIconVisibleInMenu(true); + } + } + + if (not menu.isEmpty()) + { + connect(&menu, SIGNAL(triggered(QAction*)), this, SLOT(choiceSelected(QAction*))); + + menu.exec(event->globalPos()); + event->accept(); + } +} + void BasePreview::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) @@ -577,16 +707,16 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event) xoffset -= (double) ndx * scaling; yoffset -= (double) ndy * scaling; - lock_drawing->lock(); - pixbuf->fill(0x00000000); + _lock_drawing->lock(); + _pixbuf->fill(0x00000000); updateChunks(); - lock_drawing->unlock(); + _lock_drawing->unlock(); } else { int xstart, xsize, ystart, ysize; - lock_drawing->lock(); + _lock_drawing->lock(); xoffset -= (double) ndx * scaling; yoffset -= (double) ndy * scaling; @@ -612,13 +742,13 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event) ysize = height - ndy; } - QImage part = pixbuf->copy(xstart, ystart, xsize, ysize); - pixbuf->fill(0x00000000); - QPainter painter(pixbuf); + QImage part = _pixbuf->copy(xstart, ystart, xsize, ysize); + _pixbuf->fill(0x00000000); + QPainter painter(_pixbuf); painter.drawImage(xstart + ndx, ystart + ndy, part); updateChunks(); - lock_drawing->unlock(); + _lock_drawing->unlock(); emit contentChange(); } @@ -704,32 +834,32 @@ void BasePreview::wheelEvent(QWheelEvent* event) old_scaling = scaling; updateScaling(); - width = pixbuf->width(); - height = pixbuf->height(); + width = _pixbuf->width(); + height = _pixbuf->height(); if (scaling < old_scaling) { - lock_drawing->lock(); + _lock_drawing->lock(); new_width = (int) floor(((double) width) * scaling / old_scaling); new_height = (int) floor(((double) height) * scaling / old_scaling); - QImage part = pixbuf->copy((width - new_width) / 2, (height - new_height) / 2, new_width, new_height).scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - pixbuf->fill(0x00000000); - QPainter painter(pixbuf); + QImage part = _pixbuf->copy((width - new_width) / 2, (height - new_height) / 2, new_width, new_height).scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + _pixbuf->fill(0x00000000); + QPainter painter(_pixbuf); painter.drawImage(0, 0, part); invalidatePixbuf(254); - lock_drawing->unlock(); + _lock_drawing->unlock(); emit contentChange(); } else if (scaling > old_scaling) { - lock_drawing->lock(); - QImage part = pixbuf->scaled((int) floor(((double) width) * old_scaling / scaling), (int) floor(((double) height) * old_scaling / scaling), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - pixbuf->fill(0x00000000); - QPainter painter(pixbuf); + _lock_drawing->lock(); + QImage part = _pixbuf->scaled((int) floor(((double) width) * old_scaling / scaling), (int) floor(((double) height) * old_scaling / scaling), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + _pixbuf->fill(0x00000000); + QPainter painter(_pixbuf); painter.drawImage((width - part.width()) / 2, (height - part.height()) / 2, part); invalidatePixbuf(254); - lock_drawing->unlock(); + _lock_drawing->unlock(); emit contentChange(); } diff --git a/gui_qt/basepreview.h b/gui_qt/basepreview.h index e5f9d58..73a74f5 100644 --- a/gui_qt/basepreview.h +++ b/gui_qt/basepreview.h @@ -11,6 +11,21 @@ #include "previewosd.h" #include "../lib_paysages/pack.h" +class _ContextChoice +{ +public: + QString title; + QStringList items; + int current; +}; + +class _ContextToggle +{ +public: + QString title; + bool value; +}; + class BasePreview : public QWidget { Q_OBJECT @@ -18,8 +33,6 @@ public: BasePreview(QWidget* parent); ~BasePreview(); - void addOsd(QString name); - virtual void savePack(PackStream* stream); virtual void loadPack(PackStream* stream); @@ -41,6 +54,14 @@ protected: void configScaling(double min, double max, double step, double init, bool logarithmic = true); void configScrolling(double xmin, double xmax, double xinit, double ymin, double ymax, double yinit); + void addOsd(QString name); + + void addChoice(const QString& key, const QString& title, const QStringList& choices, int init_value); + virtual void choiceChangeEvent(const QString& key, int position); + + void addToggle(const QString& key, const QString& text, bool init_value); + virtual void toggleChangeEvent(QString key, bool value); + double xoffset; double yoffset; double scaling; @@ -54,14 +75,17 @@ private: void resizeEvent(QResizeEvent* event); void paintEvent(QPaintEvent* event); + void contextMenuEvent(QContextMenuEvent* event); void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void wheelEvent(QWheelEvent* event); void leaveEvent(QEvent* event); - QMutex* lock_drawing; - QImage* pixbuf; + QMutex* _lock_drawing; + QImage* _pixbuf; QVector _osd; + QHash _choices; + QHash _toggles; QLabel* _info; @@ -96,6 +120,7 @@ signals: private slots: void handleRedraw(); + void choiceSelected(QAction* action); }; diff --git a/gui_qt/formtextures.cpp b/gui_qt/formtextures.cpp index ed0c9cd..4b4bb06 100644 --- a/gui_qt/formtextures.cpp +++ b/gui_qt/formtextures.cpp @@ -165,6 +165,7 @@ void FormTextures::revertConfig() void FormTextures::applyConfig() { + configChangeEvent(); scenerySetTextures(&_definition); BaseForm::applyConfig(); } diff --git a/gui_qt/formwater.cpp b/gui_qt/formwater.cpp index b82a9f2..15c39af 100644 --- a/gui_qt/formwater.cpp +++ b/gui_qt/formwater.cpp @@ -62,6 +62,9 @@ public: { LightDefinition light; + _background = 0; + _lighting_enabled = false; + _water = waterCreateDefinition(); _lighting = lightingCreateDefinition(); @@ -78,12 +81,18 @@ public: _renderer = rendererCreate(); _renderer.rayWalking = _rayWalking; _renderer.getLightStatus = _getLightStatus; + _renderer.applyLightStatus = _applyLightStatus; _renderer.customData[0] = &_water; _renderer.customData[1] = &_lighting; + _renderer.customData[2] = this; configScaling(10.0, 1000.0, 10.0, 250.0); //configScrolling(-30.0, 30.0, 0.0, -20.0, 20.0, 0.0); + + addChoice("bg", tr("Background"), QStringList(tr("None")) << tr("Grid") << tr("Sinusoid"), 2); + addToggle("light", tr("Lighting"), true); } + int _background; protected: QColor getColor(double x, double y) { @@ -118,15 +127,33 @@ protected: waterCopyDefinition(&_definition, &_water); _water.height = 0.0; } + void choiceChangeEvent(const QString& key, int position) + { + if (key == "bg") + { + _background = position; + redraw(); + } + } + void toggleChangeEvent(QString key, bool value) + { + if (key == "light") + { + _lighting_enabled = value; + redraw(); + } + } private: Renderer _renderer; WaterDefinition _water; LightingDefinition _lighting; + bool _lighting_enabled; static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds) { RayCastingResult result; + PreviewWaterColor* preview = (PreviewWaterColor*)renderer->customData[2]; double x, y; result.hit = 1; @@ -140,15 +167,17 @@ private: x = location.x + direction.x * (0.0 - location.z) / direction.z; y = location.y + direction.y * (0.0 - location.z) / direction.z; - //if (((int)ceil(x * 0.2) % 2 == 0) ^ ((int)ceil(y * 0.2 - 0.5) % 2 == 0)) - if (y * 0.1 > x * 0.03 + sin(x - M_PI_2)) + switch (preview->_background) { + case 1: + result.hit_color = (((int)ceil(x * 0.2) % 2 == 0) ^ ((int)ceil(y * 0.2 - 0.5) % 2 == 0)) ? COLOR_WHITE : COLOR_BLACK; + break; + case 2: + result.hit_color = (y * 0.1 > x * 0.03 + sin(x - M_PI_2)) ? COLOR_WHITE : COLOR_BLACK; + break; + default: result.hit_color = COLOR_WHITE; } - else - { - result.hit_color = COLOR_BLACK; - } result.hit_location.x = x; result.hit_location.y = y; result.hit_location.z = 0.0; @@ -156,7 +185,17 @@ private: return result; } - + static Color _applyLightStatus(Renderer* renderer, LightStatus* status, Vector3 location, Vector3 normal, SurfaceMaterial material) + { + if (((PreviewWaterColor*)renderer->customData[2])->_lighting_enabled) + { + return lightingApplyStatusToSurface(renderer, status, location, normal, material); + } + else + { + return material.base; + } + } static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location) { lightingGetStatus((LightingDefinition*)renderer->customData[1], renderer, location, status); diff --git a/i18n/paysages_fr.ts b/i18n/paysages_fr.ts index 705f7c0..a6a28c2 100644 --- a/i18n/paysages_fr.ts +++ b/i18n/paysages_fr.ts @@ -356,9 +356,8 @@ Maintenir Ctrl : Plus rapide Couverture de la couche (sans éclairage) - Color and lighting - Echantillon éclairé + Echantillon éclairé Start altitude @@ -377,11 +376,6 @@ Maintenir Ctrl : Plus rapide Lower altitude - - - Upper altitude - - Noise Bruit @@ -411,6 +405,16 @@ Maintenir Ctrl : Plus rapide Light reflection shininess Concentration de la réflexion de lumière + + + Appearance + + + + + Layer thickness + + Max coverage diff --git a/images/choice_on.png b/images/choice_on.png new file mode 100644 index 0000000..f577c11 Binary files /dev/null and b/images/choice_on.png differ diff --git a/images/toggle_on.png b/images/toggle_on.png new file mode 100644 index 0000000..a9925a0 Binary files /dev/null and b/images/toggle_on.png differ