浏览代码

Add more props in ctkMaterialPropertyWidget

Color, opacity and backfaceculling have been added
Julien Finet 14 年之前
父节点
当前提交
a635b2273d

+ 155 - 57
Libs/Widgets/Resources/UI/ctkMaterialPropertyWidget.ui

@@ -6,31 +6,25 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>370</width>
-    <height>196</height>
+    <width>248</width>
+    <height>212</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Material Property</string>
   </property>
-  <layout class="QFormLayout" name="formLayout">
-   <property name="fieldGrowthPolicy">
-    <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-   </property>
-   <property name="labelAlignment">
-    <set>Qt::AlignCenter</set>
-   </property>
+  <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,1,0,0">
    <property name="margin">
     <number>0</number>
    </property>
-   <item row="1" column="0">
+   <item row="2" column="0">
     <widget class="QLabel" name="AmbientLabel">
      <property name="text">
       <string>Ambient:</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="1">
+   <item row="2" column="1" colspan="4">
     <widget class="ctkSliderWidget" name="AmbientSliderSpinBox">
      <property name="singleStep">
       <double>0.010000000000000</double>
@@ -40,14 +34,14 @@
      </property>
     </widget>
    </item>
-   <item row="2" column="0">
+   <item row="3" column="0">
     <widget class="QLabel" name="DiffuseLabel">
      <property name="text">
       <string>Diffuse:</string>
      </property>
     </widget>
    </item>
-   <item row="2" column="1">
+   <item row="3" column="1" colspan="4">
     <widget class="ctkSliderWidget" name="DiffuseSliderSpinBox">
      <property name="singleStep">
       <double>0.010000000000000</double>
@@ -57,14 +51,14 @@
      </property>
     </widget>
    </item>
-   <item row="3" column="0">
+   <item row="4" column="0">
     <widget class="QLabel" name="SpecularLabel">
      <property name="text">
       <string>Specular:</string>
      </property>
     </widget>
    </item>
-   <item row="3" column="1">
+   <item row="4" column="1" colspan="4">
     <widget class="ctkSliderWidget" name="SpecularSliderSpinBox">
      <property name="singleStep">
       <double>0.010000000000000</double>
@@ -74,7 +68,7 @@
      </property>
     </widget>
    </item>
-   <item row="4" column="0">
+   <item row="5" column="0">
     <widget class="QLabel" name="SpecularPowerLabel">
      <property name="toolTip">
       <string>Specular power</string>
@@ -84,7 +78,7 @@
      </property>
     </widget>
    </item>
-   <item row="4" column="1">
+   <item row="5" column="1" colspan="4">
     <widget class="ctkSliderWidget" name="SpecularPowerSliderSpinBox">
      <property name="decimals">
       <number>1</number>
@@ -100,30 +94,71 @@
      </property>
     </widget>
    </item>
-   <item row="5" column="0">
+   <item row="8" column="0">
+    <widget class="QLabel" name="PreviewLabel">
+     <property name="text">
+      <string>Preview:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="1">
+    <widget class="ctkMaterialPropertyPreviewLabel" name="MaterialPropertyPreviewLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="ambient">
+      <double>0.000000000000000</double>
+     </property>
+     <property name="diffuse">
+      <double>0.000000000000000</double>
+     </property>
+     <property name="specular">
+      <double>0.000000000000000</double>
+     </property>
+     <property name="specularPower">
+      <double>1.000000000000000</double>
+     </property>
+     <property name="gridOpacity">
+      <double>0.600000000000000</double>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="3">
     <widget class="QLabel" name="PresetsLabel">
      <property name="text">
       <string>Presets:</string>
      </property>
     </widget>
    </item>
-   <item row="5" column="1">
+   <item row="8" column="4">
     <widget class="QListWidget" name="PresetsListWidget">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
      <property name="maximumSize">
       <size>
        <width>16777215</width>
-       <height>50</height>
+       <height>34</height>
       </size>
      </property>
      <property name="verticalScrollBarPolicy">
       <enum>Qt::ScrollBarAlwaysOff</enum>
      </property>
      <property name="horizontalScrollBarPolicy">
-      <enum>Qt::ScrollBarAlwaysOn</enum>
+      <enum>Qt::ScrollBarAsNeeded</enum>
      </property>
      <property name="editTriggers">
       <set>QAbstractItemView::NoEditTriggers</set>
      </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
      <property name="flow">
       <enum>QListView::LeftToRight</enum>
      </property>
@@ -132,35 +167,61 @@
      </property>
     </widget>
    </item>
-   <item row="6" column="0">
-    <widget class="QLabel" name="PreviewLabel">
+   <item row="8" column="2">
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="OpacityLabel">
      <property name="text">
-      <string>Preview:</string>
+      <string>Opacity:</string>
      </property>
     </widget>
    </item>
-   <item row="6" column="1">
-    <widget class="ctkMaterialPropertyPreviewLabel" name="MaterialPropertyPreviewLabel">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
+   <item row="1" column="1" colspan="4">
+    <widget class="ctkSliderWidget" name="OpacitySliderSpinBox">
+     <property name="singleStep">
+      <double>0.010000000000000</double>
      </property>
-     <property name="ambient">
-      <double>0.000000000000000</double>
+     <property name="maximum">
+      <double>1.000000000000000</double>
      </property>
-     <property name="diffuse">
-      <double>0.000000000000000</double>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="ColorLabel">
+     <property name="text">
+      <string>Color:</string>
      </property>
-     <property name="specular">
-      <double>0.000000000000000</double>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="4">
+    <widget class="ctkColorPickerButton" name="ColorPickerButton">
+     <property name="displayColorName">
+      <bool>false</bool>
      </property>
-     <property name="specularPower">
-      <double>1.000000000000000</double>
+    </widget>
+   </item>
+   <item row="6" column="0">
+    <widget class="QLabel" name="BackFaceCullingLabel">
+     <property name="text">
+      <string>Backface Culling:</string>
      </property>
-     <property name="gridOpacity">
-      <double>0.000000000000000</double>
+    </widget>
+   </item>
+   <item row="6" column="1" colspan="4">
+    <widget class="QCheckBox" name="BackfaceCullingCheckBox">
+     <property name="text">
+      <string/>
      </property>
     </widget>
    </item>
@@ -168,6 +229,11 @@
  </widget>
  <customwidgets>
   <customwidget>
+   <class>ctkColorPickerButton</class>
+   <extends>QPushButton</extends>
+   <header>ctkColorPickerButton.h</header>
+  </customwidget>
+  <customwidget>
    <class>ctkMaterialPropertyPreviewLabel</class>
    <extends>QFrame</extends>
    <header>ctkMaterialPropertyPreviewLabel.h</header>
@@ -187,12 +253,12 @@
    <slot>setAmbient(double)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>81</x>
-     <y>12</y>
+     <x>168</x>
+     <y>67</y>
     </hint>
     <hint type="destinationlabel">
-     <x>65</x>
-     <y>172</y>
+     <x>116</x>
+     <y>209</y>
     </hint>
    </hints>
   </connection>
@@ -203,12 +269,12 @@
    <slot>setDiffuse(double)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>115</x>
-     <y>46</y>
+     <x>202</x>
+     <y>100</y>
     </hint>
     <hint type="destinationlabel">
-     <x>74</x>
-     <y>173</y>
+     <x>116</x>
+     <y>209</y>
     </hint>
    </hints>
   </connection>
@@ -219,12 +285,12 @@
    <slot>setSpecular(double)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>135</x>
-     <y>65</y>
+     <x>222</x>
+     <y>126</y>
     </hint>
     <hint type="destinationlabel">
-     <x>76</x>
-     <y>179</y>
+     <x>116</x>
+     <y>209</y>
     </hint>
    </hints>
   </connection>
