This post is some notes, I was keeping working out how free cad is put together.(This may not make sense to anyone other than me)
So.. freshly armed with Qt-Creator 2.4.1 I’m delving into freeCAD source once again.
There is all kind fun stuff in this code. Anyway… What I want to do is to draw an Arc instead of a polyline when drawing in polyline mode and the left mouse button is released.
So.. I think the goals for me in this post:
- Find the code line where the decision needs to be made to either continue with an arc or line.
- Understand what defines polyline mode.
Seems like this should be simple enough chunk to digest in a couple of gulps. After that I need to see how to test for the keypress state and how to invoke the arc mode. Anyway, that’s another step further down…
Ok.. I think whats going on is that events get processed through a base class?Gui::ViewProvider::eventCallback. It looks like that perhaps the indivdual benches have there own implementation in virtual functions..
I believe my first goal is going to be found in:
bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVec3f &point,
const SbVec3f &normal, const SoPickedPoint *pp)
So.. Some how ViewProvider is provider is inherited by ViewProviderSketch.. (Hmm. Just a quick thought here if I do a search on ViewProvider I wonder what else pops up. I’m seeing ViewProvider* stuff in Fem,Inspection… What a second… the filename ViewProvider.h shows up in a bunch a places in the code trunk.
jonas@jonas-laptop:~/freecad$ find -name ViewProvider.h
./free-cad/src/Mod/Points/Gui/ViewProvider.h
./free-cad/src/Mod/PartDesign/Gui/ViewProvider.h
./free-cad/src/Mod/Part/Gui/ViewProvider.h
./free-cad/src/Mod/Mesh/Gui/ViewProvider.h
./free-cad/src/Gui/ViewProvider.h
Hopefully I’ll have an aha moment when I dissect that, but at first glance that seems strange.
Anyway there seems to be a bunch of headers prefixed with viewProvider:
jonas@jonas-laptop:~/freecad$ find -name ViewProvider*.h
./free-cad/src/Mod/Inspection/Gui/ViewProviderInspection.h
./free-cad/src/Mod/Image/Gui/ViewProviderImagePlane.h
./free-cad/src/Mod/Points/Gui/ViewProvider.h
./free-cad/src/Mod/Robot/Gui/ViewProviderRobotObject.h
./free-cad/src/Mod/Robot/Gui/ViewProviderTrajectoryCompound.h
./free-cad/src/Mod/Robot/Gui/ViewProviderTrajectory.h
./free-cad/src/Mod/Robot/Gui/ViewProviderEdge2TracObject.h
./free-cad/src/Mod/Robot/Gui/ViewProviderTrajectoryDressUp.h
./free-cad/src/Mod/Fem/Gui/ViewProviderFemMesh.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderHole.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderChamfer.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderFillet.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderPocket.h
./free-cad/src/Mod/PartDesign/Gui/ViewProvider.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderRevolution.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderMainPart.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderPad.h
./free-cad/src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.h
./free-cad/src/Mod/Drawing/Gui/ViewProviderView.h
./free-cad/src/Mod/Drawing/Gui/ViewProviderPage.h
./free-cad/src/Mod/Sketcher/Gui/ViewProviderPython.h
./free-cad/src/Mod/Sketcher/Gui/ViewProviderSketch.h
./free-cad/src/Mod/Part/Gui/ViewProviderCurveNet.h
./free-cad/src/Mod/Part/Gui/ViewProviderImport.h
./free-cad/src/Mod/Part/Gui/ViewProvider.h
./free-cad/src/Mod/Part/Gui/ViewProvider2DObject.h
./free-cad/src/Mod/Part/Gui/ViewProviderPython.h
./free-cad/src/Mod/Part/Gui/ViewProviderBoolean.h
./free-cad/src/Mod/Part/Gui/ViewProviderExtrusion.h
./free-cad/src/Mod/Part/Gui/ViewProviderMirror.h
./free-cad/src/Mod/Part/Gui/ViewProviderReference.h
./free-cad/src/Mod/Part/Gui/ViewProviderExt.h
./free-cad/src/Mod/Part/Gui/ViewProviderBox.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderCurvature.h
./free-cad/src/Mod/Mesh/Gui/ViewProvider.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderMeshNode.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderPython.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderTransform.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h
./free-cad/src/Mod/Mesh/Gui/ViewProviderDefects.h
./free-cad/src/Gui/ViewProvider.h
./free-cad/src/Gui/ViewProviderPythonFeaturePy.h
./free-cad/src/Gui/ViewProviderDocumentObject.h
./free-cad/src/Gui/ViewProviderDocumentObjectPy.h
./free-cad/src/Gui/ViewProviderGeometryObject.h
./free-cad/src/Gui/ViewProviderExtern.h
./free-cad/src/Gui/ViewProviderVRMLObject.h
./free-cad/src/Gui/ViewProviderBuilder.h
./free-cad/src/Gui/ViewProviderAnnotation.h
./free-cad/src/Gui/ViewProviderPy.h
./free-cad/src/Gui/ViewProviderMeasureDistance.h
./free-cad/src/Gui/ViewProviderInventorObject.h
./free-cad/src/Gui/ViewProviderPythonFeature.h
./free-cad/src/Gui/ViewProviderDocumentObjectGroup.h
./free-cad/src/Gui/ViewProviderFeature.h
jonas@jonas-laptop:~/freecad$
I think I need to see the class declaration of ViewProviderSketch to see what gets inherited
class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObject, public Gui::SelectionObserver
A couple of thing here catch my eye here…
First off whats deal with “SketcherGuiExport”.
At first glance this doesn’t seem like a normal class definition.
It looks like SketcherGuiExport is declared in PreCompiled.h
#ifndef __PRECOMPILED_GUI__
#define __PRECOMPILED_GUI__
#include
// Importing of App classes
#ifdef FC_OS_WIN32
# define PartDesignExport __declspec(dllimport)
# define PartDesignGuiExport __declspec(dllexport)
# define PartExport __declspec(dllimport)
# define PartGuiExport __declspec(dllimport)
# define SketcherExport __declspec(dllimport)
# define SketcherGuiExport __declspec(dllimport)
#else // for Linux
# define PartDesignExport
# define PartDesignGuiExport
# define PartExport
# define PartGuiExport
# define SketcherExport
# define SketcherGuiExport
#endif
So.. In linux it’s normal C++ and in windows its got this __declspec(dllimport) ?? Ok.. So it’s a microsoft thing..
Ok… Back to business.. Some how ViewProviderSketch inherits ViewProvider.
Hopefully this doesn’t go down too many layers..
Need to look at the class declaration of ViewProvider2DObject which ViewProviderSketch inherits:
class PartGuiExport ViewProvider2DObject: public PartGui::ViewProviderPart
Which is inherited from:
#if defined(FC_USE_FAST_SHAPE_RENDERING)
class PartGuiExport ViewProviderPart : public ViewProviderPartExt
{
PROPERTY_HEADER(PartGui::ViewProviderPart);
public:
/// constructor
ViewProviderPart();
/// destructor
virtual ~ViewProviderPart();
};
#else
class PartGuiExport ViewProviderPart : public ViewProviderPartBase
{
PROPERTY_HEADER(PartGui::ViewProviderPart);
public:
/// constructor
ViewProviderPart();
/// destructor
virtual ~ViewProviderPart();
};
#endif
} // namespace PartGui
Heh.. A conditional class declaration depending on whether or not FC_USE_FAST_SHAPE_RENDERING is declared. Cool but this is starting to make my eyeballs ache. Ok.. I wonder where FC_USE_FAST_SHAPE_RENDERING is defined.
It seems to be defined in without much fanfare:
// Set this to use the fast rendering of shapes
#define FC_USE_FAST_SHAPE_RENDERING
in /home/jonas/freecad/free-cad/src/Mod/Part/Gui/ViewProvider.h
Soo.. it looks like this is path taken..
class PartGuiExport ViewProviderPartExt : public Gui::ViewProviderGeometryObject
And so on:
class GuiExport ViewProviderGeometryObject : public ViewProviderDocumentObject
And so on:
class GuiExport ViewProviderDocumentObject : public ViewProvider
{
I think we’re almost there:
There you go..
class GuiExport ViewProvider : public App::PropertyContainer
Wow that’s a lot of layers.. Ok.. Back to what I was trying to do here.
bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVec3f &point,
const SbVec3f &normal, const SoPickedPoint *pp)
{
assert(edit);// Radius maximum to allow double click event
const int dblClickRadius = 5;double x,y;
SbVec3f pos = point;
if (pp) {
const SoDetail *detail = pp->getDetail();
if (detail && detail->getTypeId() == SoPointDetail::getClassTypeId()) {
pos = pp->getPoint();
}
}getCoordsOnSketchPlane(x,y,pos,normal);
snapToGrid(x, y);// Left Mouse button ****************************************************
if (Button == 1) {
if (pressed) {
// Do things depending on the mode of the user interaction
switch (Mode) {
case STATUS_NONE:{
bool done=false;
// Double click events variables
SbTime tmp = (SbTime::getTimeOfDay() – prvClickTime);
float dci = (float) QApplication::doubleClickInterval()/1000.0f;
float length = (point – prvClickPoint).length();if (edit->PreselectPoint != -1) {
//Base::Console().Log(“start dragging, point:%d\n”,this->DragPoint);
Mode = STATUS_SELECT_Point;
done = true;
} else if (edit->PreselectCurve != -1) {
//Base::Console().Log(“start dragging, point:%d\n”,this->DragPoint);
Mode = STATUS_SELECT_Edge;
done = true;
} else if (edit->PreselectCross != -1) {
//Base::Console().Log(“start dragging, point:%d\n”,this->DragPoint);
Mode = STATUS_SELECT_Cross;
done = true;
} else if (edit->PreselectConstraint != -1) {
//Base::Console().Log(“start dragging, point:%d\n”,this->DragPoint);
Mode = STATUS_SELECT_Constraint;
done = true;}
if (done && length < dblClickRadius && tmp.getValue() < dci) {
// Double Click Event Occured
editDoubleClicked();
// Reset Double Click Static Variables
prvClickTime = SbTime();
prvClickPoint = SbVec3f(0.0f, 0.0f, 0.0f);
Mode = STATUS_NONE;} else {
prvClickTime = SbTime::getTimeOfDay();
prvClickPoint = point;
}return done;
}
case STATUS_SKETCH_UseHandler:
return edit->sketchHandler->pressButton(Base::Vector2D(x,y));
default:
return false;
}
}
else {
// Do things depending on the mode of the user interaction
switch (Mode) {
case STATUS_SELECT_Point:
if (pp) {
//Base::Console().Log(“Select Point:%d\n”,this->DragPoint);
// Do selection
std::stringstream ss;
ss << “Vertex” << edit->PreselectPoint;if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(),ss.str().c_str()) ) {
Gui::Selection().rmvSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(), ss.str().c_str());
} else {
Gui::Selection().addSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument()
,ss.str().c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
this->edit->DragPoint = -1;
this->edit->DragCurve = -1;
this->edit->DragConstraint = -1;
}
}
Mode = STATUS_NONE;
return true;
case STATUS_SELECT_Edge:
if (pp) {
//Base::Console().Log(“Select Point:%d\n”,this->DragPoint);
std::stringstream ss;
if (edit->PreselectCurve >= 0)
ss << “Edge” << edit->PreselectCurve;
else // external geometry
ss << “ExternalEdge” << -edit->PreselectCurve – 3;// If edge already selected move from selection
if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(),ss.str().c_str()) ) {
Gui::Selection().rmvSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(), ss.str().c_str());
} else {
// Add edge to the selection
Gui::Selection().addSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument()
,ss.str().c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
this->edit->DragPoint = -1;
this->edit->DragCurve = -1;
this->edit->DragConstraint = -1;
}
}
Mode = STATUS_NONE;
return true;
case STATUS_SELECT_Cross:
if (pp) {
//Base::Console().Log(“Select Point:%d\n”,this->DragPoint);
std::stringstream ss;
switch(edit->PreselectCross){
case 0: ss << “RootPoint” ; break;
case 1: ss << “H_Axis” ; break;
case 2: ss << “V_Axis” ; break;
}// If cross already selected move from selection
if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(),ss.str().c_str()) ) {
Gui::Selection().rmvSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(), ss.str().c_str());
} else {
// Add cross to the selection
Gui::Selection().addSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument()
,ss.str().c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
this->edit->DragPoint = -1;
this->edit->DragCurve = -1;
this->edit->DragConstraint = -1;
}
}
Mode = STATUS_NONE;
return true;
case STATUS_SELECT_Constraint:
if (pp) {std::stringstream ss;
ss << “Constraint” << edit->PreselectConstraint;// If the constraint already selected remove
if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(),ss.str().c_str()) ) {
Gui::Selection().rmvSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(), ss.str().c_str());
} else {
// Add constraint to current selection
Gui::Selection().addSelection(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument()
,ss.str().c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
this->edit->DragPoint = -1;
this->edit->DragCurve = -1;
this->edit->DragConstraint = -1;
}
}
Mode = STATUS_NONE;
return true;
case STATUS_SKETCH_DragPoint:
if (edit->DragPoint != -1 && pp) {
int GeoId;
Sketcher::PointPos PosId;
getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId);
Gui::Command::openCommand(“Drag Point”);
Gui::Command::doCommand(Gui::Command::Doc,”App.ActiveDocument.%s.movePoint(%i,%i,App.Vector(%f,%f,0),%i)”
,getObject()->getNameInDocument()
,GeoId, PosId, x-xInit, y-yInit, relative ? 1 : 0
);
Gui::Command::commitCommand();
Gui::Command::updateActive();setPreselectPoint(edit->DragPoint);
edit->DragPoint = -1;
//updateColor();
}
resetPositionText();
Mode = STATUS_NONE;
return true;
case STATUS_SKETCH_DragCurve:
if (edit->DragCurve != -1 && pp) {
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
Gui::Command::openCommand(“Drag Curve”);a
Gui::Command::doCommand(Gui::Command::Doc,”App.ActiveDocument.%s.movePoint(%i,%i,App.Vector(%f,%f,0),%i)”
,getObject()->getNameInDocument()
,edit->DragCurve, Sketcher::none, x-xInit, y-yInit, relative ? 1 : 0
);
Gui::Command::commitCommand();
Gui::Command::updateActive();
}
edit->PreselectCurve = edit->DragCurve;
edit->DragCurve = -1;
//updateColor();
}
resetPositionText();
Mode = STATUS_NONE;
return true;
case STATUS_SKETCH_DragConstraint:
if (edit->DragConstraint != -1 && pp) {
Gui::Command::openCommand(“Drag Constraint”);
moveConstraint(edit->DragConstraint, Base::Vector2D(x, y));
edit->PreselectConstraint = edit->DragConstraint;
edit->DragConstraint = -1;
//updateColor();
}
Mode = STATUS_NONE;
return true;
case STATUS_SKETCH_UseHandler:
return edit->sketchHandler->releaseButton(Base::Vector2D(x,y));
case STATUS_NONE:
default:
return false;
}
}
}
// Right mouse button ****************************************************
else if (Button == 2) {
if (!pressed) {
Ok…I need to see what goes what gets defined when I click the mouse down after the first polyline
enum SketchMode{
STATUS_NONE, /**< enum value View provider is in neutral. */
STATUS_SELECT_Point, /**< enum value a point was selected. */
STATUS_SELECT_Edge, /**< enum value a edge was selected. */
STATUS_SELECT_Constraint, /**< enum value a constraint was selected. */
STATUS_SELECT_Cross, /**< enum value the base coordinate system was selected. */
STATUS_SKETCH_DragPoint, /**< enum value while dragging a point. */
STATUS_SKETCH_DragCurve, /**< enum value while dragging a curve. */
STATUS_SKETCH_DragConstraint, /**< enum value while dragging a compatible constraint. */
STATUS_SKETCH_UseHandler /**< enum value a DrawSketchHandler is in control. */
So… When in Polyline Mode == STATUS_SKETCH_UseHandler
So Mode is a protected variable defined within class ViewProviderSketch
Ok.. I to test mode value on mouse down for a single line.
Ok.. It looks like the magic I need is associated with the mode is set to STATUS_SKETCH_UseHandler.
Look through the code I keep seeing reference to a pointer named edit which is of type EditData. http://free-cad.sourceforge.net/SrcDocu/dd/d15/structEditData.html
As near as I can tell an object to this pointer gets created in bool ViewProviderSketch::setEdit(int ModNum)
It should be useful breakpoint where a NewEdit object is created.
Ok… I left off here…
Need to set break points in
class DrawSketchHandlerLineSet: public DrawSketchHandler
in function:
virtual bool releaseButton(Base::Vector2D onSketchPos)