Commit 39cc622b authored by Martin Heistermann's avatar Martin Heistermann

mat3x3 vis: Implement box-based visualisation

parent 51d944e8
......@@ -7,8 +7,8 @@ if(APPLE)
add_definitions(-DOVM_FORCE_STATIC_CAST)
endif()
openflipper_plugin (INSTALLDATA Icons
DIRS OpenMesh OpenVolumeMesh Widgets ScriptObjects Toolbars Models PropertyVisualizer
openflipper_plugin (INSTALLDATA Icons Shaders
DIRS OpenMesh OpenVolumeMesh Widgets ScriptObjects Toolbars Models Nodes PropertyVisualizer
DEPS OpenMesh
OPTDEPS OpenVolumeMesh
OPT_TYPES SKELETON BSPLINECURVE POLYHEDRALMESH HEXAHEDRALMESH TETRAHEDRALMESH
......
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#include <ACG/GL/acg_glew.hh>
#include "BoxesNode.hh"
#include <ACG/GL/IRenderer.hh>
namespace ACG {
namespace SceneGraph {
BoxesNode::BoxesNode(BaseNode* _parent,
std::string _name) :
MaterialNode(_parent, _name),
updateVBO_(true)
{
const std::array<Vec4f,3> dim_color = {
Vec4f{1.f,0.f,0.f,1.f},
Vec4f{0.f,1.f,0.f,1.f},
Vec4f{0.f,0.f,1.f,1.f}
};
const std::array<Vec3f, 8> vertices = {
Vec3f( 1.f, -1.f, -1.f),
Vec3f( 1.f, 1.f, -1.f),
Vec3f( 1.f, 1.f, 1.f),
Vec3f( 1.f, -1.f, 1.f),
Vec3f(-1.f, -1.f, -1.f),
Vec3f(-1.f, 1.f, -1.f),
Vec3f(-1.f, 1.f, 1.f),
Vec3f(-1.f, -1.f, 1.f)};
auto add_triangle = [this, &vertices, &dim_color]
(size_t v0, size_t v1, size_t v2, size_t dim)
{
triangles_.push_back({vertices[v0], vertices[v1], vertices[v2]});
triangle_colors_.push_back(dim_color[dim]);
};
triangles_.reserve(6*2);
triangle_colors_.reserve(6*2);
add_triangle(0, 1, 2, 0);
add_triangle(0, 2, 3, 0);
add_triangle(4, 6, 5, 0);
add_triangle(4, 7, 6, 0);
add_triangle(1, 5, 6, 1);
add_triangle(1, 6, 2, 1);
add_triangle(0, 3, 7, 1);
add_triangle(0, 7, 4, 1);
add_triangle(2, 7, 3, 2);
add_triangle(2, 6, 7, 2);
add_triangle(0, 4, 1, 2);
add_triangle(1, 4, 5, 2);
}
void
BoxesNode::
boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
{
for (const auto &be: elem_) {
_bbMax.maximize(be.pos + Vec3d(1.,1.,1.));
_bbMin.minimize(be.pos + Vec3d(-1., -1., -1.));
}
}
void BoxesNode::createVBO()
{
if (!updateVBO_)
return;
// generate if needed:
geometry_vbo_.bind();
instance_vbo_.bind();
vertexDecl_.clear();
vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, nullptr, nullptr, 0, geometry_vbo_.id());
vertexDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, nullptr, nullptr, 0, geometry_vbo_.id());
std::vector<float> geom_vbo_data; geom_vbo_data.reserve(3 * (3+4) * triangles_.size());
vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, nullptr, "inst_v0", 1, instance_vbo_.id());
vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, nullptr, "inst_v1", 1, instance_vbo_.id());
vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, nullptr, "inst_v2", 1, instance_vbo_.id());
vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, nullptr, "inst_pos", 1, instance_vbo_.id());
std::vector<float> instance_vbo_data; instance_vbo_data.reserve(3 * 4 * elem_.size());
assert(triangles_.size() == triangle_colors_.size());
for (size_t i = 0; i < triangles_.size(); ++i)
{
auto &tri = triangles_[i];
auto &color = triangle_colors_[i];
for (const auto &point: tri) {
std::copy(point.begin(), point.end(), std::back_inserter(geom_vbo_data));
std::copy(color.begin(), color.end(), std::back_inserter(geom_vbo_data));
}
}
for (const auto &be: elem_) {
for (const auto &point: {
be.transform.getRow(0),
be.transform.getRow(1),
be.transform.getRow(2),
be.pos})
{
std::copy(point.begin(), point.end(), std::back_inserter(instance_vbo_data));
}
}
geometry_vbo_.upload(
static_cast<GLsizeiptr>(geom_vbo_data.size()*sizeof(float)),
geom_vbo_data.data(),
GL_STATIC_DRAW_ARB);
instance_vbo_.upload(
static_cast<GLsizeiptr>(instance_vbo_data.size()*sizeof(float)),
instance_vbo_data.data(),
GL_STATIC_DRAW_ARB);
// Update done.
updateVBO_ = false;
}
void
BoxesNode::
getRenderObjects(IRenderer* _renderer, GLState& _state , const DrawModes::DrawMode& /* _drawMode */, const ACG::SceneGraph::Material* _mat)
{
if (elem_.empty())
return;
RenderObject ro;
ro.initFromState(&_state);
ro.setMaterial(_mat);
boxesNodeName_ = std::string("BoxesNode: ")+name();
ro.debugName = boxesNodeName_;
ro.depthTest = true;
ro.depthWrite = true;
ro.blending = true;
ro.blendSrc = GL_SRC_ALPHA;
ro.blendDest = GL_ONE_MINUS_SRC_ALPHA;
ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
ro.shaderDesc.vertexColors = true;
ro.shaderDesc.vertexTemplateFile = "BoxesNode/vert.glsl";
ro.setUniform("scale", scaleFactor_);
createVBO();
ro.vertexBuffer = geometry_vbo_.id();
ro.vertexDecl = &vertexDecl_;
ro.glDrawInstancedArrays(GL_TRIANGLES, 0,
static_cast<GLsizei>(3 * triangles_.size()),
static_cast<GLsizei>(elem_.size()));
_renderer->addRenderObject(&ro);
}
} // namespace SceneGraph
} // namespace ACG
#pragma once
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#include <ACG/Scenegraph/MaterialNode.hh>
#include <ACG/Scenegraph/DrawModes.hh>
#include <ACG/GL/VertexDeclaration.hh>
#include <ACG/GL/globjects.hh>
#include <ACG/Math/Matrix3x3T.hh>
#include <vector>
#include <limits>
namespace ACG {
namespace SceneGraph {
struct BoxElement {
Matrix3x3d transform;
Vec3d pos;
};
class ACGDLLEXPORT BoxesNode : public MaterialNode
{
public:
ACG_CLASSNAME(BoxesNode)
BoxesNode(BaseNode* _parent=nullptr,
std::string _name="<BoxesNode>" );
~BoxesNode() = default;
DrawModes::DrawMode availableDrawModes() const {
return DrawModes::SOLID_FACES_COLORED_FLAT_SHADED;
}
void boundingBox(Vec3d& _bbMin, Vec3d& _bbMax);
void clear() { elem_.clear(); updateVBO_ = true; }
void reserve(size_t _n) { elem_.reserve(_n); }
/// STL conformance
void push_back(const BoxElement& _v) { elem_.push_back(_v); updateVBO_ = true; }
typedef BoxElement value_type;
typedef BoxElement& reference;
typedef const BoxElement& const_reference;
void getRenderObjects(IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const ACG::SceneGraph::Material* _mat);
void setScaleFactor(float _val) { scaleFactor_ = _val;}
protected:
/// creates the vbo only if update was requested
void createVBO();
std::vector<BoxElement> elem_;
float scaleFactor_ = 1.0f;
// geometry of a single box
std::vector<std::array<Vec3f,3>> triangles_;
std::vector<Vec4f> triangle_colors_;
GeometryBuffer geometry_vbo_;
GeometryBuffer instance_vbo_;
// True if points changed and the vbo has to be updated
bool updateVBO_;
ACG::VertexDeclaration vertexDecl_;
std::string boxesNodeName_;
};
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================
......@@ -45,6 +45,9 @@
#include "OVMPropertyVisualizer.hh"
#include <ACG/Scenegraph/LineNode.hh>
#include <ACG/Scenegraph/MeshNode2T.hh>
#include "Nodes/BoxesNode.hh"
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <OpenVolumeMesh/Core/BaseEntities.hh>
......@@ -77,16 +80,18 @@ protected:
QString getPropertyText(unsigned int index) override;
ACG::SceneGraph::LineNode* lineNode;
ACG::SceneGraph::BoxesNode* boxesNode;
private:
template<typename EntityTag, typename EntityIterator>
void visualizeAsCrossForEntity(EntityIterator e_begin, EntityIterator e_end);
template<typename EntityTag, typename EntityIterator>
void visualizeAsBoxesForEntity(EntityIterator e_begin, EntityIterator e_end);
template<typename EntityTag, typename Property, typename EntityIterator>
void visualizeAsCrossesForEntity(Property prop, EntityIterator e_begin, EntityIterator e_end);
template<typename EntityTag, typename Property, typename EntityIterator>
void visualizeAsBoxesForEntity(Property prop, EntityIterator e_begin, EntityIterator e_end);
template<typename EntityTag, typename EntityIterator>
void visualizeForEntity(EntityIterator e_begin, EntityIterator e_end);
Matrix3x3Widget* getWidget() {return static_cast<Matrix3x3Widget*>(PropertyVisualizer::widget);}
};
#if defined(INCLUDE_TEMPLATES) && !defined(OVM_PROPERTY_VISUALIZER_MAT3X3_CC)
......
......@@ -46,8 +46,16 @@
#include <ACG/Utils/ColorConversion.hh>
#include "OVMPropertyVisualizerMatrix3x3.hh"
#include "ACG/Scenegraph/DrawModes.hh"
#include "EntityPosition.hh"
using Color4f = ACG::SceneGraph::LineNode::Color4f;
static std::array<Color4f, 3> dim_color {
Color4f{1.f,0.f,0.f,1.f},
Color4f{0.f,1.f,0.f,1.f},
Color4f{0.f,0.f,1.f,1.f}
};
template <typename MeshT>
OVMPropertyVisualizerMatrix3x3<MeshT>::OVMPropertyVisualizerMatrix3x3(MeshT* _mesh, int objectID, PropertyInfo _propertyInfo)
: OVMPropertyVisualizer<MeshT>(_mesh, objectID, _propertyInfo)
......@@ -58,7 +66,10 @@ OVMPropertyVisualizerMatrix3x3<MeshT>::OVMPropertyVisualizerMatrix3x3(MeshT* _me
BaseObjectData *bod;
PluginFunctions::getObject(objectID, bod);
lineNode = new ACG::SceneGraph::LineNode(ACG::SceneGraph::LineNode::LineSegmentsMode, bod->baseNode());
boxesNode = new ACG::SceneGraph::BoxesNode(bod->manipulatorNode());
lineNode = new ACG::SceneGraph::LineNode(ACG::SceneGraph::LineNode::LineSegmentsMode, bod->manipulatorNode());
this->connect(w->lineWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
[this](double value) {lineNode->set_line_width(value);});
}
......@@ -67,6 +78,7 @@ template <typename MeshT>
void OVMPropertyVisualizerMatrix3x3<MeshT>::clear()
{
lineNode->clear();
boxesNode->clear();
OVMPropertyVisualizer<MeshT>::clear();
}
......@@ -77,31 +89,20 @@ void OVMPropertyVisualizerMatrix3x3<MeshT>::duplicateProperty()
}
template<typename MeshT>
template<typename EntityTag, typename EntityIterator>
template<typename EntityTag, typename Property, typename EntityIterator>
void OVMPropertyVisualizerMatrix3x3<MeshT>::
visualizeAsCrossForEntity(EntityIterator e_begin, EntityIterator e_end)
visualizeAsCrossesForEntity(Property prop, EntityIterator e_begin, EntityIterator e_end)
{
using ACG::Vec3d;
using ACG::Matrix3x3d;
using Color4f = ACG::SceneGraph::LineNode::Color4f;
MeshT &m = * OVMPropertyVisualizer<MeshT>::mesh;
MeshT &m = *OVMPropertyVisualizer<MeshT>::mesh;
EntityPosition<MeshT> ep{m};
auto prop = m.template request_property<ACG::Matrix3x3d, EntityTag>(OVMPropertyVisualizer<MeshT>::propertyInfo.propName());
if (!prop)
throw VizException("Getting PropHandle from mesh for selected property failed.");
std::array<Color4f, 3> dim_color {
Color4f{1.f,0.f,0.f,1.f},
Color4f{0.f,1.f,0.f,1.f},
Color4f{0.f,0.f,1.f,1.f}
};
lineNode->clear();
bool normalized = getWidget()->normalize_colors->isChecked();
double scaleFactor = getWidget()->scale->isChecked() ? getWidget()->scaleBox->value() : 1.0;
double scaleFactor = getWidget()->getScaleFactor();
for (EntityIterator e_it = e_begin; e_it != e_end; ++e_it) {
Matrix3x3d mat = prop[*e_it];
Vec3d center_pos = ep(*e_it);
......@@ -115,11 +116,30 @@ visualizeAsCrossForEntity(EntityIterator e_begin, EntityIterator e_end)
}
template<typename MeshT>
template<typename EntityTag, typename EntityIterator>
template<typename EntityTag, typename Property, typename EntityIterator>
void OVMPropertyVisualizerMatrix3x3<MeshT>::
visualizeAsBoxesForEntity(EntityIterator e_begin, EntityIterator e_end)
visualizeAsBoxesForEntity(Property prop, EntityIterator e_begin, EntityIterator e_end)
{
using ACG::Vec3d;
using ACG::Matrix3x3d;
MeshT &m = *OVMPropertyVisualizer<MeshT>::mesh;
EntityPosition<MeshT> ep{m};
bool normalized = getWidget()->normalize_colors->isChecked();
for (EntityIterator e_it = e_begin; e_it != e_end; ++e_it) {
const Matrix3x3d &mat = prop[*e_it];
Vec3d center_pos = ep(*e_it);
std::array<Vec3d, 3> dir;
for (unsigned char dim = 0; dim < 3; ++dim) {
dir[dim] = mat.getCol(dim);
if (normalized) {
dir[dim].normalize();
}
}
boxesNode->push_back({Matrix3x3d::fromColumns(dir[0], dir[1], dir[2]), center_pos});
}
boxesNode->setScaleFactor(getWidget()->getScaleFactor());
}
template<typename MeshT>
......@@ -127,10 +147,16 @@ template<typename EntityTag, typename EntityIterator>
void OVMPropertyVisualizerMatrix3x3<MeshT>::
visualizeForEntity(EntityIterator e_begin, EntityIterator e_end)
{
clear();
MeshT &m = * OVMPropertyVisualizer<MeshT>::mesh;
auto prop = m.template request_property<ACG::Matrix3x3d, EntityTag>(OVMPropertyVisualizer<MeshT>::propertyInfo.propName());
if (!prop)
throw VizException("Getting PropHandle from mesh for selected property failed.");
if (getWidget()->as_crosses->isChecked()) {
visualizeAsCrossForEntity<EntityTag>(e_begin, e_end);
visualizeAsCrossesForEntity<EntityTag>(prop, e_begin, e_end);
} else if (getWidget()->as_boxes->isChecked()) {
visualizeAsBoxesForEntity<EntityTag>(e_begin, e_end);
visualizeAsBoxesForEntity<EntityTag>(prop, e_begin, e_end);
}
}
......
......@@ -59,7 +59,7 @@ OVMPropertyVisualizerVector<MeshT>::OVMPropertyVisualizerVector(MeshT* _mesh, in
BaseObjectData *bod;
PluginFunctions::getObject(objectID, bod);
lineNode = new ACG::SceneGraph::LineNode(ACG::SceneGraph::LineNode::LineSegmentsMode, bod->baseNode());
lineNode = new ACG::SceneGraph::LineNode(ACG::SceneGraph::LineNode::LineSegmentsMode, bod->manipulatorNode());
w->vectors_edges_rb->hide();
this->connect(w->lineWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
[this](double value) {lineNode->set_line_width(value);});
......
#version 140
in vec3 inst_v0;
in vec3 inst_v1;
in vec3 inst_v2;
in vec3 inst_pos;
uniform float scale;
void main()
{
SG_VERTEX_BEGIN;
vec4 pa_posOS = SG_INPUT_POSOS;
vec4 pa_posWS;
pa_posWS.x = dot(inst_v0, pa_posOS.xyz);
pa_posWS.y = dot(inst_v1, pa_posOS.xyz);
pa_posWS.z = dot(inst_v2, pa_posOS.xyz);
pa_posWS.w = 1.0;
pa_posWS.xyz *= scale;
pa_posWS.xyz += inst_pos;
#ifdef SG_INPUT_NORMALOS
sg_vNormalVS.x = dot(pa_worldTransform0.xyz, SG_INPUT_NORMALOS.xyz);
sg_vNormalVS.y = dot(pa_worldTransform1.xyz, SG_INPUT_NORMALOS.xyz);
sg_vNormalVS.z = dot(pa_worldTransform2.xyz, SG_INPUT_NORMALOS.xyz);
sg_vNormalVS = g_mWVIT * sg_vNormalVS;
sg_vNormalVS = normalize(sg_vNormalVS);
#endif
sg_vPosVS = g_mWV * pa_posWS;
sg_vPosPS = g_mWVP * pa_posWS;
SG_VERTEX_END;
}
......@@ -50,15 +50,17 @@
class Matrix3x3Widget : public QWidget, public Ui::Mat3x3Widget
{
Q_OBJECT
Q_OBJECT
public:
explicit Matrix3x3Widget(QWidget * parent = nullptr);
explicit Matrix3x3Widget(QWidget * parent = nullptr);
signals:
double getScaleFactor() { return scale->isChecked() ? scaleBox->value() : 1.0; }
signals:
void widgetShown();
protected:
protected:
void showEvent ( QShowEvent* /*event*/ );
};
......
......@@ -116,7 +116,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Visualize columns as:</string>
<string>Show transformation on:</string>
</property>
</widget>
</item>
......@@ -180,7 +180,7 @@
<double>50.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
<double>3.000000000000000</double>
</property>
</widget>
</item>
......@@ -197,6 +197,9 @@
<string>Scale with factor</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
......@@ -204,7 +207,7 @@
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="scaleBox">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="decimals">
<number>7</number>
......@@ -213,26 +216,12 @@
<double>1000.000000000000000</double>
</property>
<property name="value">
<double>0.200000000000000</double>
<double>0.050000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QtColorChooserButton" name="lineColor">
<property name="text">
<string>Line color: </string>
</property>
<property name="color" stdset="0">
<color>
<red>198</red>
<green>0</green>
<blue>3</blue>
</color>
</property>
</widget>
</item>
</layout>
</widget>
</item>
......@@ -270,20 +259,12 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QtColorChooserButton</class>
<extends>QPushButton</extends>
<header>ACG/QtWidgets/QtColorChooserButton.hh</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>as_crosses</tabstop>
<tabstop>as_boxes</tabstop>
<tabstop>normalize</tabstop>
<tabstop>scale</tabstop>
<tabstop>scaleBox</tabstop>
<tabstop>lineColor</tabstop>
<tabstop>vectors_edges_alpha</tabstop>
<tabstop>vectors_edges_beta</tabstop>
</tabstops>
......@@ -305,6 +286,38 @@
</hint>
</hints>
</connection>
<connection>
<sender>as_crosses</sender>
<signal>toggled(bool)</signal>
<receiver>lineWidth</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>93</x>
<y>62</y>
</hint>
<hint type="destinationlabel">
<x>260</x>
<y>147</y>
</hint>
</hints>
</connection>
<connection>
<sender>as_crosses</sender>
<signal>toggled(bool)</signal>
<receiver>lineWidthLabel</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>93</x>
<y>62</y>
</hint>
<hint type="destinationlabel">
<x>100</x>
<y>147</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="vector_buttonGroup"/>
......
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