@@ -235,14 +301,46 @@
    <slot>setSpecularPower(double)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>147</x>
-     <y>95</y>
+     <x>234</x>
+     <y>152</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>116</x>
+     <y>209</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>ColorPickerButton</sender>
+   <signal>colorChanged(QColor)</signal>
+   <receiver>MaterialPropertyPreviewLabel</receiver>
+   <slot>setColor(QColor)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>105</x>
+     <y>14</y>
     </hint>
     <hint type="destinationlabel">
-     <x>74</x>
-     <y>184</y>
+     <x>103</x>
+     <y>191</y>
     </hint>
    </hints>
   </connection>
+   <connection>
+     <sender>OpacitySliderSpinBox</sender>
+     <signal>valueChanged(double)</signal>
+     <receiver>MaterialPropertyPreviewLabel</receiver>
+     <slot>setOpacity(double)</slot>
+     <hints>
+       <hint type="sourcelabel">
+         <x>105</x>
+         <y>24</y>
+       </hint>
+       <hint type="destinationlabel">
+         <x>103</x>
+         <y>191</y>
+       </hint>
+     </hints>
+   </connection>
  </connections>
 </ui>

+ 60 - 32
Libs/Widgets/ctkMaterialPropertyPreviewLabel.cpp

@@ -41,12 +41,14 @@ protected:
 public:
   ctkMaterialPropertyPreviewLabelPrivate(ctkMaterialPropertyPreviewLabel& object);
   
+  QColor Color;
+  double Opacity;
+ 
   double Ambient;
   double Diffuse;
   double Specular;
   double SpecularPower;
-  
-  QColor Color;
+ 
   double GridOpacity;
 };
 
@@ -54,12 +56,13 @@ public:
 ctkMaterialPropertyPreviewLabelPrivate::ctkMaterialPropertyPreviewLabelPrivate(ctkMaterialPropertyPreviewLabel& object)
   :q_ptr(&object)
 {
+  this->Color = Qt::white;
+  this->Opacity = 1.;
   this->Ambient = 0.5;
   this->Diffuse = 0.5;
   this->Specular = 0.5;
   this->SpecularPower = 50;
   
-  this->Color = Qt::white;
   this->GridOpacity = 0.6;
 }
 
@@ -73,11 +76,16 @@ ctkMaterialPropertyPreviewLabel::ctkMaterialPropertyPreviewLabel(QWidget *newPar
 
 //-----------------------------------------------------------------------------
 ctkMaterialPropertyPreviewLabel::ctkMaterialPropertyPreviewLabel(
-  double ambient, double diffuse, double specular, double specularPower, QWidget *newParent)
+  const QColor& color, double opacity,
+  double ambient, double diffuse,
+  double specular, double specularPower,
+  QWidget *newParent)
   : QFrame(newParent)
   , d_ptr(new ctkMaterialPropertyPreviewLabelPrivate(*this))
 {
   Q_D(ctkMaterialPropertyPreviewLabel);
+  d->Color = color;
+  d->Opacity = opacity;
   d->Ambient = ambient;
   d->Diffuse = diffuse;
   d->Specular = specular;
@@ -165,6 +173,21 @@ QColor ctkMaterialPropertyPreviewLabel::color()const
 }
 
 //-----------------------------------------------------------------------------
