Merge pull request #17564 from kadet1090/new-transform-dialog
Gui: New transform dialog
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include <Base/ExceptionFactory.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/ServiceProvider.h>
|
||||
#include <Base/PrecisionPy.h>
|
||||
|
||||
#include "ArcOfCirclePy.h"
|
||||
@@ -187,8 +188,12 @@
|
||||
|
||||
#include <OCAF/ImportExportSettings.h>
|
||||
#include "MeasureClient.h"
|
||||
|
||||
#include <FuzzyHelper.h>
|
||||
|
||||
#include <App/Services.h>
|
||||
#include <Services.h>
|
||||
|
||||
namespace Part {
|
||||
extern PyObject* initModule();
|
||||
}
|
||||
@@ -572,7 +577,10 @@ PyMOD_INIT_FUNC(Part)
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean");
|
||||
|
||||
Part::FuzzyHelper::setBooleanFuzzy(hGrp->GetFloat("BooleanFuzzy",10.0));
|
||||
|
||||
|
||||
Base::registerServiceImplementation<App::SubObjectPlacementProvider>(new AttacherSubObjectPlacement);
|
||||
Base::registerServiceImplementation<App::CenterOfMassProvider>(new PartCenterOfMass);
|
||||
|
||||
PyMOD_Return(partModule);
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
#include "AttachExtension.h"
|
||||
#include "Tools.h"
|
||||
|
||||
#include <Geometry.h>
|
||||
|
||||
|
||||
using namespace Part;
|
||||
using namespace Attacher;
|
||||
@@ -136,6 +138,7 @@ const char* AttachEngine::eMapModeStrings[]= {
|
||||
"OYX",
|
||||
|
||||
"ParallelPlane",
|
||||
"MidPoint",
|
||||
|
||||
nullptr};
|
||||
|
||||
@@ -388,8 +391,8 @@ void AttachEngine::suggestMapModes(SuggestResult &result) const
|
||||
result.message = SuggestResult::srLinkBroken;
|
||||
result.bestFitMode = mmDeactivated;
|
||||
|
||||
std::vector<const TopoDS_Shape*> shapes;
|
||||
std::vector<TopoDS_Shape> shapeStorage;
|
||||
std::vector<const TopoShape*> shapes;
|
||||
std::vector<TopoShape> shapeStorage;
|
||||
std::vector<eRefType> typeStr;
|
||||
try{
|
||||
readLinks(getRefObjects(),subnames, shapes, shapeStorage, typeStr);
|
||||
@@ -578,8 +581,8 @@ eRefType AttachEngine::getShapeType(const App::DocumentObject *obj, const std::s
|
||||
//const_cast is worth here, to keep obj argument const. We are not going to write anything to obj through this temporary link.
|
||||
tmpLink.setValue(const_cast<App::DocumentObject*>(obj), subshape.c_str());
|
||||
|
||||
std::vector<const TopoDS_Shape*> shapes;
|
||||
std::vector<TopoDS_Shape> copiedShapeStorage;
|
||||
std::vector<const TopoShape*> shapes;
|
||||
std::vector<TopoShape> copiedShapeStorage;
|
||||
std::vector<eRefType> types;
|
||||
readLinks(tmpLink.getValues(), tmpLink.getSubValues(), shapes, copiedShapeStorage, types);
|
||||
|
||||
@@ -740,13 +743,14 @@ eRefType AttachEngine::getRefTypeByName(const std::string& typeName)
|
||||
throw AttachEngineException(errmsg.str());
|
||||
}
|
||||
|
||||
GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes)
|
||||
GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoShape*> &shapes)
|
||||
{
|
||||
//explode compounds
|
||||
TopTools_HSequenceOfShape totalSeq;
|
||||
for (const TopoDS_Shape* pSh : shapes) {
|
||||
for (auto tSh : shapes) {
|
||||
auto pSh = tSh->getShape();
|
||||
ShapeExtend_Explorer xp;
|
||||
totalSeq.Append( xp.SeqFromCompound(*pSh, /*recursive=*/true));
|
||||
totalSeq.Append( xp.SeqFromCompound(pSh, /*recursive=*/true));
|
||||
}
|
||||
if (totalSeq.Length() == 0)
|
||||
throw AttachEngineException("AttachEngine::getInertialPropsOfShape: no geometry provided");
|
||||
@@ -820,75 +824,96 @@ GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoD
|
||||
*/
|
||||
void AttachEngine::readLinks(const std::vector<App::DocumentObject*>& objs,
|
||||
const std::vector<std::string> &subs,
|
||||
std::vector<const TopoDS_Shape*> &shapes,
|
||||
std::vector<TopoDS_Shape> &storage,
|
||||
std::vector<const TopoShape*> &shapes,
|
||||
std::vector<TopoShape> &storage,
|
||||
std::vector<eRefType> &types)
|
||||
{
|
||||
storage.reserve(objs.size());
|
||||
shapes.resize(objs.size());
|
||||
types.resize(objs.size());
|
||||
|
||||
for (std::size_t i = 0; i < objs.size(); i++) {
|
||||
auto* geof = dynamic_cast<App::GeoFeature*>(objs[i]);
|
||||
auto geof = extractGeoFeature(objs[i]);
|
||||
if (!geof) {
|
||||
// Accept App::Links to GeoFeatures
|
||||
geof = dynamic_cast<App::GeoFeature*>(objs[i]->getLinkedObject());
|
||||
if (!geof) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: attached to a non App::GeoFeature '" << objs[i]->getNameInDocument() << "'");
|
||||
}
|
||||
}
|
||||
TopoDS_Shape myShape;
|
||||
|
||||
try {
|
||||
// getTopoShape support fully qualified subnames and should return shape with correct
|
||||
// global placement.
|
||||
Part::TopoShape shape = Part::Feature::getTopoShape(objs[i], subs[i].c_str(), true);
|
||||
for (;;) {
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found "
|
||||
<< objs[i]->getNameInDocument() << '.' << subs[i]);
|
||||
}
|
||||
if (shape.shapeType() != TopAbs_COMPOUND
|
||||
|| shape.countSubShapes(TopAbs_SHAPE) != 1) {
|
||||
break;
|
||||
}
|
||||
// auto extract the single sub-shape from a compound
|
||||
shape = shape.getSubTopoShape(TopAbs_SHAPE, 1);
|
||||
}
|
||||
|
||||
myShape = shape.getShape();
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << objs[i]->getNameInDocument()
|
||||
<< '.' << subs[i] << std::endl
|
||||
<< e.GetMessageString());
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << objs[i]->getNameInDocument()
|
||||
<< '.' << subs[i] << std::endl
|
||||
<< e.what());
|
||||
}
|
||||
if (myShape.IsNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.'
|
||||
<< subs[i]);
|
||||
"AttachEngine3D: attached to a non App::GeoFeature '"
|
||||
<< objs[i]->getNameInDocument() << "'");
|
||||
}
|
||||
|
||||
storage.emplace_back(myShape);
|
||||
auto shape = extractSubShape(objs[i], subs[i]);
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.'
|
||||
<< subs[i]);
|
||||
}
|
||||
|
||||
storage.emplace_back(shape);
|
||||
shapes[i] = &(storage.back());
|
||||
|
||||
// FIXME: unpack single-child compounds here? Compounds are not used so far, so it should be
|
||||
// considered later, when the need arises.
|
||||
types[i] = getShapeType(*(shapes[i]));
|
||||
types[i] = getShapeType(shapes[i]->getShape());
|
||||
|
||||
if (subs[i].length() == 0) {
|
||||
types[i] = eRefType(types[i] | rtFlagHasPlacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
App::GeoFeature* AttachEngine::extractGeoFeature(App::DocumentObject *obj)
|
||||
{
|
||||
if (auto geof = dynamic_cast<App::GeoFeature*>(obj)) {
|
||||
return geof;
|
||||
}
|
||||
|
||||
auto linkedObject = obj->getLinkedObject();
|
||||
if (auto linkedGeof = dynamic_cast<App::GeoFeature*>(linkedObject)) {
|
||||
return linkedGeof;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TopoShape AttachEngine::extractSubShape(App::DocumentObject* obj, const std::string& subname)
|
||||
{
|
||||
TopoShape shape;
|
||||
|
||||
try {
|
||||
// getTopoShape support fully qualified subnames and should return shape with correct
|
||||
// global placement.
|
||||
shape = Feature::getTopoShape(obj, subname.c_str(), true);
|
||||
|
||||
for (;;) {
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.'
|
||||
<< subname);
|
||||
}
|
||||
|
||||
if (shape.shapeType() != TopAbs_COMPOUND || shape.countSubShapes(TopAbs_SHAPE) != 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// auto extract the single sub-shape from a compound
|
||||
shape = shape.getSubTopoShape(TopAbs_SHAPE, 1);
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.'
|
||||
<< subname << std::endl
|
||||
<< e.GetMessageString());
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.'
|
||||
<< subname << std::endl
|
||||
<< e.what());
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
void AttachEngine::throwWrongMode(eMapMode mmode)
|
||||
{
|
||||
std::stringstream errmsg;
|
||||
@@ -1140,8 +1165,8 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
throw ExceptionCancel(); // to be handled in positionBySupport, to not do anything if
|
||||
// disabled
|
||||
}
|
||||
std::vector<const TopoDS_Shape*> shapes;
|
||||
std::vector<TopoDS_Shape> copiedShapeStorage;
|
||||
std::vector<const TopoShape*> shapes;
|
||||
std::vector<TopoShape> copiedShapeStorage;
|
||||
std::vector<eRefType> types;
|
||||
readLinks(objs, subs, shapes, copiedShapeStorage, types);
|
||||
|
||||
@@ -1172,7 +1197,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
throw Base::ValueError("AttachEngine3D::calculateAttachedPlacement: no subobjects "
|
||||
"specified (need one vertex).");
|
||||
}
|
||||
const TopoDS_Shape& sh = *shapes[0];
|
||||
const TopoDS_Shape& sh = shapes[0]->getShape();
|
||||
if (sh.IsNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngine3D::calculateAttachedPlacement()!");
|
||||
@@ -1207,7 +1232,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
gp_Pnt(Place.getPosition().x, Place.getPosition().y, Place.getPosition().z);
|
||||
}
|
||||
else if (isShapeOfType(types[0], rtConic) > 0) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(*shapes[0]);
|
||||
const TopoDS_Edge& e = TopoDS::Edge(shapes[0]->getShape());
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
gp_Ax3 pos;
|
||||
switch (adapt.GetType()) {
|
||||
@@ -1259,7 +1284,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
|
||||
TopoDS_Vertex vertex;
|
||||
try {
|
||||
vertex = TopoDS::Vertex(*(shapes[1]));
|
||||
vertex = TopoDS::Vertex(shapes[1]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1330,7 +1355,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
gp_Pln plane;
|
||||
bool Reverse = false;
|
||||
try {
|
||||
face = TopoDS::Face(*(shapes[0]));
|
||||
face = TopoDS::Face(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1387,14 +1412,14 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
}
|
||||
|
||||
bool bThruVertex = false;
|
||||
if (shapes[0]->ShapeType() == TopAbs_VERTEX) {
|
||||
if (shapes[0]->shapeType() == TopAbs_VERTEX) {
|
||||
std::swap(shapes[0], shapes[1]);
|
||||
bThruVertex = true;
|
||||
}
|
||||
|
||||
TopoDS_Face face;
|
||||
try {
|
||||
face = TopoDS::Face(*(shapes[0]));
|
||||
face = TopoDS::Face(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1405,7 +1430,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
|
||||
TopoDS_Vertex vertex;
|
||||
try {
|
||||
vertex = TopoDS::Vertex(*(shapes[1]));
|
||||
vertex = TopoDS::Vertex(shapes[1]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1472,14 +1497,14 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
}
|
||||
|
||||
bool bThruVertex = false;
|
||||
if (shapes[0]->ShapeType() == TopAbs_VERTEX && shapes.size() >= 2) {
|
||||
if (shapes[0]->shapeType() == TopAbs_VERTEX && shapes.size() >= 2) {
|
||||
std::swap(shapes[0], shapes[1]);
|
||||
bThruVertex = true;
|
||||
}
|
||||
|
||||
TopoDS_Edge path;
|
||||
try {
|
||||
path = TopoDS::Edge(*(shapes[0]));
|
||||
path = TopoDS::Edge(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1506,7 +1531,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
if (shapes.size() >= 2) {
|
||||
TopoDS_Vertex vertex;
|
||||
try {
|
||||
vertex = TopoDS::Vertex(*(shapes[1]));
|
||||
vertex = TopoDS::Vertex(shapes[1]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1633,7 +1658,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
std::vector<gp_Pnt> points;
|
||||
|
||||
for (const auto & shape : shapes) {
|
||||
const TopoDS_Shape &sh = *shape;
|
||||
const TopoDS_Shape &sh = shape->getShape();
|
||||
if (sh.IsNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngine3D::calculateAttachedPlacement()!");
|
||||
@@ -1725,7 +1750,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
gp_Lin lines[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
try {
|
||||
edges[i] = &TopoDS::Edge(*(shapes[i]));
|
||||
edges[i] = &TopoDS::Edge(shapes[i]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -1845,28 +1870,28 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
gp_Vec dirs[3];
|
||||
|
||||
// read out origin
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
THROWM(Base::TypeError, "AttachEngine3D::calculateAttachedPlacement: null shape!")
|
||||
}
|
||||
if (shapes[0]->ShapeType() != TopAbs_VERTEX) {
|
||||
if (shapes[0]->shapeType() != TopAbs_VERTEX) {
|
||||
THROWM(Base::TypeError,
|
||||
"AttachEngine3D::calculateAttachedPlacement: first reference must be a "
|
||||
"vertex, it's not")
|
||||
}
|
||||
SketchBasePoint = BRep_Tool::Pnt(TopoDS::Vertex(*(shapes[0])));
|
||||
SketchBasePoint = BRep_Tool::Pnt(TopoDS::Vertex(shapes[0]->getShape()));
|
||||
|
||||
// read out axes directions
|
||||
for (size_t i = 1; i < 3 && i < shapes.size(); ++i) {
|
||||
if (shapes[i]->IsNull()) {
|
||||
if (shapes[i]->isNull()) {
|
||||
THROWM(Base::TypeError,
|
||||
"AttachEngine3D::calculateAttachedPlacement: null shape!")
|
||||
}
|
||||
if (shapes[i]->ShapeType() == TopAbs_VERTEX) {
|
||||
gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(*(shapes[i])));
|
||||
if (shapes[i]->shapeType() == TopAbs_VERTEX) {
|
||||
gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(shapes[i]->getShape()));
|
||||
dirs[order[i - 1]] = gp_Vec(SketchBasePoint, p);
|
||||
}
|
||||
else if (shapes[i]->ShapeType() == TopAbs_EDGE) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(*(shapes[i]));
|
||||
else if (shapes[i]->shapeType() == TopAbs_EDGE) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(shapes[i]->getShape());
|
||||
BRepAdaptor_Curve crv(e);
|
||||
double u1 = crv.FirstParameter();
|
||||
double u2 = crv.LastParameter();
|
||||
@@ -1896,6 +1921,90 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
|
||||
plm *= this->attachmentOffset;
|
||||
return plm;
|
||||
} break;
|
||||
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());
|
||||
|
||||
switch (shape->shapeType()) {
|
||||
case TopAbs_VERTEX: {
|
||||
if (auto point = dynamic_cast<GeomPoint*>(geom.get())) {
|
||||
placement.setPosition(point->getPoint());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TopAbs_EDGE: {
|
||||
if (auto conic = dynamic_cast<GeomConic*>(geom.get())) {
|
||||
placement.setPosition(conic->getLocation());
|
||||
placement.setRotation(conic->getRotation().value_or(Base::Rotation {}));
|
||||
} else if (auto line = dynamic_cast<GeomCurve*>(geom.get())) {
|
||||
auto u1 = line->getFirstParameter();
|
||||
auto u2 = line->getLastParameter();
|
||||
|
||||
auto middle = (u1 + u2) / 2;
|
||||
|
||||
placement.setPosition(line->pointAtParameter(middle));
|
||||
|
||||
Base::Vector3d direction;
|
||||
if (!line->normalAt(middle, direction)) {
|
||||
line->tangent(middle, direction);
|
||||
}
|
||||
|
||||
placement.setRotation(Base::Rotation::fromNormalVector(direction));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TopAbs_FACE: {
|
||||
auto surface = dynamic_cast<GeomSurface*>(geom.get());
|
||||
|
||||
if (auto sphere = dynamic_cast<GeomSphere*>(geom.get())) {
|
||||
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->getBoundBox().GetCenter());
|
||||
}
|
||||
|
||||
if (auto rotation = surface->getRotation()) {
|
||||
placement.setRotation(*rotation);
|
||||
} else {
|
||||
auto adaptorSurface = BRepAdaptor_Surface(TopoDS::Face(shape->getShape()), true);
|
||||
|
||||
auto u1 = adaptorSurface.FirstUParameter();
|
||||
auto u2 = adaptorSurface.LastUParameter();
|
||||
auto v1 = adaptorSurface.FirstVParameter();
|
||||
auto v2 = adaptorSurface.LastVParameter();
|
||||
|
||||
// calculate the normal at midpoint of the surface and use it as Z axis
|
||||
gp_Dir dir;
|
||||
surface->normal((u1 + u2) / 2, (v1 + v2) / 2, dir);
|
||||
|
||||
placement.setRotation(Base::Rotation::fromNormalVector(Base::convertTo<Base::Vector3d>(-dir)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
THROWM(Base::TypeError,
|
||||
"AttachEngine3D::calculateAttachedPlacement: Unsupported shape type, "
|
||||
"must be one of: Vertex, Edge, Face");
|
||||
break;
|
||||
}
|
||||
|
||||
return placement * attachmentOffset;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throwWrongMode(mmode);
|
||||
} // switch (MapMode)
|
||||
@@ -2083,8 +2192,8 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
|
||||
Base::Placement plm;
|
||||
if (!bReUsed) {
|
||||
std::vector<const TopoDS_Shape*> shapes;
|
||||
std::vector<TopoDS_Shape> copiedShapeStorage;
|
||||
std::vector<const TopoShape*> shapes;
|
||||
std::vector<TopoShape> copiedShapeStorage;
|
||||
std::vector<eRefType> types;
|
||||
readLinks(objs, subs, shapes, copiedShapeStorage, types);
|
||||
|
||||
@@ -2157,7 +2266,7 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
std::vector<gp_Pnt> points;
|
||||
|
||||
for (const auto & shape : shapes) {
|
||||
const TopoDS_Shape &sh = *shape;
|
||||
const TopoDS_Shape &sh = shape->getShape();
|
||||
if (sh.IsNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
@@ -2197,13 +2306,13 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
} break;
|
||||
case mm1Asymptote1:
|
||||
case mm1Asymptote2: {
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
}
|
||||
TopoDS_Edge e;
|
||||
try {
|
||||
e = TopoDS::Edge(*(shapes[0]));
|
||||
e = TopoDS::Edge(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -2228,13 +2337,13 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
} break;
|
||||
case mm1Directrix1:
|
||||
case mm1Directrix2: {
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
}
|
||||
TopoDS_Edge e;
|
||||
try {
|
||||
e = TopoDS::Edge(*(shapes[0]));
|
||||
e = TopoDS::Edge(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -2283,13 +2392,13 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
"AttachEngineLine::calculateAttachedPlacement: Intersection mode requires "
|
||||
"two shapes; only one is supplied");
|
||||
}
|
||||
if (shapes[0]->IsNull() || shapes[1]->IsNull()) {
|
||||
if (shapes[0]->isNull() || shapes[1]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
}
|
||||
|
||||
const TopoDS_Face& face1 = TopoDS::Face(*(shapes[0]));
|
||||
const TopoDS_Face& face2 = TopoDS::Face(*(shapes[1]));
|
||||
const TopoDS_Face& face1 = TopoDS::Face(shapes[0]->getShape());
|
||||
const TopoDS_Face& face2 = TopoDS::Face(shapes[1]->getShape());
|
||||
|
||||
Handle(Geom_Surface) hSurf1 = BRep_Tool::Surface(face1);
|
||||
Handle(Geom_Surface) hSurf2 = BRep_Tool::Surface(face2);
|
||||
@@ -2324,15 +2433,15 @@ AttachEngineLine::_calculateAttachedPlacement(const std::vector<App::DocumentObj
|
||||
"AttachEngineLine::calculateAttachedPlacement: Proximity mode requires two "
|
||||
"shapes; only one is supplied");
|
||||
}
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
}
|
||||
if (shapes[1]->IsNull()) {
|
||||
if (shapes[1]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEngineLine::calculateAttachedPlacement()!");
|
||||
}
|
||||
BRepExtrema_DistShapeShape distancer(*(shapes[0]), *(shapes[1]));
|
||||
BRepExtrema_DistShapeShape distancer(shapes[0]->getShape(), shapes[1]->getShape());
|
||||
if (!distancer.IsDone()) {
|
||||
throw Base::ValueError("AttachEngineLine::calculateAttachedPlacement: "
|
||||
"proximity calculation failed.");
|
||||
@@ -2450,8 +2559,8 @@ AttachEnginePoint::_calculateAttachedPlacement(const std::vector<App::DocumentOb
|
||||
|
||||
Base::Placement plm;
|
||||
if (!bReUsed) {
|
||||
std::vector<const TopoDS_Shape*> shapes;
|
||||
std::vector<TopoDS_Shape> copiedShapeStorage;
|
||||
std::vector<const TopoShape*> shapes;
|
||||
std::vector<TopoShape> copiedShapeStorage;
|
||||
std::vector<eRefType> types;
|
||||
readLinks(objs, subs, shapes, copiedShapeStorage, types);
|
||||
|
||||
@@ -2470,7 +2579,7 @@ AttachEnginePoint::_calculateAttachedPlacement(const std::vector<App::DocumentOb
|
||||
std::vector<gp_Pnt> points;
|
||||
assert(!shapes.empty());
|
||||
|
||||
const TopoDS_Shape& sh = *shapes[0];
|
||||
const TopoDS_Shape& sh = shapes[0]->getShape();
|
||||
if (sh.IsNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
|
||||
@@ -2492,13 +2601,13 @@ AttachEnginePoint::_calculateAttachedPlacement(const std::vector<App::DocumentOb
|
||||
} break;
|
||||
case mm0Focus1:
|
||||
case mm0Focus2: {
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
|
||||
}
|
||||
TopoDS_Edge e;
|
||||
try {
|
||||
e = TopoDS::Edge(*(shapes[0]));
|
||||
e = TopoDS::Edge(shapes[0]->getShape());
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
@@ -2546,16 +2655,16 @@ AttachEnginePoint::_calculateAttachedPlacement(const std::vector<App::DocumentOb
|
||||
"AttachEnginePoint::calculateAttachedPlacement: Proximity mode requires "
|
||||
"two shapes; only one is supplied");
|
||||
}
|
||||
if (shapes[0]->IsNull()) {
|
||||
if (shapes[0]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
|
||||
}
|
||||
if (shapes[1]->IsNull()) {
|
||||
if (shapes[1]->isNull()) {
|
||||
throw Base::ValueError(
|
||||
"Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
|
||||
}
|
||||
|
||||
BasePoint = getProximityPoint(mmode, *(shapes[0]), *(shapes[1]));
|
||||
BasePoint = getProximityPoint(mmode, shapes[0]->getShape(), shapes[1]->getShape());
|
||||
} break;
|
||||
case mm0CenterOfMass: {
|
||||
GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes);
|
||||
|
||||
@@ -108,6 +108,7 @@ enum eMapMode {
|
||||
mmOYX,
|
||||
|
||||
mmParallelPlane,
|
||||
mmMidpoint,
|
||||
|
||||
mmDummy_NumberOfModes//a value useful to check the validity of mode value
|
||||
};//see also eMapModeStrings[] definition in .cpp
|
||||
@@ -363,7 +364,7 @@ public://helper functions that may be useful outside of the class
|
||||
|
||||
static eRefType getRefTypeByName(const std::string &typeName);
|
||||
|
||||
static GProp_GProps getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes);
|
||||
static GProp_GProps getInertialPropsOfShape(const std::vector<const Part::TopoShape*> &shapes);
|
||||
|
||||
std::vector<App::DocumentObject*> getRefObjects() const;
|
||||
const std::vector<std::string> &getSubValues() const {return subnames;}
|
||||
@@ -430,11 +431,36 @@ protected:
|
||||
}
|
||||
static void readLinks(const std::vector<App::DocumentObject*> &objs,
|
||||
const std::vector<std::string> &subs,
|
||||
std::vector<const TopoDS_Shape*>& shapes, std::vector<TopoDS_Shape> &storage,
|
||||
|
||||
std::vector<const Part::TopoShape*>& shapes,
|
||||
std::vector<Part::TopoShape> &storage,
|
||||
std::vector<eRefType> &types);
|
||||
|
||||
static void throwWrongMode(eMapMode mmode);
|
||||
|
||||
/**
|
||||
* Extracts GeoFeature instance from given DocumentObject.
|
||||
*
|
||||
* In case of object itself being GeoFeature it returns itself, in other cases (like links)
|
||||
* the method should return pointer to associated GeoFeature or nullptr if none is available.
|
||||
*
|
||||
* @param obj The document object to extract the GeoFeature.
|
||||
*
|
||||
* @return App::GeoFeature pointer associated with this document object
|
||||
*/
|
||||
static App::GeoFeature* extractGeoFeature(App::DocumentObject* obj);
|
||||
|
||||
/**
|
||||
* Tries to extract sub shape from document object with given subname.
|
||||
*
|
||||
* @param obj DocumentObject containing the sub shape
|
||||
* @param subname Name of the sub shape to extract
|
||||
*
|
||||
* @return Extracted sub shape. Can be null.
|
||||
*
|
||||
* @throws AttachEngineException If given sub shape does not exist or is impossible to obtain.
|
||||
*/
|
||||
static Part::TopoShape extractSubShape(App::DocumentObject* obj, const std::string& subname);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -553,6 +553,8 @@ SET(Part_SRCS
|
||||
PreCompiled.h
|
||||
ProgressIndicator.cpp
|
||||
ProgressIndicator.h
|
||||
Services.cpp
|
||||
Services.h
|
||||
TopoShape.cpp
|
||||
TopoShape.h
|
||||
TopoShapeCache.cpp
|
||||
|
||||
@@ -149,6 +149,8 @@
|
||||
#include "ToroidPy.h"
|
||||
#include "TopoShape.h"
|
||||
|
||||
#include <gp_Quaternion.hxx>
|
||||
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using GeomAdaptor_HCurve = GeomAdaptor_Curve;
|
||||
@@ -2127,10 +2129,25 @@ void GeomConic::setLocation(const Base::Vector3d& Center)
|
||||
|
||||
Base::Vector3d GeomConic::getCenter() const
|
||||
{
|
||||
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
|
||||
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
|
||||
gp_Ax1 axis = conic->Axis();
|
||||
const gp_Pnt& loc = axis.Location();
|
||||
return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
|
||||
return Base::Vector3d(loc.X(), loc.Y(), loc.Z());
|
||||
}
|
||||
|
||||
std::optional<Base::Rotation> GeomConic::getRotation() const
|
||||
{
|
||||
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(handle());
|
||||
|
||||
if (!conic) {
|
||||
return {};
|
||||
}
|
||||
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTransformation(conic->Position(), gp_Ax3());
|
||||
|
||||
auto q = trsf.GetRotation();
|
||||
return Base::Rotation(q.X(), q.Y(), q.Z(), q.W());
|
||||
}
|
||||
|
||||
void GeomConic::setCenter(const Base::Vector3d& Center)
|
||||
@@ -2142,7 +2159,6 @@ void GeomConic::setCenter(const Base::Vector3d& Center)
|
||||
conic->SetLocation(p1);
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
|
||||
THROWM(Base::CADKernelError,e.GetMessageString())
|
||||
}
|
||||
}
|
||||
@@ -4803,28 +4819,36 @@ GeomPlane* GeomSurface::toPlane(bool clone, double tol) const
|
||||
if (isDerivedFrom(GeomPlane::getClassTypeId())) {
|
||||
if (clone) {
|
||||
return dynamic_cast<GeomPlane*>(this->clone());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return dynamic_cast<GeomPlane*>(this->copy());
|
||||
}
|
||||
}
|
||||
|
||||
gp_Pln pln;
|
||||
if (!isPlanar(&pln, tol))
|
||||
if (!isPlanar(&pln, tol)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto res = new GeomPlane(pln);
|
||||
res->copyNonTag(this);
|
||||
if (clone)
|
||||
if (clone) {
|
||||
res->tag = this->tag;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<Base::Rotation> GeomSurface::getRotation() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
TopoDS_Shape GeomSurface::toShape() const
|
||||
{
|
||||
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
|
||||
Standard_Real u1,u2,v1,v2;
|
||||
s->Bounds(u1,u2,v1,v2);
|
||||
BRepBuilderAPI_MakeFace mkBuilder(s, u1, u2, v1, v2, Precision::Confusion() );
|
||||
Standard_Real u1, u2, v1, v2;
|
||||
s->Bounds(u1, u2, v1, v2);
|
||||
BRepBuilderAPI_MakeFace mkBuilder(s, u1, u2, v1, v2, Precision::Confusion());
|
||||
return mkBuilder.Shape();
|
||||
}
|
||||
|
||||
@@ -5180,9 +5204,24 @@ GeomElementarySurface::~GeomElementarySurface()
|
||||
|
||||
Base::Vector3d GeomElementarySurface::getLocation(void) const
|
||||
{
|
||||
Handle(Geom_ElementarySurface) surf = Handle(Geom_ElementarySurface)::DownCast(handle());
|
||||
Handle(Geom_ElementarySurface) surf = Handle(Geom_ElementarySurface)::DownCast(handle());
|
||||
gp_Pnt loc = surf->Location();
|
||||
return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
|
||||
return Base::Vector3d(loc.X(), loc.Y(), loc.Z());
|
||||
}
|
||||
|
||||
std::optional<Base::Rotation> GeomPlane::getRotation() const
|
||||
{
|
||||
Handle(Geom_ElementarySurface) s = Handle(Geom_ElementarySurface)::DownCast(handle());
|
||||
|
||||
if (!s) {
|
||||
return {};
|
||||
}
|
||||
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTransformation(s->Position().Ax2(),gp_Ax3());
|
||||
auto q = trsf.GetRotation();
|
||||
|
||||
return Base::Rotation(q.X(),q.Y(),q.Z(),q.W());
|
||||
}
|
||||
|
||||
Base::Vector3d GeomElementarySurface::getDir(void) const
|
||||
@@ -5411,6 +5450,12 @@ double GeomCone::getSemiAngle() const
|
||||
return mySurface->SemiAngle();
|
||||
}
|
||||
|
||||
Base::Vector3d GeomCone::getApex() const
|
||||
{
|
||||
Handle(Geom_ConicalSurface) s = Handle(Geom_ConicalSurface)::DownCast(handle());
|
||||
return Base::convertTo<Base::Vector3d>(s->Apex());
|
||||
}
|
||||
|
||||
bool GeomCone::isSame(const Geometry &_other, double tol, double atol) const
|
||||
{
|
||||
if(_other.getTypeId() != getTypeId())
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
|
||||
@@ -409,6 +410,7 @@ public:
|
||||
*/
|
||||
Base::Vector3d getCenter() const;
|
||||
Base::Vector3d getLocation() const;
|
||||
std::optional<Base::Rotation> getRotation() const;
|
||||
void setLocation(const Base::Vector3d& Center);
|
||||
/*!
|
||||
* \deprecated use setLocation
|
||||
@@ -882,6 +884,8 @@ public:
|
||||
|
||||
GeomPlane *toPlane(bool clone=true, double tol=1e-7) const;
|
||||
|
||||
virtual std::optional<Base::Rotation> getRotation() const;
|
||||
|
||||
bool tangentU(double u, double v, gp_Dir& dirU) const;
|
||||
bool tangentV(double u, double v, gp_Dir& dirV) const;
|
||||
bool normal(double u, double v, gp_Dir& dir) const;
|
||||
@@ -961,6 +965,7 @@ public:
|
||||
~GeomElementarySurface() override;
|
||||
|
||||
Base::Vector3d getLocation() const;
|
||||
|
||||
Base::Vector3d getDir() const;
|
||||
Base::Vector3d getXDir() const;
|
||||
Base::Vector3d getYDir() const;
|
||||
@@ -1014,6 +1019,8 @@ public:
|
||||
double getRadius() const;
|
||||
double getSemiAngle() const;
|
||||
|
||||
Base::Vector3d getApex() const;
|
||||
|
||||
bool isSame(const Geometry &other, double tol, double atol) const override;
|
||||
|
||||
void setHandle(const Handle(Geom_ConicalSurface)&);
|
||||
@@ -1091,6 +1098,8 @@ public:
|
||||
~GeomPlane() override;
|
||||
Geometry *copy() const override;
|
||||
|
||||
std::optional<Base::Rotation> getRotation() const override;
|
||||
|
||||
// Persistence implementer ---------------------
|
||||
unsigned int getMemSize() const override;
|
||||
void Save(Base::Writer &/*writer*/) const override;
|
||||
|
||||
55
src/Mod/Part/App/Services.cpp
Normal file
55
src/Mod/Part/App/Services.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 Kacper Donat <kacper@kadet.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "Services.h"
|
||||
|
||||
AttacherSubObjectPlacement::AttacherSubObjectPlacement()
|
||||
: attacher(std::make_unique<Attacher::AttachEngine3D>())
|
||||
{
|
||||
attacher->setUp({}, Attacher::mmMidpoint);
|
||||
}
|
||||
|
||||
Base::Placement AttacherSubObjectPlacement::calculate(App::SubObjectT object,
|
||||
Base::Placement basePlacement) const
|
||||
{
|
||||
attacher->setReferences({object});
|
||||
|
||||
auto calculatedAttachment = attacher->calculateAttachedPlacement(basePlacement);
|
||||
|
||||
return basePlacement.inverse() * calculatedAttachment;
|
||||
}
|
||||
|
||||
std::optional<Base::Vector3d> PartCenterOfMass::ofDocumentObject(App::DocumentObject* object) const
|
||||
{
|
||||
if (const auto feature = dynamic_cast<Part::Feature*>(object)) {
|
||||
const auto shape = feature->Shape.getShape();
|
||||
|
||||
if (const auto cog = shape.centerOfGravity()) {
|
||||
const Base::Placement comPlacement { *cog, Base::Rotation { } };
|
||||
|
||||
return (feature->Placement.getValue().inverse() * comPlacement).getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
47
src/Mod/Part/App/Services.h
Normal file
47
src/Mod/Part/App/Services.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 Kacper Donat <kacper@kadet.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PART_SERVICES_H
|
||||
#define PART_SERVICES_H
|
||||
|
||||
#include <Attacher.h>
|
||||
#include <App/Services.h>
|
||||
|
||||
class AttacherSubObjectPlacement final: public App::SubObjectPlacementProvider
|
||||
{
|
||||
public:
|
||||
AttacherSubObjectPlacement();
|
||||
|
||||
Base::Placement calculate(App::SubObjectT object, Base::Placement basePlacement) const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Attacher::AttachEngine3D> attacher;
|
||||
};
|
||||
|
||||
class PartCenterOfMass final: public App::CenterOfMassProvider
|
||||
{
|
||||
public:
|
||||
std::optional<Base::Vector3d> ofDocumentObject(App::DocumentObject* object) const override;
|
||||
};
|
||||
|
||||
#endif // PART_SERVICES_H
|
||||
@@ -81,7 +81,16 @@ void ViewProvider::setupContextMenu(QMenu* menu, QObject* receiver, const char*
|
||||
|
||||
bool ViewProvider::setEdit(int ModNum)
|
||||
{
|
||||
if (ModNum == ViewProvider::Default ) {
|
||||
if (ModNum == ViewProvider::Transform) {
|
||||
if (forwardToLink()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is feature so we need to forward the transform to the body
|
||||
forwardedViewProvider = getBodyViewProvider();
|
||||
return forwardedViewProvider->startEditing(ModNum);
|
||||
}
|
||||
else if (ModNum == ViewProvider::Default) {
|
||||
// When double-clicking on the item for this feature the
|
||||
// object unsets and sets its edit mode without closing
|
||||
// the task panel
|
||||
@@ -194,6 +203,22 @@ void ViewProvider::onChanged(const App::Property* prop) {
|
||||
PartGui::ViewProviderPartExt::onChanged(prop);
|
||||
}
|
||||
|
||||
Gui::ViewProvider* ViewProvider::startEditing(int ModNum)
|
||||
{
|
||||
// in case of transform we forward the request to body
|
||||
if (ModNum == Transform) {
|
||||
forwardedViewProvider = nullptr;
|
||||
|
||||
if (!ViewProviderPart::startEditing(ModNum)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return forwardedViewProvider;
|
||||
}
|
||||
|
||||
return ViewProviderPart::startEditing(ModNum);
|
||||
}
|
||||
|
||||
void ViewProvider::setTipIcon(bool onoff) {
|
||||
isSetTipIcon = onoff;
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
void updateData(const App::Property*) override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
Gui::ViewProvider* startEditing(int ModNum) override;
|
||||
|
||||
void setTipIcon(bool onoff);
|
||||
|
||||
//body mode means that the object is part of a body and that the body is used to set the
|
||||
|
||||
Reference in New Issue
Block a user