paysages : Added toggles and choices to previews + background and lighting for water preview.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@375 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-04 17:50:32 +00:00 committed by ThunderK
parent c0725baf87
commit fe50647a97
9 changed files with 258 additions and 60 deletions

View file

@ -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.

2
TODO
View file

@ -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)

View file

@ -6,6 +6,7 @@
#include <QTimer>
#include <QWheelEvent>
#include <QLabel>
#include <QMenu>
#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<QString, _ContextChoice> 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<QString, _ContextToggle> 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();
}

View file

@ -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<PreviewOsd*> _osd;
QHash<QString, _ContextChoice> _choices;
QHash<QString, _ContextToggle> _toggles;
QLabel* _info;
@ -96,6 +120,7 @@ signals:
private slots:
void handleRedraw();
void choiceSelected(QAction* action);
};

View file

@ -165,6 +165,7 @@ void FormTextures::revertConfig()
void FormTextures::applyConfig()
{
configChangeEvent();
scenerySetTextures(&_definition);
BaseForm::applyConfig();
}

View file

@ -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);

View file

@ -356,9 +356,8 @@ Maintenir Ctrl : Plus rapide</translation>
<translation>Couverture de la couche (sans éclairage)</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="155"/>
<source>Color and lighting</source>
<translation>Echantillon éclairé</translation>
<translation type="obsolete">Echantillon éclairé</translation>
</message>
<message>
<source>Start altitude</source>
@ -377,11 +376,6 @@ Maintenir Ctrl : Plus rapide</translation>
<source>Lower altitude</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="158"/>
<source>Upper altitude</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Noise</source>
<translation type="obsolete">Bruit</translation>
@ -411,6 +405,16 @@ Maintenir Ctrl : Plus rapide</translation>
<source>Light reflection shininess</source>
<translation type="obsolete">Concentration de la réflexion de lumière</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="155"/>
<source>Appearance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="158"/>
<source>Layer thickness</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="159"/>
<source>Max coverage</source>

BIN
images/choice_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

BIN
images/toggle_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B