+void ctkMaterialPropertyPreviewLabel::setOpacity(double newOpacity)
+{
+  Q_D(ctkMaterialPropertyPreviewLabel);
+  d->Opacity = newOpacity;
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+double ctkMaterialPropertyPreviewLabel::opacity()const
+{
+  Q_D(const ctkMaterialPropertyPreviewLabel);
+  return d->Opacity;
+}
+
+//-----------------------------------------------------------------------------
 void ctkMaterialPropertyPreviewLabel::setGridOpacity(double newGridOpacity)
 {
   Q_D(ctkMaterialPropertyPreviewLabel);
@@ -195,11 +218,13 @@ QSize ctkMaterialPropertyPreviewLabel::sizeHint()const
 void ctkMaterialPropertyPreviewLabel::paintEvent(QPaintEvent* event)
 {
   Q_UNUSED(event);
-  QImage image(this->size(), QImage::Format_ARGB32);
+  QRect cr = this->contentsRect();
+  QImage image(cr.size(), QImage::Format_ARGB32_Premultiplied);
   this->draw(image);
   
   QPainter widgetPainter(this);
-  widgetPainter.drawImage(0, 0, image);
+  this->drawFrame(&widgetPainter);
+  widgetPainter.drawImage(cr.left(), cr.top(), image);
 }
 
 //-----------------------------------------------------------------------------
@@ -207,6 +232,7 @@ void ctkMaterialPropertyPreviewLabel::paintEvent(QPaintEvent* event)
 void ctkMaterialPropertyPreviewLabel::draw(QImage& image)
 {
   Q_D(ctkMaterialPropertyPreviewLabel);
+  qreal opacity = d->Opacity;
   qreal ambient = d->Ambient;
   qreal diffuse = d->Diffuse;
   qreal specular = d->Specular;
@@ -222,6 +248,23 @@ void ctkMaterialPropertyPreviewLabel::draw(QImage& image)
     {
     for (int j = 0; j < image.height(); ++j)
       {
+      int iGrid = i / size8;
+      int jGrid = j / size8;
+      
+      if (((iGrid / 2) * 2 == iGrid &&
+           (jGrid / 2) * 2 == jGrid) ||
+          ((iGrid / 2) * 2 != iGrid &&
+           (jGrid / 2) * 2 != jGrid))
+        {
+        rgba = qRgba(0, 0, 0, d->GridOpacity * 255);
+        }
+      else
+        {
+        rgba = qRgba(255. * d->GridOpacity,
+                     255. * d->GridOpacity,
+                     255. * d->GridOpacity,
+                     255. * d->GridOpacity);
+        }
       qreal dist = static_cast<qreal>((i-size2)*(i-size2) + (j-size2)*(j-size2));
       if (dist <= radius2)
         {
@@ -252,17 +295,9 @@ void ctkMaterialPropertyPreviewLabel::draw(QImage& image)
         ref.setZ( 2.*normal.z()*dot - light.z());
         ref.normalize();
 
-        qreal diffuseComp = diffuse * dot;
-        if (diffuseComp < 0)
-          {
-          diffuseComp = 0.;
-          }
+        qreal diffuseComp = qMax(diffuse * dot, 0.);
         
-        qreal specularDot = QVector3D::dotProduct(ref, view);
-        if (specularDot < 0)
-          {
-          specularDot = 0.;
-          }
+        qreal specularDot = qMax(QVector3D::dotProduct(ref, view), 0.);
         
         qreal specularComp = specular*pow(specularDot, specular_power);
         
@@ -271,26 +306,19 @@ void ctkMaterialPropertyPreviewLabel::draw(QImage& image)
         intensity.setY( qMin((ambient + diffuseComp)*d->Color.greenF() + specularComp, 1.));
         intensity.setZ( qMin((ambient + diffuseComp)*d->Color.blueF() + specularComp, 1.));
         
-        rgba = qRgba(static_cast<unsigned char>(255. * intensity.x()),
-                     static_cast<unsigned char>(255. * intensity.y()),
-                     static_cast<unsigned char>(255. * intensity.z()),
-                     255);
-        }
-      else
-        {
-        int iGrid = i / size8;
-        int jGrid = j / size8;
-        
-        if (((iGrid / 2) * 2 == iGrid &&
-             (jGrid / 2) * 2 == jGrid) ||
-            ((iGrid / 2) * 2 != iGrid &&
-             (jGrid / 2) * 2 != jGrid))
+        if (opacity == 1.)
           {
-          rgba = qRgba(0, 0, 0, d->GridOpacity * 255);
+          rgba = qRgba(static_cast<unsigned char>(255. * intensity.x() * opacity),
+                       static_cast<unsigned char>(255. * intensity.y() * opacity),
+                       static_cast<unsigned char>(255. * intensity.z() * opacity),
+                       static_cast<unsigned char>(255. * opacity));
           }
         else
           {
-          rgba = qRgba(255, 255, 255, d->GridOpacity * 255);
+          rgba = qRgba(static_cast<unsigned char>(qMin(255. * intensity.x() * opacity + qRed(rgba)*(1. - opacity), 255.)),
+                       static_cast<unsigned char>(qMin(255. * intensity.y() * opacity + qGreen(rgba)*(1. - opacity), 255.)),
+                       static_cast<unsigned char>(qMin(255. * intensity.z() * opacity + qBlue(rgba)*(1. - opacity), 255.)),
+                       static_cast<unsigned char>(qMin(255. * opacity + qAlpha(rgba)*(1. - opacity), 255.)));
           }
         }
       image.setPixel(i,j,rgba);

+ 7 - 1
Libs/Widgets/ctkMaterialPropertyPreviewLabel.h

@@ -39,11 +39,14 @@ class CTK_WIDGETS_EXPORT ctkMaterialPropertyPreviewLabel : public QFrame
   Q_PROPERTY(double specularPower READ specularPower WRITE setSpecularPower)
 
   Q_PROPERTY(QColor color READ color WRITE setColor)
+  Q_PROPERTY(double opacity READ opacity WRITE setOpacity)
   Q_PROPERTY(double gridOpacity READ gridOpacity WRITE setGridOpacity)
 public : 
 
   ctkMaterialPropertyPreviewLabel(QWidget *parent = 0);
-  ctkMaterialPropertyPreviewLabel(double ambient, double diffuse, double specular, double specularPower, QWidget *parent = 0);
+  ctkMaterialPropertyPreviewLabel(const QColor& color, double opacity,
+    double ambient, double diffuse, double specular, double specularPower,
+    QWidget *parent = 0);
   virtual ~ctkMaterialPropertyPreviewLabel();
   
   double ambient()const;
@@ -52,6 +55,7 @@ public :
   double specularPower()const;
   
   QColor color()const;
+  double opacity()const;
   double gridOpacity()const;
 
   /// Reimplemented to make it square
@@ -69,6 +73,8 @@ public slots:
   void setSpecularPower(double newSpecularPower);
   
   void setColor(const QColor& newColor);
+  /// Valid range: [0, 1]
+  void setOpacity(double newOpacity);
   void setGridOpacity(double newGridOpacity);
 
 protected: 

+ 145 - 21
Libs/Widgets/ctkMaterialPropertyWidget.cpp

@@ -55,21 +55,38 @@ ctkMaterialPropertyWidget::ctkMaterialPropertyWidget(QWidget* _parent)
   Q_D(ctkMaterialPropertyWidget);
   
   d->setupUi(this);
+
+  connect(d->ColorPickerButton, SIGNAL(colorChanged(QColor)),
+          this, SLOT(onColorChanged(QColor)));
+  connect(d->OpacitySliderSpinBox, SIGNAL(valueChanged(double)),
+          this, SLOT(onOpacityChanged(double)));
   
+  connect(d->AmbientSliderSpinBox, SIGNAL(valueChanged(double)),
+          this, SLOT(onAmbientChanged(double)));
+  connect(d->DiffuseSliderSpinBox, SIGNAL(valueChanged(double)),
+          this, SLOT(onDiffuseChanged(double)));
+  connect(d->SpecularSliderSpinBox, SIGNAL(valueChanged(double)),
+          this, SLOT(onSpecularChanged(double)));
+  connect(d->SpecularPowerSliderSpinBox, SIGNAL(valueChanged(double)),
+          this, SLOT(onSpecularPowerChanged(double)));
+
+  connect(d->BackfaceCullingCheckBox, SIGNAL(toggled(bool)),
+          this, SLOT(onBackfaceCullingChanged(bool)));
+
   connect(d->PresetsListWidget, SIGNAL(itemClicked(QListWidgetItem*)),
           this, SLOT(selectPreset(QListWidgetItem*)));
-
-  this->addPreset(1.,0.,0.,1.,"Full ambient eliminating all directional shading.");
-  this->addPreset(0.2,1.,0.,1.,"Dull material properties (no specular lighting).");
-  this->addPreset(0.1,0.9,0.2,10.,"Smooth material properties (moderate specular lighting).");
-  this->addPreset(0.1,0.6,0.5,40.,"Shiny material properties (high specular lighting).");
+  // default presets
+  this->addPreset(Qt::white,1.,1.,0.,0.,1.,"Full ambient eliminating all directional shading.");
+  this->addPreset(Qt::white,1.,0.2,1.,0.,1.,"Dull material properties (no specular lighting).");
+  this->addPreset(Qt::white,1.,0.1,0.9,0.2,10.,"Smooth material properties (moderate specular lighting).");
+  this->addPreset(Qt::white,1.,0.1,0.6,0.5,40.,"Shiny material properties (high specular lighting).");
   
   d->PresetsListWidget->viewport()->setAutoFillBackground( false);
   d->PresetsListWidget->setAutoFillBackground( false );
-  d->PresetsListWidget->setMaximumHeight(
-    d->MaterialPropertyPreviewLabel->sizeHint().height()
-    + d->PresetsListWidget->horizontalScrollBar()->sizeHint().height()
-    + 2. * d->PresetsListWidget->frameWidth());
+  d->PresetsListWidget->setMinimumWidth(
+    d->PresetsListWidget->frameWidth() // left frame width
+    + d->PresetsListWidget->count() * d->MaterialPropertyPreviewLabel->sizeHint().width()
+    + d->PresetsListWidget->frameWidth() ); // right frame width
 }
 
 // --------------------------------------------------------------------------
@@ -78,17 +95,45 @@ ctkMaterialPropertyWidget::~ctkMaterialPropertyWidget()
 }
 
 // --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::setColor(const QColor& newColor)
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  d->ColorPickerButton->setColor(newColor);
+}
+
+// --------------------------------------------------------------------------
+QColor ctkMaterialPropertyWidget::color()const
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  return d->ColorPickerButton->color();
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::setOpacity(double newOpacity)
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  d->OpacitySliderSpinBox->setValue(newOpacity);
+}
+
+// --------------------------------------------------------------------------
+double ctkMaterialPropertyWidget::opacity()const
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  return d->OpacitySliderSpinBox->value();
+}
+
+// --------------------------------------------------------------------------
 void ctkMaterialPropertyWidget::setAmbient(double newAmbient)
 {
   Q_D(const ctkMaterialPropertyWidget);
-  d->DiffuseSliderSpinBox->setValue(newAmbient);
+  d->AmbientSliderSpinBox->setValue(newAmbient);
 }
 
 // --------------------------------------------------------------------------
 double ctkMaterialPropertyWidget::ambient()const
 {
   Q_D(const ctkMaterialPropertyWidget);
-  return d->DiffuseSliderSpinBox->value();
+  return d->AmbientSliderSpinBox->value();
 }
 
 // --------------------------------------------------------------------------
