PartDesign: Add transparent previews

This commit is contained in:
Kacper Donat
2024-10-13 13:33:18 +02:00
parent 38db306a84
commit 7f87d87f61
58 changed files with 1438 additions and 1021 deletions

View File

@@ -44,6 +44,8 @@
#include "Body.h"
#include "ShapeBinder.h"
#include <BRep_Builder.hxx>
FC_LOG_LEVEL_INIT("PartDesign", true, true)
@@ -70,6 +72,7 @@ Feature::Feature()
BaseFeature.setStatus(App::Property::Hidden, true);
App::SuppressibleExtension::initExtension(this);
Part::PreviewExtension::initExtension(this);
}
App::DocumentObjectExecReturn* Feature::recompute()
@@ -103,9 +106,17 @@ App::DocumentObjectExecReturn* Feature::recompute()
if (!failed) {
updateSuppressedShape();
}
return App::DocumentObject::StdReturn;
}
App::DocumentObjectExecReturn* Feature::recomputePreview()
{
updatePreviewShape();
return StdReturn;
}
void Feature::setMaterialToBodyMaterial()
{
auto body = getFeatureBody();
@@ -172,7 +183,8 @@ void Feature::onChanged(const App::Property *prop)
{
if (!this->isRestoring()
&& this->getDocument()
&& !this->getDocument()->isPerformingTransaction()) {
&& !this->getDocument()->isPerformingTransaction()
) {
if (prop == &Visibility || prop == &BaseFeature) {
auto body = Body::findBodyOf(this);
if (body) {
@@ -343,6 +355,51 @@ Part::TopoShape Feature::getBaseTopoShape(bool silent) const
return result;
}
void Feature::getGeneratedShapes(std::vector<int>& faces,
std::vector<int>& edges,
std::vector<int>& vertices) const
{
static const auto addAllSubShapesToSet = [](
const Part::TopoShape& shape,
const Part::TopoShape& face,
TopAbs_ShapeEnum type,
std::set<int>& set
) {
for (auto &subShape : face.getSubShapes(type)) {
if (int subShapeId = shape.findShape(subShape); subShapeId > 0) {
set.insert(subShapeId);
}
}
};
Part::TopoShape shape = Shape.getShape();
std::set<int> edgeSet;
std::set<int> vertexSet;
int count = shape.countSubShapes(TopAbs_FACE);
for (int faceId = 1; faceId <= count; ++faceId) {
if (Data::MappedName mapped = shape.getMappedName(Data::IndexedName::fromConst("Face", faceId));
shape.isElementGenerated(mapped)) {
faces.push_back(faceId);
Part::TopoShape face = shape.getSubTopoShape(TopAbs_FACE, faceId);
addAllSubShapesToSet(shape, face, TopAbs_EDGE, edgeSet);
addAllSubShapesToSet(shape, face, TopAbs_VERTEX, vertexSet);
}
}
std::ranges::copy(edgeSet, std::back_inserter(edges));
std::ranges::copy(vertexSet, std::back_inserter(vertices));
}
void Feature::updatePreviewShape()
{
// no-op
}
PyObject* Feature::getPyObject()
{
if (PythonObject.is(Py::_None())){

View File

@@ -27,6 +27,7 @@
#include <App/PropertyStandard.h>
#include <App/SuppressibleExtension.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/PreviewExtension.h>
#include <Mod/PartDesign/PartDesignGlobal.h>
class gp_Pnt;
@@ -45,7 +46,7 @@ class Body;
* Base class of all PartDesign features.
* This kind of features only produce solids or fail.
*/
class PartDesignExport Feature : public Part::Feature, public App::SuppressibleExtension
class PartDesignExport Feature : public Part::Feature, public App::SuppressibleExtension, public Part::PreviewExtension
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::Feature);
@@ -62,7 +63,9 @@ public:
Part::PropertyPartShape SuppressedShape;
/// Keep a copy of the placement before suppression to restore it back when unsuppressed, fix #20205
Base::Placement SuppressedPlacement;
App::DocumentObjectExecReturn* recompute() override;
App::DocumentObjectExecReturn* recomputePreview() override;
short mustExecute() const override;
@@ -84,6 +87,13 @@ public:
/// Returns the BaseFeature property's TopoShape (if any)
Part::TopoShape getBaseTopoShape(bool silent=false) const;
// Fills up information about which sub-shapes were generated by the feature
virtual void getGeneratedShapes(std::vector<int>& faces,
std::vector<int>& edges,
std::vector<int>& vertices) const;
virtual void updatePreviewShape();
PyObject* getPyObject() override;
const char* getViewProviderName() const override {

View File

@@ -28,10 +28,13 @@
#include <App/FeaturePythonPyImp.h>
#include <Mod/Part/App/modelRefine.h>
#include <Mod/Part/App/TopoShapeOpCode.h>
#include "FeatureAddSub.h"
#include "FeaturePy.h"
#include <Mod/Part/App/Tools.h>
using namespace PartDesign;
@@ -43,7 +46,12 @@ PROPERTY_SOURCE(PartDesign::FeatureAddSub, PartDesign::FeatureRefine)
FeatureAddSub::FeatureAddSub()
{
ADD_PROPERTY(AddSubShape,(TopoDS_Shape()));
ADD_PROPERTY(AddSubShape, (TopoDS_Shape()));
}
void FeatureAddSub::onChanged(const App::Property* property)
{
Feature::onChanged(property);
}
FeatureAddSub::Type FeatureAddSub::getAddSubType()
@@ -58,16 +66,53 @@ short FeatureAddSub::mustExecute() const
return PartDesign::Feature::mustExecute();
}
void FeatureAddSub::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShape)
void FeatureAddSub::getAddSubShape(Part::TopoShape& addShape, Part::TopoShape& subShape)
{
if (addSubType == Additive)
if (addSubType == Additive) {
addShape = AddSubShape.getShape();
else if (addSubType == Subtractive)
}
else if (addSubType == Subtractive) {
subShape = AddSubShape.getShape();
}
}
void FeatureAddSub::updatePreviewShape()
{
const auto notifyWarning = [](const QString& message) {
Base::Console().translatedUserWarning(
"Preview",
tr("Failure while computing removed volume preview: %1")
.arg(message)
.toUtf8());
};
// for subtractive shapes we want to also showcase removed volume, not only the tool
if (addSubType == Subtractive) {
TopoShape base = getBaseTopoShape(true).moved(getLocation().Inverted());
if (const TopoShape& addSubShape = AddSubShape.getShape(); !addSubShape.isEmpty()) {
try {
base.makeElementBoolean(Part::OpCodes::Common, { base, addSubShape });
} catch (Standard_Failure& e) {
notifyWarning(QString::fromUtf8(e.GetMessageString()));
} catch (Base::Exception& e) {
notifyWarning(QString::fromStdString(e.getMessage()));
}
if (base.isEmpty()) {
notifyWarning(tr("Resulting shape is empty. That may indicate that no material will be removed or a problem with the model."));
}
PreviewShape.setValue(base);
return;
}
}
PreviewShape.setValue(AddSubShape.getShape());
}
} // namespace PartDesign
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(PartDesign::FeatureAddSubPython, PartDesign::FeatureAddSub)

View File

@@ -26,12 +26,15 @@
#include "FeatureRefine.h"
#include <QtCore>
/// Base class of all additive features in PartDesign
namespace PartDesign
{
class PartDesignExport FeatureAddSub : public PartDesign::FeatureRefine
{
Q_DECLARE_TR_FUNCTIONS(PartDesign::FeatureAddSub)
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::FeatureAddSub);
public:
@@ -42,12 +45,15 @@ public:
FeatureAddSub();
void onChanged(const App::Property *) override;
Type getAddSubType();
short mustExecute() const override;
virtual void getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShape);
void updatePreviewShape() override;
Part::PropertyPartShape AddSubShape;

View File

@@ -293,53 +293,62 @@ void DressUp::onChanged(const App::Property* prop)
Feature::onChanged(prop);
}
void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShape)
void DressUp::getAddSubShape(Part::TopoShape& addShape, Part::TopoShape& subShape)
{
Part::TopoShape res = AddSubShape.getShape();
if(res.isNull()) {
if (res.isNull()) {
try {
std::vector<Part::TopoShape> shapes;
Part::TopoShape shape = Shape.getShape();
shape.setPlacement(Base::Placement());
FeatureAddSub *base = nullptr;
if(SupportTransform.getValue()) {
FeatureAddSub* base = nullptr;
if (SupportTransform.getValue()) {
// SupportTransform means transform the support together with
// the dressing. So we need to find the previous support
// feature (which must be of type FeatureAddSub), and skipping
// any consecutive DressUp in-between.
for(Feature *current=this; ;current=static_cast<DressUp*>(base)) {
for (Feature* current = this;; current = static_cast<DressUp*>(base)) {
base = freecad_cast<FeatureAddSub*>(current->getBaseObject(true));
if(!base)
if (!base) {
FC_THROWM(Base::CADKernelError,
"Cannot find additive or subtractive support for " << getFullName());
if(!base->isDerivedFrom<DressUp>())
"Cannot find additive or subtractive support for "
<< getFullName());
}
if (!base->isDerivedFrom<DressUp>()) {
break;
}
}
}
Part::TopoShape baseShape;
if(base) {
if (base) {
baseShape = base->getBaseTopoShape(true);
baseShape.move(base->getLocation().Inverted());
if (base->getAddSubType() == Additive) {
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
if (!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID)) {
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
else
}
else {
shapes.push_back(shape);
} else {
}
}
else {
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
// push an empty compound to indicate null additive shape
shapes.emplace_back(comp);
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
if (!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID)) {
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
else
}
else {
shapes.push_back(shape);
}
}
} else {
}
else {
baseShape = getBaseTopoShape();
baseShape.move(getLocation().Inverted());
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
@@ -350,34 +359,73 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
// bceause a dressing (e.g. a fillet) can either be additive or
// subtractive. And the dressup feature can contain mixture of both.
AddSubShape.setValue(Part::TopoShape().makeElementCompound(shapes));
} catch (Standard_Failure &e) {
FC_THROWM(Base::CADKernelError, "Failed to calculate AddSub shape: "
<< e.GetMessageString());
}
catch (Standard_Failure& e) {
FC_THROWM(Base::CADKernelError,
"Failed to calculate AddSub shape: " << e.GetMessageString());
}
res = AddSubShape.getShape();
}
if(res.isNull())
if (res.isNull()) {
throw Part::NullShapeException("Null AddSub shape");
}
if(res.getShape().ShapeType() != TopAbs_COMPOUND) {
if (res.getShape().ShapeType() != TopAbs_COMPOUND) {
addShape = res;
} else {
}
else {
int count = res.countSubShapes(TopAbs_SHAPE);
if(!count)
if (!count) {
throw Part::NullShapeException("Null AddSub shape");
if(count) {
Part::TopoShape s = res.getSubTopoShape(TopAbs_SHAPE, 1);
if(!s.isNull() && s.hasSubShape(TopAbs_SOLID))
addShape = s;
}
if(count > 1) {
if (count) {
Part::TopoShape s = res.getSubTopoShape(TopAbs_SHAPE, 1);
if (!s.isNull() && s.hasSubShape(TopAbs_SOLID)) {
addShape = s;
}
}
if (count > 1) {
Part::TopoShape s = res.getSubTopoShape(TopAbs_SHAPE, 2);
if(!s.isNull() && s.hasSubShape(TopAbs_SOLID))
if (!s.isNull() && s.hasSubShape(TopAbs_SOLID)) {
subShape = s;
}
}
}
}
void DressUp::updatePreviewShape()
{
auto shape = Shape.getShape();
auto baseFeature = freecad_cast<Feature*>(BaseFeature.getValue());
if (!baseFeature || baseFeature->Shape.getShape().isNull()) {
PreviewShape.setValue(Shape.getShape());
return;
}
std::vector<int> faces, edges, vertices;
getGeneratedShapes(faces, edges, vertices);
if (faces.empty()) {
PreviewShape.setValue(TopoDS_Shape());
return;
}
shape.setPlacement(Base::Placement());
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for (int faceId : faces) {
builder.Add(comp, shape.getSubShape(TopAbs_FACE, faceId));
}
Part::TopoShape preview(comp);
preview.mapSubElement(shape);
PreviewShape.setValue(preview);
}
} // namespace PartDesign

View File

@@ -65,6 +65,7 @@ public:
std::vector<TopoShape> getFaces(const TopoShape &shape);
void getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShape) override;
void updatePreviewShape() override;
protected:
void onChanged(const App::Property* prop) override;

View File

@@ -150,10 +150,11 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
void FeaturePrimitive::onChanged(const App::Property* prop)
{
if (prop == &AttachmentOffset){
this->touch();
if (prop == &AttachmentOffset) {
this->recompute();
return;
}
FeatureAddSub::onChanged(prop);
}

View File

@@ -155,7 +155,6 @@ PyMOD_INIT_FUNC(PartDesignGui)
PartDesignGui::ViewProviderSubShapeBinder::init();
PartDesignGui::ViewProviderSubShapeBinderPython::init();
PartDesignGui::ViewProviderBoolean ::init();
PartDesignGui::ViewProviderAddSub ::init();
PartDesignGui::ViewProviderPrimitive ::init();
PartDesignGui::ViewProviderPipe ::init();
PartDesignGui::ViewProviderLoft ::init();

View File

@@ -109,8 +109,6 @@ SET(PartDesignGuiViewProvider_SRCS
ViewProviderShapeBinder.cpp
ViewProviderBoolean.cpp
ViewProviderBoolean.h
ViewProviderAddSub.cpp
ViewProviderAddSub.h
ViewProviderPrimitive.h
ViewProviderPrimitive.cpp
ViewProviderPipe.h

View File

@@ -182,7 +182,7 @@ void TaskChamferParameters::onCheckBoxUseAllEdgesToggled(bool checked)
void TaskChamferParameters::setButtons(const selectionModes mode)
{
ui->buttonRefSel->setChecked(mode == refSel);
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr() : btnSelectStr());
ui->buttonRefSel->setText(mode == refSel ? stopSelectionLabel() : startSelectionLabel());
}
void TaskChamferParameters::onRefDeleted()
@@ -349,7 +349,7 @@ bool TaskDlgChamferParameters::accept()
{
auto obj = getObject();
if (!obj->isError()) {
parameter->showObject();
getViewObject()->showPreviousFeature(false);
}
parameter->apply();

View File

@@ -170,7 +170,7 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
void TaskDraftParameters::setButtons(const selectionModes mode)
{
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr() : btnSelectStr());
ui->buttonRefSel->setText(mode == refSel ? stopSelectionLabel() : startSelectionLabel());
ui->buttonRefSel->setChecked(mode == refSel);
ui->buttonLine->setChecked(mode == line);
ui->buttonPlane->setChecked(mode == plane);
@@ -180,7 +180,7 @@ void TaskDraftParameters::onButtonPlane(bool checked)
{
if (checked) {
setButtons(plane);
hideObject();
getViewObject()->showPreviousFeature(true);
selectionMode = plane;
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(
@@ -193,7 +193,7 @@ void TaskDraftParameters::onButtonLine(bool checked)
{
if (checked) {
setButtons(line);
hideObject();
getViewObject()->showPreviousFeature(true);
selectionMode = line;
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(
@@ -311,7 +311,7 @@ bool TaskDlgDraftParameters::accept()
{
auto tobj = getObject();
if (!tobj->isError()) {
parameter->showObject();
getViewObject()->showPreviousFeature(false);
}
parameter->apply();

View File

@@ -55,10 +55,7 @@ using namespace Gui;
/* TRANSLATOR PartDesignGui::TaskDressUpParameters */
TaskDressUpParameters::TaskDressUpParameters(ViewProviderDressUp *DressUpView, bool selectEdges, bool selectFaces, QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap(DressUpView->featureIcon().c_str()),
DressUpView->menuName,
true,
parent)
: TaskFeatureParameters(DressUpView, parent, DressUpView->featureIcon(), DressUpView->menuName)
, proxy(nullptr)
, deleteAction(nullptr)
, addAllEdgesAction(nullptr)
@@ -70,7 +67,6 @@ TaskDressUpParameters::TaskDressUpParameters(ViewProviderDressUp *DressUpView, b
App::GetApplication().getActiveTransaction(&transactionID);
selectionMode = none;
showObject();
}
TaskDressUpParameters::~TaskDressUpParameters()
@@ -282,6 +278,16 @@ void TaskDressUpParameters::tryAddSelection(const std::string& doc,
}
}
QString TaskDressUpParameters::startSelectionLabel()
{
return tr("Select");
}
QString TaskDressUpParameters::stopSelectionLabel()
{
return tr("Confirm Selection");
}
void TaskDressUpParameters::itemClickedTimeout() {
// executed after double-click time passed
wasDoubleClicked = false;
@@ -368,34 +374,7 @@ void TaskDressUpParameters::removeItemFromListWidget(QListWidget* widget, const
void TaskDressUpParameters::hideOnError()
{
App::DocumentObject* dressup = DressUpView->getObject();
if (dressup->isError())
hideObject();
else
showObject();
}
void TaskDressUpParameters::setDressUpVisibility(bool visible)
{
App::DocumentObject* base = getBase();
if (base) {
App::DocumentObject* duv = DressUpView->getObject();
if (duv->Visibility.getValue() != visible) {
duv->Visibility.setValue(visible);
}
if (base->Visibility.getValue() == visible) {
base->Visibility.setValue(!visible);
}
}
}
void TaskDressUpParameters::hideObject()
{
setDressUpVisibility(false);
}
void TaskDressUpParameters::showObject()
{
setDressUpVisibility(true);
DressUpView->setErrorState(dressup->isError());
}
ViewProviderDressUp* TaskDressUpParameters::getDressUpView() const
@@ -427,16 +406,12 @@ void TaskDressUpParameters::setSelectionMode(selectionModes mode)
setButtons(mode);
if (mode == none) {
showObject();
Gui::Selection().rmvSelectionGate();
// remove any highlights and selections
DressUpView->highlightReferences(false);
}
else {
hideObject();
AllowSelectionFlags allow;
allow.setFlag(AllowSelection::EDGE, allowEdges);
allow.setFlag(AllowSelection::FACE, allowFaces);

View File

@@ -42,7 +42,7 @@ namespace Part {
namespace PartDesignGui {
class TaskDressUpParameters : public Gui::TaskView::TaskBox, public Gui::SelectionObserver
class TaskDressUpParameters : public TaskFeatureParameters, public Gui::SelectionObserver
{
Q_OBJECT
@@ -53,13 +53,8 @@ public:
const std::vector<std::string> getReferences() const;
Part::Feature *getBase() const;
void hideObject();
void showObject();
void setupTransaction();
/// Apply the changes made to the object to it
virtual void apply() {}
int getTransactionID() const {
return transactionID;
}
@@ -92,17 +87,6 @@ protected:
ViewProviderDressUp* getDressUpView() const;
template<typename T = App::DocumentObject> T* getObject() const
{
static_assert(std::is_base_of<App::DocumentObject, T>::value, "Wrong template argument");
if (!DressUpView.expired()) {
return DressUpView->getObject<T>();
}
return nullptr;
}
private:
void tryAddSelection(const std::string& doc, const std::string& obj, const std::string& sub);
void setDressUpVisibility(bool visible);
@@ -116,8 +100,8 @@ protected:
selectionModes selectionMode;
int transactionID;
static const QString btnPreviewStr();
static const QString btnSelectStr();
static QString stopSelectionLabel();
static QString startSelectionLabel();
private:
Gui::WeakPtrT<ViewProviderDressUp> DressUpView;

View File

@@ -32,7 +32,6 @@
#include <Gui/Command.h>
#include <Gui/Tools.h>
#include <Mod/PartDesign/App/FeatureExtrude.h>
#include <Mod/Part/Gui/ReferenceHighlighter.h>
#include "ui_TaskPadPocketParameters.h"
#include "TaskExtrudeParameters.h"

View File

@@ -52,6 +52,9 @@ TaskFeatureParameters::TaskFeatureParameters(PartDesignGui::ViewProvider *vp, QW
{
Gui::Document* doc = vp->getDocument();
this->attachDocument(doc);
vp->showPreviousFeature(true);
vp->showPreview(true);
}
void TaskFeatureParameters::slotDeletedObject(const Gui::ViewProviderDocumentObject& Obj)

View File

@@ -134,7 +134,7 @@ void TaskFilletParameters::onCheckBoxUseAllEdgesToggled(bool checked)
void TaskFilletParameters::setButtons(const selectionModes mode)
{
ui->buttonRefSel->setChecked(mode == refSel);
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr() : btnSelectStr());
ui->buttonRefSel->setText(mode == refSel ? stopSelectionLabel() : startSelectionLabel());
}
void TaskFilletParameters::onRefDeleted()
@@ -216,7 +216,7 @@ bool TaskDlgFilletParameters::accept()
{
auto obj = getObject();
if (!obj->isError()) {
parameter->showObject();
getViewObject()->showPreviousFeature(false);
}
parameter->apply();

View File

@@ -286,7 +286,7 @@
<item>
<widget class="QCheckBox" name="checkBoxUpdateView">
<property name="text">
<string>Update view</string>
<string>Recompute on change</string>
</property>
<property name="checked">
<bool>true</bool>

View File

@@ -241,8 +241,6 @@ TaskHoleParameters::TaskHoleParameters(ViewProviderHole* HoleView, QWidget* pare
this, &TaskHoleParameters::baseProfileTypeChanged);
// clang-format on
getViewObject()->show();
ui->Diameter->bind(pcHole->Diameter);
ui->HoleCutDiameter->bind(pcHole->HoleCutDiameter);
ui->HoleCutDepth->bind(pcHole->HoleCutDepth);

View File

@@ -117,7 +117,7 @@
<item>
<widget class="QCheckBox" name="checkBoxUpdateView">
<property name="text">
<string>Update view</string>
<string>Recompute on change</string>
</property>
<property name="checked">
<bool>true</bool>

View File

@@ -468,7 +468,7 @@ measured along the specified direction</string>
<item>
<widget class="QCheckBox" name="checkBoxUpdateView">
<property name="text">
<string>Update view</string>
<string>Recompute on change</string>
</property>
<property name="checked">
<bool>true</bool>

View File

@@ -52,6 +52,9 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent)
, ui(new Ui_DlgPrimitives)
, vp(vp)
{
vp->showPreview(true);
vp->showPreviousFeature(true);
proxy = new QWidget(this);
ui->setupUi(proxy);
@@ -972,8 +975,9 @@ bool TaskBoxPrimitives::setPrimitive(App::DocumentObject* obj)
return true;
}
TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* PrimitiveView)
: vp_prm(PrimitiveView)
TaskDlgPrimitiveParameters::TaskDlgPrimitiveParameters(ViewProviderPrimitive* PrimitiveView)
: TaskDlgFeatureParameters(PrimitiveView)
, vp_prm(PrimitiveView)
{
assert(PrimitiveView);
@@ -983,9 +987,9 @@ TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* Primitiv
Content.push_back(parameter);
}
TaskPrimitiveParameters::~TaskPrimitiveParameters() = default;
TaskDlgPrimitiveParameters::~TaskDlgPrimitiveParameters() = default;
bool TaskPrimitiveParameters::accept()
bool TaskDlgPrimitiveParameters::accept()
{
bool primitiveOK = primitive->setPrimitive(vp_prm->getObject());
if (!primitiveOK) {
@@ -997,7 +1001,7 @@ bool TaskPrimitiveParameters::accept()
return true;
}
bool TaskPrimitiveParameters::reject()
bool TaskDlgPrimitiveParameters::reject()
{
// roll back the done things
Gui::Command::abortCommand();
@@ -1006,7 +1010,7 @@ bool TaskPrimitiveParameters::reject()
return true;
}
QDialogButtonBox::StandardButtons TaskPrimitiveParameters::getStandardButtons() const
QDialogButtonBox::StandardButtons TaskDlgPrimitiveParameters::getStandardButtons() const
{
return Gui::TaskView::TaskDialog::getStandardButtons();
}

View File

@@ -31,6 +31,7 @@
#include "ViewProviderPrimitive.h"
#include "TaskDatumParameters.h"
#include "TaskFeatureParameters.h"
namespace App {
class Property;
@@ -117,13 +118,13 @@ private:
ViewProviderPrimitive* vp;
};
class TaskPrimitiveParameters : public Gui::TaskView::TaskDialog
class TaskDlgPrimitiveParameters : public TaskDlgFeatureParameters
{
Q_OBJECT
public:
explicit TaskPrimitiveParameters(ViewProviderPrimitive *PrimitiveView);
~TaskPrimitiveParameters() override;
explicit TaskDlgPrimitiveParameters(ViewProviderPrimitive *PrimitiveView);
~TaskDlgPrimitiveParameters() override;
protected:
QDialogButtonBox::StandardButtons getStandardButtons() const override;

View File

@@ -189,7 +189,7 @@
<item>
<widget class="QCheckBox" name="checkBoxUpdateView">
<property name="text">
<string>Update view</string>
<string>Recompute on change</string>
</property>
<property name="checked">
<bool>true</bool>

View File

@@ -90,22 +90,37 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan
void TaskSketchBasedParameters::startReferenceSelection(App::DocumentObject* profile,
App::DocumentObject* base)
{
if (Gui::Document* doc = getGuiDocument()) {
doc->setHide(profile->getNameInDocument());
if (base) {
doc->setShow(base->getNameInDocument());
const auto* bodyViewProvider = getViewObject<ViewProvider>()->getBodyViewProvider();
previouslyVisibleViewProvider = bodyViewProvider->getShownViewProvider();
if (!base) {
return;
}
if (Document* doc = getGuiDocument()) {
if (previouslyVisibleViewProvider) {
previouslyVisibleViewProvider->hide();
}
doc->setShow(base->getNameInDocument());
}
}
void TaskSketchBasedParameters::finishReferenceSelection(App::DocumentObject* profile,
App::DocumentObject* base)
{
if (Gui::Document* doc = getGuiDocument()) {
doc->setShow(profile->getNameInDocument());
if (!previouslyVisibleViewProvider) {
return;
}
if (Document* doc = getGuiDocument()) {
if (base) {
doc->setHide(base->getNameInDocument());
}
previouslyVisibleViewProvider->show();
previouslyVisibleViewProvider = nullptr;
}
}

View File

@@ -72,6 +72,9 @@ protected:
/// or the subelement's name if the object is a solid.
QString make2DLabel(const App::DocumentObject* section,
const std::vector<std::string>& subValues);
private:
Gui::ViewProvider* previouslyVisibleViewProvider {nullptr};
};
class TaskDlgSketchBasedParameters : public PartDesignGui::TaskDlgFeatureParameters

View File

@@ -144,7 +144,7 @@ void TaskThicknessParameters::onSelectionChanged(const Gui::SelectionChanges& ms
void TaskThicknessParameters::setButtons(const selectionModes mode)
{
ui->buttonRefSel->setChecked(mode == refSel);
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr() : btnSelectStr());
ui->buttonRefSel->setText(mode == refSel ? stopSelectionLabel() : startSelectionLabel());
}
void TaskThicknessParameters::onRefDeleted()
@@ -280,7 +280,7 @@ bool TaskDlgThicknessParameters::accept()
{
auto obj = getObject();
if (!obj->isError()) {
parameter->showObject();
getViewObject()->showPreviousFeature(false);
}
parameter->apply();

View File

@@ -119,7 +119,7 @@
<item>
<widget class="QCheckBox" name="checkBoxUpdateView">
<property name="text">
<string>Update view</string>
<string>Recompute on change</string>
</property>
<property name="checked">
<bool>true</bool>

View File

@@ -26,8 +26,10 @@
#ifndef _PreComp_
# include <QMessageBox>
# include <QAction>
# include <QApplication>
# include <QMenu>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <BRep_Builder.hxx>
#endif
#include <Base/Exception.h>
@@ -37,15 +39,23 @@
#include <Gui/CommandT.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/Selection/SoFCUnifiedSelection.h>
#include <Gui/Inventor/So3DAnnotation.h>
#include <Gui/MainWindow.h>
#include <Gui/Utilities.h>
#include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/Feature.h>
#include <Mod/PartDesign/App/FeatureAddSub.h>
#include <Mod/Part/Gui/ViewProvider.h>
#include <Mod/Part/Gui/ViewProviderExt.h>
#include <Mod/Part/Gui/SoBrepEdgeSet.h>
#include <Mod/Part/Gui/ViewProviderPreviewExtension.h>
#include "TaskFeatureParameters.h"
#include "ViewProvider.h"
#include "ViewProviderPy.h"
using namespace PartDesignGui;
PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesignGui::ViewProvider, PartGui::ViewProviderPart)
@@ -53,11 +63,31 @@ PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesignGui::ViewProvider, PartGui::ViewProvid
ViewProvider::ViewProvider()
{
ViewProviderSuppressibleExtension::initExtension(this);
PartGui::ViewProviderAttachExtension::initExtension(this);
ViewProviderAttachExtension::initExtension(this);
ViewProviderPreviewExtension::initExtension(this);
}
ViewProvider::~ViewProvider() = default;
void ViewProvider::beforeDelete()
{
ViewProviderPart::beforeDelete();
}
void ViewProvider::attach(App::DocumentObject* pcObject)
{
ViewProviderPart::attach(pcObject);
if (auto addSubFeature = getObject<PartDesign::FeatureAddSub>()) {
const Base::Color green(0.0F, 1.0F, 0.6F);
const Base::Color red(1.0F, 0.0F, 0.0F);
bool isAdditive = addSubFeature->getAddSubType() == PartDesign::FeatureAddSub::Additive;
PreviewColor.setValue(isAdditive ? green : red);
}
}
bool ViewProvider::doubleClicked()
{
try {
@@ -149,6 +179,8 @@ TaskDlgFeatureParameters *ViewProvider::getEditDialog() {
void ViewProvider::unsetEdit(int ModNum)
{
showPreview(false);
// return to the WB we were in before editing the PartDesign feature
if (!oldWb.empty()) {
Gui::Command::assureWorkbench(oldWb.c_str());
@@ -170,15 +202,42 @@ void ViewProvider::unsetEdit(int ModNum)
void ViewProvider::updateData(const App::Property* prop)
{
// TODO What's that? (2015-07-24, Fat-Zer)
if (prop->is<Part::PropertyPartShape>() &&
strcmp(prop->getName(),"AddSubShape") == 0) {
return;
if (strcmp(prop->getName(), "PreviewShape") == 0) {
updatePreviewShape();
}
inherited::updateData(prop);
}
void ViewProvider::attachPreview()
{
ViewProviderPreviewExtension::attachPreview();
pcToolPreview = new PartGui::SoPreviewShape;
pcToolPreview->transparency = 0.95F;
pcToolPreview->color.connectFrom(&pcPreviewShape->color);
pcPreviewRoot->addChild(pcToolPreview);
}
void ViewProvider::updatePreview()
{
ViewProviderPreviewExtension::updatePreview();
if (auto* addSubFeature = getObject<PartDesign::FeatureAddSub>()) {
// we only want to show the additional tool preview for subtractive features
if (addSubFeature->getAddSubType() != PartDesign::FeatureAddSub::Subtractive) {
return;
}
Part::TopoShape toolShape = addSubFeature->AddSubShape.getShape();
updatePreviewShape(toolShape, pcToolPreview);
} else {
updatePreviewShape({}, pcToolPreview);
}
}
void ViewProvider::onChanged(const App::Property* prop) {
//if the object is inside of a body we make sure it is the only visible one on activation
@@ -267,12 +326,52 @@ bool ViewProvider::onDelete(const std::vector<std::string>&)
//
// fixes (#3084)
FCMD_OBJ_CMD(body,"removeObject(" << Gui::Command::getObjectCmd(feature) << ')');
FCMD_OBJ_CMD(body, "removeObject(" << Gui::Command::getObjectCmd(feature) << ')');
}
return true;
}
Part::TopoShape ViewProvider::getPreviewShape() const
{
if (auto feature = getObject()->getExtensionByType<Part::PreviewExtension>(true)) {
// Feature is responsible for generating proper shape and this ViewProvider
// is using it instead of more normal `Shape` property.
return feature->PreviewShape.getShape();
}
return {};
}
void ViewProvider::showPreviousFeature(bool enable)
{
PartDesign::Feature* feature {getObject<PartDesign::Feature>()};
PartDesign::Feature* baseFeature { nullptr };
ViewProvider* baseFeatureViewProvider { nullptr };
if (!feature) {
return;
}
baseFeature = dynamic_cast<PartDesign::Feature*>(feature->BaseFeature.getValue());
if (baseFeature) {
baseFeatureViewProvider = freecad_cast<ViewProvider*>(Gui::Application::Instance->getViewProvider(baseFeature));
}
if (!baseFeatureViewProvider) {
baseFeatureViewProvider = this;
}
if (enable) {
baseFeatureViewProvider->show();
hide();
} else {
baseFeatureViewProvider->hide();
show();
}
}
void ViewProvider::setBodyMode(bool bodymode) {
std::vector<App::Property*> props;
@@ -331,8 +430,6 @@ ViewProviderBody* ViewProvider::getBodyViewProvider() {
return nullptr;
}
namespace Gui {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(PartDesignGui::ViewProviderPython, PartDesignGui::ViewProvider)

View File

@@ -24,12 +24,16 @@
#ifndef PARTGUI_ViewProvider_H
#define PARTGUI_ViewProvider_H
#include <Mod/Part/Gui/ViewProvider.h>
#include "ViewProviderBody.h"
#include <App/DocumentObject.h>
#include <Gui/ViewProviderFeaturePython.h>
#include "Gui/ViewProviderSuppressibleExtension.h"
#include <Gui/ViewProviderSuppressibleExtension.h>
#include <Mod/Part/Gui/ViewProvider.h>
#include <Mod/Part/Gui/ViewProviderAttachExtension.h>
#include <Mod/Part/Gui/ViewProviderPreviewExtension.h>
#include <Mod/PartDesign/App/Feature.h>
#include "ViewProviderBody.h"
namespace PartDesignGui {
@@ -40,7 +44,8 @@ class TaskDlgFeatureParameters;
*/
class PartDesignGuiExport ViewProvider : public PartGui::ViewProviderPart,
Gui::ViewProviderSuppressibleExtension,
PartGui::ViewProviderAttachExtension
PartGui::ViewProviderAttachExtension,
public PartGui::ViewProviderPreviewExtension
{
using inherited = PartGui::ViewProviderPart;
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProvider);
@@ -51,8 +56,10 @@ public:
/// destructor
~ViewProvider() override;
void beforeDelete() override;
void attach(App::DocumentObject* pcObject) override;
bool doubleClicked() override;
void updateData(const App::Property*) override;
void onChanged(const App::Property* prop) override;
Gui::ViewProvider* startEditing(int ModNum) override;
@@ -73,6 +80,11 @@ public:
//Returns the ViewProvider of the body the feature belongs to, or NULL, if not in a body
ViewProviderBody* getBodyViewProvider();
/// Provides preview shape
Part::TopoShape getPreviewShape() const override;
/// Toggles visibility of the preview
void showPreviousFeature(bool);
PyObject* getPyObject() override;
QIcon mergeColorfulOverlayIcons (const QIcon & orig) const override;
@@ -81,6 +93,10 @@ protected:
void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override;
bool setEdit(int ModNum) override;
void unsetEdit(int ModNum) override;
void updateData(const App::Property* prop) override;
void attachPreview() override;
void updatePreview() override;
bool onDelete(const std::vector<std::string> &) override;
@@ -92,7 +108,11 @@ protected:
std::string oldWb;
ViewProvider* previouslyShownViewProvider { nullptr };
bool isSetTipIcon { false };
private:
Gui::CoinPtr<PartGui::SoPreviewShape> pcToolPreview;
};
using ViewProviderPython = Gui::ViewProviderFeaturePythonT<ViewProvider>;

View File

@@ -1,261 +0,0 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoSwitch.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoNormal.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <Bnd_Box.hxx>
# include <BRep_Tool.hxx>
# include <BRepBndLib.hxx>
# include <BRepMesh_IncrementalMesh.hxx>
# include <Standard_Version.hxx>
# include <TopExp_Explorer.hxx>
# include <TopoDS.hxx>
#endif
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Gui/Application.h>
#include <Mod/Part/App/Tools.h>
#include <Mod/Part/Gui/SoBrepFaceSet.h>
#include <Mod/PartDesign/App/FeatureAddSub.h>
#include "ViewProviderAddSub.h"
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderAddSub,PartDesignGui::ViewProvider)
ViewProviderAddSub::ViewProviderAddSub()
{
previewShape = new SoSeparator();
previewShape->ref();
previewFaceSet = new PartGui::SoBrepFaceSet();
previewFaceSet->ref();
previewCoords = new SoCoordinate3();
previewCoords->ref();
previewNorm = new SoNormal();
previewNorm->ref();
whichChild = -1;
}
ViewProviderAddSub::~ViewProviderAddSub()
{
previewFaceSet->unref();
previewCoords->unref();
previewNorm->unref();
previewShape->unref();
}
void ViewProviderAddSub::attach(App::DocumentObject* obj) {
ViewProvider::attach(obj);
auto* bind = new SoMaterialBinding();
bind->value = SoMaterialBinding::OVERALL;
auto* material = new SoMaterial();
if (static_cast<PartDesign::FeatureAddSub*>(obj)->getAddSubType() == PartDesign::FeatureAddSub::Additive)
material->diffuseColor = SbColor(1,1,0);
else
material->diffuseColor = SbColor(1,0,0);
material->transparency = 0.7f;
auto* pick = new SoPickStyle();
pick->style = SoPickStyle::UNPICKABLE;
previewShape->addChild(pick);
previewShape->addChild(bind);
previewShape->addChild(material);
previewShape->addChild(previewCoords);
previewShape->addChild(previewNorm);
previewShape->addChild(previewFaceSet);
addDisplayMaskMode(previewShape, "Shape preview");
updateAddSubShapeIndicator();
}
void ViewProviderAddSub::updateAddSubShapeIndicator() {
TopoDS_Shape cShape(getObject<PartDesign::FeatureAddSub>()->AddSubShape.getValue());
if (cShape.IsNull()) {
previewCoords ->point .setNum(0);
previewNorm ->vector .setNum(0);
previewFaceSet ->coordIndex .setNum(0);
previewFaceSet ->partIndex .setNum(0);
return;
}
try {
// calculating the deflection value
Bnd_Box bounds;
BRepBndLib::Add(cShape, bounds);
bounds.SetGap(0.0);
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();
// create or use the mesh on the data structure
Standard_Real AngDeflectionRads = Base::toRadians(AngularDeflection.getValue());
BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True);
// We must reset the location here because the transformation data
// are set in the placement property
TopLoc_Location aLoc;
cShape.Location(aLoc);
// count triangles and nodes in the mesh
int numTriangles=0,numNodes=0,numNorms=0,numFaces=0;
TopExp_Explorer Ex;
for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
// Note: we must also count empty faces
if (!mesh.IsNull()) {
numTriangles += mesh->NbTriangles();
numNodes += mesh->NbNodes();
numNorms += mesh->NbNodes();
}
numFaces++;
}
// create memory for the nodes and indexes
previewCoords ->point .setNum(numNodes);
previewNorm ->vector .setNum(numNorms);
previewFaceSet ->coordIndex .setNum(numTriangles*4);
previewFaceSet ->partIndex .setNum(numFaces);
// get the raw memory for fast fill up
SbVec3f* verts = previewCoords ->point .startEditing();
SbVec3f* previewNorms = previewNorm ->vector .startEditing();
int32_t* index = previewFaceSet ->coordIndex .startEditing();
int32_t* parts = previewFaceSet ->partIndex .startEditing();
// preset the previewNormal vector with null vector
for (int i=0;i < numNorms;i++)
previewNorms[i]= SbVec3f(0.0,0.0,0.0);
int ii = 0,faceNodeOffset=0,faceTriaOffset=0;
for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
TopLoc_Location loc;
Handle(Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace, loc);
if (mesh.IsNull())
continue;
// get triangulation
std::vector<gp_Pnt> points;
std::vector<Poly_Triangle> facets;
Part::Tools::getTriangulation(actFace, points, facets);
// get normal per vertex
std::vector<gp_Vec> vertexnormals;
Part::Tools::getPointNormals(actFace, mesh, vertexnormals);
Part::Tools::applyTransformationOnNormals(loc, vertexnormals);
// getting size of node and triangle array of this face
std::size_t nbNodesInFace = points.size();
std::size_t nbTriInFace = facets.size();
for (std::size_t i = 0; i < points.size(); i++) {
verts[faceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z());
}
for (std::size_t i = 0; i < vertexnormals.size(); i++) {
previewNorms[faceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z());
}
// cycling through the poly mesh
for (std::size_t g=0; g < nbTriInFace; g++) {
// Get the triangle
Standard_Integer N1,N2,N3;
facets[g].Get(N1,N2,N3);
// set the index vector with the 3 point indexes and the end delimiter
index[faceTriaOffset*4+4*g] = faceNodeOffset+N1;
index[faceTriaOffset*4+4*g+1] = faceNodeOffset+N2;
index[faceTriaOffset*4+4*g+2] = faceNodeOffset+N3;
index[faceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX;
}
parts[ii] = nbTriInFace; // new part
// counting up the per Face offsets
faceNodeOffset += nbNodesInFace;
faceTriaOffset += nbTriInFace;
}
// previewNormalize all previewNormals
for (int i = 0; i< numNorms ;i++)
previewNorms[i].normalize();
// end the editing of the nodes
previewCoords ->point .finishEditing();
previewNorm ->vector .finishEditing();
previewFaceSet ->coordIndex .finishEditing();
previewFaceSet ->partIndex .finishEditing();
}
catch (...) {
Base::Console().error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument());
}
}
void ViewProviderAddSub::updateData(const App::Property* p) {
if(p->getName() && strcmp(p->getName(), "AddSubShape")==0)
updateAddSubShapeIndicator();
PartDesignGui::ViewProvider::updateData(p);
}
void ViewProviderAddSub::setPreviewDisplayMode(bool onoff) {
// A mask mode is always set, also for hidden objects.
// Now when changing to another mask mode this automatically
// displays an object and when restoring the previous state it's
// not sufficient to only revert the mask mode. Also the child
// number of the switch node must be reverted.
if (onoff) {
if(pcModeSwitch->getChild(getDefaultMode()) == previewShape)
return;
displayMode = getActiveDisplayMode();
whichChild = pcModeSwitch->whichChild.getValue();
setDisplayMaskMode("Shape preview");
}
if (!onoff) {
if(pcModeSwitch->getChild(getDefaultMode()) != previewShape)
return;
setDisplayMaskMode(displayMode.c_str());
pcModeSwitch->whichChild.setValue(whichChild);
}
App::DocumentObject* obj = getObject<PartDesign::Feature>()->BaseFeature.getValue();
if (obj)
static_cast<PartDesignGui::ViewProvider*>(Gui::Application::Instance->getViewProvider(obj))->makeTemporaryVisible(onoff);
}

View File

@@ -1,62 +0,0 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTGUI_ViewProviderAddSub_H
#define PARTGUI_ViewProviderAddSub_H
#include "ViewProvider.h"
#include <Mod/Part/Gui/SoBrepFaceSet.h>
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderAddSub : public ViewProvider
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderAddSub);
public:
/// constructor
ViewProviderAddSub();
/// destructor
~ViewProviderAddSub() override;
void attach(App::DocumentObject*) override;
void updateData(const App::Property*) override;
protected:
void updateAddSubShapeIndicator();
void setPreviewDisplayMode(bool);
SoSeparator* previewShape;
PartGui::SoBrepFaceSet* previewFaceSet;
SoCoordinate3* previewCoords;
SoNormal* previewNorm;
private:
int whichChild;
std::string displayMode;
};
} // namespace PartDesignGui
#endif // PARTGUI_ViewProviderBoolean_H

View File

@@ -39,11 +39,23 @@
#include "ViewProviderDressUp.h"
#include "TaskDressUpParameters.h"
#include <Gui/Utilities.h>
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderDressUp,PartDesignGui::ViewProvider)
PROPERTY_SOURCE(PartDesignGui::ViewProviderDressUp, PartDesignGui::ViewProvider)
void ViewProviderDressUp::attach(App::DocumentObject* pcObject)
{
ViewProvider::attach(pcObject);
const Base::Color magenta(1.0F, 0.0F, 1.0F);
PreviewColor.setValue(magenta);
setErrorState(false);
}
void ViewProviderDressUp::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
QString text = QString::fromStdString(getObject()->Label.getStrValue());
@@ -121,3 +133,13 @@ void ViewProviderDressUp::highlightReferences(const bool on)
}
}
void ViewProviderDressUp::setErrorState(bool error)
{
const Base::Color red(1.0, 0.0, 0.0);
constexpr float errorTransparency = 0.95F;
pcPreviewShape->transparency = error ? errorTransparency : PartGui::SoPreviewShape::defaultTransparency;
pcPreviewShape->color = Base::convertTo<SbColor>(error ? red : PreviewColor.getValue());
}

View File

@@ -40,7 +40,9 @@ public:
/// constructor
ViewProviderDressUp() = default;
/// destructor
~ViewProviderDressUp() override = default;
~ViewProviderDressUp() override = default;
void attach(App::DocumentObject* pcObject) override;
/// grouping handling
void setupContextMenu(QMenu*, QObject*, const char*) override;
@@ -48,6 +50,9 @@ public:
/// Highlight the references that have been selected
void highlightReferences(const bool on);
/// Set preview parameters to indicate error state
void setErrorState(bool error);
/**
* Returns the feature Name associated with the view provider.
* Should be reimplemented in the successor.

View File

@@ -49,12 +49,12 @@ ViewProviderHelix::~ViewProviderHelix() = default;
void ViewProviderHelix::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
addDefaultAction(menu, QObject::tr("Edit Helix"));
PartDesignGui::ViewProviderAddSub::setupContextMenu(menu, receiver, member);
ViewProvider::setupContextMenu(menu, receiver, member);
}
TaskDlgFeatureParameters *ViewProviderHelix::getEditDialog()
{
return new TaskDlgHelixParameters( this );
return new TaskDlgHelixParameters(this);
}
QIcon ViewProviderHelix::getIcon() const {
@@ -69,23 +69,6 @@ QIcon ViewProviderHelix::getIcon() const {
return PartDesignGui::ViewProvider::mergeGreyableOverlayIcons(Gui::BitmapFactory().pixmap(str.toStdString().c_str()));
}
bool ViewProviderHelix::setEdit(int ModNum)
{
if (ModNum == ViewProvider::Default ) {
auto* prim = getObject<PartDesign::Helix>();
setPreviewDisplayMode(TaskHelixParameters::showPreview(prim));
}
return ViewProviderAddSub::setEdit(ModNum);
}
void ViewProviderHelix::unsetEdit(int ModNum)
{
setPreviewDisplayMode(false);
// Rely on parent class to:
// restitute old workbench (set setEdit above) and close the dialog if exiting editing
PartDesignGui::ViewProvider::unsetEdit(ModNum);
}
std::vector<App::DocumentObject*> ViewProviderHelix::claimChildren() const {
std::vector<App::DocumentObject*> temp;
App::DocumentObject* sketch = getObject<PartDesign::ProfileBased>()->Profile.getValue();

View File

@@ -24,12 +24,12 @@
#ifndef PARTGUI_ViewProviderHelix_H
#define PARTGUI_ViewProviderHelix_H
#include "ViewProviderAddSub.h"
#include "ViewProvider.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderHelix : public ViewProviderAddSub
class PartDesignGuiExport ViewProviderHelix : public ViewProvider
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderHelix);
@@ -51,8 +51,6 @@ protected:
/// Returns a newly created TaskDlgHelixParameters
TaskDlgFeatureParameters *getEditDialog() override;
bool setEdit(int ModNum) override;
void unsetEdit(int ModNum) override;
};

View File

@@ -63,59 +63,24 @@ void ViewProviderHole::setupContextMenu(QMenu* menu, QObject* receiver, const ch
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member); // clazy:exclude=skipped-base-method
}
bool ViewProviderHole::setEdit(int ModNum)
{
if (ModNum == ViewProvider::Default ) {
// When double-clicking on the item for this hole the
// object unsets and sets its edit mode without closing
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskDlgHoleParameters *holeDlg = qobject_cast<TaskDlgHoleParameters *>(dlg);
if (holeDlg && holeDlg->getViewObject() != this)
holeDlg = nullptr; // another hole left open its task panel
if (dlg && !holeDlg) {
QMessageBox msgBox(Gui::getMainWindow());
msgBox.setText(QObject::tr("A dialog is already open in the task panel"));
msgBox.setInformativeText(QObject::tr("Close this dialog?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
if (ret == QMessageBox::Yes)
Gui::Control().closeDialog();
else
return false;
}
// clear the selection (convenience)
Gui::Selection().clearSelection();
// always change to PartDesign WB, remember where we come from
oldWb = Gui::Command::assureWorkbench("PartDesignWorkbench");
// start the edit dialog
if (holeDlg)
Gui::Control().showDialog(holeDlg);
else
Gui::Control().showDialog(new TaskDlgHoleParameters(this));
return true;
}
else {
return PartGui::ViewProviderPart::setEdit(ModNum); // clazy:exclude=skipped-base-method
}
}
bool ViewProviderHole::onDelete(const std::vector<std::string> &s)
bool ViewProviderHole::onDelete(const std::vector<std::string>& s)
{
// get the Sketch
PartDesign::Hole* pcHole = getObject<PartDesign::Hole>();
Sketcher::SketchObject *pcSketch = nullptr;
if (pcHole->Profile.getValue())
Sketcher::SketchObject* pcSketch = nullptr;
if (pcHole->Profile.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcHole->Profile.getValue());
}
// if abort command deleted the object the sketch is visible again
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch)) {
Gui::Application::Instance->getViewProvider(pcSketch)->show();
}
return ViewProvider::onDelete(s);
}
TaskDlgFeatureParameters* ViewProviderHole::getEditDialog()
{
return new TaskDlgHoleParameters(this);
}

View File

@@ -43,8 +43,9 @@ public:
std::vector<App::DocumentObject*> claimChildren()const override;
void setupContextMenu(QMenu *menu, QObject *receiver, const char *member) override;
bool onDelete(const std::vector<std::string> &s) override;
protected:
bool setEdit(int ModNum) override;
TaskDlgFeatureParameters* getEditDialog() override;
};

View File

@@ -37,7 +37,7 @@
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderLoft,PartDesignGui::ViewProvider)
PROPERTY_SOURCE(PartDesignGui::ViewProviderLoft, PartDesignGui::ViewProvider)
ViewProviderLoft::ViewProviderLoft() = default;
@@ -64,28 +64,13 @@ std::vector<App::DocumentObject*> ViewProviderLoft::claimChildren()const
void ViewProviderLoft::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
addDefaultAction(menu, QObject::tr("Edit Loft"));
PartDesignGui::ViewProvider::setupContextMenu(menu, receiver, member);
}
bool ViewProviderLoft::setEdit(int ModNum)
{
if (ModNum == ViewProvider::Default)
setPreviewDisplayMode(true);
return ViewProviderAddSub::setEdit(ModNum);
ViewProvider::setupContextMenu(menu, receiver, member);
}
TaskDlgFeatureParameters* ViewProviderLoft::getEditDialog() {
return new TaskDlgLoftParameters(this);
}
void ViewProviderLoft::unsetEdit(int ModNum) {
setPreviewDisplayMode(false);
ViewProviderAddSub::unsetEdit(ModNum);
}
bool ViewProviderLoft::onDelete(const std::vector<std::string> & /*s*/)
{/*
PartDesign::Loft* pcLoft = getObject<PartDesign::Loft>();

View File

@@ -24,11 +24,11 @@
#ifndef PARTGUI_ViewProviderLoft_H
#define PARTGUI_ViewProviderLoft_H
#include "ViewProviderAddSub.h"
#include "ViewProvider.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderLoft : public ViewProviderAddSub
class PartDesignGuiExport ViewProviderLoft : public ViewProvider
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderLoft);
@@ -55,8 +55,6 @@ public:
protected:
QIcon getIcon() const override;
bool setEdit(int ModNum) override;
void unsetEdit(int ModNum) override;
TaskDlgFeatureParameters* getEditDialog() override;
private:

View File

@@ -75,19 +75,6 @@ void ViewProviderPipe::setupContextMenu(QMenu* menu, QObject* receiver, const ch
PartDesignGui::ViewProvider::setupContextMenu(menu, receiver, member);
}
bool ViewProviderPipe::setEdit(int ModNum) {
if (ModNum == ViewProvider::Default )
setPreviewDisplayMode(true);
return PartDesignGui::ViewProvider::setEdit(ModNum);
}
void ViewProviderPipe::unsetEdit(int ModNum) {
setPreviewDisplayMode(false);
PartDesignGui::ViewProvider::unsetEdit(ModNum);
}
TaskDlgFeatureParameters* ViewProviderPipe::getEditDialog() {
return new TaskDlgPipeParameters(this, false);
}

View File

@@ -24,11 +24,11 @@
#ifndef PARTGUI_ViewProviderPipe_H
#define PARTGUI_ViewProviderPipe_H
#include "ViewProviderAddSub.h"
#include "ViewProvider.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderPipe : public ViewProviderAddSub
class PartDesignGuiExport ViewProviderPipe : public ViewProvider
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderPipe);
@@ -54,8 +54,6 @@ public:
protected:
QIcon getIcon() const override;
bool setEdit(int ModNum) override;
void unsetEdit(int ModNum) override;
/// Returns a newly created TaskDlgPipeParameters
TaskDlgFeatureParameters *getEditDialog() override;

View File

@@ -46,71 +46,15 @@ ViewProviderPrimitive::ViewProviderPrimitive() = default;
ViewProviderPrimitive::~ViewProviderPrimitive() = default;
void ViewProviderPrimitive::attach(App::DocumentObject* obj) {
ViewProviderAddSub::attach(obj);
}
void ViewProviderPrimitive::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
addDefaultAction(menu, QObject::tr("Edit Primitive"));
PartDesignGui::ViewProvider::setupContextMenu(menu, receiver, member);
}
bool ViewProviderPrimitive::setEdit(int ModNum)
TaskDlgFeatureParameters* ViewProviderPrimitive::getEditDialog()
{
if (ModNum == ViewProvider::Default ) {
// When double-clicking on the item for this fillet the
// object unsets and sets its edit mode without closing
// the task panel
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
TaskPrimitiveParameters *primitiveDlg = qobject_cast<TaskPrimitiveParameters *>(dlg);
if (dlg && !primitiveDlg) {
QMessageBox msgBox(Gui::getMainWindow());
msgBox.setText(QObject::tr("A dialog is already open in the task panel"));
msgBox.setInformativeText(QObject::tr("Close this dialog?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
if (ret == QMessageBox::Yes)
Gui::Control().closeDialog();
else
return false;
}
// clear the selection (convenience)
Gui::Selection().clearSelection();
// always change to PartDesign WB, remember where we come from
oldWb = Gui::Command::assureWorkbench("PartDesignWorkbench");
// start the edit dialog
// another pad left open its task panel
if (primitiveDlg)
Gui::Control().showDialog(primitiveDlg);
else
Gui::Control().showDialog(new TaskPrimitiveParameters(this));
setPreviewDisplayMode(true);
return true;
}
else {
return ViewProviderAddSub::setEdit(ModNum);
}
}
void ViewProviderPrimitive::unsetEdit(int ModNum)
{
setPreviewDisplayMode(false);
// Rely on parent class to:
// restitute old workbench (set setEdit above) and close the dialog if exiting editing
PartDesignGui::ViewProvider::unsetEdit(ModNum);
}
void ViewProviderPrimitive::updateData(const App::Property* p) {
PartDesignGui::ViewProviderAddSub::updateData(p);
return new TaskDlgPrimitiveParameters(this);
}
QIcon ViewProviderPrimitive::getIcon() const {

View File

@@ -24,11 +24,11 @@
#ifndef PARTGUI_ViewProviderPrimitive_H
#define PARTGUI_ViewProviderPrimitive_H
#include "ViewProviderAddSub.h"
#include "ViewProvider.h"
namespace PartDesignGui {
class PartDesignGuiExport ViewProviderPrimitive : public ViewProviderAddSub
class PartDesignGuiExport ViewProviderPrimitive : public ViewProvider
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderPrimitive);
@@ -38,16 +38,11 @@ public:
/// destructor
~ViewProviderPrimitive() override;
void attach(App::DocumentObject*) override;
void updateData(const App::Property*) override;
protected:
QIcon getIcon() const override;
void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override;
bool setEdit(int ModNum) override;
void unsetEdit(int ModNum) override;
void updateAddSubShapeIndicator();
TaskDlgFeatureParameters *getEditDialog() override;
std::string displayMode;
};

View File

@@ -23,7 +23,7 @@
#ifndef VIEWPROVIDERSKETCHBASED_H_QKP3UG9A
#define VIEWPROVIDERSKETCHBASED_H_QKP3UG9A
#include "ViewProviderAddSub.h"
#include "ViewProvider.h"
namespace PartDesignGui {
@@ -41,7 +41,7 @@ public:
~ViewProviderSketchBased() override;
/// grouping handling
std::vector<App::DocumentObject*> claimChildren()const override;
std::vector<App::DocumentObject*> claimChildren() const override;
bool onDelete(const std::vector<std::string> &) override;