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 <QMessageBox>
55 
56 texturePropertiesWidget::texturePropertiesWidget(QWidget *parent)
57  : QDialog(parent)
58 {
59  setupUi(this);
60 
61  connect(buttonBox, SIGNAL( clicked(QAbstractButton*) ), this , SLOT ( slotButtonBoxClicked(QAbstractButton*) ) );
62  connect(textureList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(textureChanged(QTreeWidgetItem*,int)) );
63  connect(textureList, SIGNAL(itemPressed(QTreeWidgetItem*,int)), this, SLOT(textureAboutToChange(QTreeWidgetItem*,int)) );
64 
65  //remember changes
66  connect(repeatBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
67  connect(clampBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
68  connect(centerBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
69  connect(absBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
70  connect(scaleBox, SIGNAL( clicked() ), this , SLOT ( slotPropertiesChanged() ) );
71 
72  connect(max_val, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
73  connect(clamp_min, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
74  connect(clamp_max, SIGNAL( valueChanged(double) ), this , SLOT ( slotPropertiesChanged(double) ) );
75 
76  connect(changeImageButton, SIGNAL( clicked() ), this, SLOT( slotChangeImage() ) );
77 
78 
79  texData_ = 0;
80 
81  #ifdef WITH_QWT
82  QGridLayout* layout = new QGridLayout( originalData);
83 
84  functionPlot_ = new ACG::QwtFunctionPlot(0);
85 
86  layout->addWidget( functionPlot_ , 0,0 );
87 
88  #endif
89 
90 }
91 
92 void 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 
161 void 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 
189 void 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  #ifdef WITH_QWT
312 
313  std::vector< double > coords;
314 
315  emit getCoordinates1D(textureName_, id_, coords);
316 
317  if ( ! coords.empty() ){
318 
319  functionPlot_->setFunction( coords );
320 
321  functionPlot_->setParameters(repeatBox->isChecked(), max_val->value(),
322  clampBox->isChecked(), clamp_min->value(), clamp_max->value(),
323  centerBox->isChecked(),
324  absBox->isChecked(),
325  scaleBox->isChecked());
326 
327  bool ok = false;
328  image_ = imageStore().getImage(texture.textureImageId(),&ok);
329  if ( !ok ) {
330  std::cerr << imageStore().error().toStdString();
331  }
332 
333 
334  functionPlot_->setImage( &image_ );
335 
336  functionPlot_->replot();
337  }
338 
339  #endif
340  }
341 
342  propChanged_ = false;
343  curItem_ = textureList->currentItem();
344 
345 }
346 
347 void texturePropertiesWidget::slotChangeImage()
348 {
349 
350  QString fileName = QFileDialog::getOpenFileName(this,
351  tr("Open Image"),
352  OpenFlipper::Options::currentTextureDirStr(),
353  tr("Images (*.png *.xpm *.jpg *.tga *.tif *.tiff *.bmp);;All Files (*.*)"));
354 
355  if (QFile(fileName).exists()) {
356  QFileInfo fileInfo(fileName);
357  OpenFlipper::Options::currentTextureDir(fileInfo.absolutePath());
358 
359  imageLabel->setPixmap(fileName);
360  imageLabel->setScaledContents(true);
361 
362  fileLabel->setText("File: " + fileName);
363 
364  currentImage_ = fileName;
365  image_ = imageLabel->pixmap()->toImage();
366 
367  #ifdef WITH_QWT
368  functionPlot_->setImage(&image_);
369  functionPlot_->replot();
370  #endif
371 
372  propChanged_ = true;
373  }
374 
375 }
376 
377 void texturePropertiesWidget::slotButtonBoxClicked(QAbstractButton* _button){
378 
379  QDialogButtonBox::StandardButton btn = buttonBox->standardButton(_button);
380 
381  if ( btn == QDialogButtonBox::Apply || btn == QDialogButtonBox::Ok){
382 
383  //applySettings
384  bool changed = false;
385 
386  Texture& texture = texData_->texture(textureName_);
387 
388  if ( texture.parameters.repeat != repeatBox->isChecked() ){
389  texture.parameters.repeat=repeatBox->isChecked();
390  changed = true;
391  }
392  if ( texture.parameters.clamp != clampBox->isChecked() ){
393  texture.parameters.clamp=clampBox->isChecked();
394  changed = true;
395  }
396  if ( texture.parameters.center != centerBox->isChecked() ){
397  texture.parameters.center=centerBox->isChecked();
398  changed = true;
399  }
400  if ( texture.parameters.abs != absBox->isChecked() ){
401  texture.parameters.abs=absBox->isChecked();
402  changed = true;
403  }
404  if ( texture.parameters.scale != scaleBox->isChecked() ){
405  texture.parameters.scale=scaleBox->isChecked();
406  changed = true;
407  }
408 
409  if ( texture.parameters.repeatMax != max_val->value() ){
410  texture.parameters.repeatMax = max_val->value();
411  changed = true;
412  }
413 
414  if ( texture.parameters.clampMin != clamp_min->value() ){
415  texture.parameters.clampMin = clamp_min->value();
416  changed = true;
417  }
418 
419  if ( texture.parameters.clampMax != clamp_max->value() ){
420  texture.parameters.clampMax = clamp_max->value();
421  changed = true;
422  }
423 
424  if ( texture.filename() != currentImage_ ){
425  // Set the new filename of the image
426  texture.filename( currentImage_ );
427 
428  // Add it to the imagestore and set the index in the texture description
429  texture.textureImageId( imageStore().addImageFile(currentImage_) );
430 
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 
447 void texturePropertiesWidget::slotPropertiesChanged(double /*_value*/){
448  propChanged_ = true;
449 
450  #ifdef WITH_QWT
451  functionPlot_->setParameters(repeatBox->isChecked(), max_val->value(),
452  clampBox->isChecked(), clamp_min->value(), clamp_max->value(),
453  centerBox->isChecked(),
454  absBox->isChecked(),
455  scaleBox->isChecked());
456 
457  functionPlot_->replot();
458  #endif
459 }
DLLEXPORT void currentTextureDir(QDir _dir)
Sets the Path to the current texture-directory.
TexParameters parameters
Parameters of the texture.
Definition: TextureData.hh:138