From dfd29e06ea0c1b9782fbb1a9d018cd4a3fc70961 Mon Sep 17 00:00:00 2001 From: captain0xff Date: Sat, 21 Jun 2025 23:14:07 +0530 Subject: [PATCH 1/3] Gui: refactor SoRotationDragger --- src/Gui/Inventor/Draggers/SoLinearDragger.cpp | 13 +- .../Inventor/Draggers/SoRotationDragger.cpp | 221 +++++++++++++----- src/Gui/Inventor/Draggers/SoRotationDragger.h | 61 ++++- .../Inventor/Draggers/SoTransformDragger.cpp | 156 +++++-------- .../Inventor/Draggers/SoTransformDragger.h | 17 +- 5 files changed, 283 insertions(+), 185 deletions(-) diff --git a/src/Gui/Inventor/Draggers/SoLinearDragger.cpp b/src/Gui/Inventor/Draggers/SoLinearDragger.cpp index e65b739391..c4c2d99c3c 100644 --- a/src/Gui/Inventor/Draggers/SoLinearDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoLinearDragger.cpp @@ -84,7 +84,6 @@ SoLinearDragger::SoLinearDragger() FC_ADD_CATALOG_ENTRY(secondaryColor, SoBaseColor, activeSwitch); FC_ADD_CATALOG_ENTRY(coneSeparator, SoSeparator, translator); FC_ADD_CATALOG_ENTRY(cylinderSeparator, SoSeparator, translator); - // For some reason changing the whichChild parameter of this switch doesn't hide the label FC_ADD_CATALOG_ENTRY(labelSwitch, SoSwitch, translator); FC_ADD_CATALOG_ENTRY(labelSeparator, SoSeparator, labelSwitch); @@ -101,10 +100,10 @@ SoLinearDragger::SoLinearDragger() SO_KIT_INIT_INSTANCE(); setupGeometryCalculator(); - SoInteractionKit::setPart("cylinderSeparator", buildCylinderGeometry()); - SoInteractionKit::setPart("coneSeparator", buildConeGeometry()); - SoInteractionKit::setPart("labelSeparator", buildLabelGeometry()); - SoInteractionKit::setPart("secondaryColor", buildActiveColor()); + setPart("cylinderSeparator", buildCylinderGeometry()); + setPart("coneSeparator", buildConeGeometry()); + setPart("labelSeparator", buildLabelGeometry()); + setPart("secondaryColor", buildActiveColor()); FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE); setLabelVisibility(true); @@ -427,8 +426,8 @@ SoLinearDraggerContainer::SoLinearDraggerContainer() SO_KIT_INIT_INSTANCE(); - SoInteractionKit::setPart("baseColor", buildColor()); - SoInteractionKit::setPart("transform", buildTransform()); + setPart("baseColor", buildColor()); + setPart("transform", buildTransform()); setVisibility(true); } diff --git a/src/Gui/Inventor/Draggers/SoRotationDragger.cpp b/src/Gui/Inventor/Draggers/SoRotationDragger.cpp index 3d62d3af52..2bda576f76 100644 --- a/src/Gui/Inventor/Draggers/SoRotationDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoRotationDragger.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #endif #include @@ -55,7 +56,7 @@ #include "SoRotationDragger.h" #include "MainWindow.h" -#include "SoFCDB.h" +#include "Utilities.h" #include @@ -75,30 +76,26 @@ SoRotationDragger::SoRotationDragger() this->ref(); #endif - SO_KIT_ADD_CATALOG_ENTRY(rotatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(rotator, SoSeparator, TRUE, rotatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(rotatorActive, SoSeparator, TRUE, rotatorSwitch, "", TRUE); - - arcRadius = 8.0; - - if (SO_KIT_IS_FIRST_INSTANCE()) { - buildFirstInstance(); - } + FC_ADD_CATALOG_ENTRY(activeSwitch, SoSwitch, geomSeparator); + FC_ADD_CATALOG_ENTRY(secondaryColor, SoBaseColor, activeSwitch); + FC_ADD_CATALOG_ENTRY(rotator, SoSeparator, geomSeparator); 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 / 2.0f)); + SO_KIT_ADD_FIELD(sphereRadius, (0.8)); + SO_KIT_ADD_FIELD(arcThickness, (4.0)); SO_KIT_INIT_INSTANCE(); - // initialize default parts. - // first is from 'SO_KIT_CATALOG_ENTRY_HEADER' macro - // second is unique name from buildFirstInstance(). - this->setPartAsDefault("rotator", "CSysDynamics_RDragger_Rotator"); - this->setPartAsDefault("rotatorActive", "CSysDynamics_RDragger_RotatorActive"); + setupGeometryCalculator(); + setPart("secondaryColor", buildActiveColor()); + setPart("rotator", buildGeometry()); - SoSwitch* sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, 0); + FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE); this->addStartCallback(&SoRotationDragger::startCB); this->addMotionCallback(&SoRotationDragger::motionCB); @@ -118,50 +115,28 @@ 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); } -void SoRotationDragger::buildFirstInstance() +SoSeparator* SoRotationDragger::buildGeometry() { - SoGroup* geometryGroup = buildGeometry(); + auto root = new SoSeparator(); - auto localRotator = new SoSeparator(); - localRotator->setName("CSysDynamics_RDragger_Rotator"); - localRotator->addChild(geometryGroup); - SoFCDB::getStorage()->addChild(localRotator); - - auto localRotatorActive = new SoSeparator(); - localRotatorActive->setName("CSysDynamics_RDragger_RotatorActive"); - auto colorActive = new SoBaseColor(); - colorActive->rgb.setValue(1.0, 1.0, 0.0); - localRotatorActive->addChild(colorActive); - localRotatorActive->addChild(geometryGroup); - SoFCDB::getStorage()->addChild(localRotatorActive); -} - -SoGroup* SoRotationDragger::buildGeometry() -{ - auto root = new SoGroup(); - - // arc auto coordinates = new SoCoordinate3(); - - unsigned int segments = 15; - - float angleIncrement = (std::numbers::pi_v / 2.f) / static_cast(segments); - SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement); - SbVec3f point(arcRadius, 0.0, 0.0); - for (unsigned int index = 0; index <= segments; ++index) { - coordinates->point.set1Value(index, point); - rotation.multVec(point, point); - } + this->coordinates = coordinates; + setupArcSensors(); root->addChild(coordinates); auto drawStyle = new SoDrawStyle(); - drawStyle->lineWidth = 4.0; + drawStyle->lineWidth.connectFrom(&arcThickness); root->addChild(drawStyle); auto lightModel = new SoLightModel(); @@ -178,20 +153,67 @@ SoGroup* SoRotationDragger::buildGeometry() root->addChild(pickStyle); // sphere. - SbVec3f origin(1.0, 1.0, 0.0); - origin.normalize(); - origin *= arcRadius; auto sphereTranslation = new SoTranslation(); - sphereTranslation->translation.setValue(origin); + sphereTranslation->translation.connectFrom(&calculator->oA); root->addChild(sphereTranslation); auto sphere = new SoSphere(); - sphere->radius.setValue(0.8F); + sphere->radius.connectFrom(&sphereRadius); root->addChild(sphere); return root; } +void SoRotationDragger::arcSensorCB(void* userdata, SoSensor*) +{ + auto sudoThis = static_cast(userdata); + assert(sudoThis->coordinates); + auto coordinates = sudoThis->coordinates; + float angleIncrement = sudoThis->arcAngle.getValue() / static_cast(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; + color->rgb.connectFrom(&activeColor); + + 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(d); @@ -232,10 +254,7 @@ void SoRotationDragger::valueChangedCB(void*, SoDragger* d) assert(sudoThis); SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft - // all this just to get the translation? - SbVec3f translationDummy, scaleDummy; - SbRotation localRotation, scaleOrientationDummy; - matrix.getTransform(translationDummy, localRotation, scaleDummy, scaleOrientationDummy); + SbRotation localRotation = getMatrixTransform(matrix).rotation; sudoThis->fieldSensor.detach(); if (sudoThis->rotation.getValue() != localRotation) { @@ -246,9 +265,7 @@ void SoRotationDragger::valueChangedCB(void*, SoDragger* d) void SoRotationDragger::dragStart() { - SoSwitch* sw; - sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, 1); + FC_SET_SWITCH("activeSwitch", SO_SWITCH_ALL); projector.setViewVolume(this->getViewVolume()); projector.setWorkingSpace(this->getLocalToWorldMatrix()); @@ -320,9 +337,7 @@ void SoRotationDragger::drag() void SoRotationDragger::dragFinish() { - SoSwitch* sw; - sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, 0); + FC_SET_SWITCH("activeSwitch", SO_SWITCH_NONE); } SbBool SoRotationDragger::setUpConnections(SbBool onoff, SbBool doitalways) @@ -365,3 +380,81 @@ int SoRotationDragger::roundIncrement(const float& radiansIn) return rCount; } + +SO_KIT_SOURCE(SoRotationDraggerContainer) + +void SoRotationDraggerContainer::initClass() +{ + SoRotationDragger::initClass(); + SO_KIT_INIT_CLASS(SoRotationDraggerContainer, SoInteractionKit, "InteractionKit"); +} + +SoRotationDraggerContainer::SoRotationDraggerContainer() +{ + SO_KIT_CONSTRUCTOR(SoRotationDraggerContainer); + +#if defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + this->ref(); +#endif + + FC_ADD_CATALOG_ENTRY(draggerSwitch, SoSwitch, geomSeparator); + FC_ADD_CATALOG_ENTRY(baseColor, SoBaseColor, draggerSwitch); + FC_ADD_CATALOG_ENTRY(transform, SoTransform, draggerSwitch); + FC_ADD_CATALOG_ENTRY(dragger, SoRotationDragger, draggerSwitch); + + 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_INIT_INSTANCE(); + + setPart("baseColor", buildColor()); + setPart("transform", buildTransform()); + + setVisibility(true); +} + +SoBaseColor* SoRotationDraggerContainer::buildColor() +{ + auto color = new SoBaseColor; + color->rgb.connectFrom(&this->color); + + return color; +} + +SoTransform* SoRotationDraggerContainer::buildTransform() { + auto transform = new SoTransform; + transform->translation.connectFrom(&this->translation); + transform->rotation.connectFrom(&this->rotation); + + 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); +} + +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}; + + Base::Vector3d axis = draggerDir.Cross(dir).Normalize(); + double ang = draggerDir.GetAngleOriented(dir, axis); + + SbRotation rot{Base::convertTo(axis), static_cast(ang)}; + rotation.setValue(rot); +} diff --git a/src/Gui/Inventor/Draggers/SoRotationDragger.h b/src/Gui/Inventor/Draggers/SoRotationDragger.h index b19af13f73..292b47ca98 100644 --- a/src/Gui/Inventor/Draggers/SoRotationDragger.h +++ b/src/Gui/Inventor/Draggers/SoRotationDragger.h @@ -33,6 +33,11 @@ #include #include #include +#include + +class SoTransform; +class SoCalculator; +class SoCoordinate3; namespace Gui { @@ -46,16 +51,22 @@ namespace Gui class SoRotationDragger : public SoDragger { SO_KIT_HEADER(SoRotationDragger); - SO_KIT_CATALOG_ENTRY_HEADER(rotatorSwitch); SO_KIT_CATALOG_ENTRY_HEADER(rotator); - SO_KIT_CATALOG_ENTRY_HEADER(rotatorActive); + SO_KIT_CATALOG_ENTRY_HEADER(activeSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(secondaryColor); + public: static void initClass(); SoRotationDragger(); + 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 color; //!< set from outside. non-active color. + SoSFColor activeColor; + SoSFFloat arcRadius; + SoSFFloat arcAngle; //!< in radians + SoSFFloat sphereRadius; + SoSFFloat arcThickness; protected: ~SoRotationDragger() override; @@ -73,15 +84,53 @@ protected: SoFieldSensor fieldSensor; SbPlaneProjector projector; - float arcRadius; private: - void buildFirstInstance(); + 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); - SoGroup* buildGeometry(); + SoSeparator* buildGeometry(); + static void arcSensorCB(void* userdata, SoSensor*); + SoBaseColor* buildActiveColor(); + void setupGeometryCalculator(); + void setupArcSensors(); + using inherited = SoDragger; }; +class SoRotationDraggerContainer: public SoInteractionKit +{ + SO_KIT_HEADER(SoRotationDraggerContainer); + SO_KIT_CATALOG_ENTRY_HEADER(draggerSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(baseColor); + SO_KIT_CATALOG_ENTRY_HEADER(transform); + SO_KIT_CATALOG_ENTRY_HEADER(dragger); + +public: + static void initClass(); + SoRotationDraggerContainer(); + + SoSFRotation rotation; + SoSFColor color; + SoSFVec3f translation; + + void setVisibility(bool visible); + bool isVisible(); + void setPointerDirection(const Base::Vector3d& dir); + + SoRotationDragger* getDragger(); + +private: + SoBaseColor* buildColor(); + SoTransform* buildTransform(); + + using inherited = SoInteractionKit; +}; + } #endif /* GUI_ROTATION_DRAGGER_H */ diff --git a/src/Gui/Inventor/Draggers/SoTransformDragger.cpp b/src/Gui/Inventor/Draggers/SoTransformDragger.cpp index f44ee2e3c9..d253237b6c 100644 --- a/src/Gui/Inventor/Draggers/SoTransformDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoTransformDragger.cpp @@ -96,7 +96,7 @@ void SoTransformDragger::initClass() { SoLinearDraggerContainer::initClass(); SoPlanarDragger::initClass(); - SoRotationDragger::initClass(); + SoRotationDraggerContainer::initClass(); SO_KIT_INIT_CLASS(SoTransformDragger, SoDragger, "Dragger"); } @@ -201,26 +201,9 @@ SoTransformDragger::SoTransformDragger() TRUE); // Rotator - - SO_KIT_ADD_CATALOG_ENTRY(xRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); - - SO_KIT_ADD_CATALOG_ENTRY(xRotatorSeparator, SoSeparator, TRUE, xRotatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yRotatorSeparator, SoSeparator, TRUE, yRotatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zRotatorSeparator, SoSeparator, TRUE, zRotatorSwitch, "", TRUE); - - SO_KIT_ADD_CATALOG_ENTRY(xRotatorColor, SoBaseColor, TRUE, xRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yRotatorColor, SoBaseColor, TRUE, yRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zRotatorColor, SoBaseColor, TRUE, zRotatorSeparator, "", TRUE); - - SO_KIT_ADD_CATALOG_ENTRY(xRotatorRotation, SoRotation, TRUE, xRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yRotatorRotation, SoRotation, TRUE, yRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zRotatorRotation, SoRotation, TRUE, zRotatorSeparator, "", TRUE); - - SO_KIT_ADD_CATALOG_ENTRY(xRotatorDragger, SoRotationDragger, TRUE, xRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yRotatorDragger, SoRotationDragger, TRUE, yRotatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zRotatorDragger, SoRotationDragger, TRUE, zRotatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(xRotatorDragger, SoRotationDraggerContainer, TRUE, annotation, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yRotatorDragger, SoRotationDraggerContainer, TRUE, annotation, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zRotatorDragger, SoRotationDraggerContainer, TRUE, annotation, "", TRUE); // Other SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0)); @@ -269,17 +252,9 @@ SoTransformDragger::SoTransformDragger() tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementYCount); + // Rotator - SoRotationDragger* rDragger; - rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDragger); - rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); - rotationIncrementCountX.connectFrom(&rDragger->rotationIncrementCount); - rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDragger); - rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); - rotationIncrementCountY.connectFrom(&rDragger->rotationIncrementCount); - rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDragger); - rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); - rotationIncrementCountZ.connectFrom(&rDragger->rotationIncrementCount); + setupRotationDraggers(); // Switches SoSwitch* sw; @@ -290,13 +265,6 @@ SoTransformDragger::SoTransformDragger() SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); - // Rotator - sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); - sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); - sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); // Rotations @@ -311,16 +279,17 @@ SoTransformDragger::SoTransformDragger() localRotation = SO_GET_ANY_PART(this, "zxPlanarTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle); // Rotator - localRotation = SO_GET_ANY_PART(this, "xRotatorRotation", SoRotation); + SoRotationDraggerContainer* rDragger; + rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); tempRotation = SbRotation(SbVec3f(1.0, 0.0, 0.0), angle); tempRotation *= SbRotation(SbVec3f(0.0, 0.0, 1.0), angle); - localRotation->rotation.setValue(tempRotation); - localRotation = SO_GET_ANY_PART(this, "yRotatorRotation", SoRotation); + rDragger->rotation.setValue(tempRotation); + rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); tempRotation = SbRotation(SbVec3f(0.0, -1.0, 0.0), angle); tempRotation *= SbRotation(SbVec3f(0.0, 0.0, -1.0), angle); - localRotation->rotation.setValue(tempRotation); - localRotation = SO_GET_ANY_PART(this, "zRotatorRotation", SoRotation); - localRotation->rotation.setValue(SbRotation::identity()); + rDragger->rotation.setValue(tempRotation); + rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); + rDragger->rotation.setValue(SbRotation::identity()); // this is for non-autoscale mode. this will be disconnected for autoscale // and won't be used. see setUpAutoScale. @@ -387,9 +356,9 @@ SbBool SoTransformDragger::setUpConnections(SbBool onoff, SbBool doitalways) SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", SoPlanarDragger); SoPlanarDragger* tPlanarDraggerZX = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", SoPlanarDragger); - SoRotationDragger* rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDragger); - SoRotationDragger* rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDragger); - SoRotationDragger* rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDragger); + auto rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); + auto rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); + auto rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); if (onoff) { inherited::setUpConnections(onoff, doitalways); @@ -400,9 +369,9 @@ SbBool SoTransformDragger::setUpConnections(SbBool onoff, SbBool doitalways) registerChildDragger(tPlanarDraggerXZ); registerChildDragger(tPlanarDraggerYZ); registerChildDragger(tPlanarDraggerZX); - registerChildDragger(rDraggerX); - registerChildDragger(rDraggerY); - registerChildDragger(rDraggerZ); + registerChildDragger(rDraggerX->getDragger()); + registerChildDragger(rDraggerY->getDragger()); + registerChildDragger(rDraggerZ->getDragger()); translationSensorCB(this, nullptr); if (this->translationSensor.getAttachedField() != &this->translation) { @@ -421,9 +390,9 @@ SbBool SoTransformDragger::setUpConnections(SbBool onoff, SbBool doitalways) unregisterChildDragger(tPlanarDraggerXZ); unregisterChildDragger(tPlanarDraggerYZ); unregisterChildDragger(tPlanarDraggerZX); - unregisterChildDragger(rDraggerX); - unregisterChildDragger(rDraggerY); - unregisterChildDragger(rDraggerZ); + unregisterChildDragger(rDraggerX->getDragger()); + unregisterChildDragger(rDraggerY->getDragger()); + unregisterChildDragger(rDraggerZ->getDragger()); inherited::setUpConnections(onoff, doitalways); @@ -642,12 +611,13 @@ void SoTransformDragger::setAxisColors(unsigned long x, unsigned long y, unsigne color = SO_GET_ANY_PART(this, "zxPlanarTranslatorColor", SoBaseColor); color->rgb.setValue(colorY[0], colorY[1], colorY[2]); // Rotator - color = SO_GET_ANY_PART(this, "xRotatorColor", SoBaseColor); - color->rgb.setValue(colorX[0], colorX[1], colorX[2]); - color = SO_GET_ANY_PART(this, "yRotatorColor", SoBaseColor); - color->rgb.setValue(colorY[0], colorY[1], colorY[2]); - color = SO_GET_ANY_PART(this, "zRotatorColor", SoBaseColor); - color->rgb.setValue(colorZ[0], colorZ[1], colorZ[2]); + SoRotationDraggerContainer* rDragger; + rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); + rDragger->color.setValue(colorX[0], colorX[1], colorX[2]); + rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); + rDragger->color.setValue(colorY[0], colorY[1], colorY[2]); + rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); + rDragger->color.setValue(colorZ[0], colorZ[1], colorZ[2]); } // Visibility API Functions @@ -769,66 +739,50 @@ bool SoTransformDragger::isHiddenPlanarTranslationZX() // Rotator void SoTransformDragger::showRotationX() { - SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(true); } void SoTransformDragger::showRotationY() { - SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(true); } void SoTransformDragger::showRotationZ() { - SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(true); } void SoTransformDragger::hideRotationX() { - SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(false); } void SoTransformDragger::hideRotationY() { - SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(false); } void SoTransformDragger::hideRotationZ() { - SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); + rDragger->setVisibility(false); } bool SoTransformDragger::isShownRotationX() { - SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); + return rDragger->isVisible(); } bool SoTransformDragger::isShownRotationY() { - SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); + return rDragger->isVisible(); } bool SoTransformDragger::isShownRotationZ() { - SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); -} - -bool SoTransformDragger::isHiddenRotationX() -{ - SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); -} -bool SoTransformDragger::isHiddenRotationY() -{ - SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); -} -bool SoTransformDragger::isHiddenRotationZ() -{ - SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); + return rDragger->isVisible(); } void SoTransformDragger::setupTranslationDraggers() @@ -850,3 +804,19 @@ void SoTransformDragger::setupTranslationDragger(const std::string& name, SoSFSt draggerContainer->setPointerDirection(Base::convertTo(rotDir)); } + +void SoTransformDragger::setupRotationDraggers() +{ + setupRotationDragger("xRotatorDragger", rotationIncrementCountX); + setupRotationDragger("yRotatorDragger", rotationIncrementCountY); + setupRotationDragger("zRotatorDragger", rotationIncrementCountZ); +} + +void SoTransformDragger::setupRotationDragger(const std::string& name, SoSFInt32& incrementCount) +{ + SoRotationDraggerContainer* draggerContainer = SO_GET_ANY_PART(this, name.c_str(), SoRotationDraggerContainer); + SoRotationDragger* dragger = draggerContainer->getDragger(); + + dragger->rotationIncrement.connectFrom(&this->rotationIncrement); + incrementCount.connectFrom(&dragger->rotationIncrementCount); +} diff --git a/src/Gui/Inventor/Draggers/SoTransformDragger.h b/src/Gui/Inventor/Draggers/SoTransformDragger.h index 27199421fa..cde2038aa0 100644 --- a/src/Gui/Inventor/Draggers/SoTransformDragger.h +++ b/src/Gui/Inventor/Draggers/SoTransformDragger.h @@ -82,18 +82,6 @@ class GuiExport SoTransformDragger : public SoDragger SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorDragger); SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorDragger); // Rotator - SO_KIT_CATALOG_ENTRY_HEADER(xRotatorSwitch); - SO_KIT_CATALOG_ENTRY_HEADER(yRotatorSwitch); - SO_KIT_CATALOG_ENTRY_HEADER(zRotatorSwitch); - SO_KIT_CATALOG_ENTRY_HEADER(xRotatorSeparator); - SO_KIT_CATALOG_ENTRY_HEADER(yRotatorSeparator); - SO_KIT_CATALOG_ENTRY_HEADER(zRotatorSeparator); - SO_KIT_CATALOG_ENTRY_HEADER(xRotatorColor); - SO_KIT_CATALOG_ENTRY_HEADER(yRotatorColor); - SO_KIT_CATALOG_ENTRY_HEADER(zRotatorColor); - SO_KIT_CATALOG_ENTRY_HEADER(xRotatorRotation); - SO_KIT_CATALOG_ENTRY_HEADER(yRotatorRotation); - SO_KIT_CATALOG_ENTRY_HEADER(zRotatorRotation); SO_KIT_CATALOG_ENTRY_HEADER(xRotatorDragger); SO_KIT_CATALOG_ENTRY_HEADER(yRotatorDragger); SO_KIT_CATALOG_ENTRY_HEADER(zRotatorDragger); @@ -168,9 +156,6 @@ public: bool isShownRotationX(); //!< is x rotation dragger shown. bool isShownRotationY(); //!< is x rotation dragger shown. bool isShownRotationZ(); //!< is x rotation dragger shown. - bool isHiddenRotationX(); //!< is x rotation dragger hidden. - bool isHiddenRotationY(); //!< is x rotation dragger hidden. - bool isHiddenRotationZ(); //!< is x rotation dragger hidden. //@} void GLRender(SoGLRenderAction * action) override; @@ -202,6 +187,8 @@ private: void setupTranslationDraggers(); void setupTranslationDragger(const std::string& name, SoSFString* label, SoSFInt32& incrementCount, const SbVec3d& rotDir); + void setupRotationDraggers(); + void setupRotationDragger(const std::string& name, SoSFInt32& incrementCount); using inherited = SoDragger; }; From 5aba7125055d207128f3c06eef23a0e47e0442cc Mon Sep 17 00:00:00 2001 From: captain0xff Date: Sun, 6 Jul 2025 23:28:52 +0530 Subject: [PATCH 2/3] Gui: add SoToggleSwitch class update --- src/Gui/CMakeLists.txt | 2 ++ src/Gui/Inventor/SoToggleSwitch.cpp | 54 ++++++++++++++++++++++++++++ src/Gui/Inventor/SoToggleSwitch.h | 56 +++++++++++++++++++++++++++++ src/Gui/Utilities.h | 7 ++++ 4 files changed, 119 insertions(+) create mode 100644 src/Gui/Inventor/SoToggleSwitch.cpp create mode 100644 src/Gui/Inventor/SoToggleSwitch.h diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index ab93d16cac..47ea8eb749 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1079,6 +1079,7 @@ SET(Inventor_CPP_SRCS Inventor/SoFCBoundingBox.cpp Inventor/SoMouseWheelEvent.cpp Inventor/SoFCTransform.cpp + Inventor/SoToggleSwitch.cpp Inventor/Draggers/SoTransformDragger.cpp Inventor/Draggers/SoLinearDragger.cpp Inventor/Draggers/SoPlanarDragger.cpp @@ -1115,6 +1116,7 @@ SET(Inventor_SRCS Inventor/SoFCBoundingBox.h Inventor/SoMouseWheelEvent.h Inventor/SoFCTransform.h + Inventor/SoToggleSwitch.h Inventor/Draggers/SoTransformDragger.h Inventor/Draggers/SoLinearDragger.h Inventor/Draggers/SoPlanarDragger.h diff --git a/src/Gui/Inventor/SoToggleSwitch.cpp b/src/Gui/Inventor/SoToggleSwitch.cpp new file mode 100644 index 0000000000..0fc1694220 --- /dev/null +++ b/src/Gui/Inventor/SoToggleSwitch.cpp @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Sayantan Deb * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#include "SoToggleSwitch.h" + +SO_NODE_SOURCE(SoToggleSwitch) + +void SoToggleSwitch::initClass() +{ + SO_NODE_INIT_CLASS(SoToggleSwitch, SoSwitch, "Switch"); +} + +SoToggleSwitch::SoToggleSwitch() +{ + SO_NODE_CONSTRUCTOR(SoToggleSwitch); + SO_NODE_ADD_FIELD(on, (1)); + + whichChild = SO_SWITCH_ALL; +} + +void SoToggleSwitch::toggle() +{ + on = !on.getValue(); +} + +void SoToggleSwitch::notify(SoNotList* notList) +{ + assert(notList); + if (notList->getLastField() == &on) { + whichChild = on.getValue()? SO_SWITCH_ALL : SO_SWITCH_NONE; + } + + inherited::notify(notList); +} diff --git a/src/Gui/Inventor/SoToggleSwitch.h b/src/Gui/Inventor/SoToggleSwitch.h new file mode 100644 index 0000000000..11c9c90dd6 --- /dev/null +++ b/src/Gui/Inventor/SoToggleSwitch.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Sayantan Deb * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#ifndef SO_TOGGLE_SWITCH +#define SO_TOGGLE_SWITCH + +#include +#include + + +/** + * A switch that can be used to show or hide all child nodes + */ +class SoToggleSwitch: public SoSwitch +{ + SO_NODE_HEADER(SoToggleSwitch); + +public: + static void initClass(); + SoToggleSwitch(); + + // the switch is on be default + SoSFBool on; + // toggles the switch state + void toggle(); + +protected: + ~SoToggleSwitch() override = default; + + void notify(SoNotList* notList) override; + +private: + using inherited = SoSwitch; +}; + +#endif /* SO_TOGGLE_SWITCH */ diff --git a/src/Gui/Utilities.h b/src/Gui/Utilities.h index cae7971abe..623165742d 100644 --- a/src/Gui/Utilities.h +++ b/src/Gui/Utilities.h @@ -446,9 +446,16 @@ private: #define FC_SET_SWITCH(__name__, __state__) \ do { \ SoSwitch* sw = SO_GET_ANY_PART(this, __name__, SoSwitch); \ + assert(sw); \ sw->whichChild = __state__; \ } while (0) +#define FC_SET_TOGGLE_SWITCH(__name__, __state__) \ +do { \ + SoToggleSwitch* sw = SO_GET_ANY_PART(this, __name__, SoToggleSwitch); \ + assert(sw); \ + sw->on = __state__; \ +} while (0) struct RotationComponents { float angle; From 35fe77efd04eeb43f760b44993bb95d67afec2dd Mon Sep 17 00:00:00 2001 From: captain0xff Date: Sun, 6 Jul 2025 23:30:08 +0530 Subject: [PATCH 3/3] Gui: move geometry data to separate classes from dragger components --- src/Gui/Inventor/Draggers/SoLinearDragger.cpp | 203 ++++++++--------- src/Gui/Inventor/Draggers/SoLinearDragger.h | 74 ++++-- .../Inventor/Draggers/SoRotationDragger.cpp | 214 +++++++++--------- src/Gui/Inventor/Draggers/SoRotationDragger.h | 76 +++++-- .../Inventor/Draggers/SoTransformDragger.cpp | 36 +-- src/Gui/SoFCDB.cpp | 8 + 6 files changed, 339 insertions(+), 272 deletions(-) diff --git a/src/Gui/Inventor/Draggers/SoLinearDragger.cpp b/src/Gui/Inventor/Draggers/SoLinearDragger.cpp index c4c2d99c3c..9e34b702e9 100644 --- a/src/Gui/Inventor/Draggers/SoLinearDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoLinearDragger.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #endif #include @@ -61,9 +62,83 @@ #include "Utilities.h" #include +#include 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(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); diff --git a/src/Gui/Inventor/Draggers/SoLinearDragger.h b/src/Gui/Inventor/Draggers/SoLinearDragger.h index cb212bdcc7..a51ec390c0 100644 --- a/src/Gui/Inventor/Draggers/SoLinearDragger.h +++ b/src/Gui/Inventor/Draggers/SoLinearDragger.h @@ -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(); diff --git a/src/Gui/Inventor/Draggers/SoRotationDragger.cpp b/src/Gui/Inventor/Draggers/SoRotationDragger.cpp index 2bda576f76..a5a408d362 100644 --- a/src/Gui/Inventor/Draggers/SoRotationDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoRotationDragger.cpp @@ -59,9 +59,93 @@ #include "Utilities.h" #include +#include 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 / 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(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 / 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(userdata); - assert(sudoThis->coordinates); - auto coordinates = sudoThis->coordinates; - float angleIncrement = sudoThis->arcAngle.getValue() / static_cast(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(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( + SO_GET_ANY_PART(this, "rotator", SoRotatorGeometryKit)->pivotPosition.getValue() + ); Base::Vector3d axis = draggerDir.Cross(dir).Normalize(); double ang = draggerDir.GetAngleOriented(dir, axis); diff --git a/src/Gui/Inventor/Draggers/SoRotationDragger.h b/src/Gui/Inventor/Draggers/SoRotationDragger.h index 292b47ca98..c5051a4c45 100644 --- a/src/Gui/Inventor/Draggers/SoRotationDragger.h +++ b/src/Gui/Inventor/Draggers/SoRotationDragger.h @@ -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(); diff --git a/src/Gui/Inventor/Draggers/SoTransformDragger.cpp b/src/Gui/Inventor/Draggers/SoTransformDragger.cpp index d253237b6c..c5ead6cfbf 100644 --- a/src/Gui/Inventor/Draggers/SoTransformDragger.cpp +++ b/src/Gui/Inventor/Draggers/SoTransformDragger.cpp @@ -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() diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index a548c344b8..c732b3b696 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -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();