@@ -134,19 +179,79 @@ double ctkMaterialPropertyWidget::specularPower()const
 }
 
 // --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::setBackfaceCulling(bool newBackfaceCulling)
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  d->BackfaceCullingCheckBox->setChecked(newBackfaceCulling);
+}
+
+// --------------------------------------------------------------------------
+bool ctkMaterialPropertyWidget::backfaceCulling()const
+{
+  Q_D(const ctkMaterialPropertyWidget);
+  return d->BackfaceCullingCheckBox->isChecked();
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onColorChanged(const QColor& newColor)
+{
+  emit colorChanged(newColor);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onOpacityChanged(double newOpacity)
+{
+  emit opacityChanged(newOpacity);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onAmbientChanged(double newAmbient)
+{
+  emit ambientChanged(newAmbient);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onDiffuseChanged(double newDiffuse)
+{
+  emit diffuseChanged(newDiffuse);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onSpecularChanged(double newSpecular)
+{
+  emit specularChanged(newSpecular);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onSpecularPowerChanged(double newSpecularPower)
+{
+  emit specularPowerChanged(newSpecularPower);
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::onBackfaceCullingChanged(bool newBackfaceCulling)
+{
+  emit backfaceCullingChanged(newBackfaceCulling);
+}
+
+// --------------------------------------------------------------------------
 void ctkMaterialPropertyWidget::addPreset(
-  double ambient, double diffuse, double specular, double power, const QString& label)
+  const QColor& color, double opacity,
+  double ambient, double diffuse, double specular, double power,
+  const QString& label)
 {
   Q_D(ctkMaterialPropertyWidget);
   d->PresetsListWidget->addItem("");
   QListWidgetItem* item = d->PresetsListWidget->item(d->PresetsListWidget->count()-1);
   item->setToolTip(label);
-  item->setData(Qt::UserRole, ambient); 
-  item->setData(Qt::UserRole + 1, diffuse);
-  item->setData(Qt::UserRole + 2, specular);
-  item->setData(Qt::UserRole + 3, power);
+  item->setData(Qt::UserRole, color);
+  item->setData(Qt::UserRole + 1, opacity);
+  item->setData(Qt::UserRole + 2, ambient); 
+  item->setData(Qt::UserRole + 3, diffuse);
+  item->setData(Qt::UserRole + 4, specular);
+  item->setData(Qt::UserRole + 5, power);
   ctkMaterialPropertyPreviewLabel* preset =
-    new ctkMaterialPropertyPreviewLabel(ambient, diffuse, specular, power);
+    new ctkMaterialPropertyPreviewLabel(color, opacity, ambient, diffuse, specular, power);
   preset->setColor(d->MaterialPropertyPreviewLabel->color());
   preset->setGridOpacity(d->MaterialPropertyPreviewLabel->gridOpacity());
   item->setSizeHint(preset->sizeHint());
@@ -157,8 +262,27 @@ void ctkMaterialPropertyWidget::addPreset(
 void ctkMaterialPropertyWidget::selectPreset(QListWidgetItem* preset)
 {
   Q_D(ctkMaterialPropertyWidget);
-  d->AmbientSliderSpinBox->setValue(preset->data(Qt::UserRole).toDouble());
-  d->DiffuseSliderSpinBox->setValue(preset->data(Qt::UserRole + 1).toDouble());
-  d->SpecularSliderSpinBox->setValue(preset->data(Qt::UserRole + 2).toDouble());
-  d->SpecularPowerSliderSpinBox->setValue(preset->data(Qt::UserRole + 3).toDouble());
+  d->ColorPickerButton->setColor(preset->data(Qt::UserRole).value<QColor>());
+  d->OpacitySliderSpinBox->setValue(preset->data(Qt::UserRole + 1).toDouble());
+  d->AmbientSliderSpinBox->setValue(preset->data(Qt::UserRole + 2).toDouble());
+  d->DiffuseSliderSpinBox->setValue(preset->data(Qt::UserRole + 3).toDouble());
+  d->SpecularSliderSpinBox->setValue(preset->data(Qt::UserRole + 4).toDouble());
+  d->SpecularPowerSliderSpinBox->setValue(preset->data(Qt::UserRole + 5).toDouble());
+}
+
+// --------------------------------------------------------------------------
+void ctkMaterialPropertyWidget::resizeEvent(QResizeEvent* resize)
+{
+  Q_D(ctkMaterialPropertyWidget);
+  this->QWidget::resizeEvent(resize);
+  d->PresetsListWidget->setMaximumWidth(
+    d->PresetsListWidget->frameWidth() // left frame width
+    + d->PresetsListWidget->count() * d->MaterialPropertyPreviewLabel->sizeHint().width()
+    + d->PresetsListWidget->frameWidth() ); // right frame width
+  d->PresetsListWidget->setMaximumHeight(
+    d->PresetsListWidget->frameWidth() // top frame height
+    + d->MaterialPropertyPreviewLabel->sizeHint().height()
+    + (d->PresetsListWidget->horizontalScrollBar()->isVisibleTo(d->PresetsListWidget) ? 
+      d->PresetsListWidget->horizontalScrollBar()->sizeHint().height() : 0)
+    + d->PresetsListWidget->frameWidth() ); // bottom frame height
 }

+ 33 - 2
Libs/Widgets/ctkMaterialPropertyWidget.h

@@ -33,10 +33,13 @@ class QListWidgetItem;
 class CTK_WIDGETS_EXPORT ctkMaterialPropertyWidget : public QWidget
 {
   Q_OBJECT
+  Q_PROPERTY(QColor color  READ color WRITE setColor);
+  Q_PROPERTY(double opacity READ opacity WRITE setOpacity);
   Q_PROPERTY(double ambient READ ambient WRITE setAmbient);
   Q_PROPERTY(double diffuse READ diffuse WRITE setDiffuse);
   Q_PROPERTY(double specular READ specular WRITE setSpecular);
   Q_PROPERTY(double specularPower READ specularPower WRITE setSpecularPower);
+  Q_PROPERTY(bool backfaceCulling READ backfaceCulling WRITE setBackfaceCulling);
 public:
   /// Superclass typedef
   typedef QWidget Superclass;
@@ -46,32 +49,60 @@ public:
   
   /// Destructor
   virtual ~ctkMaterialPropertyWidget();
+  
+  QColor color()const;
+  double opacity()const;
 
   double ambient()const;
   double diffuse()const;
   double specular()const;
   double specularPower()const;
   
-  void addPreset(double ambient, double diffuse, double specular, double power, const QString& label);
+  bool backfaceCulling()const;
+  
+  void addPreset(const QColor& color, double opacity,
+                 double ambient, double diffuse,
+                 double specular, double power,
+                 const QString& label);
 
 public slots:
+  void setColor(const QColor& newColor);
+  void setOpacity(double newOpacity);
+
   void setAmbient(double newAmbient);
   void setDiffuse(double newDiffuse);
   void setSpecular(double newSpecular);
   void setSpecularPower(double newSpecularPower);
 
+  void setBackfaceCulling(bool enable);
+
 signals:
+  void colorChanged(QColor newColor);
+  void opacityChanged(double newOpacity);
+
   void ambientChanged(double newAmbient);
   void diffuseChanged(double newDiffuse);
   void specularChanged(double newSpecular);
   void specularPowerChanged(double newSpecularPower);
-  
+
+  void backfaceCullingChanged(bool newBackfaceCulling);
 protected slots:
+  virtual void onColorChanged(const QColor& newColor);
+  virtual void onOpacityChanged(double newOpacity);
+
+  virtual void onAmbientChanged(double newAmbient);
+  virtual void onDiffuseChanged(double newDiffuse);
+  virtual void onSpecularChanged(double newSpecular);
+  virtual void onSpecularPowerChanged(double newSpecularPower);
+  
+  virtual void onBackfaceCullingChanged(bool newBackFaceCulling);
+
   void selectPreset(QListWidgetItem*);
 
 protected:
   QScopedPointer<ctkMaterialPropertyWidgetPrivate> d_ptr;
 
+  virtual void resizeEvent(QResizeEvent* resize);
 private:
   Q_DECLARE_PRIVATE(ctkMaterialPropertyWidget);
   Q_DISABLE_COPY(ctkMaterialPropertyWidget);