Gui: improve scale handling in SoFCCSysDragger
Because of the scale transformion in Link, the dragger may have undesired behavior. This patch checks scaling factor in scenegraph transformation, and auto scale the dragger axis accordingly.
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
#include <Inventor/nodes/SoSphere.h>
|
||||
#include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
#include <Inventor/nodes/SoPerspectiveCamera.h>
|
||||
#include <Inventor/actions/SoGLRenderAction.h>
|
||||
|
||||
#include <Inventor/SbRotation.h>
|
||||
|
||||
@@ -638,6 +639,8 @@ void SoFCCSysDragger::initClass()
|
||||
}
|
||||
|
||||
SoFCCSysDragger::SoFCCSysDragger()
|
||||
:axisScale(1.0f,1.0f,1.0f)
|
||||
,scaleInited(false)
|
||||
{
|
||||
SO_KIT_CONSTRUCTOR(SoFCCSysDragger);
|
||||
|
||||
@@ -939,6 +942,44 @@ void SoFCCSysDragger::cameraCB(void *data, SoSensor *)
|
||||
sudoThis->idleSensor.schedule();
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::GLRender(SoGLRenderAction * action)
|
||||
{
|
||||
if(!scaleInited) {
|
||||
scaleInited = true;
|
||||
updateDraggerCache(action->getCurPath());
|
||||
updateAxisScale();
|
||||
}
|
||||
|
||||
inherited::GLRender(action);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::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 SoFCCSysDragger::handleEvent(SoHandleEventAction * action)
|
||||
{
|
||||
this->ref();
|
||||
|
||||
inherited::handleEvent(action);
|
||||
updateAxisScale();
|
||||
|
||||
this->unref();
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::idleCB(void *data, SoSensor *)
|
||||
{
|
||||
SoFCCSysDragger *sudoThis = reinterpret_cast<SoFCCSysDragger *>(data);
|
||||
@@ -953,7 +994,9 @@ void SoFCCSysDragger::idleCB(void *data, SoSensor *)
|
||||
SbViewVolume viewVolume = camera->getViewVolume();
|
||||
float radius = sudoThis->draggerSize.getValue() / 2.0;
|
||||
float localScale = viewVolume.getWorldToScreenScale(origin, radius);
|
||||
SbVec3f scaleVector(localScale, localScale, localScale);
|
||||
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);
|
||||
|
||||
@@ -239,8 +239,11 @@ public:
|
||||
bool isHiddenRotationZ(); //!< is x rotation dragger hidden.
|
||||
//@}
|
||||
|
||||
virtual void GLRender(SoGLRenderAction * action);
|
||||
|
||||
protected:
|
||||
virtual SbBool setUpConnections(SbBool onoff, SbBool doitalways = FALSE) override;
|
||||
virtual void handleEvent(SoHandleEventAction * action) override;
|
||||
|
||||
static void translationSensorCB(void *f, SoSensor *);
|
||||
static void rotationSensorCB(void *f, SoSensor *);
|
||||
@@ -255,6 +258,14 @@ protected:
|
||||
SoFieldSensor cameraSensor;
|
||||
|
||||
private:
|
||||
// Used to compensate for axis scale in world transformation when doing
|
||||
// auto scale.
|
||||
SbVec3f axisScale;
|
||||
|
||||
bool scaleInited;
|
||||
|
||||
void updateAxisScale();
|
||||
|
||||
typedef SoDragger inherited;
|
||||
};
|
||||
|
||||
|
||||
@@ -2572,15 +2572,7 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN
|
||||
viewer->setupEditingRoot(group,&dragCtx->preTransform);
|
||||
}else{
|
||||
SoFCCSysDragger* dragger = static_cast<SoFCCSysDragger*>(pcDragger.get());
|
||||
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->draggerSize.setValue(0.05f);
|
||||
dragger->setUpAutoScale(viewer->getSoRenderManager()->getCamera());
|
||||
viewer->setupEditingRoot(pcDragger,&dragCtx->preTransform);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user