Commit 23b10f4b authored by Haocheng LIU's avatar Haocheng LIU Committed by Kitware Robot

Merge topic 'avoid-wrongly-setting-color-on-entity'

c0bb9d73 Query an entity's color status before fetching its color
82481608 Add support for translucency to _Assign Colors_.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: David Thompson's avatarDavid Thompson <david.thompson@kitware.com>
Merge-request: !1492
parents 9a0400f5 c0bb9d73
Pipeline #131927 running with stage
Add support for translucency to assign color operator
......@@ -38,7 +38,7 @@ static bool hexDigitValue(int& value, char digit)
* This returns true when \a colorSpec is a valid color and false otherwise.
* If false is returned, then \a rgba is unmodified.
*/
bool Color::stringToFloatRGBA(double* rgba, const std::string& colorSpec)
bool Color::stringToFloatRGBA(double* rgba, const std::string& colorSpec, double defaultAlpha)
{
if (colorSpec.empty())
return false;
......@@ -81,7 +81,7 @@ bool Color::stringToFloatRGBA(double* rgba, const std::string& colorSpec)
// Fill out any remaining components.
for (; cc < 4; ++cc)
{
rgba[cc] = (cc == 3 ? 1.0 : 0.0);
rgba[cc] = (cc == 3 ? defaultAlpha : 0.0);
}
return true;
}
......
......@@ -26,12 +26,14 @@ namespace common
class SMTKCORE_EXPORT Color
{
public:
static bool stringToFloatRGBA(double* rgba, const std::string& colorSpec);
static bool stringToFloatRGBA(
double* rgba, const std::string& colorSpec, double defaultAlpha = 1.0);
/// Convenience to convert a string color specifier into a vector instead of a pointer.
static bool stringToFloatRGBA(std::vector<double>& rgba, const std::string& colorSpec)
static bool stringToFloatRGBA(
std::vector<double>& rgba, const std::string& colorSpec, double defaultAlpha = 1.0)
{
rgba.resize(4);
return Color::stringToFloatRGBA(&rgba[0], colorSpec);
return Color::stringToFloatRGBA(&rgba[0], colorSpec, defaultAlpha);
}
};
......
......@@ -27,9 +27,9 @@ py::class_< smtk::common::Color > pybind11_init_smtk_common_Color(py::module &m)
(smtk::common::Color & (smtk::common::Color::*)(::smtk::common::Color const &))
&smtk::common::Color::operator=)
.def_static("stringToFloatRGBA",
(bool (*)(::std::vector<double, std::allocator<double> > &, ::std::string const &))
(bool (*)(::std::vector<double, std::allocator<double> > &, ::std::string const &, double))
&smtk::common::Color::stringToFloatRGBA,
py::arg("rgba"), py::arg("colorSpec"))
py::arg("rgba"), py::arg("colorSpec"), py::arg("defaultAlpha"))
;
return instance;
}
......
......@@ -6,56 +6,62 @@
<rect>
<x>0</x>
<y>0</y>
<width>468</width>
<height>112</height>
<width>398</width>
<height>151</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Assign Colors</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QToolButton" name="ChooseColorBtn">
<item row="0" column="0">
<widget class="QLabel" name="OperationLabel">
<property name="text">
<string>apply colors:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="ApplyDefaultColorBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Click here to change the default color above.</string>
<string>Click here to assign this color to all the associated entities.</string>
</property>
<property name="text">
<string>change color</string>
<string>color</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>apply colors:</string>
<enum>Qt::ToolButtonIconOnly</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="ChoosePaletteBtn">
<item row="0" column="2">
<widget class="QToolButton" name="ApplyDefaultPaletteBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Click here to change the default palette above.</string>
<string>Click here to assign a color from this palette to each associated entity.</string>
</property>
<property name="text">
<string>change palette</string>
<string>palette</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
<enum>Qt::ToolButtonIconOnly</enum>
</property>
</widget>
</item>
......@@ -72,8 +78,15 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="ApplyDefaultColorBtn">
<item row="1" column="0">
<widget class="QToolButton" name="InfoBtn">
<property name="text">
<string>info</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="ChooseColorBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -81,18 +94,18 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>Click here to assign this color to all the associated entities.</string>
<string>Click here to change the default color above.</string>
</property>
<property name="text">
<string>color</string>
<string>change color</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="ApplyDefaultPaletteBtn">
<item row="1" column="2">
<widget class="QToolButton" name="ChoosePaletteBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -100,23 +113,64 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>Click here to assign a color from this palette to each associated entity.</string>
<string>Click here to change the default palette above.</string>
</property>
<property name="text">
<string>palette</string>
<string>change palette</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QToolButton" name="InfoBtn">
<item row="2" column="1">
<widget class="QLabel" name="OpacityLabel">
<property name="text">
<string>info</string>
<string>opacity</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSlider" name="ApplyOpacitySlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
<property name="tickInterval">
<number>16</number>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
......
......@@ -12,6 +12,7 @@
#include "smtk/extension/paraview/operators/ui_smtkAssignColorsParameters.h"
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/DoubleItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/extension/qt/qtAttribute.h"
......@@ -311,6 +312,10 @@ void smtkAssignColorsView::createWidget()
QObject::connect( // Allow the user to choose a new preference.
this->Internals->ChooseColorBtn, SIGNAL(released()), this, SLOT(chooseDefaultColorAndApply()));
// Signals and slots related to opacity mode:
QObject::connect( // When asked, apply the opacity specified by the slider.
this->Internals->ApplyOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(applyOpacity(int)));
QObject::connect( // When asked, invalidate colors on the associated entities.
this->Internals->RemoveColorBtn, SIGNAL(released()), this, SLOT(removeColors()));
......@@ -412,8 +417,12 @@ void smtkAssignColorsView::applyDefaultColor()
//std::cout << "Apply default color\n";
auto opacityItem = this->Internals->CurrentAtt->attribute()->findDouble("opacity");
opacityItem->setIsEnabled(false);
smtk::attribute::StringItem::Ptr colorsItem =
this->Internals->CurrentAtt->attribute()->findString("colors");
colorsItem->setIsEnabled(true);
colorsItem->setNumberOfValues(1);
colorsItem->setValue(0, color.name().toUtf8().constData());
......@@ -454,8 +463,11 @@ void smtkAssignColorsView::applyDefaultPalette()
return;
}
auto opacityItem = this->Internals->CurrentAtt->attribute()->findDouble("opacity");
opacityItem->setIsEnabled(false);
smtk::attribute::StringItem::Ptr colorsItem =
this->Internals->CurrentAtt->attribute()->findString("colors");
colorsItem->setIsEnabled(true);
colorsItem->setNumberOfValues(palette.size());
for (int pp = 0; pp < palette.size(); ++pp)
{
......@@ -465,6 +477,22 @@ void smtkAssignColorsView::applyDefaultPalette()
this->requestOperation(this->Internals->CurrentOp);
}
void smtkAssignColorsView::applyOpacity(int val)
{
// Enable opacity assignment
double opacity = val / 255.0;
auto opacityItem = this->Internals->CurrentAtt->attribute()->findDouble("opacity");
opacityItem->setIsEnabled(true);
opacityItem->setValue(opacity);
// Disable color assignment
smtk::attribute::StringItem::Ptr colorsItem =
this->Internals->CurrentAtt->attribute()->findString("colors");
colorsItem->setIsEnabled(false);
this->requestOperation(this->Internals->CurrentOp);
}
void smtkAssignColorsView::removeColors()
{
if (!this->Internals->CurrentAtt || !this->Internals->CurrentOp)
......@@ -472,8 +500,12 @@ void smtkAssignColorsView::removeColors()
return;
}
auto opacityItem = this->Internals->CurrentAtt->attribute()->findDouble("opacity");
opacityItem->setIsEnabled(false);
smtk::attribute::StringItem::Ptr colorsItem =
this->Internals->CurrentAtt->attribute()->findString("colors");
colorsItem->setIsEnabled(true);
colorsItem->setNumberOfValues(0);
this->requestOperation(this->Internals->CurrentOp);
}
......
......@@ -53,6 +53,7 @@ protected slots:
virtual void chooseDefaultColorAndApply();
virtual void applyDefaultColor();
virtual void applyDefaultPalette();
virtual void applyOpacity(int);
virtual void removeColors();
virtual void setDefaultPaletteAndApply();
......
......@@ -1492,7 +1492,7 @@
</Documentation>
</DoubleMapProperty>
<IntVectorProperty command="SetUseInternalAttributes"
default_values="1"
default_values="0"
name="UseInternalAttributes"
number_of_elements="1">
<BooleanDomain name="bool" />
......
......@@ -69,6 +69,14 @@ void SetAttributeBlockColorToEntity(vtkCompositeDataDisplayAttributes* atts, vtk
// FloatList is a typedef for std::vector<double>, so it is safe to
// pass the raw pointer to its data.
atts->SetBlockColor(block, color.data());
if (color[3] < 1.0)
{
atts->SetBlockOpacity(block, color[3]);
}
else
{
atts->RemoveBlockOpacity(block);
}
}
void ColorBlockAsEntity(vtkGlyph3DMapper* mapper, vtkDataObject* block,
......@@ -1207,6 +1215,7 @@ void vtkSMTKModelRepresentation::ColorByVolume(vtkCompositeDataSet* data)
// Traverse the blocks and set the volume's color
this->EntityMapper->GetCompositeDataDisplayAttributes()->RemoveBlockColors();
this->EntityMapper->GetCompositeDataDisplayAttributes()->RemoveBlockOpacities();
vtkCompositeDataIterator* it = data->NewIterator();
it->GoToFirstItem();
while (!it->IsDoneWithTraversal())
......@@ -1245,6 +1254,7 @@ void vtkSMTKModelRepresentation::ColorByEntity(vtkMultiBlockDataSet* data)
// Traverse the blocks and set the entity's color
this->EntityMapper->GetCompositeDataDisplayAttributes()->RemoveBlockColors();
this->EntityMapper->GetCompositeDataDisplayAttributes()->RemoveBlockOpacities();
vtkCompositeDataIterator* it = data->NewIterator();
it->GoToFirstItem();
while (!it->IsDoneWithTraversal())
......
......@@ -359,7 +359,7 @@ void EntityRef::setVisible(bool vis)
*/
FloatList EntityRef::color() const
{
FloatList result = this->floatProperty("color");
FloatList result = !this->hasColor() ? FloatList{} : this->floatProperty("color");
int ncomp = static_cast<int>(result.size());
if (ncomp < 4)
{
......
......@@ -1247,8 +1247,9 @@ bool Resource::hasFloatProperty(const UUID& entity, const std::string& propName)
return false;
}
FloatData::const_iterator sit = uit->second.find(propName);
// FIXME: Should we return true even when the array (*sit) is empty?
return sit == uit->second.end() ? false : true;
// when the array (*sit) is empty, we return true due to the fact that defing a dummy
// property should be considered ill formed
return sit == uit->second.end() ? false : !sit->second.empty();
}
bool Resource::removeFloatProperty(const UUID& entity, const std::string& propName)
......
......@@ -15,6 +15,7 @@
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ComponentItem.h"
#include "smtk/attribute/DoubleItem.h"
#include "smtk/attribute/ModelEntityItem.h"
#include "smtk/attribute/StringItem.h"
......@@ -25,6 +26,7 @@
#include <cstddef> // for size_t
using smtk::attribute::StringItem;
using smtk::attribute::DoubleItem;
using smtk::resource::PersistentObjectPtr;
namespace smtk
......@@ -34,9 +36,41 @@ namespace model
AssignColors::Result AssignColors::operateInternal()
{
auto associations = this->parameters()->associations();
auto entities = associations->as<EntityRefArray>([](PersistentObjectPtr obj) {
return smtk::model::EntityRef(std::dynamic_pointer_cast<smtk::model::Entity>(obj));
});
EntityRefArray modified;
// I. Set opacities
DoubleItem::Ptr opacitySpec = this->parameters()->findDouble("opacity");
double opacity = opacitySpec->isEnabled() ? opacitySpec->value() : -1.0;
if (opacity >= 0.0)
{
for (auto entity : entities)
{
bool skip = false;
// If we are setting the opacity on an entity with no
// existing color, assign it to be white by default:
FloatList color{ 1., 1., 1., opacity };
if (entity.hasColor())
{
color = entity.color();
skip = (color[3] == opacity);
color[3] = opacity;
}
if (!skip)
{
entity.setColor(color);
modified.push_back(entity);
}
}
}
// II. Set colors
std::vector<FloatList> colors;
StringItem::Ptr colorSpec = this->parameters()->findString("colors");
size_t numColors = colorSpec->numberOfValues();
size_t numColors = colorSpec->isEnabled() ? colorSpec->numberOfValues() : 0;
if (numColors > 0)
{
......@@ -44,7 +78,8 @@ AssignColors::Result AssignColors::operateInternal()
for (size_t cc = 0; cc < numColors; ++cc)
{
FloatList rgba;
if (smtk::common::Color::stringToFloatRGBA(rgba, colorSpec->value(cc)))
if (smtk::common::Color::stringToFloatRGBA(
rgba, colorSpec->value(cc), opacity >= 0.0 ? opacity : 1.0))
{
colors.push_back(rgba);
}
......@@ -62,11 +97,6 @@ AssignColors::Result AssignColors::operateInternal()
return this->createResult(smtk::operation::Operation::Outcome::FAILED);
}
auto associations = this->parameters()->associations();
auto entities = associations->as<EntityRefArray>([](PersistentObjectPtr obj) {
return smtk::model::EntityRef(std::dynamic_pointer_cast<smtk::model::Entity>(obj));
});
EntityRefArray modified;
if (numColors > 0)
{
size_t cc = 0;
......@@ -82,7 +112,7 @@ AssignColors::Result AssignColors::operateInternal()
}
}
}
else
else if (colorSpec->isEnabled())
{ // remove (or at least invalidate) colors instead
for (auto ent : entities)
{
......
......@@ -19,7 +19,7 @@
model entities if the list of colors to assign is empty.
</DetailedDescription>
<ItemDefinitions>
<String Name="colors" NumberOfRequiredValues="0" Extensible="true">
<String Name="colors" NumberOfRequiredValues="0" Extensible="true" Optional="true" IsEnabledByDefault="true">
<BriefDescription>A list of colors to assign to the associated entities.</BriefDescription>
<DetailedDescription>
Each color in the list is either a canonical color name or
......@@ -27,9 +27,18 @@
(e.g., "#ff0000" or "#f00" for pure, fully-saturated red).
An empty list indicates that the color property should be removed
from each entity.
from each entity, but only if the item is enabled.
If the item is disabled and the list is empty, there is no effect.
</DetailedDescription>
</String>
<Double Name="opacity" NumberOfRequiredValues="1" Optional="true" IsEnabledByDefault="false">
<BriefDescription>An opacity to assign to the associated entities.</BriefDescription>
<DefaultValue>1.0</DefaultValue>
<RangeInfo>
<Min Inclusive="true">0.0</Min>
<Max Inclusive="true">1.0</Max>
</RangeInfo>
</Double>
</ItemDefinitions>
</AttDef>
<!-- Result -->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment