diff --git a/src/Gui/ViewProviderDragger.cpp b/src/Gui/ViewProviderDragger.cpp index ddff8f4eca..4d74931229 100644 --- a/src/Gui/ViewProviderDragger.cpp +++ b/src/Gui/ViewProviderDragger.cpp @@ -21,6 +21,7 @@ ***************************************************************************/ #include +#include #include #include #include @@ -29,10 +30,11 @@ #include #include +#include +#include #include #include #include -#include "Gui/ViewParams.h" #include "Application.h" #include "BitmapFactory.h" @@ -41,16 +43,15 @@ #include "Inventor/Draggers/SoTransformDragger.h" #include "Inventor/Draggers/Gizmo.h" #include "Inventor/SoFCPlacementIndicatorKit.h" +#include "Inventor/So3DAnnotation.h" #include "SoFCUnifiedSelection.h" #include "TaskTransform.h" #include "View3DInventorViewer.h" #include "ViewProviderDragger.h" #include "Utilities.h" +#include "ViewParams.h" +#include "ViewProviderLink.h" -#include -#include -#include -#include using namespace Gui; @@ -144,35 +145,50 @@ ViewProvider* ViewProviderDragger::startEditing(int mode) bool ViewProviderDragger::forwardToLink() { - // Trying to detect if the editing request is forwarded by a link object, - // usually by doubleClicked(). If so, we route the request back. There shall - // be no risk of infinite recursion, as ViewProviderLink handles - // ViewProvider::Transform request by itself. - ViewProviderDocumentObject* vpParent = nullptr; - std::string subname; + // typically we want to transform the selected object, but if the selected object is in the link, + // we want to transform the link instead. + // + // To achieve that, we use the sub object path and look for the first link in the chain, and + // we forward the request there. + const auto findFirstLinkViewProvider = [this]() -> ViewProvider* { + ViewProviderDocumentObject* vpParent = nullptr; + std::string subname; - auto doc = Application::Instance->editDocument(); - if (!doc) { - return false; + auto doc = Application::Instance->editDocument(); + if (!doc) { + return nullptr; + } + + doc->getInEdit(&vpParent, &subname); + if (!vpParent) { + return nullptr; + } + + for (const auto subObjects = vpParent->getObject()->getSubObjectList(subname.c_str()); + const auto subObject : std::views::reverse(subObjects)) { + + // we don't want to try to edit objects in other documents + if (subObject->getDocument() != getObject()->getDocument()) { + return nullptr; + } + + if (auto subObjectViewProvider = Application::Instance->getViewProvider(subObject); + subObjectViewProvider && subObjectViewProvider->isDerivedFrom()) { + return subObjectViewProvider; + } + } + + return nullptr; + }; + + if (ViewProvider* subObjectViewProvider = findFirstLinkViewProvider(); + subObjectViewProvider && subObjectViewProvider != this) { + forwardedViewProvider = subObjectViewProvider->startEditing(Transform); } - doc->getInEdit(&vpParent, &subname); - if (!vpParent) { - return false; - } - - if (vpParent == this) { - return false; - } - - if (!vpParent->isDerivedFrom()) { - return false; - } - - forwardedViewProvider = vpParent->startEditing(ViewProvider::Transform); - return forwardedViewProvider != nullptr; } + App::PropertyPlacement* ViewProviderDragger::getPlacementProperty() const { auto object = getObject(); @@ -200,8 +216,8 @@ bool ViewProviderDragger::setEdit(int ModNum) transformDragger = new SoTransformDragger(); transformDragger->setAxisColors(Gui::ViewParams::instance()->getAxisXColor(), - Gui::ViewParams::instance()->getAxisYColor(), - Gui::ViewParams::instance()->getAxisZColor()); + Gui::ViewParams::instance()->getAxisYColor(), + Gui::ViewParams::instance()->getAxisZColor()); transformDragger->draggerSize.setValue(ViewParams::instance()->getDraggerScale()); transformDragger->addStartCallback(dragStartCallback, this); diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index ee5d9345dc..3809773cd3 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -2715,10 +2715,7 @@ bool ViewProviderLink::initDraggingPlacement() { dragCtx = std::make_unique(); dragCtx->preTransform = doc->getEditingTransform(); - doc->setEditingTransform(dragCtx->preTransform); - - const auto &pla = ext->getPlacementProperty()? - ext->getPlacementValue():ext->getLinkPlacementValue(); + const auto &pla = getPlacementProperty()->getValue(); // Cancel out our own transformation from the editing transform, because // the dragger is meant to change our transformation. @@ -2732,38 +2729,16 @@ bool ViewProviderLink::initDraggingPlacement() { dragCtx->bbox.ScaleY(scale.y); dragCtx->bbox.ScaleZ(scale.z); - auto modifier = QApplication::queryKeyboardModifiers(); - // Determine the dragger base position - // if CTRL key is down, force to use bound box center, - // if SHIFT key is down, force to use origine, - // if not a sub link, use origine, - // else (e.g. group, array, sub link), use bound box center - if(modifier != Qt::ShiftModifier - && ((ext->getLinkedObjectValue() && !linkView->hasSubs()) - || modifier == Qt::ControlModifier)) - { - App::PropertyPlacement *propPla = nullptr; - if(ext->getLinkTransformValue() && ext->getLinkedObjectValue()) { - propPla = freecad_cast( - ext->getLinkedObjectValue()->getPropertyByName("Placement")); - } - if(propPla) { - dragCtx->initialPlacement = pla * propPla->getValue(); - dragCtx->mat *= propPla->getValue().inverse().toMatrix(); - } else - dragCtx->initialPlacement = pla; - + App::PropertyPlacement *propPla = nullptr; + if(ext->getLinkTransformValue() && ext->getLinkedObjectValue()) { + propPla = freecad_cast( + ext->getLinkedObjectValue()->getPropertyByName("Placement")); + } + if(propPla) { + dragCtx->initialPlacement = pla * propPla->getValue(); + dragCtx->mat *= propPla->getValue().inverse().toMatrix(); } else { - auto offset = dragCtx->bbox.GetCenter(); - - // This determines the initial placement of the dragger. We place it at the - // center of our bounding box. - dragCtx->initialPlacement = pla * Base::Placement(offset, Base::Rotation()); - - // dragCtx->mat is to transform the dragger placement to our own placement. - // Since the dragger is placed at the center, we set the transformation by - // moving the same amount in reverse direction. - dragCtx->mat.move(Vector3d() - offset); + dragCtx->initialPlacement = pla; } return true; @@ -2872,6 +2847,8 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN } ViewProviderDragger::setEditViewer(viewer, ModNum); + + viewer->setupEditingRoot(transformDragger, &dragCtx->preTransform); } void ViewProviderLink::unsetEditViewer(Gui::View3DInventorViewer* viewer)