Skip to content

Commit

Permalink
Merge branch 'Moult-fix-draft-edit-with-modifiers'
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed May 8, 2019
2 parents 5eb38b0 + dc284e4 commit 64d7ed3
Show file tree
Hide file tree
Showing 9 changed files with 799 additions and 372 deletions.
25 changes: 25 additions & 0 deletions src/Gui/Selection.cpp
Expand Up @@ -1077,6 +1077,8 @@ PyMethodDef SelectionSingleton::Methods[] = {
"given the complete selection is cleared."},
{"isSelected", (PyCFunction) SelectionSingleton::sIsSelected, METH_VARARGS,
"isSelected(object) -- Check if a given object is selected"},
{"setPreselection", (PyCFunction) SelectionSingleton::sSetPreselection, METH_VARARGS,
"setPreselection() -- Set preselected object"},
{"getPreselection", (PyCFunction) SelectionSingleton::sGetPreselection, METH_VARARGS,
"getPreselection() -- Get preselected object"},
{"clearPreselection", (PyCFunction) SelectionSingleton::sRemPreselection, METH_VARARGS,
Expand Down Expand Up @@ -1263,6 +1265,29 @@ PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
}
}

PyObject *SelectionSingleton::sSetPreselection(PyObject * /*self*/, PyObject *args)
{
PyObject *object;
char* subname=0;
float x=0,y=0,z=0;
if (PyArg_ParseTuple(args, "O!|sfff", &(App::DocumentObjectPy::Type),&object,&subname,&x,&y,&z)) {
App::DocumentObjectPy* docObjPy = static_cast<App::DocumentObjectPy*>(object);
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
if (!docObj || !docObj->getNameInDocument()) {
PyErr_SetString(Base::BaseExceptionFreeCADError, "Cannot check invalid object");
return NULL;
}

Selection().setPreselect(docObj->getDocument()->getName(),
docObj->getNameInDocument(),
subname,x,y,z);
Py_Return;
}

PyErr_SetString(PyExc_ValueError, "type must be 'DocumentObject[,subname[,x,y,z]]'");
return 0;
}

