Gui: move geometry data to separate classes from dragger components

This commit is contained in:
captain0xff
2025-07-06 23:30:08 +05:30
parent 5aba712505
commit 35fe77efd0
6 changed files with 339 additions and 272 deletions

View File

@@ -51,6 +51,7 @@
#include <Inventor/nodes/SoAnnotation.h>
#include <Inventor/nodes/SoFontStyle.h>
#include <Inventor/draggers/SoDragger.h>
#include <Inventor/nodekits/SoSubKit.h>
#endif
#include <Base/Quantity.h>
@@ -61,9 +62,83 @@
#include "Utilities.h"
#include <SoTextLabel.h>
#include <Inventor/SoToggleSwitch.h>
using namespace Gui;
SO_KIT_SOURCE(SoLinearGeometryKit)
void SoLinearGeometryKit::initClass()
{
SO_KIT_INIT_CLASS(SoLinearGeometryKit, SoBaseKit, "BaseKit");
}
SoLinearGeometryKit::SoLinearGeometryKit()
{
SO_KIT_CONSTRUCTOR(SoLinearGeometryKit);
SO_KIT_ADD_FIELD(tipPosition, (0.0, 0.0, 0.0));
SO_KIT_INIT_INSTANCE();
}
SO_KIT_SOURCE(SoArrowGeometry)
void SoArrowGeometry::initClass()
{
SO_KIT_INIT_CLASS(SoArrowGeometry, SoLinearGeometryKit, "LinearGeometryKit");
}
SoArrowGeometry::SoArrowGeometry()
{
SO_KIT_CONSTRUCTOR(SoArrowGeometry);
SO_KIT_ADD_CATALOG_ENTRY(lightModel, SoLightModel, false, this, "", false);
SO_KIT_ADD_CATALOG_ENTRY(arrowBody, SoCylinder, false, this, "", true);
SO_KIT_ADD_CATALOG_ENTRY(arrowTip, SoCone, false, this, "", true);
SO_KIT_ADD_CATALOG_ENTRY(_arrowBodyTranslation, SoTranslation, false, this, arrowBody, false);
SO_KIT_ADD_CATALOG_ENTRY(_arrowTipTranslation, SoTranslation, false, this, arrowTip, false);
SO_KIT_ADD_FIELD(coneBottomRadius, (0.8));
SO_KIT_ADD_FIELD(coneHeight, (2.5));
SO_KIT_ADD_FIELD(cylinderHeight, (10.0));
SO_KIT_ADD_FIELD(cylinderRadius, (0.1));
SO_KIT_INIT_INSTANCE();
auto arrowBody = SO_GET_ANY_PART(this, "arrowBody", SoCylinder);
arrowBody->height.connectFrom(&cylinderHeight);
arrowBody->radius.connectFrom(&cylinderRadius);
auto arrowTip = SO_GET_ANY_PART(this, "arrowTip", SoCone);
arrowTip->height.connectFrom(&coneHeight);
arrowTip->bottomRadius.connectFrom(&coneBottomRadius);
auto lightModel = SO_GET_ANY_PART(this, "lightModel", SoLightModel);
lightModel->model = SoLightModel::BASE_COLOR;
// forces the notify method to get called so that the initial translations and tipPostion are set
cylinderHeight.touch();
}
void SoArrowGeometry::notify(SoNotList* notList)
{
assert(notList);
SoField* lastField = notList->getLastField();
if (lastField == &cylinderHeight) {
auto translation = SO_GET_ANY_PART(this, "_arrowBodyTranslation", SoTranslation);
translation->translation = SbVec3f(0, cylinderHeight.getValue() / 2.0f, 0);
}
if (lastField == &coneHeight || lastField == &cylinderHeight) {
auto translation = SO_GET_ANY_PART(this, "_arrowTipTranslation", SoTranslation);
translation->translation = SbVec3f(0, (cylinderHeight.getValue() + coneHeight.getValue()) / 2.0f, 0);
tipPosition = {0, cylinderHeight.getValue() + 1.5f * coneHeight.getValue(), 0};
}
}
SO_KIT_SOURCE(SoLinearDragger)
void SoLinearDragger::initClass()
@@ -79,34 +154,31 @@ SoLinearDragger::SoLinearDragger()
this->ref();
#endif
FC_ADD_CATALOG_ENTRY(translator, SoSeparator, geomSeparator);
FC_ADD_CATALOG_ENTRY(activeSwitch, SoSwitch, translator);
FC_ADD_CATALOG_ENTRY(activeSwitch, SoToggleSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(secondaryColor, SoBaseColor, activeSwitch);
FC_ADD_CATALOG_ENTRY(coneSeparator, SoSeparator, translator);
FC_ADD_CATALOG_ENTRY(cylinderSeparator, SoSeparator, translator);
FC_ADD_CATALOG_ENTRY(labelSwitch, SoSwitch, translator);
FC_ADD_CATALOG_ENTRY(labelSwitch, SoToggleSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(labelSeparator, SoSeparator, labelSwitch);
FC_ADD_CATALOG_ENTRY(scale, SoScale, geomSeparator);
SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(arrow, SoLinearGeometryKit, SoArrowGeometry, true, geomSeparator, "", true);
SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0));
SO_KIT_ADD_FIELD(translationIncrement, (1.0));
SO_KIT_ADD_FIELD(translationIncrementCount, (0));
SO_KIT_ADD_FIELD(autoScaleResult, (1.0));
SO_KIT_ADD_FIELD(coneBottomRadius, (0.8));
SO_KIT_ADD_FIELD(coneHeight, (2.5));
SO_KIT_ADD_FIELD(cylinderHeight, (10.0));
SO_KIT_ADD_FIELD(cylinderRadius, (0.1));
SO_KIT_ADD_FIELD(activeColor, (1, 1, 0));
SO_KIT_ADD_FIELD(labelVisible, (1));
SO_KIT_ADD_FIELD(geometryScale, (1, 1, 1));
SO_KIT_INIT_INSTANCE();
setupGeometryCalculator();
setPart("cylinderSeparator", buildCylinderGeometry());
setPart("coneSeparator", buildConeGeometry());
setPart("labelSeparator", buildLabelGeometry());
setPart("secondaryColor", buildActiveColor());
FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE);
setLabelVisibility(true);
auto sw = SO_GET_ANY_PART(this, "labelSwitch", SoToggleSwitch);
sw->on.connectFrom(&labelVisible);
auto scale = SO_GET_ANY_PART(this, "scale", SoScale);
scale->scaleFactor.connectFrom(&geometryScale);
this->addStartCallback(&SoLinearDragger::startCB);
this->addMotionCallback(&SoLinearDragger::motionCB);
@@ -119,6 +191,8 @@ SoLinearDragger::SoLinearDragger()
fieldSensor.setPriority(0);
this->setUpConnections(TRUE, TRUE);
FC_SET_TOGGLE_SWITCH("activeSwitch", false);
}
SoLinearDragger::~SoLinearDragger()
@@ -132,66 +206,15 @@ SoLinearDragger::~SoLinearDragger()
removeValueChangedCallback(&SoLinearDragger::valueChangedCB);
}
SoSeparator* SoLinearDragger::buildCylinderGeometry()
{
auto cylinderSeparator = new SoSeparator();
auto cylinderLightModel = new SoLightModel();
cylinderLightModel->model = SoLightModel::BASE_COLOR;
cylinderSeparator->addChild(cylinderLightModel);
auto cylinderTranslation = new SoTranslation();
cylinderSeparator->addChild(cylinderTranslation);
cylinderTranslation->translation.connectFrom(&calculator->oA);
auto cylinder = new SoCylinder();
cylinder->radius.setValue(cylinderRadius.getValue());
cylinder->height.setValue(cylinderHeight.getValue());
cylinderSeparator->addChild(cylinder);
cylinder->radius.connectFrom(&cylinderRadius);
cylinder->height.connectFrom(&cylinderHeight);
calculator->a.connectFrom(&cylinder->height);
return cylinderSeparator;
}
SoSeparator* SoLinearDragger::buildConeGeometry()
{
auto coneLightModel = new SoLightModel();
coneLightModel->model = SoLightModel::BASE_COLOR;
auto coneSeparator = new SoSeparator();
coneSeparator->addChild(coneLightModel);
auto pickStyle = new SoPickStyle();
pickStyle->style.setValue(SoPickStyle::SHAPE_ON_TOP);
pickStyle->setOverride(TRUE);
coneSeparator->addChild(pickStyle);
auto coneTranslation = new SoTranslation();
coneSeparator->addChild(coneTranslation);
coneTranslation->translation.connectFrom(&calculator->oB);
auto cone = new SoCone();
cone->bottomRadius.setValue(coneBottomRadius.getValue());
cone->height.setValue(coneHeight.getValue());
coneSeparator->addChild(cone);
cone->bottomRadius.connectFrom(&coneBottomRadius);
cone->height.connectFrom(&coneHeight);
calculator->b.connectFrom(&cone->height);
return coneSeparator;
}
SoSeparator* SoLinearDragger::buildLabelGeometry()
{
auto labelSeparator = new SoSeparator;
auto labelTranslation = new SoTranslation();
labelSeparator->addChild(labelTranslation);
labelTranslation->translation.connectFrom(&calculator->oC);
auto arrow = SO_GET_PART(this, "arrow", SoLinearGeometryKit);
labelTranslation->translation.connectFrom(&arrow->tipPosition);
auto label = new SoFrameLabel();
label->string.connectFrom(&this->label);
@@ -213,21 +236,6 @@ SoBaseColor* SoLinearDragger::buildActiveColor()
return color;
}
void SoLinearDragger::setupGeometryCalculator()
{
calculator = new SoCalculator;
// Recalculate the corresponding variables in the left hand side whenever any of the variables in the right hand side change
// oA -> cylinderTranslation
// oB -> coneTranslation
// oC -> labelTranslation
// a -> cylinderHeight
// b -> coneHeight
calculator->expression =
"oA = vec3f(0, a * 0.5, 0); "
"oB = vec3f(0, a + b * 0.5, 0); "
"oC = vec3f(0, a + b * 1.5, 0); ";
}
void SoLinearDragger::startCB(void*, SoDragger* d)
{
auto sudoThis = static_cast<SoLinearDragger*>(d);
@@ -278,7 +286,7 @@ void SoLinearDragger::valueChangedCB(void*, SoDragger* d)
void SoLinearDragger::dragStart()
{
FC_SET_SWITCH("activeSwitch", SO_SWITCH_ALL);
FC_SET_TOGGLE_SWITCH("activeSwitch", true);
// do an initial projection to eliminate discrepancies
// in arrow head pick. we define the arrow in the y+ direction
@@ -336,7 +344,7 @@ void SoLinearDragger::drag()
void SoLinearDragger::dragFinish()
{
FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE);
FC_SET_TOGGLE_SWITCH("activeSwitch", false);
}
SbBool SoLinearDragger::setUpConnections(SbBool onoff, SbBool doitalways)
@@ -390,15 +398,6 @@ SbVec3f SoLinearDragger::roundTranslation(const SbVec3f& vecIn, float incrementI
return out;
}
void SoLinearDragger::setLabelVisibility(bool visible) {
FC_SET_SWITCH("labelSwitch", visible? SO_SWITCH_ALL : SO_SWITCH_NONE);
}
bool SoLinearDragger::isLabelVisible() {
auto* sw = SO_GET_ANY_PART(this, "labelSwitch", SoSwitch);
return sw->whichChild.getValue() == SO_SWITCH_ALL;
}
SO_KIT_SOURCE(SoLinearDraggerContainer)
void SoLinearDraggerContainer::initClass()
@@ -415,7 +414,7 @@ SoLinearDraggerContainer::SoLinearDraggerContainer()
this->ref();
#endif
FC_ADD_CATALOG_ENTRY(draggerSwitch, SoSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(draggerSwitch, SoToggleSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(baseColor, SoBaseColor, draggerSwitch);
FC_ADD_CATALOG_ENTRY(transform, SoTransform, draggerSwitch);
FC_ADD_CATALOG_ENTRY(dragger, SoLinearDragger, draggerSwitch);
@@ -423,13 +422,15 @@ SoLinearDraggerContainer::SoLinearDraggerContainer()
SO_KIT_ADD_FIELD(rotation, (0, 0, 0, 0));
SO_KIT_ADD_FIELD(color, (0, 0, 0));
SO_KIT_ADD_FIELD(translation, (0, 0, 0));
SO_KIT_ADD_FIELD(visible, (1));
SO_KIT_INIT_INSTANCE();
setPart("baseColor", buildColor());
setPart("transform", buildTransform());
setVisibility(true);
auto sw = SO_GET_ANY_PART(this, "draggerSwitch", SoToggleSwitch);
sw->on.connectFrom(&visible);
}
SoBaseColor* SoLinearDraggerContainer::buildColor()
@@ -448,16 +449,6 @@ SoTransform* SoLinearDraggerContainer::buildTransform() {
return transform;
}
void SoLinearDraggerContainer::setVisibility(bool visible)
{
FC_SET_SWITCH("draggerSwitch", visible? SO_SWITCH_ALL : SO_SWITCH_NONE);
}
bool SoLinearDraggerContainer::isVisible() {
auto* sw = SO_GET_ANY_PART(this, "draggerSwitch", SoSwitch);
return sw->whichChild.getValue() == SO_SWITCH_ALL;
}
SoLinearDragger* SoLinearDraggerContainer::getDragger()
{
return SO_GET_PART(this, "dragger", SoLinearDragger);

View File

@@ -43,6 +43,56 @@ class SoCalculator;
namespace Gui
{
class SoLinearGeometryKit: public SoBaseKit
{
SO_KIT_HEADER(SoLinearGeometryKit);
public:
static void initClass();
SoSFVec3f tipPosition;
protected:
SoLinearGeometryKit();
~SoLinearGeometryKit() override = default;
private:
using inherited = SoBaseKit;
};
/*!
* @brief Arrow geometry
*
* A class to contain the geometry for SoLinearDragger
*/
class SoArrowGeometry: public SoLinearGeometryKit
{
SO_KIT_HEADER(SoArrowGeometry);
SO_KIT_CATALOG_ENTRY_HEADER(lightModel);
SO_KIT_CATALOG_ENTRY_HEADER(arrowBody);
SO_KIT_CATALOG_ENTRY_HEADER(arrowTip);
SO_KIT_CATALOG_ENTRY_HEADER(_arrowBodyTranslation);
SO_KIT_CATALOG_ENTRY_HEADER(_arrowTipTranslation);
public:
static void initClass();
SoArrowGeometry();
SoSFFloat coneBottomRadius;
SoSFFloat coneHeight;
SoSFFloat cylinderHeight;
SoSFFloat cylinderRadius;
protected:
~SoArrowGeometry() override = default;
void notify(SoNotList* notList) override;
private:
using inherited = SoLinearGeometryKit;
};
/*! @brief Translation Dragger.
*
* used for translating along axis. Set the
@@ -54,13 +104,12 @@ namespace Gui
class SoLinearDragger : public SoDragger
{
SO_KIT_HEADER(SoLinearDragger);
SO_KIT_CATALOG_ENTRY_HEADER(translator);
SO_KIT_CATALOG_ENTRY_HEADER(activeSwitch);
SO_KIT_CATALOG_ENTRY_HEADER(secondaryColor);
SO_KIT_CATALOG_ENTRY_HEADER(cylinderSeparator);
SO_KIT_CATALOG_ENTRY_HEADER(coneSeparator);
SO_KIT_CATALOG_ENTRY_HEADER(labelSwitch);
SO_KIT_CATALOG_ENTRY_HEADER(labelSeparator);
SO_KIT_CATALOG_ENTRY_HEADER(scale);
SO_KIT_CATALOG_ENTRY_HEADER(arrow);
public:
static void initClass();
@@ -71,14 +120,9 @@ public:
SoSFDouble translationIncrement; //!< set from outside and used for rounding.
SoSFInt32 translationIncrementCount; //!< number of steps. used from outside.
SoSFFloat autoScaleResult; //!< set from parent dragger.
SoSFFloat coneBottomRadius;
SoSFFloat coneHeight;
SoSFFloat cylinderHeight;
SoSFFloat cylinderRadius;
SoSFColor activeColor;
void setLabelVisibility(bool visible);
bool isLabelVisible();
SoSFColor activeColor; //!< colour of the dragger while being dragged
SoSFBool labelVisible; //!< controls the visibility of the dragger label
SoSFVec3f geometryScale; //!< the scale of the dragger geometry
protected:
~SoLinearDragger() override;
@@ -98,15 +142,10 @@ protected:
SbLineProjector projector;
private:
SoCalculator* calculator;
SbVec3f roundTranslation(const SbVec3f &vecIn, float incrementIn);
SoSeparator* buildCylinderGeometry();
SoSeparator* buildConeGeometry();
SoSeparator* buildLabelGeometry();
SoBaseColor* buildActiveColor();
void setupGeometryCalculator();
using inherited = SoDragger;
};
@@ -126,9 +165,8 @@ public:
SoSFRotation rotation;
SoSFColor color;
SoSFVec3f translation;
SoSFBool visible;
void setVisibility(bool visible);
bool isVisible();
void setPointerDirection(const Base::Vector3d& dir);
SoLinearDragger* getDragger();

View File

@@ -59,9 +59,93 @@
#include "Utilities.h"
#include <SoTextLabel.h>
#include <Inventor/SoToggleSwitch.h>
using namespace Gui;
SO_KIT_SOURCE(SoRotatorGeometryKit)
void SoRotatorGeometryKit::initClass()
{
SO_KIT_INIT_CLASS(SoRotatorGeometryKit, SoBaseKit, "BaseKit");
}
SoRotatorGeometryKit::SoRotatorGeometryKit()
{
SO_KIT_CONSTRUCTOR(SoRotatorGeometryKit);
SO_KIT_ADD_FIELD(pivotPosition, (0.0, 0.0, 0.0));
SO_KIT_INIT_INSTANCE();
}
SO_KIT_SOURCE(SoRotatorGeometry)
void SoRotatorGeometry::initClass()
{
SO_KIT_INIT_CLASS(SoRotatorGeometry, SoRotatorGeometryKit, "RotatorGeometryKit");
}
SoRotatorGeometry::SoRotatorGeometry()
{
SO_KIT_CONSTRUCTOR(SoRotatorGeometry);
SO_KIT_ADD_CATALOG_ENTRY(lightModel, SoLightModel, false, this, "", false);
SO_KIT_ADD_CATALOG_ENTRY(drawStyle, SoDrawStyle, false, this, "", false);
SO_KIT_ADD_CATALOG_ENTRY(arcCoords, SoCoordinate3, false, this, "", true);
SO_KIT_ADD_CATALOG_ENTRY(arc, SoLineSet, false, this, "", true);
SO_KIT_ADD_CATALOG_ENTRY(rotorPivot, SoSphere, false, this, "", true);
SO_KIT_ADD_CATALOG_ENTRY(_rotorPivotTranslation, SoTranslation, false, this, rotorPivot, false);
SO_KIT_ADD_FIELD(arcRadius, (8.0));
SO_KIT_ADD_FIELD(arcAngle, (std::numbers::pi_v<float> / 2.0f));
SO_KIT_ADD_FIELD(sphereRadius, (0.8));
SO_KIT_ADD_FIELD(arcThickness, (4.0));
SO_KIT_INIT_INSTANCE();
auto rotorPivot = SO_GET_ANY_PART(this, "rotorPivot", SoSphere);
rotorPivot->radius.connectFrom(&sphereRadius);
auto drawStyle = SO_GET_ANY_PART(this, "drawStyle", SoDrawStyle);
drawStyle->lineWidth.connectFrom(&arcThickness);
auto translation = SO_GET_ANY_PART(this, "_rotorPivotTranslation", SoTranslation);
pivotPosition.connectFrom(&translation->translation);
auto arc = SO_GET_ANY_PART(this, "arc", SoLineSet);
arc->numVertices = segments + 1;
auto lightModel = SO_GET_ANY_PART(this, "lightModel", SoLightModel);
lightModel->model = SoLightModel::BASE_COLOR;
// forces the notify method to get called so that the initial translations and other values are set
arcRadius.touch();
}
void SoRotatorGeometry::notify(SoNotList* notList)
{
assert(notList);
SoField* lastField = notList->getLastField();
if (lastField == &arcRadius || lastField == &arcAngle) {
float angle = arcAngle.getValue();
float radius = arcRadius.getValue();
auto coordinates = SO_GET_ANY_PART(this, "arcCoords", SoCoordinate3);
float angleIncrement = angle / static_cast<float>(segments);
SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement);
SbVec3f point(radius, 0.0, 0.0);
for (int index = 0; index <= segments; ++index) {
coordinates->point.set1Value(index, point);
rotation.multVec(point, point);
}
auto translation = SO_GET_ANY_PART(this, "_rotorPivotTranslation", SoTranslation);
translation->translation = {radius * cos(angle / 2.0f), radius * sin(angle / 2.0f), 0};
}
}
SO_KIT_SOURCE(SoRotationDragger)
void SoRotationDragger::initClass()
@@ -76,26 +160,23 @@ SoRotationDragger::SoRotationDragger()
this->ref();
#endif
FC_ADD_CATALOG_ENTRY(activeSwitch, SoSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(activeSwitch, SoToggleSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(secondaryColor, SoBaseColor, activeSwitch);
FC_ADD_CATALOG_ENTRY(rotator, SoSeparator, geomSeparator);
FC_ADD_CATALOG_ENTRY(scale, SoScale, geomSeparator);
SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(rotator, SoRotatorGeometryKit, SoRotatorGeometry, false, geomSeparator, "", true);
SO_KIT_ADD_FIELD(rotation, (SbVec3f(0.0, 0.0, 1.0), 0.0));
SO_KIT_ADD_FIELD(rotationIncrement, (std::numbers::pi / 8.0));
SO_KIT_ADD_FIELD(rotationIncrementCount, (0));
SO_KIT_ADD_FIELD(activeColor, (1, 1, 0));
SO_KIT_ADD_FIELD(arcRadius, (8.0));
SO_KIT_ADD_FIELD(arcAngle, (std::numbers::pi_v<float> / 2.0f));
SO_KIT_ADD_FIELD(sphereRadius, (0.8));
SO_KIT_ADD_FIELD(arcThickness, (4.0));
SO_KIT_ADD_FIELD(geometryScale, (1, 1, 1));
SO_KIT_INIT_INSTANCE();
setupGeometryCalculator();
setPart("secondaryColor", buildActiveColor());
setPart("rotator", buildGeometry());
FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE);
auto scale = SO_GET_ANY_PART(this, "scale", SoScale);
scale->scaleFactor.connectFrom(&geometryScale);
this->addStartCallback(&SoRotationDragger::startCB);
this->addMotionCallback(&SoRotationDragger::motionCB);
@@ -108,6 +189,8 @@ SoRotationDragger::SoRotationDragger()
fieldSensor.setPriority(0);
this->setUpConnections(TRUE, TRUE);
FC_SET_TOGGLE_SWITCH("activeSwitch", false);
}
SoRotationDragger::~SoRotationDragger()
@@ -115,69 +198,12 @@ SoRotationDragger::~SoRotationDragger()
fieldSensor.setData(nullptr);
fieldSensor.detach();
arcRadiusSensor.setData(nullptr);
arcRadiusSensor.detach();
arcAngleSensor.setData(nullptr);
arcAngleSensor.detach();
this->removeStartCallback(&SoRotationDragger::startCB);
this->removeMotionCallback(&SoRotationDragger::motionCB);
this->removeFinishCallback(&SoRotationDragger::finishCB);
removeValueChangedCallback(&SoRotationDragger::valueChangedCB);
}
SoSeparator* SoRotationDragger::buildGeometry()
{
auto root = new SoSeparator();
auto coordinates = new SoCoordinate3();
this->coordinates = coordinates;
setupArcSensors();
root->addChild(coordinates);
auto drawStyle = new SoDrawStyle();
drawStyle->lineWidth.connectFrom(&arcThickness);
root->addChild(drawStyle);
auto lightModel = new SoLightModel();
lightModel->model = SoLightModel::BASE_COLOR;
root->addChild(lightModel);
auto lineSet = new SoLineSet();
lineSet->numVertices.setValue(segments + 1);
root->addChild(lineSet);
auto pickStyle = new SoPickStyle();
pickStyle->style.setValue(SoPickStyle::SHAPE_ON_TOP);
pickStyle->setOverride(TRUE);
root->addChild(pickStyle);
// sphere.
auto sphereTranslation = new SoTranslation();
sphereTranslation->translation.connectFrom(&calculator->oA);
root->addChild(sphereTranslation);
auto sphere = new SoSphere();
sphere->radius.connectFrom(&sphereRadius);
root->addChild(sphere);
return root;
}
void SoRotationDragger::arcSensorCB(void* userdata, SoSensor*)
{
auto sudoThis = static_cast<SoRotationDragger*>(userdata);
assert(sudoThis->coordinates);
auto coordinates = sudoThis->coordinates;
float angleIncrement = sudoThis->arcAngle.getValue() / static_cast<float>(segments);
SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement);
SbVec3f point(sudoThis->arcRadius.getValue(), 0.0, 0.0);
for (unsigned int index = 0; index <= segments; ++index) {
coordinates->point.set1Value(index, point);
rotation.multVec(point, point);
}
}
SoBaseColor* SoRotationDragger::buildActiveColor()
{
auto color = new SoBaseColor;
@@ -186,34 +212,6 @@ SoBaseColor* SoRotationDragger::buildActiveColor()
return color;
}
void SoRotationDragger::setupGeometryCalculator()
{
calculator = new SoCalculator;
// Recalculate the corresponding variables in the left hand side whenever any of the variables in the right hand side change
// oA -> sphereTranslation
// a -> arcRadius
// b -> arcAngle
calculator->expression = "oA = vec3f(a * cos(b / 2), a * sin(b / 2), 0)";
calculator->a.connectFrom(&arcRadius);
calculator->b.connectFrom(&arcAngle);
}
void SoRotationDragger::setupArcSensors()
{
arcRadiusSensor.setFunction(arcSensorCB);
arcRadiusSensor.setData(this);
arcRadiusSensor.setPriority(0);
arcRadiusSensor.attach(&arcRadius);
arcRadius.touch();
arcAngleSensor.setFunction(arcSensorCB);
arcAngleSensor.setData(this);
arcAngleSensor.setPriority(0);
arcAngleSensor.attach(&arcAngle);
arcAngle.touch();
}
void SoRotationDragger::startCB(void*, SoDragger* d)
{
auto sudoThis = static_cast<SoRotationDragger*>(d);
@@ -265,7 +263,7 @@ void SoRotationDragger::valueChangedCB(void*, SoDragger* d)
void SoRotationDragger::dragStart()
{
FC_SET_SWITCH("activeSwitch", SO_SWITCH_ALL);
FC_SET_TOGGLE_SWITCH("activeSwitch", true);
projector.setViewVolume(this->getViewVolume());
projector.setWorkingSpace(this->getLocalToWorldMatrix());
@@ -337,7 +335,7 @@ void SoRotationDragger::drag()
void SoRotationDragger::dragFinish()
{
FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE);
FC_SET_TOGGLE_SWITCH("activeSwitch", false);
}
SbBool SoRotationDragger::setUpConnections(SbBool onoff, SbBool doitalways)
@@ -397,7 +395,7 @@ SoRotationDraggerContainer::SoRotationDraggerContainer()
this->ref();
#endif
FC_ADD_CATALOG_ENTRY(draggerSwitch, SoSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(draggerSwitch, SoToggleSwitch, geomSeparator);
FC_ADD_CATALOG_ENTRY(baseColor, SoBaseColor, draggerSwitch);
FC_ADD_CATALOG_ENTRY(transform, SoTransform, draggerSwitch);
FC_ADD_CATALOG_ENTRY(dragger, SoRotationDragger, draggerSwitch);
@@ -405,13 +403,15 @@ SoRotationDraggerContainer::SoRotationDraggerContainer()
SO_KIT_ADD_FIELD(rotation, (0, 0, 0, 0));
SO_KIT_ADD_FIELD(color, (0, 0, 0));
SO_KIT_ADD_FIELD(translation, (0, 0, 0));
SO_KIT_ADD_FIELD(visible, (1));
SO_KIT_INIT_INSTANCE();
setPart("baseColor", buildColor());
setPart("transform", buildTransform());
setVisibility(true);
auto sw = SO_GET_ANY_PART(this, "draggerSwitch", SoToggleSwitch);
sw->on.connectFrom(&visible);
}
SoBaseColor* SoRotationDraggerContainer::buildColor()
@@ -430,16 +430,6 @@ SoTransform* SoRotationDraggerContainer::buildTransform() {
return transform;
}
void SoRotationDraggerContainer::setVisibility(bool visible)
{
FC_SET_SWITCH("draggerSwitch", visible? SO_SWITCH_ALL : SO_SWITCH_NONE);
}
bool SoRotationDraggerContainer::isVisible() {
auto* sw = SO_GET_ANY_PART(this, "draggerSwitch", SoSwitch);
return sw->whichChild.getValue() == SO_SWITCH_ALL;
}
SoRotationDragger* SoRotationDraggerContainer::getDragger()
{
return SO_GET_PART(this, "dragger", SoRotationDragger);
@@ -447,10 +437,10 @@ SoRotationDragger* SoRotationDraggerContainer::getDragger()
void Gui::SoRotationDraggerContainer::setPointerDirection(const Base::Vector3d& dir)
{
// This is the direction of normal from the origin to the spherical handle of
// the dragger in its local space
float arcAngle = getDragger()->arcAngle.getValue();
Base::Vector3d draggerDir{std::cos(arcAngle), std::sin(arcAngle), 0};
// This is the direction from the origin to the spherical pivot of the rotator
Base::Vector3d draggerDir = Base::convertTo<Base::Vector3d>(
SO_GET_ANY_PART(this, "rotator", SoRotatorGeometryKit)->pivotPosition.getValue()
);
Base::Vector3d axis = draggerDir.Cross(dir).Normalize();
double ang = draggerDir.GetAngleOriented(dir, axis);

View File

@@ -41,6 +41,59 @@ class SoCoordinate3;
namespace Gui
{
class SoRotatorGeometryKit: public SoBaseKit
{
SO_KIT_HEADER(SoLinearGeometryKit);
public:
static void initClass();
SoSFVec3f pivotPosition;
protected:
SoRotatorGeometryKit();
~SoRotatorGeometryKit() override = default;
private:
using inherited = SoBaseKit;
};
/*!
* @brief Rotator geometry
*
* A class to contain the geometry for SoRotationDragger
*/
class SoRotatorGeometry: public SoRotatorGeometryKit
{
SO_KIT_HEADER(SoArrowGeometry);
SO_KIT_CATALOG_ENTRY_HEADER(lightModel);
SO_KIT_CATALOG_ENTRY_HEADER(drawStyle);
SO_KIT_CATALOG_ENTRY_HEADER(arcCoords);
SO_KIT_CATALOG_ENTRY_HEADER(arc);
SO_KIT_CATALOG_ENTRY_HEADER(rotorPivot);
SO_KIT_CATALOG_ENTRY_HEADER(_rotorPivotTranslation);
public:
static void initClass();
SoRotatorGeometry();
SoSFFloat arcAngle; //!< in radians
SoSFFloat arcRadius;
SoSFFloat sphereRadius;
SoSFFloat arcThickness;
protected:
~SoRotatorGeometry() override = default;
void notify(SoNotList* notList) override;
private:
constexpr static int segments = 10; //!< segments of the arc per arcAngle
using inherited = SoRotatorGeometryKit;
};
/*! @brief Rotation Dragger.
*
* used for rotating around an axis. Set the rotation
@@ -51,9 +104,10 @@ namespace Gui
class SoRotationDragger : public SoDragger
{
SO_KIT_HEADER(SoRotationDragger);
SO_KIT_CATALOG_ENTRY_HEADER(rotator);
SO_KIT_CATALOG_ENTRY_HEADER(activeSwitch);
SO_KIT_CATALOG_ENTRY_HEADER(secondaryColor);
SO_KIT_CATALOG_ENTRY_HEADER(scale);
SO_KIT_CATALOG_ENTRY_HEADER(rotator);
public:
static void initClass();
@@ -62,11 +116,8 @@ public:
SoSFRotation rotation; //!< set from outside and used from outside for single precision.
SoSFDouble rotationIncrement; //!< set from outside and used for rounding.
SoSFInt32 rotationIncrementCount; //!< number of steps. used from outside.
SoSFColor activeColor;
SoSFFloat arcRadius;
SoSFFloat arcAngle; //!< in radians
SoSFFloat sphereRadius;
SoSFFloat arcThickness;
SoSFColor activeColor; //!< colour of the dragger while being dragged.
SoSFVec3f geometryScale; //!< the scale of the dragger geometry
protected:
~SoRotationDragger() override;
@@ -86,18 +137,8 @@ protected:
SbPlaneProjector projector;
private:
SoCalculator* calculator;
SoCoordinate3* coordinates = nullptr;
SoFieldSensor arcRadiusSensor;
SoFieldSensor arcAngleSensor;
constexpr static int segments = 10; //!< segments of the arc per arcAngle
int roundIncrement(const float &radiansIn);
SoSeparator* buildGeometry();
static void arcSensorCB(void* userdata, SoSensor*);
SoBaseColor* buildActiveColor();
void setupGeometryCalculator();
void setupArcSensors();
using inherited = SoDragger;
};
@@ -117,9 +158,8 @@ public:
SoSFRotation rotation;
SoSFColor color;
SoSFVec3f translation;
SoSFBool visible;
void setVisibility(bool visible);
bool isVisible();
void setPointerDirection(const Base::Vector3d& dir);
SoRotationDragger* getDragger();

View File

@@ -626,49 +626,49 @@ void SoTransformDragger::setAxisColors(unsigned long x, unsigned long y, unsigne
void SoTransformDragger::showTranslationX()
{
auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(true);
tDragger->visible = true;
}
void SoTransformDragger::showTranslationY()
{
auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(true);
tDragger->visible = true;
}
void SoTransformDragger::showTranslationZ()
{
auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(true);
tDragger->visible = true;
}
void SoTransformDragger::hideTranslationX()
{
auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(false);
tDragger->visible = false;
}
void SoTransformDragger::hideTranslationY()
{
auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(false);
tDragger->visible = false;
}
void SoTransformDragger::hideTranslationZ()
{
auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer);
tDragger->setVisibility(false);
tDragger->visible = false;
}
bool SoTransformDragger::isShownTranslationX()
{
auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer);
return tDragger->isVisible();
return tDragger->visible.getValue();
}
bool SoTransformDragger::isShownTranslationY()
{
auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer);
return tDragger->isVisible();
return tDragger->visible.getValue();
}
bool SoTransformDragger::isShownTranslationZ()
{
auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer);
return tDragger->isVisible();
return tDragger->visible.getValue();
}
// Planar Translator
@@ -740,49 +740,49 @@ bool SoTransformDragger::isHiddenPlanarTranslationZX()
void SoTransformDragger::showRotationX()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(true);
rDragger->visible = true;
}
void SoTransformDragger::showRotationY()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(true);
rDragger->visible = true;
}
void SoTransformDragger::showRotationZ()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(true);
rDragger->visible = true;
}
void SoTransformDragger::hideRotationX()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(false);
rDragger->visible = false;
}
void SoTransformDragger::hideRotationY()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(false);
rDragger->visible = false;
}
void SoTransformDragger::hideRotationZ()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer);
rDragger->setVisibility(false);
rDragger->visible = false;
}
bool SoTransformDragger::isShownRotationX()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer);
return rDragger->isVisible();
return rDragger->visible.getValue();
}
bool SoTransformDragger::isShownRotationY()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer);
return rDragger->isVisible();
return rDragger->visible.getValue();
}
bool SoTransformDragger::isShownRotationZ()
{
SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer);
return rDragger->isVisible();
return rDragger->visible.getValue();
}
void SoTransformDragger::setupTranslationDraggers()

View File

@@ -51,6 +51,8 @@
#include "Camera.h"
#include "Flag.h"
#include "Inventor/Draggers/SoTransformDragger.h"
#include "Inventor/Draggers/SoLinearDragger.h"
#include "Inventor/Draggers/SoRotationDragger.h"
#include "Navigation/GestureNavigationStyle.h"
#include "Navigation/NavigationStyle.h"
#include "Navigation/SiemensNXNavigationStyle.h"
@@ -77,6 +79,7 @@
#include "Inventor/SoFCBoundingBox.h"
#include "Inventor/SoMouseWheelEvent.h"
#include "Inventor/SoFCTransform.h"
#include "Inventor/SoToggleSwitch.h"
#include "propertyeditor/PropertyItem.h"
#include "ArcEngine.h"
@@ -144,6 +147,11 @@ void Gui::SoFCDB::init()
SoAutoZoomTranslation ::initClass();
MarkerBitmaps ::initClass();
SoTransformDragger ::initClass();
SoLinearGeometryKit ::initClass();
SoArrowGeometry ::initClass();
SoRotatorGeometryKit ::initClass();
SoRotatorGeometry ::initClass();
SoToggleSwitch ::initClass();
SmSwitchboard ::initClass();
SoFCSeparator ::initClass();
SoFCSelectionRoot ::initClass();