From a48ec3ce45d5af4f1309cda7faff736a9178adb5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 27 Feb 2014 14:43:07 +0100 Subject: [PATCH] + fixes #0001441: entering Transform mode degrades the Placemens rotation to single precision --- src/Gui/ViewProviderGeometryObject.cpp | 47 ++++++++++++++++++++++++++ src/Gui/ViewProviderGeometryObject.h | 1 + 2 files changed, 48 insertions(+) diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index 698e1e608382..638891ca4394 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -226,12 +226,17 @@ bool ViewProviderGeometryObject::setEdit(int ModNum) SoDragger* dragger = manip->getDragger(); dragger->addStartCallback(dragStartCallback, this); dragger->addFinishCallback(dragFinishCallback, this); +#if 1 + dragger->addMotionCallback(dragMotionCallback, this); + dragger->setUserData(manip); +#else // Attach a sensor to the transform manipulator and set it as its user // data to delete it when the view provider leaves the edit mode SoNodeSensor* sensor = new SoNodeSensor(sensorCallback, this); //sensor->setPriority(0); sensor->attach(manip); manip->setUserData(sensor); +#endif return manip->replaceNode(path); } return false; @@ -289,16 +294,20 @@ void ViewProviderGeometryObject::unsetEdit(int ModNum) // The manipulator has a sensor as user data and this sensor contains the view provider SoCenterballManip * manip = static_cast(path->getTail()); +#if 0 SoNodeSensor* sensor = reinterpret_cast(manip->getUserData()); +#endif // #0000939: Pressing Escape while pivoting a box crashes // #0000942: Crash when 2xdouble-click on part SoDragger* dragger = manip->getDragger(); if (dragger && dragger->getHandleEventAction()) dragger->grabEventsCleanup(); +#if 0 // detach sensor sensor->detach(); delete sensor; +#endif SoTransform* transform = this->pcTransform; manip->replaceManip(path, transform); @@ -430,6 +439,44 @@ void ViewProviderGeometryObject::sensorCallback(void * data, SoSensor * s) #endif } +void ViewProviderGeometryObject::dragMotionCallback(void * data, SoDragger * d) +{ + SoNode* node = reinterpret_cast(d->getUserData()); + if (node && node->getTypeId().isDerivedFrom(SoCenterballManip::getClassTypeId())) { + // apply the transformation data to the placement + SoCenterballManip* manip = static_cast(node); + float q0, q1, q2, q3; + // See also SoTransformManip::valueChangedCB + // to get translation directly from dragger + SbVec3f move = manip->translation.getValue(); + SbVec3f center = manip->center.getValue(); + manip->rotation.getValue().getValue(q0, q1, q2, q3); + + // get the placement + ViewProviderGeometryObject* view = reinterpret_cast(data); + if (view && view->pcObject && view->pcObject->getTypeId().isDerivedFrom(App::GeoFeature::getClassTypeId())) { + App::GeoFeature* geometry = static_cast(view->pcObject); + // Note: If R is the rotation, c the rotation center and t the translation + // vector then Inventor applies the following transformation: R*(x-c)+c+t + // In FreeCAD a placement only has a rotation and a translation part but + // no rotation center. This means that we must divide the transformation + // in a rotation and translation part. + // R * (x-c) + c + t = R * x - R * c + c + t + // The rotation part is R, the translation part t', however, is: + // t' = t + c - R * c + Base::Placement p; + p.setRotation(Base::Rotation(q0,q1,q2,q3)); + Base::Vector3d t(move[0],move[1],move[2]); + Base::Vector3d c(center[0],center[1],center[2]); + t += c; + p.getRotation().multVec(c,c); + t -= c; + p.setPosition(t); + geometry->Placement.setValue(p); + } + } +} + void ViewProviderGeometryObject::dragStartCallback(void *data, SoDragger *) { // This is called when a manipulator is about to manipulating diff --git a/src/Gui/ViewProviderGeometryObject.h b/src/Gui/ViewProviderGeometryObject.h index 114bdcbfc888..08e7dd56058d 100644 --- a/src/Gui/ViewProviderGeometryObject.h +++ b/src/Gui/ViewProviderGeometryObject.h @@ -105,6 +105,7 @@ class GuiExport ViewProviderGeometryObject : public ViewProviderDocumentObject static void sensorCallback(void * data, SoSensor * sensor); static void dragStartCallback(void * data, SoDragger * d); static void dragFinishCallback(void * data, SoDragger * d); + static void dragMotionCallback(void * data, SoDragger * d); protected: SoFCSelection * pcHighlight;