PyObject *SelectionSingleton::sGetPreselection(PyObject * /*self*/, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
Expand Down
1 change: 1 addition & 0 deletions src/Gui/Selection.h
Expand Up @@ -341,6 +341,7 @@ class GuiExport SelectionSingleton : public Base::Subject<const SelectionChanges
static PyObject *sIsSelected (PyObject *self,PyObject *args);
static PyObject *sCountObjectsOfType (PyObject *self,PyObject *args);
static PyObject *sGetSelection (PyObject *self,PyObject *args);
static PyObject *sSetPreselection (PyObject *self,PyObject *args);
static PyObject *sGetPreselection (PyObject *self,PyObject *args);
static PyObject *sRemPreselection (PyObject *self,PyObject *args);
static PyObject *sGetCompleteSelection(PyObject *self,PyObject *args);
Expand Down
22 changes: 22 additions & 0 deletions src/Gui/SoFCUnifiedSelection.cpp
Expand Up @@ -374,6 +374,28 @@ void SoFCUnifiedSelection::doAction(SoAction *action)
currenthighlight->unref();
currenthighlight = 0;
}
} else if (hilaction->SelChange.Type == SelectionChanges::SetPreselect) {
if (currenthighlight) {
SoHighlightElementAction action;
action.apply(currenthighlight);
currenthighlight->unref();
currenthighlight = 0;
}
App::Document* doc = App::GetApplication().getDocument(hilaction->SelChange.pDocName);
App::DocumentObject* obj = doc->getObject(hilaction->SelChange.pObjectName);
ViewProvider*vp = Application::Instance->getViewProvider(obj);
SoDetail* detail = vp->getDetail(hilaction->SelChange.pSubName);
SoHighlightElementAction action;
action.setHighlighted(true);
action.setColor(this->colorHighlight.getValue());
action.setElement(detail);
action.apply(vp->getRoot());
delete detail;
SoSearchAction sa;
sa.setNode(vp->getRoot());
sa.apply(vp->getRoot());
currenthighlight = static_cast<SoFullPath*>(sa.getPath()->copy());
currenthighlight->ref();
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/Gui/View3DInventorViewer.cpp
Expand Up @@ -643,7 +643,8 @@ void View3DInventorViewer::OnChange(Gui::SelectionSingleton::SubjectType& rCalle
SoFCSelectionAction cAct(Reason);
cAct.apply(pcViewProviderRoot);
}
else if (Reason.Type == SelectionChanges::RmvPreselect) {
else if (Reason.Type == SelectionChanges::RmvPreselect ||
Reason.Type == SelectionChanges::SetPreselect) {
SoFCHighlightAction cAct(Reason);
cAct.apply(pcViewProviderRoot);
}
Expand Down
250 changes: 165 additions & 85 deletions src/Mod/Draft/Draft.py
Expand Up @@ -1488,12 +1488,62 @@ def cut(object1,object2):

return obj

def moveVertex(object, vertex_index, vector):
points = object.Points
points[vertex_index] = points[vertex_index].add(vector)
object.Points = points

def moveEdge(object, edge_index, vector):
moveVertex(object, edge_index, vector)
if isClosedEdge(edge_index, object):
moveVertex(object, 0, vector)
else:
moveVertex(object, edge_index+1, vector)

def copyMovedEdges(arguments):
copied_edges = []
for argument in arguments:
copied_edges.append(copyMovedEdge(argument[0], argument[1], argument[2]))
joinWires(copied_edges)

def copyMovedEdge(object, edge_index, vector):
vertex1 = object.Placement.multVec(object.Points[edge_index]).add(vector)
if isClosedEdge(edge_index, object):
vertex2 = object.Placement.multVec(object.Points[0]).add(vector)
else:
vertex2 = object.Placement.multVec(object.Points[edge_index+1]).add(vector)
return makeLine(vertex1, vertex2)

def copyRotatedEdges(arguments):
copied_edges = []
for argument in arguments:
copied_edges.append(copyRotatedEdge(argument[0], argument[1],
argument[2], argument[3], argument[4]))
joinWires(copied_edges)

def copyRotatedEdge(object, edge_index, angle, center, axis):
vertex1 = rotateVectorFromCenter(
object.Placement.multVec(object.Points[edge_index]),
angle, axis, center)
if isClosedEdge(edge_index, object):
vertex2 = rotateVectorFromCenter(
object.Placement.multVec(object.Points[0]),
angle, axis, center)
else:
vertex2 = rotateVectorFromCenter(
object.Placement.multVec(object.Points[edge_index+1]),
angle, axis, center)
return makeLine(vertex1, vertex2)

def isClosedEdge(edge_index, object):
return edge_index + 1 >= len(object.Points)

def move(objectslist,vector,copy=False):
'''move(objects,vector,[copy]): Moves the objects contained
in objects (that can be an object or a list of objects)
in the direction and distance indicated by the given
vector. If copy is True, the actual objects are not moved, but copies
are created instead.he objects (or their copies) are returned.'''
are created instead. The objects (or their copies) are returned.'''
typecheck([(vector,Vector), (copy,bool)], "move")
if not isinstance(objectslist,list): objectslist = [objectslist]
objectslist.extend(getMovableChildren(objectslist))
Expand Down Expand Up @@ -1651,6 +1701,26 @@ def filterObjectsForModifiers(objects, isCopied=False):
filteredObjects.append(object)
return filteredObjects

def rotateVertex(object, vertex_index, angle, center, axis):
points = object.Points
points[vertex_index] = object.Placement.inverse().multVec(
rotateVectorFromCenter(
object.Placement.multVec(points[vertex_index]),
angle, axis, center))
object.Points = points

def rotateVectorFromCenter(vector, angle, axis, center):
rv = vector.sub(center)
rv = DraftVecUtils.rotate(rv, math.radians(angle), axis)
return center.add(rv)

def rotateEdge(object, edge_index, angle, center, axis):
rotateVertex(object, edge_index, angle, center, axis)
if isClosedEdge(edge_index, object):
rotateVertex(object, 0, angle, center, axis)
else:
rotateVertex(object, edge_index+1, angle, center, axis)

def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False):
'''rotate(objects,angle,[center,axis,copy]): Rotates the objects contained
in objects (that can be a list of objects or an object) of the given angle
Expand Down Expand Up @@ -1719,95 +1789,105 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False)
if len(newobjlist) == 1: return newobjlist[0]
return newobjlist

def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy=False):
def scaleVectorFromCenter(vector, scale, center):
return vector.sub(center).scale(scale.x, scale.y, scale.z).add(center)

