Assembly: Enable moving objects while making joints.

This commit is contained in:
PaddleStroke
2024-06-26 15:25:41 +02:00
parent 40feca037c
commit a0c4a273ba
7 changed files with 113 additions and 48 deletions

View File

@@ -528,7 +528,7 @@ std::vector<App::DocumentObject*> AssemblyObject::getJoints(bool updateJCS, bool
// add sub assemblies joints.
for (auto& assembly : getSubAssemblies()) {
auto subJoints = assembly->getJoints(updateJCS);
auto subJoints = assembly->getJoints(updateJCS, delBadJoints);
joints.insert(joints.end(), subJoints.begin(), subJoints.end());
}

View File

@@ -184,7 +184,7 @@ public:
void jointParts(std::vector<App::DocumentObject*> joints);
JointGroup* getJointGroup();
ViewGroup* getExplodedViewGroup();
std::vector<App::DocumentObject*> getJoints(bool updateJCS = true, bool delBadJoints = true);
std::vector<App::DocumentObject*> getJoints(bool updateJCS = true, bool delBadJoints = false);
std::vector<App::DocumentObject*> getGroundedJoints();
std::vector<App::DocumentObject*> getJointsOfObj(App::DocumentObject* obj);
std::vector<App::DocumentObject*> getJointsOfPart(App::DocumentObject* part);

View File

@@ -92,6 +92,8 @@ ViewProviderAssembly::ViewProviderAssembly()
, canStartDragging(false)
, partMoving(false)
, enableMovement(true)
, moveOnlyPreselected(false)
, moveInCommand(true)
, jointVisibilityBackup(false)
, ctrlPressed(false)
, docsToMove({})
@@ -139,7 +141,6 @@ bool ViewProviderAssembly::canDragObject(App::DocumentObject* obj) const
// else if a solid is removed, remove associated joints if any.
bool prompted = false;
auto* assemblyPart = static_cast<AssemblyObject*>(getObject());
std::vector<App::DocumentObject*> joints = assemblyPart->getJoints();
// Combine the joints and groundedJoints vectors into one for simplicity.
std::vector<App::DocumentObject*> allJoints = assemblyPart->getJoints();
@@ -505,30 +506,33 @@ bool ViewProviderAssembly::getSelectedObjectsWithinAssembly(bool addPreselection
return false;
}
for (auto& selObj : Gui::Selection().getSelectionEx("",
App::DocumentObject::getClassTypeId(),
Gui::ResolveMode::NoResolve)) {
// getSubNames() returns ["Body001.Pad.Face14", "Body002.Pad.Face7"]
// if you have several objects within the same assembly selected.
if (!moveOnlyPreselected) {
for (auto& selObj : Gui::Selection().getSelectionEx("",
App::DocumentObject::getClassTypeId(),
Gui::ResolveMode::NoResolve)) {
// getSubNames() returns ["Body001.Pad.Face14", "Body002.Pad.Face7"]
// if you have several objects within the same assembly selected.
std::vector<std::string> objsSubNames = selObj.getSubNames();
for (auto& subNamesStr : objsSubNames) {
std::vector<std::string> subNames = parseSubNames(subNamesStr);
if (subNames.empty()) {
continue;
std::vector<std::string> objsSubNames = selObj.getSubNames();
for (auto& subNamesStr : objsSubNames) {
std::vector<std::string> subNames = parseSubNames(subNamesStr);
if (subNames.empty()) {
continue;
}
if (onlySolids && subNames.back() != "") {
continue;
}
App::DocumentObject* obj = getObjectFromSubNames(subNames);
if (!canDragObjectIn3d(obj)) {
continue;
}
auto* pPlc =
dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName("Placement"));
docsToMove.emplace_back(obj, pPlc->getValue());
}
if (onlySolids && subNames.back() != "") {
continue;
}
App::DocumentObject* obj = getObjectFromSubNames(subNames);
if (!canDragObjectIn3d(obj)) {
continue;
}
auto* pPlc = dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName("Placement"));
docsToMove.emplace_back(obj, pPlc->getValue());
}
}
@@ -557,7 +561,7 @@ bool ViewProviderAssembly::getSelectedObjectsWithinAssembly(bool addPreselection
if (!alreadyIn) {
auto* pPlc =
dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName("Placement"));
if (!ctrlPressed) {
if (!ctrlPressed && !moveOnlyPreselected) {
Gui::Selection().clearSelection();
docsToMove.clear();
}
@@ -772,8 +776,9 @@ void ViewProviderAssembly::initMove(const SbVec2s& cursorPos, Gui::View3DInvento
prevPosition = initialPosition;
}
Gui::Command::openCommand(tr("Move part").toStdString().c_str());
if (moveInCommand) {
Gui::Command::openCommand(tr("Move part").toStdString().c_str());
}
partMoving = true;
// prevent selection while moving
@@ -825,7 +830,9 @@ void ViewProviderAssembly::endMove()
assemblyPart->setObjMasses({});
}
Gui::Command::commitCommand();
if (moveInCommand) {
Gui::Command::commitCommand();
}
}
void ViewProviderAssembly::initMoveDragger()

View File

@@ -114,6 +114,22 @@ public:
{
return enableMovement;
}
virtual void setMoveOnlyPreselected(bool enable = true)
{
moveOnlyPreselected = enable;
}
virtual bool getMoveOnlyPreselected() const
{
return moveOnlyPreselected;
}
virtual void setMoveInCommand(bool enable = true)
{
moveInCommand = enable;
}
virtual bool getMoveInCommand() const
{
return moveInCommand;
}
bool canDragObjectIn3d(App::DocumentObject* obj) const;
@@ -150,6 +166,8 @@ public:
bool canStartDragging;
bool partMoving;
bool enableMovement;
bool moveOnlyPreselected;
bool moveInCommand;
bool jointVisibilityBackup;
bool ctrlPressed;
int numberOfSel;

View File

@@ -31,6 +31,18 @@
</Documentation>
<Parameter Name="EnableMoving" Type="Boolean" />
</Attribute>
<Attribute Name="MoveOnlyPreselected">
<Documentation>
<UserDocu>If enabled, only the preselected object will move.</UserDocu>
</Documentation>
<Parameter Name="MoveOnlyPreselected" Type="Boolean" />
</Attribute>
<Attribute Name="MoveInCommand">
<Documentation>
<UserDocu>If enabled, each move will be wrapped in a command.</UserDocu>
</Documentation>
<Parameter Name="MoveInCommand" Type="Boolean" />
</Attribute>
<Attribute Name="DraggerVisibility">
<Documentation>
<UserDocu>Show or hide the assembly dragger.</UserDocu>

View File

@@ -52,6 +52,26 @@ void ViewProviderAssemblyPy::setEnableMovement(Py::Boolean arg)
getViewProviderAssemblyPtr()->setEnableMovement(arg);
}
Py::Boolean ViewProviderAssemblyPy::getMoveOnlyPreselected() const
{
return {getViewProviderAssemblyPtr()->getMoveOnlyPreselected()};
}
void ViewProviderAssemblyPy::setMoveOnlyPreselected(Py::Boolean arg)
{
getViewProviderAssemblyPtr()->setMoveOnlyPreselected(arg);
}
Py::Boolean ViewProviderAssemblyPy::getMoveInCommand() const
{
return {getViewProviderAssemblyPtr()->getMoveInCommand()};
}
void ViewProviderAssemblyPy::setMoveInCommand(Py::Boolean arg)
{
getViewProviderAssemblyPtr()->setMoveInCommand(arg);
}
Py::Boolean ViewProviderAssemblyPy::getDraggerVisibility() const
{
return {getViewProviderAssemblyPtr()->getDraggerVisibility()};

View File

@@ -1223,14 +1223,6 @@ class MakeJointSelGate:
# Only objects within the assembly.
return False
if Gui.Selection.isSelected(obj, sub, Gui.Selection.ResolveMode.NoResolve):
# If it's to deselect then it's ok
return True
if len(self.taskbox.current_selection) >= 2:
# No more than 2 elements can be selected for basic joints.
return False
full_obj_name = ".".join(objs_names)
full_element_name = full_obj_name + "." + element_name
selected_object = UtilsAssembly.getObject(full_element_name)
@@ -1247,15 +1239,6 @@ class MakeJointSelGate:
else:
return False
part_containing_selected_object = UtilsAssembly.getContainingPart(
full_element_name, selected_object, self.assembly
)
for selection_dict in self.taskbox.current_selection:
if selection_dict["part"] == part_containing_selected_object:
# Can't join a solid to itself. So the user need to select 2 different parts.
return False
return True
@@ -1285,7 +1268,8 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
return
if self.activeType == "Assembly":
self.assembly.ViewObject.EnableMovement = False
self.assembly.ViewObject.MoveOnlyPreselected = True
self.assembly.ViewObject.MoveInCommand = False
self.form = Gui.PySideUic.loadUi(":/panels/TaskAssemblyCreateJoint.ui")
@@ -1358,6 +1342,8 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
self.form.featureList.installEventFilter(self)
self.addition_rejected = False
def accept(self):
if len(self.current_selection) != 2:
App.Console.PrintWarning(
@@ -1389,7 +1375,8 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
if self.activeType == "Assembly":
self.assembly.clearUndo()
self.assembly.ViewObject.EnableMovement = True
self.assembly.ViewObject.MoveOnlyPreselected = False
self.assembly.ViewObject.MoveInCommand = True
Gui.Selection.removeSelectionGate()
Gui.Selection.removeObserver(self)
@@ -1831,6 +1818,23 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
element_name = UtilsAssembly.getElementName(full_element_name)
part_containing_selected_object = self.getContainingPart(full_element_name, selected_object)
# Check if the addition is acceptable (we are not doing this in selection gate to let user move objects)
acceptable = True
if len(self.current_selection) >= 2:
# No more than 2 elements can be selected for basic joints.
acceptable = False
for selection_dict in self.current_selection:
if selection_dict["part"] == part_containing_selected_object:
# Can't join a solid to itself. So the user need to select 2 different parts.
acceptable = False
if not acceptable:
self.addition_rejected = True
Gui.Selection.removeSelection(doc_name, obj_name, sub_name)
return
# Selection is acceptable so add it
selection_dict = {
"object": selected_object,
"part": part_containing_selected_object,
@@ -1851,6 +1855,10 @@ class TaskAssemblyCreateJoint(QtCore.QObject):
self.joint.ViewObject.Proxy.showPreviewJCS(False)
def removeSelection(self, doc_name, obj_name, sub_name, mousePos=None):
if self.addition_rejected:
self.addition_rejected = False
return
full_element_name = UtilsAssembly.getFullElementName(obj_name, sub_name)
selected_object = UtilsAssembly.getObject(full_element_name)
element_name = UtilsAssembly.getElementName(full_element_name)