Gui: Fix transform of link sub-elements
This commit is contained in:
committed by
Chris Hennes
parent
29c18019ae
commit
707ee60d64
@@ -21,6 +21,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
@@ -29,10 +30,11 @@
|
||||
#include <Inventor/nodes/SoTransform.h>
|
||||
|
||||
#include <App/GeoFeature.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Placement.h>
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Base/Converter.h>
|
||||
#include "Gui/ViewParams.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
@@ -41,16 +43,15 @@
|
||||
#include "Inventor/Draggers/SoTransformDragger.h"
|
||||
#include "Inventor/Draggers/Gizmo.h"
|
||||
#include "Inventor/SoFCPlacementIndicatorKit.h"
|
||||
#include "Inventor/So3DAnnotation.h"
|
||||
#include "SoFCUnifiedSelection.h"
|
||||
#include "TaskTransform.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "ViewProviderDragger.h"
|
||||
#include "Utilities.h"
|
||||
#include "ViewParams.h"
|
||||
#include "ViewProviderLink.h"
|
||||
|
||||
#include <ViewProviderLink.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Inventor/So3DAnnotation.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
@@ -144,35 +145,50 @@ ViewProvider* ViewProviderDragger::startEditing(int mode)
|
||||
|
||||
bool ViewProviderDragger::forwardToLink()
|
||||
{
|
||||
// Trying to detect if the editing request is forwarded by a link object,
|
||||
// usually by doubleClicked(). If so, we route the request back. There shall
|
||||
// be no risk of infinite recursion, as ViewProviderLink handles
|
||||
// ViewProvider::Transform request by itself.
|
||||
ViewProviderDocumentObject* vpParent = nullptr;
|
||||
std::string subname;
|
||||
// typically we want to transform the selected object, but if the selected object is in the link,
|
||||
// we want to transform the link instead.
|
||||
//
|
||||
// To achieve that, we use the sub object path and look for the first link in the chain, and
|
||||
// we forward the request there.
|
||||
const auto findFirstLinkViewProvider = [this]() -> ViewProvider* {
|
||||
ViewProviderDocumentObject* vpParent = nullptr;
|
||||
std::string subname;
|
||||
|
||||
auto doc = Application::Instance->editDocument();
|
||||
if (!doc) {
|
||||
return false;
|
||||
auto doc = Application::Instance->editDocument();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
doc->getInEdit(&vpParent, &subname);
|
||||
if (!vpParent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto subObjects = vpParent->getObject()->getSubObjectList(subname.c_str());
|
||||
const auto subObject : std::views::reverse(subObjects)) {
|
||||
|
||||
// we don't want to try to edit objects in other documents
|
||||
if (subObject->getDocument() != getObject()->getDocument()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (auto subObjectViewProvider = Application::Instance->getViewProvider(subObject);
|
||||
subObjectViewProvider && subObjectViewProvider->isDerivedFrom<ViewProviderLink>()) {
|
||||
return subObjectViewProvider;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (ViewProvider* subObjectViewProvider = findFirstLinkViewProvider();
|
||||
subObjectViewProvider && subObjectViewProvider != this) {
|
||||
forwardedViewProvider = subObjectViewProvider->startEditing(Transform);
|
||||
}
|
||||
|
||||
doc->getInEdit(&vpParent, &subname);
|
||||
if (!vpParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vpParent == this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vpParent->isDerivedFrom<ViewProviderLink>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
forwardedViewProvider = vpParent->startEditing(ViewProvider::Transform);
|
||||
|
||||
return forwardedViewProvider != nullptr;
|
||||
}
|
||||
|
||||
App::PropertyPlacement* ViewProviderDragger::getPlacementProperty() const
|
||||
{
|
||||
auto object = getObject();
|
||||
@@ -200,8 +216,8 @@ bool ViewProviderDragger::setEdit(int ModNum)
|
||||
|
||||
transformDragger = new SoTransformDragger();
|
||||
transformDragger->setAxisColors(Gui::ViewParams::instance()->getAxisXColor(),
|
||||
Gui::ViewParams::instance()->getAxisYColor(),
|
||||
Gui::ViewParams::instance()->getAxisZColor());
|
||||
Gui::ViewParams::instance()->getAxisYColor(),
|
||||
Gui::ViewParams::instance()->getAxisZColor());
|
||||
transformDragger->draggerSize.setValue(ViewParams::instance()->getDraggerScale());
|
||||
|
||||
transformDragger->addStartCallback(dragStartCallback, this);
|
||||
|
||||
@@ -2715,10 +2715,7 @@ bool ViewProviderLink::initDraggingPlacement() {
|
||||
dragCtx = std::make_unique<DraggerContext>();
|
||||
|
||||
dragCtx->preTransform = doc->getEditingTransform();
|
||||
doc->setEditingTransform(dragCtx->preTransform);
|
||||
|
||||
const auto &pla = ext->getPlacementProperty()?
|
||||
ext->getPlacementValue():ext->getLinkPlacementValue();
|
||||
const auto &pla = getPlacementProperty()->getValue();
|
||||
|
||||
// Cancel out our own transformation from the editing transform, because
|
||||
// the dragger is meant to change our transformation.
|
||||
@@ -2732,38 +2729,16 @@ bool ViewProviderLink::initDraggingPlacement() {
|
||||
dragCtx->bbox.ScaleY(scale.y);
|
||||
dragCtx->bbox.ScaleZ(scale.z);
|
||||
|
||||
auto modifier = QApplication::queryKeyboardModifiers();
|
||||
// Determine the dragger base position
|
||||
// if CTRL key is down, force to use bound box center,
|
||||
// if SHIFT key is down, force to use origine,
|
||||
// if not a sub link, use origine,
|
||||
// else (e.g. group, array, sub link), use bound box center
|
||||
if(modifier != Qt::ShiftModifier
|
||||
&& ((ext->getLinkedObjectValue() && !linkView->hasSubs())
|
||||
|| modifier == Qt::ControlModifier))
|
||||
{
|
||||
App::PropertyPlacement *propPla = nullptr;
|
||||
if(ext->getLinkTransformValue() && ext->getLinkedObjectValue()) {
|
||||
propPla = freecad_cast<App::PropertyPlacement*>(
|
||||
ext->getLinkedObjectValue()->getPropertyByName("Placement"));
|
||||
}
|
||||
if(propPla) {
|
||||
dragCtx->initialPlacement = pla * propPla->getValue();
|
||||
dragCtx->mat *= propPla->getValue().inverse().toMatrix();
|
||||
} else
|
||||
dragCtx->initialPlacement = pla;
|
||||
|
||||
App::PropertyPlacement *propPla = nullptr;
|
||||
if(ext->getLinkTransformValue() && ext->getLinkedObjectValue()) {
|
||||
propPla = freecad_cast<App::PropertyPlacement*>(
|
||||
ext->getLinkedObjectValue()->getPropertyByName("Placement"));
|
||||
}
|
||||
if(propPla) {
|
||||
dragCtx->initialPlacement = pla * propPla->getValue();
|
||||
dragCtx->mat *= propPla->getValue().inverse().toMatrix();
|
||||
} else {
|
||||
auto offset = dragCtx->bbox.GetCenter();
|
||||
|
||||
// This determines 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->initialPlacement = pla;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2872,6 +2847,8 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN
|
||||
}
|
||||
|
||||
ViewProviderDragger::setEditViewer(viewer, ModNum);
|
||||
|
||||
viewer->setupEditingRoot(transformDragger, &dragCtx->preTransform);
|
||||
}
|
||||
|
||||
void ViewProviderLink::unsetEditViewer(Gui::View3DInventorViewer* viewer)
|
||||
|
||||
Reference in New Issue
Block a user