Draft: add support for point link array
This commit is contained in:
committed by
Yorik van Havre
parent
423c374258
commit
e3e7686773
@@ -64,6 +64,7 @@
|
||||
<file>icons/Draft_PlaneProxy.svg</file>
|
||||
<file>icons/Draft_Point.svg</file>
|
||||
<file>icons/Draft_PointArray.svg</file>
|
||||
<file>icons/Draft_PointLinkArray.svg</file>
|
||||
<file>icons/Draft_PolarArray.svg</file>
|
||||
<file>icons/Draft_PolarLinkArray.svg</file>
|
||||
<file>icons/Draft_Polygon.svg</file>
|
||||
|
||||
351
src/Mod/Draft/Resources/icons/Draft_PointLinkArray.svg
Normal file
351
src/Mod/Draft/Resources/icons/Draft_PointLinkArray.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 13 KiB |
@@ -55,7 +55,7 @@ class ArrayGroup:
|
||||
return ("Draft_OrthoArray",
|
||||
"Draft_PolarArray", "Draft_CircularArray",
|
||||
"Draft_PathArray", "Draft_PathLinkArray",
|
||||
"Draft_PointArray",
|
||||
"Draft_PointArray", "Draft_PointLinkArray")
|
||||
"Draft_PathTwistedArray", "Draft_PathTwistedLinkArray")
|
||||
|
||||
def GetResources(self):
|
||||
|
||||
@@ -56,7 +56,18 @@ True if Draft_rc.__name__ else False
|
||||
|
||||
|
||||
class PointArray(gui_base_original.Modifier):
|
||||
"""Gui Command for the Point array tool."""
|
||||
"""Gui Command for the Point array tool.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
use_link: bool, optional
|
||||
It defaults to `False`. If it is `True`, the created object
|
||||
will be a `Point link array`.
|
||||
"""
|
||||
|
||||
def __init__(self, use_link=False):
|
||||
super(PointArray, self).__init__()
|
||||
self.use_link = use_link
|
||||
|
||||
def GetResources(self):
|
||||
"""Set icon, menu and tooltip."""
|
||||
@@ -78,9 +89,9 @@ class PointArray(gui_base_original.Modifier):
|
||||
'MenuText': QT_TRANSLATE_NOOP("Draft_PointArray", _menu),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Draft_PointArray", _tip)}
|
||||
|
||||
def Activated(self):
|
||||
def Activated(self, name="Point array"):
|
||||
"""Execute when the command is called."""
|
||||
self.name = "Point array"
|
||||
self.name = name
|
||||
super(PointArray, self).Activated(name=_tr(self.name))
|
||||
# This was deactivated because it doesn't work correctly;
|
||||
# the selection needs to be made on two objects, but currently
|
||||
@@ -120,7 +131,8 @@ class PointArray(gui_base_original.Modifier):
|
||||
_cmd += "("
|
||||
_cmd += "App.ActiveDocument." + base_object.Name + ", "
|
||||
_cmd += "App.ActiveDocument." + point_object.Name + ", "
|
||||
_cmd += "extra=" + str(extra)
|
||||
_cmd += "extra=" + str(extra) + ", "
|
||||
_cmd += 'use_link=' + str(self.use_link)
|
||||
_cmd += ")"
|
||||
|
||||
_cmd_list = ["_obj_ = " + _cmd,
|
||||
@@ -135,4 +147,26 @@ class PointArray(gui_base_original.Modifier):
|
||||
|
||||
Gui.addCommand('Draft_PointArray', PointArray())
|
||||
|
||||
class PointLinkArray(PointArray):
|
||||
"""Gui Command for the PointLinkArray tool based on the PointArray tool."""
|
||||
|
||||
def __init__(self):
|
||||
super(PointLinkArray, self).__init__(use_link=True)
|
||||
|
||||
def GetResources(self):
|
||||
"""Set icon, menu and tooltip."""
|
||||
_tip = ("Like the PointArray tool, but creates a 'Point link array' instead.\n"
|
||||
"A 'Point link array' is more efficient when handling many copies.")
|
||||
|
||||
return {'Pixmap': 'Draft_PointLinkArray',
|
||||
'MenuText': QT_TRANSLATE_NOOP("Draft_PointLinkArray", "PointLinkArray"),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Draft_PointLinkArray", _tip)}
|
||||
|
||||
def Activated(self):
|
||||
"""Execute when the command is called."""
|
||||
super(PointLinkArray, self).Activated(name="Point link array")
|
||||
|
||||
|
||||
Gui.addCommand('Draft_PointLinkArray', PointLinkArray())
|
||||
|
||||
## @}
|
||||
|
||||
@@ -45,9 +45,10 @@ from draftobjects.pointarray import PointArray
|
||||
|
||||
if App.GuiUp:
|
||||
from draftviewproviders.view_array import ViewProviderDraftArray
|
||||
from draftviewproviders.view_draftlink import ViewProviderDraftLink
|
||||
|
||||
|
||||
def make_point_array(base_object, point_object, extra=None):
|
||||
def make_point_array(base_object, point_object, extra=None, use_link=True):
|
||||
"""Make a Draft PointArray object.
|
||||
|
||||
Distribute copies of a `base_object` in the points
|
||||
@@ -154,19 +155,29 @@ def make_point_array(base_object, point_object, extra=None):
|
||||
elif isinstance(extra, App.Rotation):
|
||||
extra = App.Placement(App.Vector(), extra)
|
||||
|
||||
new_obj = doc.addObject("Part::FeaturePython", "PointArray")
|
||||
PointArray(new_obj)
|
||||
if use_link:
|
||||
# The PointArray class must be called in this special way
|
||||
# to make it a LinkArray
|
||||
new_obj = doc.addObject("Part::FeaturePython", "PointArray",
|
||||
PointArray(None), None, True)
|
||||
else:
|
||||
new_obj = doc.addObject("Part::FeaturePython", "PointArray")
|
||||
PointArray(new_obj)
|
||||
|
||||
new_obj.Base = base_object
|
||||
new_obj.PointObject = point_object
|
||||
new_obj.ExtraPlacement = extra
|
||||
|
||||
if App.GuiUp:
|
||||
ViewProviderDraftArray(new_obj.ViewObject)
|
||||
gui_utils.formatObject(new_obj, new_obj.Base)
|
||||
if use_link:
|
||||
ViewProviderDraftLink(new_obj.ViewObject)
|
||||
else:
|
||||
ViewProviderDraftArray(new_obj.ViewObject)
|
||||
gui_utils.format_object(new_obj, new_obj.Base)
|
||||
|
||||
if hasattr(new_obj.Base.ViewObject, "DiffuseColor"):
|
||||
if len(new_obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
new_obj.ViewObject.Proxy.resetColors(new_obj.ViewObject)
|
||||
if hasattr(new_obj.Base.ViewObject, "DiffuseColor"):
|
||||
if len(new_obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
new_obj.ViewObject.Proxy.resetColors(new_obj.ViewObject)
|
||||
|
||||
new_obj.Base.ViewObject.hide()
|
||||
gui_utils.select(new_obj)
|
||||
|
||||
@@ -45,7 +45,7 @@ import draftutils.utils as utils
|
||||
|
||||
from draftutils.messages import _wrn, _err
|
||||
from draftutils.translate import translate, _tr
|
||||
from draftobjects.base import DraftObject
|
||||
from draftobjects.draftlink import DraftLink
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
@@ -54,12 +54,17 @@ Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
# @{
|
||||
|
||||
|
||||
class PointArray(DraftObject):
|
||||
class PointArray(DraftLink):
|
||||
"""The Draft Point Array object."""
|
||||
|
||||
def __init__(self, obj):
|
||||
super(PointArray, self).__init__(obj, "PointArray")
|
||||
|
||||
def attach(self, obj):
|
||||
"""Set up the properties when the object is attached."""
|
||||
self.set_properties(obj)
|
||||
super(PointArray, self).attach(obj)
|
||||
obj.configLinkProperty(ElementCount='Count')
|
||||
|
||||
def set_properties(self, obj):
|
||||
"""Set properties only if they don't exist."""
|
||||
@@ -109,19 +114,22 @@ class PointArray(DraftObject):
|
||||
_tip)
|
||||
obj.ExtraPlacement = App.Placement()
|
||||
|
||||
if self.use_link and "ExpandArray" not in properties:
|
||||
_tip = _tr("Show the individual array elements "
|
||||
"(only for Link arrays)")
|
||||
obj.addProperty("App::PropertyBool",
|
||||
"ExpandArray",
|
||||
"Objects",
|
||||
_tip)
|
||||
obj.setPropertyStatus('Shape', 'Transient')
|
||||
|
||||
def execute(self, obj):
|
||||
"""Run when the object is created or recomputed."""
|
||||
if not hasattr(obj.Base, 'Shape'):
|
||||
_err(_tr("Base object doesn't have a 'Shape', "
|
||||
"it cannot be used for an array."))
|
||||
obj.Count = 0
|
||||
return
|
||||
|
||||
pt_list, count = get_point_list(obj.PointObject)
|
||||
shape = build_copies(obj.Base, pt_list, obj.ExtraPlacement)
|
||||
pls = build_placements(obj.Base, pt_list, obj.ExtraPlacement)
|
||||
|
||||
obj.Shape = shape
|
||||
obj.Count = count
|
||||
return super(PointArray, self).buildShape(obj, obj.Placement, pls)
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
"""Execute code when the document is restored.
|
||||
@@ -147,6 +155,7 @@ class PointArray(DraftObject):
|
||||
|
||||
self.set_properties(obj)
|
||||
self.migrate_properties_0v19(obj)
|
||||
return super(PointArray, self).onDocumentRestored(obj)
|
||||
|
||||
def migrate_properties_0v19(self, obj):
|
||||
"""Migrate properties."""
|
||||
@@ -231,33 +240,30 @@ def get_point_list(point_object):
|
||||
count = len(pt_list)
|
||||
return pt_list, count
|
||||
|
||||
|
||||
def build_copies(base_object, pt_list=None, placement=App.Placement()):
|
||||
"""Build a compound of copies from the base object and list of points.
|
||||
def build_placements(base_object, pt_list=None, placement=App.Placement()):
|
||||
"""Build a placements from the base object and list of points.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Part::TopoShape
|
||||
The compound shape created by `Part.makeCompound`.
|
||||
list(App.Placement)
|
||||
"""
|
||||
if not pt_list:
|
||||
_err(translate("Draft",
|
||||
"Point object doesn't have a discrete point, "
|
||||
"it cannot be used for an array."))
|
||||
shape = base_object.Shape.copy()
|
||||
return shape
|
||||
return []
|
||||
|
||||
copies = list()
|
||||
pls = list()
|
||||
|
||||
for point in pt_list:
|
||||
new_shape = base_object.Shape.copy()
|
||||
original_rotation = new_shape.Placement.Rotation
|
||||
new_pla = base_object.Placement.copy()
|
||||
original_rotation = new_pla.Rotation
|
||||
|
||||
# Reset the position of the copy, and combine the original rotation
|
||||
# with the provided rotation. Two rotations (quaternions)
|
||||
# are combined by multiplying them.
|
||||
new_shape.Placement.Base = placement.Base
|
||||
new_shape.Placement.Rotation = original_rotation * placement.Rotation
|
||||
new_pla.Base = placement.Base
|
||||
new_pla.Rotation = original_rotation * placement.Rotation
|
||||
|
||||
if point.TypeId == "Part::Vertex":
|
||||
# For this object the final position is the value of the Placement
|
||||
@@ -288,7 +294,33 @@ def build_copies(base_object, pt_list=None, placement=App.Placement()):
|
||||
# translate by the X, Y, Z coordinates
|
||||
place = App.Vector(point.X, point.Y, point.Z)
|
||||
|
||||
new_shape.translate(place)
|
||||
new_pla.translate(place)
|
||||
|
||||
pls.append(new_pla)
|
||||
|
||||
return pls
|
||||
|
||||
def build_copies(base_object, pt_list=None, placement=App.Placement()):
|
||||
"""Build a compound of copies from the base object and list of points.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Part::TopoShape
|
||||
The compound shape created by `Part.makeCompound`.
|
||||
"""
|
||||
|
||||
if not pt_list:
|
||||
_err(translate("Draft",
|
||||
"Point object doesn't have a discrete point, "
|
||||
"it cannot be used for an array."))
|
||||
shape = base_object.Shape.copy()
|
||||
return shape
|
||||
|
||||
copies = list()
|
||||
|
||||
for pla in build_copies(base_object, pt_list, placement):
|
||||
new_shape = base_object.Shape.copy()
|
||||
new_shape.Placement = pla
|
||||
|
||||
copies.append(new_shape)
|
||||
|
||||
|
||||
@@ -28,24 +28,14 @@
|
||||
|
||||
## \addtogroup draftviewproviders
|
||||
# @{
|
||||
from draftviewproviders.view_base import ViewProviderDraft
|
||||
|
||||
|
||||
class ViewProviderDraftLink:
|
||||
class ViewProviderDraftLink(ViewProviderDraft):
|
||||
""" A view provider for link type object.
|
||||
"""
|
||||
|
||||
def __init__(self,vobj):
|
||||
self.Object = vobj.Object
|
||||
vobj.Proxy = self
|
||||
|
||||
def attach(self,vobj):
|
||||
self.Object = vobj.Object
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
super(ViewProviderDraftLink, self).__init__(vobj)
|
||||
|
||||
def getIcon(self):
|
||||
tp = self.Object.Proxy.Type
|
||||
@@ -60,6 +50,8 @@ class ViewProviderDraftLink:
|
||||
return ":/icons/Draft_PathLinkArray.svg"
|
||||
elif tp == 'PathTwistedArray':
|
||||
return ":/icons/Draft_PathTwistedLinkArray.svg"
|
||||
elif tp == 'PointArray':
|
||||
return ":/icons/Draft_PointLinkArray.svg"
|
||||
|
||||
def claimChildren(self):
|
||||
obj = self.Object
|
||||
@@ -68,7 +60,7 @@ class ViewProviderDraftLink:
|
||||
else:
|
||||
expand = obj.ShowElement
|
||||
if not expand:
|
||||
return [obj.Base]
|
||||
return super(ViewProviderDraftLink, self).claimChildren()
|
||||
else:
|
||||
return obj.ElementList
|
||||
|
||||
|
||||
Reference in New Issue
Block a user