/*************************************************************************** * Copyright (c) 2015 Thomas Anderson * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include "SoTransformDragger.h" #include "SoLinearDragger.h" #include "SoPlanarDragger.h" #include "SoRotationDragger.h" #include "Utilities.h" #include /* GENERAL NOTE ON COIN3D CUSTOM DRAGGERS * You basically have two choices for creating custom dragger geometry. * 1) create an .iv file and set environment variable to the file path. This * comes with install headaches. * 2) create an .iv file and run through a mock compiler that generates a header * file to include in the project. I would have gone this way but after installing * inventor-demo(ubuntu), the mock compiler tool was there only in source and make * didn't do anything. Didn't want to put any time into something I didn't like anyway. * * static SbList * defaultdraggerparts = NULL; is a global definition * in SoInteractionKit that contains the geometry. There doesn't appear to be anyway * to add to this other than readDefaultParts, that takes a file. So maybe a temp file? * * naming appears to be central to the core. It looks like as long as an object * is alive SoNode::getByName() will find it. So maybe just create my own little * container of objects to keep the default geometry alive....This appears to be * working and I like this solution. * * SoInteractionKit warns about these * names all being the same scope and do NOT have to be unique. Need to make names * descriptive to avoid collisions. * this is point of the SoGroup accessed from SoFCDB::getStorage(). */ using namespace Gui; SO_KIT_SOURCE(SoTransformDragger) void SoTransformDragger::initClass() { SoLinearDraggerContainer::initClass(); SoPlanarDragger::initClass(); SoRotationDraggerContainer::initClass(); SO_KIT_INIT_CLASS(SoTransformDragger, SoDragger, "Dragger"); } SoTransformDragger::SoTransformDragger() : axisScale(1.0f, 1.0f, 1.0f) { SO_KIT_CONSTRUCTOR(SoTransformDragger); #if defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) this->ref(); #endif SO_KIT_ADD_CATALOG_ENTRY(annotation, So3DAnnotation, TRUE, geomSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(scaleNode, SoScale, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(pickStyle, SoPickStyle, TRUE, annotation, "", TRUE); // Translator SO_KIT_ADD_CATALOG_ENTRY(xTranslatorDragger, SoLinearDraggerContainer, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yTranslatorDragger, SoLinearDraggerContainer, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zTranslatorDragger, SoLinearDraggerContainer, TRUE, annotation, "", TRUE); // Planar Translator SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSeparator, SoSeparator, TRUE, xyPlanarTranslatorSwitch, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSeparator, SoSeparator, TRUE, yzPlanarTranslatorSwitch, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSeparator, SoSeparator, TRUE, zxPlanarTranslatorSwitch, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorColor, SoBaseColor, TRUE, xyPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorColor, SoBaseColor, TRUE, yzPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorColor, SoBaseColor, TRUE, zxPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorRotation, SoRotation, TRUE, xyPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorRotation, SoRotation, TRUE, yzPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorRotation, SoRotation, TRUE, zxPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorDragger, SoPlanarDragger, TRUE, xyPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorDragger, SoPlanarDragger, TRUE, yzPlanarTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorDragger, SoPlanarDragger, TRUE, zxPlanarTranslatorSeparator, "", TRUE); // Rotator 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)); SO_KIT_ADD_FIELD(translationIncrement, (1.0)); SO_KIT_ADD_FIELD(translationIncrementCountX, (0)); SO_KIT_ADD_FIELD(translationIncrementCountY, (0)); SO_KIT_ADD_FIELD(translationIncrementCountZ, (0)); 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(rotationIncrementCountX, (0)); SO_KIT_ADD_FIELD(rotationIncrementCountY, (0)); SO_KIT_ADD_FIELD(rotationIncrementCountZ, (0)); SO_KIT_ADD_FIELD(draggerSize, (1.0)); SO_KIT_ADD_FIELD(autoScaleResult, (1.0)); SO_KIT_ADD_FIELD(xAxisLabel, ("X")); SO_KIT_ADD_FIELD(yAxisLabel, ("Y")); SO_KIT_ADD_FIELD(zAxisLabel, ("Z")); SO_KIT_INIT_INSTANCE(); // Colors setAxisColors(SbColor(1.0, 0, 0).getPackedValue(0.0f), SbColor(0, 1.0, 0).getPackedValue(0.0f), SbColor(0, 0, 1.0).getPackedValue(0.0f)); // Translator setupTranslationDraggers(); // Planar Translator SoPlanarDragger* tPlanarDragger; tPlanarDragger = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", SoPlanarDragger); tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount); tPlanarDragger = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", SoPlanarDragger); tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementXCount); translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount); tPlanarDragger = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", SoPlanarDragger); tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementYCount); // Rotator setupRotationDraggers(); // Switches SoSwitch* sw; // Planar Translator sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); // Rotations SoRotation* localRotation; SbRotation tempRotation; auto angle = static_cast(std::numbers::pi / 2.0); // Planar Translator localRotation = SO_GET_ANY_PART(this, "xyPlanarTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbRotation::identity()); localRotation = SO_GET_ANY_PART(this, "yzPlanarTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(0.0, -1.0, 0.0), angle); localRotation = SO_GET_ANY_PART(this, "zxPlanarTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle); // Rotator 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); 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); 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. auto scaleEngine = new SoComposeVec3f(); // uses coin ref scheme. scaleEngine->x.connectFrom(&draggerSize); scaleEngine->y.connectFrom(&draggerSize); scaleEngine->z.connectFrom(&draggerSize); SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.connectFrom(&scaleEngine->vector); autoScaleResult.connectFrom(&draggerSize); SoPickStyle* localPickStyle = SO_GET_ANY_PART(this, "pickStyle", SoPickStyle); localPickStyle->style = SoPickStyle::SHAPE_ON_TOP; addValueChangedCallback(&SoTransformDragger::valueChangedCB); translationSensor.setFunction(&SoTransformDragger::translationSensorCB); translationSensor.setData(this); translationSensor.setPriority(0); rotationSensor.setFunction(&SoTransformDragger::rotationSensorCB); rotationSensor.setData(this); rotationSensor.setPriority(0); cameraSensor.setFunction(&SoTransformDragger::cameraCB); cameraSensor.setData(this); idleSensor.setFunction(&SoTransformDragger::idleCB); idleSensor.setData(this); this->addFinishCallback(&SoTransformDragger::finishDragCB, this); this->setUpConnections(TRUE, TRUE); } SoTransformDragger::~SoTransformDragger() { translationSensor.setData(nullptr); translationSensor.detach(); rotationSensor.setData(nullptr); rotationSensor.detach(); cameraSensor.setData(nullptr); cameraSensor.detach(); idleSensor.setData(nullptr); idleSensor.unschedule(); removeValueChangedCallback(&SoTransformDragger::valueChangedCB); removeFinishCallback(&SoTransformDragger::finishDragCB, this); } SbBool SoTransformDragger::setUpConnections(SbBool onoff, SbBool doitalways) { if (!doitalways && (connectionsSetUp == onoff)) { return onoff; } auto tDraggerX = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer); auto tDraggerY = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer); auto tDraggerZ = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer); SoPlanarDragger* tPlanarDraggerXZ = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", SoPlanarDragger); SoPlanarDragger* tPlanarDraggerYZ = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", SoPlanarDragger); SoPlanarDragger* tPlanarDraggerZX = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", SoPlanarDragger); 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); registerChildDragger(tDraggerX->getDragger()); registerChildDragger(tDraggerY->getDragger()); registerChildDragger(tDraggerZ->getDragger()); registerChildDragger(tPlanarDraggerXZ); registerChildDragger(tPlanarDraggerYZ); registerChildDragger(tPlanarDraggerZX); registerChildDragger(rDraggerX->getDragger()); registerChildDragger(rDraggerY->getDragger()); registerChildDragger(rDraggerZ->getDragger()); translationSensorCB(this, nullptr); if (this->translationSensor.getAttachedField() != &this->translation) { this->translationSensor.attach(&this->translation); } rotationSensorCB(this, nullptr); if (this->rotationSensor.getAttachedField() != &this->rotation) { this->rotationSensor.attach(&this->rotation); } } else { unregisterChildDragger(tDraggerX->getDragger()); unregisterChildDragger(tDraggerY->getDragger()); unregisterChildDragger(tDraggerZ->getDragger()); unregisterChildDragger(tPlanarDraggerXZ); unregisterChildDragger(tPlanarDraggerYZ); unregisterChildDragger(tPlanarDraggerZX); unregisterChildDragger(rDraggerX->getDragger()); unregisterChildDragger(rDraggerY->getDragger()); unregisterChildDragger(rDraggerZ->getDragger()); inherited::setUpConnections(onoff, doitalways); if (this->translationSensor.getAttachedField()) { this->translationSensor.detach(); } if (this->rotationSensor.getAttachedField()) { this->rotationSensor.detach(); } } return !(this->connectionsSetUp = onoff); } void SoTransformDragger::translationSensorCB(void* f, SoSensor*) { auto sudoThis = static_cast(f); if (!f) { return; } SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } void SoTransformDragger::rotationSensorCB(void* f, SoSensor*) { auto sudoThis = static_cast(f); if (!f) { return; } SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } void SoTransformDragger::valueChangedCB(void*, SoDragger* d) { auto sudoThis = dynamic_cast(d); assert(sudoThis); SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft // all this just to get the translation? SbVec3f localTranslation, scaleDummy; SbRotation localRotation, scaleOrientationDummy; matrix.getTransform(localTranslation, localRotation, scaleDummy, scaleOrientationDummy); sudoThis->translationSensor.detach(); if (sudoThis->translation.getValue() != localTranslation) { sudoThis->translation = localTranslation; } sudoThis->translationSensor.attach(&sudoThis->translation); sudoThis->rotationSensor.detach(); if (sudoThis->rotation.getValue() != localRotation) { sudoThis->rotation = localRotation; } sudoThis->rotationSensor.attach(&sudoThis->rotation); } void SoTransformDragger::setUpAutoScale(SoCamera* cameraIn) { // note: sofieldsensor checks if the current sensor is already attached // and takes appropriate action. So it is safe to attach to a field without // checking current attachment state. if (cameraIn->getTypeId() == SoOrthographicCamera::getClassTypeId()) { auto localCamera = dynamic_cast(cameraIn); assert(localCamera); cameraSensor.attach(&localCamera->height); SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.disconnect(); autoScaleResult.disconnect(&draggerSize); cameraCB(this, nullptr); } else if (cameraIn->getTypeId() == SoPerspectiveCamera::getClassTypeId()) { auto localCamera = dynamic_cast(cameraIn); assert(localCamera); cameraSensor.attach(&localCamera->position); SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.disconnect(); autoScaleResult.disconnect(&draggerSize); cameraCB(this, nullptr); } } void SoTransformDragger::cameraCB(void* data, SoSensor*) { auto sudoThis = static_cast(data); if (!sudoThis) { return; } if (!sudoThis->idleSensor.isScheduled()) { sudoThis->idleSensor.schedule(); } } void SoTransformDragger::GLRender(SoGLRenderAction* action) { if (!scaleInited) { scaleInited = true; updateDraggerCache(action->getCurPath()); updateAxisScale(); } inherited::GLRender(action); } void SoTransformDragger::updateAxisScale() { SbMatrix localToWorld = getLocalToWorldMatrix(); SbVec3f origin; localToWorld.multVecMatrix(SbVec3f(0.0, 0.0, 0.0), origin); SbVec3f vx, vy, vz; localToWorld.multVecMatrix(SbVec3f(1.0f, 0.0f, 0.0f), vx); localToWorld.multVecMatrix(SbVec3f(0.0f, 1.0f, 0.0f), vy); localToWorld.multVecMatrix(SbVec3f(0.0f, 0.0f, 1.0f), vz); float x = std::max((vx - origin).length(), 1e-7f); float y = std::max((vy - origin).length(), 1e-7f); float z = std::max((vz - origin).length(), 1e-7f); if (!axisScale.equals(SbVec3f(x, y, z), 1e-7f)) { axisScale.setValue(x, y, z); idleCB(this, &idleSensor); } } void SoTransformDragger::handleEvent(SoHandleEventAction* action) { this->ref(); inherited::handleEvent(action); updateAxisScale(); this->unref(); } void SoTransformDragger::idleCB(void* data, SoSensor*) { auto sudoThis = static_cast(data); if (!data) { return; } SoField* field = sudoThis->cameraSensor.getAttachedField(); if (field) { auto camera = static_cast(field->getContainer()); SbMatrix localToWorld = sudoThis->getLocalToWorldMatrix(); SbVec3f origin; localToWorld.multVecMatrix(SbVec3f(0.0, 0.0, 0.0), origin); SbViewVolume viewVolume = camera->getViewVolume(); float radius = sudoThis->draggerSize.getValue() / 2.0; float localScale = viewVolume.getWorldToScreenScale(origin, radius); float sx, sy, sz; sudoThis->axisScale.getValue(sx, sy, sz); SbVec3f scaleVector(localScale / sx, localScale / sy, localScale / sz); SoScale* localScaleNode = SO_GET_ANY_PART(sudoThis, "scaleNode", SoScale); localScaleNode->scaleFactor.setValue(scaleVector); sudoThis->autoScaleResult.setValue(localScale); } } void SoTransformDragger::finishDragCB(void* data, SoDragger*) { auto sudoThis = static_cast(data); assert(sudoThis); // note: when creating a second view of the document and then closing // the first viewer it deletes the camera. However, the attached field // of the cameraSensor will be detached automatically. SoField* field = sudoThis->cameraSensor.getAttachedField(); if (field) { auto camera = static_cast(field->getContainer()); if (camera->getTypeId() == SoPerspectiveCamera::getClassTypeId()) { cameraCB(sudoThis, nullptr); } } } void SoTransformDragger::clearIncrementCounts() { translationIncrementCountX.setValue(0); translationIncrementCountY.setValue(0); translationIncrementCountZ.setValue(0); rotationIncrementCountX.setValue(0); rotationIncrementCountY.setValue(0); rotationIncrementCountZ.setValue(0); } void SoTransformDragger::setAxisColors(unsigned long x, unsigned long y, unsigned long z) { SbColor colorX; SbColor colorY; SbColor colorZ; float t = 0.0f; colorX.setPackedValue(x, t); colorY.setPackedValue(y, t); colorZ.setPackedValue(z, t); SoBaseColor* color; // Translator SoLinearDraggerContainer* tDragger; tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer); tDragger->color.setValue(colorX[0], colorX[1], colorX[2]); tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer); tDragger->color.setValue(colorY[0], colorY[1], colorY[2]); tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer); tDragger->color.setValue(colorZ[0], colorZ[1], colorZ[2]); // Planar Translator color = SO_GET_ANY_PART(this, "xyPlanarTranslatorColor", SoBaseColor); color->rgb.setValue(colorZ[0], colorZ[1], colorZ[2]); color = SO_GET_ANY_PART(this, "yzPlanarTranslatorColor", SoBaseColor); color->rgb.setValue(colorX[0], colorX[1], colorX[2]); color = SO_GET_ANY_PART(this, "zxPlanarTranslatorColor", SoBaseColor); color->rgb.setValue(colorY[0], colorY[1], colorY[2]); // Rotator 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 // Translator void SoTransformDragger::showTranslationX() { auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = true; } void SoTransformDragger::showTranslationY() { auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = true; } void SoTransformDragger::showTranslationZ() { auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = true; } void SoTransformDragger::hideTranslationX() { auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = false; } void SoTransformDragger::hideTranslationY() { auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = false; } void SoTransformDragger::hideTranslationZ() { auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer); tDragger->visible = false; } bool SoTransformDragger::isShownTranslationX() { auto tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", SoLinearDraggerContainer); return tDragger->visible.getValue(); } bool SoTransformDragger::isShownTranslationY() { auto tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", SoLinearDraggerContainer); return tDragger->visible.getValue(); } bool SoTransformDragger::isShownTranslationZ() { auto tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", SoLinearDraggerContainer); return tDragger->visible.getValue(); } // Planar Translator void SoTransformDragger::showPlanarTranslationXY() { SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoTransformDragger::showPlanarTranslationYZ() { SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoTransformDragger::showPlanarTranslationZX() { SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoTransformDragger::hidePlanarTranslationXY() { SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoTransformDragger::hidePlanarTranslationYZ() { SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoTransformDragger::hidePlanarTranslationZX() { SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } bool SoTransformDragger::isShownPlanarTranslationXY() { SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoTransformDragger::isShownPlanarTranslationYZ() { SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoTransformDragger::isShownPlanarTranslationZX() { SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoTransformDragger::isHiddenPlanarTranslationXY() { SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoTransformDragger::isHiddenPlanarTranslationYZ() { SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoTransformDragger::isHiddenPlanarTranslationZX() { SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_NONE); } // Rotator void SoTransformDragger::showRotationX() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); rDragger->visible = true; } void SoTransformDragger::showRotationY() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); rDragger->visible = true; } void SoTransformDragger::showRotationZ() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); rDragger->visible = true; } void SoTransformDragger::hideRotationX() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); rDragger->visible = false; } void SoTransformDragger::hideRotationY() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); rDragger->visible = false; } void SoTransformDragger::hideRotationZ() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); rDragger->visible = false; } bool SoTransformDragger::isShownRotationX() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", SoRotationDraggerContainer); return rDragger->visible.getValue(); } bool SoTransformDragger::isShownRotationY() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "yRotatorDragger", SoRotationDraggerContainer); return rDragger->visible.getValue(); } bool SoTransformDragger::isShownRotationZ() { SoRotationDraggerContainer* rDragger = SO_GET_ANY_PART(this, "zRotatorDragger", SoRotationDraggerContainer); return rDragger->visible.getValue(); } void SoTransformDragger::setupTranslationDraggers() { setupTranslationDragger("xTranslatorDragger", &xAxisLabel, translationIncrementCountX, SbVec3d(1.0, 0.0, 0.0)); setupTranslationDragger("yTranslatorDragger", &yAxisLabel, translationIncrementCountY, SbVec3d(0.0, 1.0, 0.0)); setupTranslationDragger("zTranslatorDragger", &zAxisLabel, translationIncrementCountZ, SbVec3d(0.0, 0.0, 1.0)); } void SoTransformDragger::setupTranslationDragger(const std::string& name, SoSFString* label, SoSFInt32& incrementCount, const SbVec3d& rotDir) { SoLinearDraggerContainer* draggerContainer = SO_GET_ANY_PART(this, name.c_str(), SoLinearDraggerContainer); SoLinearDragger* dragger = draggerContainer->getDragger(); dragger->translationIncrement.connectFrom(&this->translationIncrement); dragger->autoScaleResult.connectFrom(&this->autoScaleResult); dragger->label.connectFrom(label); incrementCount.connectFrom(&dragger->translationIncrementCount); 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); }