From e8389219b2d3e63e3cd4f891b0e047bc16e06957 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Fri, 4 Oct 2019 19:01:32 +0800 Subject: [PATCH] Gui: fix ViewProviderLink dragger behavior with scale --- src/Gui/ViewProviderLink.cpp | 66 ++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index 8fdcfbbaae..da105122d7 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include "Application.h" @@ -2331,8 +2332,13 @@ bool ViewProviderLink::doubleClicked() { void ViewProviderLink::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { auto ext = getLinkExtension(); - if(linkEdit(ext)) + if(linkEdit(ext)) { linkView->getLinkedView()->setupContextMenu(menu,receiver,member); + } else if(ext->getPlacementProperty() || ext->getLinkPlacementProperty()) { + QAction* act = menu->addAction(QObject::tr("Transform"), receiver, member); + act->setData(QVariant((int)ViewProvider::Transform)); + } + if(ext && ext->getColoredElementsProperty()) { bool found = false; for(auto action : menu->actions()) { @@ -2400,20 +2406,33 @@ bool ViewProviderLink::initDraggingPlacement() { dragCtx.reset(new DraggerContext); + dragCtx->preTransform = doc->getEditingTransform(); + const auto &pla = ext->getPlacementProperty()? ext->getPlacementValue():ext->getLinkPlacementValue(); - dragCtx->preTransform = doc->getEditingTransform(); - auto plaMat = pla.toMatrix(); - plaMat.inverseGauss(); - dragCtx->preTransform *= plaMat; + // Cancel out our our transformation from the editing transform, because + // the dragger is meant to change our transformation. + dragCtx->preTransform *= pla.inverse().toMatrix(); + + dragCtx->bbox = getBoundingBox(0,false); + // The returned bounding box is before out own transform, but we still need + // to scale it to get the correct center. + auto scale = ext->getScaleVector(); + dragCtx->bbox.ScaleX(scale.x); + dragCtx->bbox.ScaleY(scale.y); + dragCtx->bbox.ScaleZ(scale.z); + auto offset = dragCtx->bbox.GetCenter(); + + // This determins 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->bbox = linkView->getBoundBox(); - const auto &offset = Base::Placement( - dragCtx->bbox.GetCenter(),Base::Rotation()); - dragCtx->initialPlacement = pla * offset; - dragCtx->mat = offset.toMatrix(); - dragCtx->mat.inverseGauss(); return true; } @@ -2427,7 +2446,15 @@ ViewProvider *ViewProviderLink::startEditing(int mode) { return inherited::startEditing(mode); } + static thread_local bool _pendingTransform; + static thread_local Base::Matrix4D _editingTransform; + + auto doc = Application::Instance->editDocument(); + if(mode==ViewProvider::Transform) { + if(_pendingTransform && doc) + doc->setEditingTransform(_editingTransform); + if(!initDraggingPlacement()) return 0; if(useCenterballDragger) @@ -2453,7 +2480,6 @@ ViewProvider *ViewProviderLink::startEditing(int mode) { // and set color. We need to find a better place to declare this constant. mode &= ~0x8000; - auto doc = Application::Instance->editDocument(); if(!doc) { FC_ERR("no editing document"); return 0; @@ -2473,8 +2499,12 @@ ViewProvider *ViewProviderLink::startEditing(int mode) { FC_ERR("no linked viewprovider"); return 0; } - // amend the editing transformation with the link transformation + // Amend the editing transformation with the link transformation. + // But save it first in case the linked object reroute the editing request + // back to us. + _editingTransform = doc->getEditingTransform(); doc->setEditingTransform(doc->getEditingTransform()*mat); + Base::FlagToggler<> guard(_pendingTransform); return vpd->startEditing(mode); } @@ -2542,7 +2572,15 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN viewer->setupEditingRoot(group,&dragCtx->preTransform); }else{ SoFCCSysDragger* dragger = static_cast(pcDragger.get()); - dragger->draggerSize.setValue(0.05f); + auto doc = Application::Instance->editDocument(); + if(doc) { + Base::Vector3d v0, v1(1,0,0); + doc->getEditingTransform().multVec(v0,v0); + doc->getEditingTransform().multVec(v1,v1); + // Compensate for possible scaling + dragger->draggerSize.setValue(0.05f / (v1-v0).Length()); + } else + dragger->draggerSize.setValue(0.05f); dragger->setUpAutoScale(viewer->getSoRenderManager()->getCamera()); viewer->setupEditingRoot(pcDragger,&dragCtx->preTransform);