Developer Documentation
textureProperties.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44
45
46
47#include "textureProperties.hh"
48
52#include "ImageStorage.hh"
53
54#include "QChartsPlot.hh"
55
56#include <QMessageBox>
57
58texturePropertiesWidget::texturePropertiesWidget(QWidget *parent)
59 : QDialog(parent)
60{
61 setupUi(this);
62
63 connect(buttonBox, SIGNAL( clicked(QAbstractButton*) ), this , SLOT ( slotButtonBoxClicked(QAbstractButton*) ) );
64 connect(textureList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(textureChanged(QTreeWidgetItem*,int)) );
65 connect(textureList, SIGNAL(itemPressed(QTreeWidgetItem*,int)), this, SLOT(textureAboutToChange(QTreeWidgetItem*,int)) );
66
67 //remember changes
68 connect(repeatBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
69 connect(clampBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
70 connect(centerBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
71 connect(absBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
72 connect(scaleBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
73
74 connect(max_val, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
75 connect(clamp_min, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
76 connect(clamp_max, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
77
78 connect(changeImageButton, SIGNAL( clicked() ), this, SLOT( slotChangeImage() ) );
79
80
81 texData_ = 0;
82
83 QGridLayout* layout = new QGridLayout( originalData);
84
85 plot_ = new QChartsPlot(originalData);
86 plot_->setMinimumHeight(200);
87
88 layout->addWidget(plot_, 0, 0);
89
90}
91
92void texturePropertiesWidget::show(TextureData* _texData, int _id, QString _name){
93
94 texData_ = _texData;
95 id_ = _id;
96
97 textureList->clear();
98
99 QTreeWidgetItem* activeItem = 0;
100
101 for (unsigned int i=0; i < texData_->textures().size(); i++) {
102 if ( ! texData_->textures()[i].hidden() ) {
103 if ( texData_->textures()[i].type() != MULTITEXTURE ) {
104
105 QTreeWidgetItem* item = 0;
106
107 if ( !texData_->textures()[i].visibleName().isEmpty() )
108 item = new QTreeWidgetItem((QTreeWidget*)0, QStringList( texData_->textures()[i].visibleName() ) );
109 else
110 item = new QTreeWidgetItem((QTreeWidget*)0, QStringList( texData_->textures()[i].name() ) );
111
112 textureList->addTopLevelItem( item );
113
114 if (texData_->textures()[i].enabled())
115 activeItem = item;
116
117 } else {
118 QTreeWidgetItem* parent = 0;
119 if ( !texData_->textures()[i].visibleName().isEmpty() )
120 parent = new QTreeWidgetItem((QTreeWidget*)0, QStringList( texData_->textures()[i].visibleName() ) );
121 else
122 parent = new QTreeWidgetItem((QTreeWidget*)0, QStringList( texData_->textures()[i].name() ) );
123
124 textureList->addTopLevelItem( parent ) ;
125 for ( int j = 0 ; j < texData_->textures()[i].multiTextureList.size() ; ++j )
126 textureList->addTopLevelItem( new QTreeWidgetItem(parent, QStringList(texData_->textures()[i].multiTextureList[j] )) );
127
128 if (texData_->textures()[i].enabled())
129 activeItem = parent;
130 }
131 }
132 }
133
134 if ( textureList->invisibleRootItem()->childCount() == 0 ) {
135 QMessageBox msgBox(this);
136 msgBox.setText("Cannot show Properties. No Textures available!");
137 msgBox.exec();
138 return;
139 }
140
141 if (id_ == -1)
142 textureLabel->setText("<B>Global Textures</B>");
143 else
144 textureLabel->setText("<B>Textures for object '" + _name + "'</B>");
145
146 propChanged_ = false;
147
148 if (activeItem == 0){
149
150 textureList->setCurrentItem( textureList->topLevelItem(0) );
151 textureChanged( textureList->topLevelItem(0), 0 );
152
153 } else {
154 textureList->setCurrentItem( activeItem );
155 textureChanged( activeItem, 0 );
156 }
157
158 QDialog::show();
159}
160
161void texturePropertiesWidget::textureAboutToChange(QTreeWidgetItem* _item, int _column){
162
163 if (propChanged_){
164 QMessageBox msgBox(this);
165 msgBox.setText("The properties of the current texture have been changed.");
166 msgBox.setInformativeText("Do you want to apply these changes?");
167 msgBox.setStandardButtons(QMessageBox::Apply | QMessageBox::Discard );
168 msgBox.setDefaultButton(QMessageBox::Apply);
169 int ret = msgBox.exec();
170
171 if (ret == QMessageBox::Apply){
172 //just hit the applyButton ;)
173 for (int i=0; i < buttonBox->buttons().count(); i++)
174 if ( buttonBox->standardButton( buttonBox->buttons()[i] ) == QDialogButtonBox::Apply )
175 slotButtonBoxClicked( buttonBox->buttons()[i] );
176
177 textureList->setCurrentItem( _item );
178 textureChanged( _item,_column );
179
180 } else {
181 propChanged_ = false;
182
183 textureList->setCurrentItem( _item );
184 textureChanged( _item,_column );
185 }
186 }
187}
188
189void texturePropertiesWidget::textureChanged(QTreeWidgetItem* _item, int _column){
190
191 // ================================================================================
192 // opened changes for the last texture so switch back
193 // ================================================================================
194 if ( propChanged_ ){
195 textureList->setCurrentItem( curItem_ );
196 return;
197 }
198
199 // ================================================================================
200 // Unable to find the right texture
201 // ================================================================================
202 if ( !texData_->textureExists( _item->text(_column) ) )
203 return;
204
205 // ================================================================================
206 // Set name of the texture
207 // ================================================================================
208 textureName_ = _item->text(_column);
209
210 // ================================================================================
211 // Get Object to parse Properties
212 // ================================================================================
213// BaseObjectData* obj;
214// if ( PluginFunctions::getObject( id_ , obj ) ) {
215// if( obj->dataType( DATA_TRIANGLE_MESH ) ){
216// TriMesh* mesh = PluginFunctions::triMeshObject(obj)->mesh();
217// std::string fprops;
218// mesh->fprop_stats(fprops);
219// QString facePropertyString(fprops.c_str());
220// QStringList faceProperties = facePropertyString.split(QRegExp("\n"));
221//
222// std::cerr << "Got : \n" ;
223// for ( int i = 0 ; i < faceProperties.size(); ++i ) {
224// faceProperties[i] = faceProperties[i].trimmed();
225// if ( ( ! faceProperties[i].size() == 0 ) && faceProperties[i] != "<fprop>" )
226// std::cerr << faceProperties[i].toStdString() << std::endl;
227// else
228// continue;
229//
230// OpenMesh::FPropHandleT< int > indexPropertyTest;
231// if ( mesh->get_property_handle(indexPropertyTest,faceProperties[i].toStdString()) ) {
232// std::cerr << "Got handle : " << faceProperties[i].toStdString() << std::endl;
233// } else {
234// std::cerr << "Unable to get Handle : " << faceProperties[i].toStdString() << std::endl;
235// }
236// }
237//
238// } else if( obj->dataType( DATA_POLY_MESH ) ){
239// PolyMesh* mesh = PluginFunctions::polyMeshObject(obj)->mesh();
240// }
241// }
242
243 // ================================================================================
244 // Update the dialog
245 // ================================================================================
246 Texture& texture = texData_->texture(textureName_);
247
248 repeatBox->setChecked(texture.parameters.repeat);
249 clampBox->setChecked(texture.parameters.clamp);
250 centerBox->setChecked(texture.parameters.center);
251 absBox->setChecked(texture.parameters.abs);
252
253 max_val->setValue( texture.parameters.repeatMax );
254 clamp_min->setValue( texture.parameters.clampMin );
255 clamp_max->setValue( texture.parameters.clampMax );
256
257 switch (texture.type()) {
258 case MULTITEXTURE:
259 typeLabel->setText("Type: MultiTexture");
260 indexLabel->setEnabled(true);
261 indexBox->setEnabled(true);
262 indexBox->clear();
263 indexBox->addItem("TODO");
264 break;
265 case HALFEDGEBASED:
266 typeLabel->setText("Type: HalfedgeBased");
267 indexLabel->setEnabled(false);
268 indexBox->setEnabled(false);
269 indexBox->clear();
270 break;
271 case VERTEXBASED:
272 typeLabel->setText("Type: VertexBased");
273 indexLabel->setEnabled(false);
274 indexBox->setEnabled(false);
275 indexBox->clear();
276 break;
277 case ENVIRONMENT:
278 typeLabel->setText("Type: Environment Map");
279 indexLabel->setEnabled(false);
280 indexBox->setEnabled(false);
281 indexBox->clear();
282 break;
283 case UNSET:
284 typeLabel->setText("Type: Unset");
285 indexLabel->setEnabled(false);
286 indexBox->setEnabled(false);
287 indexBox->clear();
288 break;
289 }
290
291 // Show the texture Image
292 bool ok = false;
293 imageLabel->setPixmap(QPixmap::fromImage( imageStore().getImage(texture.textureImageId(),&ok) ));
294
295 if ( !ok ) {
296 std::cerr<< imageStore().error().toStdString();
297 }
298
299 imageLabel->setScaledContents(true);
300
301 if ( texture.filename().startsWith("/") )
302 fileLabel->setText( "File: " + texture.filename() );
303 else
304 fileLabel->setText( "File: " + OpenFlipper::Options::textureDirStr() + QDir::separator() + texture.filename() );
305
306 currentImage_ = texture.filename();
307
308 // update plot only when dimension is 1
309 if ( texture.dimension() == 1 && id_ != -1) {
310
311 std::vector< double > coords;
312
313 emit getCoordinates1D(textureName_, id_, coords);
314
315 if ( ! coords.empty() ){
316
317 bool ok = false;
318 image_ = imageStore().getImage(texture.textureImageId(),&ok);
319 if ( !ok ) {
320 std::cerr << imageStore().error().toStdString();
321 }
322
323 plot_->setFunction(coords);
324
325 plot_->setParameters(repeatBox->isChecked(), max_val->value(),
326 clampBox->isChecked(), clamp_min->value(), clamp_max->value(),
327 centerBox->isChecked(),
328 absBox->isChecked(),
329 scaleBox->isChecked());
330
331 plot_->setImage( &image_ );
332
333 plot_->replot();
334 }
335
336 }
337
338 propChanged_ = false;
339 curItem_ = textureList->currentItem();
340
341}
342
343void texturePropertiesWidget::slotChangeImage()
344{
345
346 QString fileName = QFileDialog::getOpenFileName(this,
347 tr("Open Image"),
348 OpenFlipper::Options::currentTextureDirStr(),
349 tr("Images (*.png *.xpm *.jpg *.tga *.tif *.tiff *.bmp);;All Files (*.*)"));
350
351 if (QFile(fileName).exists()) {
352 QFileInfo fileInfo(fileName);
353 OpenFlipper::Options::currentTextureDir(fileInfo.absolutePath());
354
355 imageLabel->setPixmap(fileName);
356 imageLabel->setScaledContents(true);
357
358 fileLabel->setText("File: " + fileName);
359
360 currentImage_ = fileName;
361
362 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
363 image_ = imageLabel->pixmap()->toImage();
364 #else
365 image_ = imageLabel->pixmap(Qt::ReturnByValue).toImage();
366 #endif
367
368 plot_->setImage(&image_);
369 plot_->replot();
370
371 propChanged_ = true;
372 }
373
374}
375
376void texturePropertiesWidget::slotButtonBoxClicked(QAbstractButton* _button){
377
378 QDialogButtonBox::StandardButton btn = buttonBox->standardButton(_button);
379
380 if ( btn == QDialogButtonBox::Apply || btn == QDialogButtonBox::Ok){
381
382 //applySettings
383 bool changed = false;
384
385 Texture& texture = texData_->texture(textureName_);
386
387 if ( texture.parameters.repeat != repeatBox->isChecked() ){
388 texture.parameters.repeat=repeatBox->isChecked();
389 changed = true;
390 }
391 if ( texture.parameters.clamp != clampBox->isChecked() ){
392 texture.parameters.clamp=clampBox->isChecked();
393 changed = true;
394 }
395 if ( texture.parameters.center != centerBox->isChecked() ){
396 texture.parameters.center=centerBox->isChecked();
397 changed = true;
398 }
399 if ( texture.parameters.abs != absBox->isChecked() ){
400 texture.parameters.abs=absBox->isChecked();
401 changed = true;
402 }
403 if ( texture.parameters.scale != scaleBox->isChecked() ){
404 texture.parameters.scale=scaleBox->isChecked();
405 changed = true;
406 }
407
408 if ( texture.parameters.repeatMax != max_val->value() ){
409 texture.parameters.repeatMax = max_val->value();
410 changed = true;
411 }
412
413 if ( texture.parameters.clampMin != clamp_min->value() ){
414 texture.parameters.clampMin = clamp_min->value();
415 changed = true;
416 }
417
418 if ( texture.parameters.clampMax != clamp_max->value() ){
419 texture.parameters.clampMax = clamp_max->value();
420 changed = true;
421 }
422
423 if ( texture.filename() != currentImage_ ){
424 // Set the new filename of the image
425 texture.filename( currentImage_ );
426
427 // Add it to the imagestore and set the index in the texture description
428 int newImageId = imageStore().addImageFile(currentImage_);
429 texture.textureImageId( newImageId );
430 texData_->addManagedImageId( newImageId );
431 changed = true;
432 }
433
434 //inform the plugin about the update
435 if (changed)
436 emit applyProperties(texData_, textureName_, id_ );
437
438 propChanged_ = false;
439 }
440
441 if ( btn == QDialogButtonBox::Apply )
442 return;
443 else
444 hide();
445}
446
447void texturePropertiesWidget::slotPropertiesChanged(double /*_value*/){
448 propChanged_ = true;
449
450 plot_->setParameters(repeatBox->isChecked(), max_val->value(),
451 clampBox->isChecked(), clamp_min->value(), clamp_max->value(),
452 centerBox->isChecked(),
453 absBox->isChecked(),
454 scaleBox->isChecked());
455
456 plot_->replot();
457}
void setFunction(const std::vector< double > &_values)
set the function to plot
Definition: QChartsPlot.cc:185
void setParameters(const TexParameters &_parameters)
Set all parameters as one block.
Definition: QChartsPlot.cc:187
Texture & texture(QString _textureName)
Get the texture object.
Definition: TextureData.cc:275
std::vector< Texture > & textures()
Get reference to the texture vector.
Definition: TextureData.cc:314
bool textureExists(QString _textureName)
Check if a texture exists.
Definition: TextureData.cc:91
TexParameters parameters
Parameters of the texture.
Definition: TextureData.hh:142