def scaleVertex(object, vertex_index, scale, center):
points = object.Points
points[vertex_index] = object.Placement.inverse().multVec(
scaleVectorFromCenter(
object.Placement.multVec(points[vertex_index]),
scale, center))
object.Points = points

def scaleEdge(object, edge_index, scale, center):
scaleVertex(object, edge_index, scale, center)
if isClosedEdge(edge_index, object):
scaleVertex(object, 0, scale, center)
else:
scaleVertex(object, edge_index+1, scale, center)

def copyScaledEdges(arguments):
copied_edges = []
for argument in arguments:
copied_edges.append(copyScaledEdge(argument[0], argument[1],
argument[2], argument[3]))
joinWires(copied_edges)

def copyScaledEdge(object, edge_index, scale, center):
vertex1 = scaleVectorFromCenter(
object.Placement.multVec(object.Points[edge_index]),
scale, center)
if isClosedEdge(edge_index, object):
vertex2 = scaleVectorFromCenter(
object.Placement.multVec(object.Points[0]),
scale, center)
else:
vertex2 = scaleVectorFromCenter(
object.Placement.multVec(object.Points[edge_index+1]),
scale, center)
return makeLine(vertex1, vertex2)

def scale(objectslist,scale=Vector(1,1,1),center=Vector(0,0,0),copy=False):
'''scale(objects,vector,[center,copy,legacy]): Scales the objects contained
in objects (that can be a list of objects or an object) of the given scale
factors defined by the given vector (in X, Y and Z directions) around
given center. If legacy is True, direct (old) mode is used, otherwise
a parametric copy is made. If copy is True, the actual objects are not moved,
but copies are created instead. The objects (or their copies) are returned.'''
if not isinstance(objectslist,list): objectslist = [objectslist]
if legacy:
newobjlist = []
for obj in objectslist:
if copy:
newobj = makeCopy(obj)
else:
newobj = obj
if obj.isDerivedFrom("Part::Feature"):
sh = obj.Shape.copy()
m = FreeCAD.Matrix()
m.scale(delta)
sh = sh.transformGeometry(m)
corr = Vector(center.x,center.y,center.z)
corr.scale(delta.x,delta.y,delta.z)
corr = (corr.sub(center)).negative()
sh.translate(corr)
if getType(obj) == "Rectangle":
p = []
for v in sh.Vertexes: p.append(v.Point)
pl = obj.Placement.copy()
pl.Base = p[0]
diag = p[2].sub(p[0])
bb = p[1].sub(p[0])
bh = p[3].sub(p[0])
nb = DraftVecUtils.project(diag,bb)
nh = DraftVecUtils.project(diag,bh)
if obj.Length < 0: l = -nb.Length
else: l = nb.Length
if obj.Height < 0: h = -nh.Length
else: h = nh.Length
newobj.Length = l
newobj.Height = h
tr = p[0].sub(obj.Shape.Vertexes[0].Point)
newobj.Placement = pl
elif getType(obj) == "Wire":
p = []
for v in sh.Vertexes: p.append(v.Point)
#print(p)
newobj.Points = p
elif getType(obj) == "BSpline":
p = []
for p1 in obj.Points:
p2 = p1.sub(center)
p2.scale(delta.x,delta.y,delta.z)
p.append(p2)
newobj.Points = p
elif (obj.isDerivedFrom("Part::Feature")):
newobj.Shape = sh
elif (obj.TypeId == "App::Annotation"):
factor = delta.y * obj.ViewObject.FontSize
newobj.ViewObject.FontSize = factor
d = obj.Position.sub(center)
newobj.Position = center.add(Vector(d.x*delta.x,d.y*delta.y,d.z*delta.z))
if copy:
formatObject(newobj,obj)
newobjlist.append(newobj)
if copy and getParam("selectBaseObjects",False):
select(objectslist)
given center. If copy is True, the actual objects are not moved, but copies
are created instead. The objects (or their copies) are returned.'''
if not isinstance(objectslist, list):
objectslist = [objectslist]
newobjlist = []
for obj in objectslist:
if copy:
newobj = makeCopy(obj)
else:
select(newobjlist)
if len(newobjlist) == 1: return newobjlist[0]
return newobjlist
newobj = obj
if obj.isDerivedFrom("Part::Feature"):
scaled_shape = obj.Shape.copy()
m = FreeCAD.Matrix()
m.move(obj.Placement.Base.negative())
m.move(center.negative())
m.multiply(scale)
m.move(center)
m.move(obj.Placement.Base)
scaled_shape = scaled_shape.transformGeometry(m)
if getType(obj) == "Rectangled":
p = []
for v in scaled_shape.Vertexes: p.append(v.Point)
pl = obj.Placement.copy()
pl.Base = p[0]
diag = p[2].sub(p[0])
bb = p[1].sub(p[0])
bh = p[3].sub(p[0])
nb = DraftVecUtils.project(diag,bb)
nh = DraftVecUtils.project(diag,bh)
if obj.Length < 0: l = -nb.Length
else: l = nb.Length
if obj.Height < 0: h = -nh.Length
else: h = nh.Length
newobj.Length = l
newobj.Height = h
tr = p[0].sub(obj.Shape.Vertexes[0].Point)
newobj.Placement = pl
elif getType(obj) == "Wire" or getType(obj) == "BSpline":
for index, point in enumerate(newobj.Points):
scaleVertex(newobj, index, scale, center)
elif (obj.isDerivedFrom("Part::Feature")):
newobj.Shape = scaled_shape
elif (obj.TypeId == "App::Annotation"):
factor = scale.y * obj.ViewObject.FontSize
newobj.ViewObject.FontSize = factor
d = obj.Position.sub(center)
newobj.Position = center.add(Vector(d.x*scale.x,d.y*scale.y,d.z*scale.z))
if copy:
formatObject(newobj,obj)
newobjlist.append(newobj)
if copy and getParam("selectBaseObjects",False):
select(objectslist)
else:
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Scale")
_Clone(obj)
obj.Objects = objectslist
obj.Scale = delta
corr = Vector(center.x,center.y,center.z)
corr.scale(delta.x,delta.y,delta.z)
corr = (corr.sub(center)).negative()
p = obj.Placement
p.move(corr)
obj.Placement = p
if not copy:
for o in objectslist:
o.ViewObject.hide()
if gui:
_ViewProviderClone(obj.ViewObject)
formatObject(obj,objectslist[-1])
select(obj)
return obj
select(newobjlist)
if len(newobjlist) == 1: return newobjlist[0]
return newobjlist

def offset(obj,delta,copy=False,bind=False,sym=False,occ=False):
'''offset(object,delta,[copymode],[bind]): offsets the given wire by
Expand Down

0 comments on commit 64d7ed3

Please sign in to comment.