Gui: Make ViewProviderLink based on ViewProviderDragger
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public:
|
||||
void updatePlacementFromDragger();
|
||||
void updateTransformFromDragger();
|
||||
|
||||
Base::Placement getObjectPlacement() const;
|
||||
Base::Placement getDraggerPlacement() const;
|
||||
void setDraggerPlacement(const Base::Placement& placement);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user