Gui: Make ViewProviderLink based on ViewProviderDragger

This commit is contained in:
Kacper Donat
2024-12-05 14:42:13 +01:00
parent 1df3b5be6c
commit fab235682d
9 changed files with 88 additions and 207 deletions

View File

@@ -101,9 +101,7 @@ TaskTransform::TaskTransform(Gui::ViewProviderDragger* vp,
vp->resetTransformOrigin();
if (auto geoFeature = vp->getObject<App::GeoFeature>()) {
originalPlacement = geoFeature->Placement.getValue();
}
originalPlacement = vp->getObjectPlacement();
setupGui();
}
@@ -400,23 +398,29 @@ void TaskTransform::onSelectionChanged(const SelectionChanges& msg)
return;
}
if (!msg.pOriginalMsg) {
// this should not happen! Original should contain unresolved message.
return;
}
auto doc = Application::Instance->getDocument(msg.pDocName);
auto obj = doc->getDocument()->getObject(msg.pObjectName);
auto globalPlacement = App::GeoFeature::getGlobalPlacement(obj);
auto orgDoc = Application::Instance->getDocument(msg.pOriginalMsg->pDocName);
auto orgObj = orgDoc->getDocument()->getObject(msg.pOriginalMsg->pObjectName);
auto globalPlacement = App::GeoFeature::getGlobalPlacement(obj, orgObj, msg.pOriginalMsg->pSubName);
auto localPlacement = App::GeoFeature::getPlacementFromProp(obj, "Placement");
auto rootPlacement = App::GeoFeature::getGlobalPlacement(vp->getObject());
auto attachedPlacement = subObjectPlacementProvider->calculate(msg.Object, localPlacement);
auto selectedObjectPlacement = rootPlacement.inverse() * globalPlacement
* subObjectPlacementProvider->calculate(msg.Object, localPlacement);
auto selectedObjectPlacement = rootPlacement.inverse() * globalPlacement * attachedPlacement;
switch (selectionMode) {
case SelectionMode::SelectTransformOrigin: {auto label = msg.pOriginalMsg
? QStringLiteral("%1#%2.%3")
.arg(QLatin1String(msg.pOriginalMsg->pObjectName),
QLatin1String(msg.pObjectName),
QLatin1String(msg.pSubName))
: QStringLiteral("%1.%2").arg(QLatin1String(msg.pObjectName), QLatin1String(msg.pSubName));
case SelectionMode::SelectTransformOrigin: {auto label = QStringLiteral("%1#%2.%3")
.arg(QLatin1String(msg.pOriginalMsg->pObjectName),
QLatin1String(msg.pObjectName),
QLatin1String(msg.pSubName));
ui->referenceLineEdit->setText(label);
@@ -491,7 +495,7 @@ void TaskTransform::updateTransformOrigin()
return {};
case PlacementMode::Centroid:
if (const auto com = centerOfMassProvider->ofDocumentObject(vp->getObject())) {
return Base::Placement {*com, {}};
return {*com, {}};
}
return {};
case PlacementMode::Custom:

View File

@@ -49,6 +49,7 @@
#include "ViewProviderDragger.h"
#include "Utilities.h"
#include <App/DocumentObjectGroup.h>
#include <Base/Tools.h>
using namespace Gui;
@@ -208,9 +209,7 @@ void ViewProviderDragger::setEditViewer(Gui::View3DInventorViewer* viewer, int M
csysDragger->setUpAutoScale(viewer->getSoRenderManager()->getCamera());
auto mat = viewer->getDocument()->getEditingTransform();
if (auto geoFeature = getObject<App::GeoFeature>()) {
mat *= geoFeature->Placement.getValue().inverse().toMatrix();
}
mat *= getObjectPlacement().inverse().toMatrix();
viewer->getDocument()->setEditingTransform(mat);
viewer->setupEditingRoot(csysDragger, &mat);
@@ -249,13 +248,13 @@ void ViewProviderDragger::dragMotionCallback(void* data, SoDragger* d)
void ViewProviderDragger::updatePlacementFromDragger()
{
const auto geoFeature = getObject<App::GeoFeature>();
const auto placement = getObject()->getPropertyByName<App::PropertyPlacement>("Placement");
if (!geoFeature) {
if (!placement) {
return;
}
geoFeature->Placement.setValue(getDraggerPlacement() * getTransformOrigin().inverse());
placement->setValue(getDraggerPlacement() * getTransformOrigin().inverse());
}
void ViewProviderDragger::updateTransformFromDragger()
@@ -266,6 +265,15 @@ void ViewProviderDragger::updateTransformFromDragger()
pcTransform->rotation.setValue(Base::convertTo<SbRotation>(placement.getRotation()));
}
Base::Placement ViewProviderDragger::getObjectPlacement() const
{
if (auto placement = getObject()->getPropertyByName<App::PropertyPlacement>("Placement")) {
return placement->getValue();
}
return {};
}
Base::Placement ViewProviderDragger::getDraggerPlacement() const
{
const double translationStep = csysDragger->translationIncrement.getValue();
@@ -314,7 +322,7 @@ void ViewProviderDragger::updateDraggerPosition()
return;
}
auto placement = getObject<App::GeoFeature>()->Placement.getValue() * getTransformOrigin();
auto placement = getObjectPlacement() * getTransformOrigin();
setDraggerPlacement(placement);
}

View File

@@ -77,6 +77,7 @@ public:
void updatePlacementFromDragger();
void updateTransformFromDragger();
Base::Placement getObjectPlacement() const;
Base::Placement getDraggerPlacement() const;
void setDraggerPlacement(const Base::Placement& placement);

View File

@@ -1624,7 +1624,7 @@ static const char *_LinkElementIcon = "LinkElement";
ViewProviderLink::ViewProviderLink()
:linkType(LinkTypeNone),hasSubName(false),hasSubElement(false)
,useCenterballDragger(false),childVp(nullptr),overlayCacheKey(0)
,childVp(nullptr),overlayCacheKey(0)
{
sPixmap = _LinkIcon;
@@ -1670,7 +1670,7 @@ ViewProviderLink::~ViewProviderLink()
}
bool ViewProviderLink::isSelectable() const {
return !pcDragger && Selectable.getValue();
return Selectable.getValue();
}
void ViewProviderLink::attach(App::DocumentObject *pcObj) {
@@ -1851,7 +1851,7 @@ void ViewProviderLink::updateDataPrivate(App::LinkBaseExtension *ext, const App:
auto propLinkPlacement = ext->getLinkPlacementProperty();
if(!propLinkPlacement || propLinkPlacement == prop) {
const auto &pla = static_cast<const App::PropertyPlacement*>(prop)->getValue();
ViewProviderGeometryObject::updateTransform(pla, pcTransform);
// ViewProviderGeometryObject::updateTransform(pla, pcTransform);
const auto &v = ext->getScaleVector();
if(canScale(v))
pcTransform->scaleFactor.setValue(v.x,v.y,v.z);
@@ -2764,25 +2764,28 @@ ViewProvider *ViewProviderLink::startEditing(int mode) {
}
static thread_local bool _pendingTransform;
static thread_local Base::Matrix4D _editingTransform;
static thread_local Matrix4D _editingTransform;
auto doc = Application::Instance->editDocument();
if(mode==ViewProvider::Transform) {
if(_pendingTransform && doc)
if (mode == ViewProvider::Transform) {
if (_pendingTransform && doc) {
doc->setEditingTransform(_editingTransform);
}
if(!initDraggingPlacement())
if (!initDraggingPlacement()) {
return nullptr;
if(useCenterballDragger)
pcDragger = CoinPtr<SoCenterballDragger>(new SoCenterballDragger);
else
pcDragger = CoinPtr<SoFCCSysDragger>(new SoFCCSysDragger);
updateDraggingPlacement(dragCtx->initialPlacement,true);
pcDragger->addStartCallback(dragStartCallback, this);
pcDragger->addFinishCallback(dragFinishCallback, this);
pcDragger->addMotionCallback(dragMotionCallback, this);
return inherited::startEditing(mode);
}
if (auto result = inherited::startEditing(mode)) {
csysDragger->addStartCallback(dragStartCallback, this);
csysDragger->addFinishCallback(dragFinishCallback, this);
csysDragger->addMotionCallback(dragMotionCallback, this);
setDraggerPlacement(dragCtx->initialPlacement);
return result;
}
}
if(!linkEdit()) {
@@ -2839,6 +2842,7 @@ bool ViewProviderLink::setEdit(int ModNum)
Selection().clearSelection();
return true;
}
return inherited::setEdit(ModNum);
}
@@ -2849,125 +2853,21 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN
return;
}
if (pcDragger && viewer)
{
auto rootPickStyle = new SoPickStyle();
rootPickStyle->style = SoPickStyle::UNPICKABLE;
static_cast<SoFCUnifiedSelection*>(
viewer->getSceneGraph())->insertChild(rootPickStyle, 0);
if(useCenterballDragger) {
auto dragger = static_cast<SoCenterballDragger*>(pcDragger.get());
auto group = new SoAnnotation;
auto pickStyle = new SoPickStyle;
pickStyle->setOverride(true);
group->addChild(pickStyle);
group->addChild(pcDragger);
// Because the dragger is not grouped with the actual geometry,
// we use an invisible cube sized by the bounding box obtained from
// initDraggingPlacement() to scale the centerball dragger properly
auto * ss = static_cast<SoSurroundScale*>(dragger->getPart("surroundScale", TRUE));
ss->numNodesUpToContainer = 3;
ss->numNodesUpToReset = 2;
auto *geoGroup = new SoGroup;
group->addChild(geoGroup);
auto *style = new SoDrawStyle;
style->style.setValue(SoDrawStyle::INVISIBLE);
style->setOverride(TRUE);
geoGroup->addChild(style);
auto *cube = new SoCube;
geoGroup->addChild(cube);
auto length = std::max(std::max(dragCtx->bbox.LengthX(),
dragCtx->bbox.LengthY()), dragCtx->bbox.LengthZ());
cube->width = length;
cube->height = length;
cube->depth = length;
viewer->setupEditingRoot(group,&dragCtx->preTransform);
} else {
auto dragger = static_cast<SoFCCSysDragger*>(pcDragger.get());
dragger->draggerSize.setValue(ViewParams::instance()->getDraggerScale());
dragger->setUpAutoScale(viewer->getSoRenderManager()->getCamera());
viewer->setupEditingRoot(pcDragger,&dragCtx->preTransform);
auto task = new TaskCSysDragger(nullptr, dragger);
Gui::Control().showDialog(task);
}
}
ViewProviderDragger::setEditViewer(viewer, ModNum);
}
void ViewProviderLink::unsetEditViewer(Gui::View3DInventorViewer* viewer)
{
SoNode *child = static_cast<SoFCUnifiedSelection*>(viewer->getSceneGraph())->getChild(0);
if (child && child->isOfType(SoPickStyle::getClassTypeId()))
static_cast<SoFCUnifiedSelection*>(viewer->getSceneGraph())->removeChild(child);
pcDragger.reset();
dragCtx.reset();
Gui::Control().closeDialog();
inherited::unsetEditViewer(viewer);
}
Base::Placement ViewProviderLink::currentDraggingPlacement() const
{
// if there isn't an active dragger return a default placement
if (!pcDragger)
return Base::Placement();
SbVec3f v;
SbRotation r;
if (useCenterballDragger) {
auto dragger = static_cast<SoCenterballDragger*>(pcDragger.get());
v = dragger->center.getValue();
r = dragger->rotation.getValue();
}
else {
auto dragger = static_cast<SoFCCSysDragger*>(pcDragger.get());
v = dragger->translation.getValue();
r = dragger->rotation.getValue();
}
float q1,q2,q3,q4;
r.getValue(q1,q2,q3,q4);
return Base::Placement(Base::Vector3d(v[0],v[1],v[2]),Base::Rotation(q1,q2,q3,q4));
}
void ViewProviderLink::enableCenterballDragger(bool enable) {
if(enable == useCenterballDragger)
return;
if(pcDragger)
LINK_THROW(Base::RuntimeError,"Cannot change dragger during dragging");
useCenterballDragger = enable;
}
void ViewProviderLink::updateDraggingPlacement(const Base::Placement &pla, bool force) {
if(pcDragger && (force || currentDraggingPlacement()!=pla)) {
const auto &pos = pla.getPosition();
const auto &rot = pla.getRotation();
FC_LOG("updating dragger placement (" << pos.x << ", " << pos.y << ", " << pos.z << ')');
if(useCenterballDragger) {
auto dragger = static_cast<SoCenterballDragger*>(pcDragger.get());
SbBool wasenabled = dragger->enableValueChangedCallbacks(FALSE);
SbMatrix matrix;
matrix = convert(pla.toMatrix());
dragger->center.setValue(SbVec3f(0,0,0));
dragger->setMotionMatrix(matrix);
if (wasenabled) {
dragger->enableValueChangedCallbacks(TRUE);
dragger->valueChanged();
}
}else{
auto dragger = static_cast<SoFCCSysDragger*>(pcDragger.get());
dragger->translation.setValue(SbVec3f(pos.x,pos.y,pos.z));
dragger->rotation.setValue(rot[0],rot[1],rot[2],rot[3]);
}
}
}
bool ViewProviderLink::callDraggerProxy(const char *fname, bool update) {
if(!pcDragger)
bool ViewProviderLink::callDraggerProxy(const char* fname) {
if (!csysDragger) {
return false;
}
Base::PyGILStateLocker lock;
try {
auto* proxy = getPropertyByName("Proxy");
@@ -2986,48 +2886,32 @@ bool ViewProviderLink::callDraggerProxy(const char *fname, bool update) {
return true;
}
if(update) {
auto ext = getLinkExtension();
if(ext) {
const auto &pla = currentDraggingPlacement();
auto prop = ext->getLinkPlacementProperty();
if(!prop)
prop = ext->getPlacementProperty();
if(prop) {
auto plaNew = pla * Base::Placement(dragCtx->mat);
if(prop->getValue()!=plaNew)
prop->setValue(plaNew);
}
updateDraggingPlacement(pla);
}
}
return false;
}
void ViewProviderLink::dragStartCallback(void *data, SoDragger *) {
auto me = static_cast<ViewProviderLink*>(data);
me->dragCtx->initialPlacement = me->currentDraggingPlacement();
if(!me->callDraggerProxy("onDragStart",false)) {
me->dragCtx->cmdPending = true;
me->getDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Link Transform"));
}else
me->dragCtx->cmdPending = false;
me->dragCtx->initialPlacement = me->getDraggerPlacement();
me->callDraggerProxy("onDragStart");
}
void ViewProviderLink::dragFinishCallback(void *data, SoDragger *) {
auto me = static_cast<ViewProviderLink*>(data);
me->callDraggerProxy("onDragEnd",true);
if(me->dragCtx->cmdPending) {
if(me->currentDraggingPlacement() == me->dragCtx->initialPlacement)
me->callDraggerProxy("onDragEnd");
if (me->dragCtx->cmdPending) {
if (me->getDraggerPlacement() == me->dragCtx->initialPlacement) {
me->getDocument()->abortCommand();
else
} else {
me->getDocument()->commitCommand();
}
}
}
void ViewProviderLink::dragMotionCallback(void *data, SoDragger *) {
auto me = static_cast<ViewProviderLink*>(data);
me->callDraggerProxy("onDragMotion",true);
me->callDraggerProxy("onDragMotion");
}
void ViewProviderLink::updateLinks(ViewProvider *vp) {

View File

@@ -184,10 +184,10 @@ protected:
Py::Object PythonObject;
};
class GuiExport ViewProviderLink : public ViewProviderDocumentObject
class GuiExport ViewProviderLink : public ViewProviderDragger
{
PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderLink);
using inherited = ViewProviderDocumentObject;
using inherited = ViewProviderDragger;
public:
App::PropertyBool OverrideMaterial;
@@ -248,11 +248,6 @@ public:
static void updateLinks(ViewProvider *vp);
void updateDraggingPlacement(const Base::Placement &pla, bool force=false);
Base::Placement currentDraggingPlacement() const;
void enableCenterballDragger(bool enable);
bool isUsingCenterballDragger() const { return useCenterballDragger; }
std::map<std::string, App::Color> getElementColors(const char *subname=nullptr) const override;
void setElementColors(const std::map<std::string, App::Color> &colors) override;
@@ -311,7 +306,7 @@ protected:
ViewProvider *getLinkedView(bool real,const App::LinkBaseExtension *ext=nullptr) const;
bool initDraggingPlacement();
bool callDraggerProxy(const char *fname, bool update);
bool callDraggerProxy(const char* fname);
private:
static void dragStartCallback(void * data, SoDragger * d);
@@ -323,7 +318,6 @@ protected:
LinkType linkType;
bool hasSubName;
bool hasSubElement;
bool useCenterballDragger;
struct DraggerContext{
Base::Matrix4D preTransform;
@@ -333,7 +327,6 @@ protected:
bool cmdPending;
};
std::unique_ptr<DraggerContext> dragCtx;
CoinPtr<SoDragger> pcDragger;
ViewProviderDocumentObject *childVp;
LinkInfoPtr childVpLink;
mutable qint64 overlayCacheKey;

View File

@@ -19,12 +19,6 @@
</Documentation>
<Parameter Name="DraggingPlacement" Type="Object" />
</Attribute>
<Attribute Name="UseCenterballDragger">
<Documentation>
<UserDocu>Get/set dragger type</UserDocu>
</Documentation>
<Parameter Name="UseCenterballDragger" Type="Boolean" />
</Attribute>
<Attribute Name="LinkView" ReadOnly="true">
<Documentation>
<UserDocu>Get the associated LinkView object</UserDocu>

View File

@@ -46,29 +46,16 @@ std::string ViewProviderLinkPy::representation() const
Py::Object ViewProviderLinkPy::getDraggingPlacement() const {
return Py::asObject(new Base::PlacementPy(new Base::Placement(
getViewProviderLinkPtr()->currentDraggingPlacement())));
getViewProviderLinkPtr()->getDraggerPlacement())));
}
void ViewProviderLinkPy::setDraggingPlacement(Py::Object arg) {
if(!PyObject_TypeCheck(arg.ptr(),&Base::PlacementPy::Type))
throw Py::TypeError("expects a placement");
getViewProviderLinkPtr()->updateDraggingPlacement(
getViewProviderLinkPtr()->setDraggerPlacement(
*static_cast<Base::PlacementPy*>(arg.ptr())->getPlacementPtr());
}
Py::Boolean ViewProviderLinkPy::getUseCenterballDragger() const {
return {getViewProviderLinkPtr()->isUsingCenterballDragger()};
}
void ViewProviderLinkPy::setUseCenterballDragger(Py::Boolean arg) {
try {
getViewProviderLinkPtr()->enableCenterballDragger(arg);
}catch(const Base::Exception &e){
e.setPyException();
throw Py::Exception();
}
}
Py::Object ViewProviderLinkPy::getLinkView() const {
return Py::Object(getViewProviderLinkPtr()->getPyLinkView(),true);
}

View File

@@ -1901,6 +1901,11 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
case mmMidpoint: {
Base::Placement placement;
// special case for planes
if (auto plane = dynamic_cast<App::Plane*>(objs[0])) {
return plane->Placement.getValue() * attachmentOffset;
}
auto shape = shapes.front();
auto geom = Geometry::fromShape(shape->getShape());
@@ -1929,7 +1934,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
line->tangent(middle, direction);
}
placement.setRotation(Base::Rotation::fromNormalVector(-direction));
placement.setRotation(Base::Rotation::fromNormalVector(direction));
}
}
break;
@@ -1941,8 +1946,10 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
placement.setPosition(sphere->getLocation());
} else if (auto cone = dynamic_cast<GeomCone*>(geom.get())) {
placement.setPosition(cone->getApex());
} else if (auto com = shape->centerOfGravity()) {
placement.setPosition(*com);
} else {
placement.setPosition(shape->centerOfGravity().value());
placement.setPosition(shape->getBoundBox().GetCenter());
}
if (auto rotation = surface->getRotation()) {

View File

@@ -33,7 +33,10 @@ Base::Placement AttacherSubObjectPlacement::calculate(App::SubObjectT object,
Base::Placement basePlacement) const
{
attacher->setReferences({object});
return basePlacement.inverse() * attacher->calculateAttachedPlacement(basePlacement);
auto calculatedAttachment = attacher->calculateAttachedPlacement(basePlacement);
return basePlacement.inverse() * calculatedAttachment;
}
std::optional<Base::Vector3d> PartCenterOfMass::ofDocumentObject(App::DocumentObject* object) const