Gui: fix ViewProviderLink dragger behavior with scale

This commit is contained in:
Zheng, Lei
2019-10-04 19:01:32 +08:00
committed by wmayer
parent c7a0e7a2f5
commit e8389219b2

View File

@@ -51,6 +51,7 @@
#include <Base/PlacementPy.h>
#include <Base/MatrixPy.h>
#include <Base/BoundBoxPy.h>
#include <Base/Tools.h>
#include <App/ComplexGeoData.h>
#include <App/GeoFeature.h>
#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<SoFCCSysDragger*>(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);