Draft: move grouping functions to draftutils.groups module

These functions were previously in `draftutils.utils`,
and are related to grouping objects and finding objects
inside groups. These include `get_group_names`, `ungroup`,
`get_windows`, `get_group_contents`, `get_movable_children`.
These are imported in the main `Draft.py` module, so compatibility
is retained.

Modules which use these functions are updated; these include
Gui Commands like `Move`, `Rotate`, `Scale`, `AddToGroup`,
as well as objects like `DrawingView` and `Shape2DView`,
and `ViewProviderClone`.
The code inside the `importDXF` module is also updated.

The Arch Workbench uses many of these functions
but it does so from the `Draft` namespace, so these edits
don't change the situation for these commands.
This commit is contained in:
vocx-fc
2020-06-25 21:34:09 -05:00
committed by Yorik van Havre
parent ec1a720bfb
commit 6503d9351d
14 changed files with 396 additions and 294 deletions

View File

@@ -68,6 +68,7 @@ SET(Draft_tests
SET(Draft_utilities
draftutils/__init__.py
draftutils/groups.py
draftutils/init_tools.py
draftutils/init_draft_statusbar.py
draftutils/units.py

View File

@@ -117,14 +117,6 @@ from draftutils.utils import is_clone
from draftutils.utils import getCloneBase
from draftutils.utils import get_clone_base
from draftutils.utils import getGroupNames
from draftutils.utils import get_group_names
from draftutils.utils import ungroup
from draftutils.utils import getGroupContents
from draftutils.utils import get_group_contents
from draftutils.utils import printShape
from draftutils.utils import print_shape
@@ -139,9 +131,6 @@ from draftutils.utils import load_svg_patterns
from draftutils.utils import svgpatterns
from draftutils.utils import svg_patterns
from draftutils.utils import getMovableChildren
from draftutils.utils import get_movable_children
from draftutils.utils import filter_objects_for_modifiers
from draftutils.utils import filterObjectsForModifiers
@@ -185,6 +174,13 @@ from draftutils.gui_utils import select
from draftutils.gui_utils import loadTexture
from draftutils.gui_utils import load_texture
from draftutils.groups import (get_group_names,
getGroupNames,
ungroup,
get_group_contents,
getGroupContents,
get_movable_children,
getMovableChildren)
#---------------------------------------------------------------------------
# Draft functions

View File

@@ -28,8 +28,9 @@
import FreeCAD as App
import draftutils.gui_utils as gui_utils
import draftutils.utils as utils
import draftutils.groups as groups
import draftutils.gui_utils as gui_utils
from draftmake.make_copy import make_copy
from draftmake.make_line import make_line
@@ -59,8 +60,10 @@ def move(objectslist, vector, copy=False):
The objects (or their copies) are returned.
"""
utils.type_check([(vector, App.Vector), (copy,bool)], "move")
if not isinstance(objectslist, list): objectslist = [objectslist]
objectslist.extend(utils.get_movable_children(objectslist))
if not isinstance(objectslist, list):
objectslist = [objectslist]
objectslist.extend(groups.get_movable_children(objectslist))
newobjlist = []
newgroups = {}
objectslist = utils.filter_objects_for_modifiers(objectslist, copy)
@@ -103,7 +106,7 @@ def move(objectslist, vector, copy=False):
newobj = obj
newobj.Position = obj.Position.add(real_vector)
elif utils.get_type(obj) == "Text":
elif utils.get_type(obj) in ("Text", "DraftText"):
if copy:
newobj = make_copy(obj)
else:
@@ -136,7 +139,7 @@ def move(objectslist, vector, copy=False):
if newobj is not None:
newobjlist.append(newobj)
if copy:
for p in obj.InList:
if p.isDerivedFrom("App::DocumentObjectGroup") and (p in objectslist):
@@ -150,7 +153,8 @@ def move(objectslist, vector, copy=False):
gui_utils.select(objectslist)
else:
gui_utils.select(newobjlist)
if len(newobjlist) == 1: return newobjlist[0]
if len(newobjlist) == 1:
return newobjlist[0]
return newobjlist

View File

@@ -29,15 +29,14 @@
import math
import FreeCAD as App
import DraftVecUtils
import draftutils.gui_utils as gui_utils
import draftutils.utils as utils
import draftutils.groups as groups
import draftutils.gui_utils as gui_utils
from draftmake.make_line import make_line
from draftfunctions.join import join_wires
from draftmake.make_line import make_line
from draftmake.make_copy import make_copy
@@ -70,11 +69,14 @@ def rotate(objectslist, angle, center=App.Vector(0,0,0),
"""
import Part
utils.type_check([(copy,bool)], "rotate")
if not isinstance(objectslist,list): objectslist = [objectslist]
objectslist.extend(utils.get_movable_children(objectslist))
if not isinstance(objectslist,list):
objectslist = [objectslist]
objectslist.extend(groups.get_movable_children(objectslist))
newobjlist = []
newgroups = {}
objectslist = utils.filter_objects_for_modifiers(objectslist, copy)
for obj in objectslist:
newobj = None
# real_center and real_axis are introduced to take into account
@@ -143,7 +145,8 @@ def rotate(objectslist, angle, center=App.Vector(0,0,0),
break
gui_utils.select(newobjlist)
if len(newobjlist) == 1: return newobjlist[0]
if len(newobjlist) == 1:
return newobjlist[0]
return newobjlist

View File

@@ -39,6 +39,7 @@ import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
import draftutils.utils as utils
import draftutils.groups as groups
import draftguitools.gui_base as gui_base
from draftutils.translate import _tr, translate
@@ -79,7 +80,7 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection):
super(AddToGroup, self).Activated()
self.groups = [self.ungroup]
self.groups.extend(utils.get_group_names())
self.groups.extend(groups.get_group_names())
self.labels = [self.ungroup]
for group in self.groups:
@@ -115,7 +116,7 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection):
if labelname == self.ungroup:
for obj in Gui.Selection.getSelection():
try:
utils.ungroup(obj)
groups.ungroup(obj)
except Exception:
pass
else:
@@ -193,7 +194,7 @@ class SelectGroup(gui_base.GuiCommandNeedsSelection):
sel = Gui.Selection.getSelection()
if len(sel) == 1:
if sel[0].isDerivedFrom("App::DocumentObjectGroup"):
cts = utils.get_group_contents(Gui.Selection.getSelection())
cts = groups.get_group_contents(Gui.Selection.getSelection())
for o in cts:
Gui.Selection.addSelection(o)
return
@@ -281,7 +282,7 @@ class SetAutoGroup(gui_base.GuiCommandSimplest):
self.groups = ["None"]
gn = [o.Name for o in self.doc.Objects if utils.get_type(o) == "Layer"]
if App.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM").GetBool("AutogroupAddGroups", False):
gn.extend(utils.get_group_names())
gn.extend(groups.get_group_names())
if gn:
self.groups.extend(gn)
self.labels = [translate("draft", "None")]

View File

@@ -33,12 +33,15 @@ import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
import DraftVecUtils
import draftutils.utils as utils
import draftutils.groups as groups
import draftutils.todo as todo
import draftguitools.gui_base_original as gui_base_original
from draftguitools.gui_subelements import SubelementHighlight
import draftguitools.gui_tool_utils as gui_tool_utils
import draftguitools.gui_trackers as trackers
from draftguitools.gui_subelements import SubelementHighlight
from draftutils.messages import _msg, _err
from draftutils.translate import translate
@@ -90,10 +93,11 @@ class Move(gui_base_original.Modifier):
if self.call:
self.view.removeEventCallback("SoEvent", self.call)
self.selected_objects = Gui.Selection.getSelection()
self.selected_objects = utils.getGroupContents(self.selected_objects,
addgroups=True,
spaces=True,
noarchchild=True)
self.selected_objects = \
groups.get_group_contents(self.selected_objects,
addgroups=True,
spaces=True,
noarchchild=True)
self.selected_subelements = Gui.Selection.getSelectionEx()
self.ui.lineUi(self.name)
self.ui.modUi()

View File

@@ -33,13 +33,15 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
from FreeCAD import Units as U
import DraftVecUtils
import draftutils.utils as utils
import draftutils.groups as groups
import draftutils.todo as todo
import draftguitools.gui_base_original as gui_base_original
import draftguitools.gui_tool_utils as gui_tool_utils
import draftguitools.gui_trackers as trackers
from FreeCAD import Units as U
from draftutils.messages import _msg, _err
from draftutils.translate import translate, _tr
@@ -88,10 +90,11 @@ class Rotate(gui_base_original.Modifier):
if self.call:
self.view.removeEventCallback("SoEvent", self.call)
self.selected_objects = Gui.Selection.getSelection()
self.selected_objects = utils.getGroupContents(self.selected_objects,
addgroups=True,
spaces=True,
noarchchild=True)
self.selected_objects = \
groups.get_group_contents(self.selected_objects,
addgroups=True,
spaces=True,
noarchchild=True)
self.selected_subelements = Gui.Selection.getSelectionEx()
self.step = 0
self.center = None

View File

@@ -40,12 +40,15 @@ import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
import DraftVecUtils
import draftutils.utils as utils
import draftutils.groups as groups
import draftutils.todo as todo
import draftguitools.gui_base_original as gui_base_original
import draftguitools.gui_tool_utils as gui_tool_utils
import draftguitools.gui_trackers as trackers
import drafttaskpanels.task_scale as task_scale
from draftutils.messages import _msg, _err
from draftutils.translate import translate
@@ -93,7 +96,8 @@ class Scale(gui_base_original.Modifier):
self.view.removeEventCallback("SoEvent", self.call)
self.selected_objects = Gui.Selection.getSelection()
self.selected_objects = utils.getGroupContents(self.selected_objects)
self.selected_objects = \
groups.get_group_contents(self.selected_objects)
self.selected_subelements = Gui.Selection.getSelectionEx()
self.refs = []
self.ui.pointUi(self.name)

View File

@@ -27,18 +27,12 @@ This module is obsolete, since Drawing was substituted by TechDraw.
# \ingroup DRAFT
# \brief This module provides the object code for the Draft DrawingView object.
import math
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import DraftVecUtils
from getSVG import getSVG
import getSVG
import draftutils.utils as utils
import draftutils.groups as groups
from draftobjects.base import DraftObject
@@ -105,16 +99,16 @@ class DrawingView(DraftObject):
svg = ""
shapes = []
others = []
objs = utils.getGroupContents([obj.Source])
objs = groups.get_group_contents([obj.Source])
for o in objs:
v = o.ViewObject.isVisible()
if hasattr(obj,"AlwaysOn"):
if obj.AlwaysOn:
v = True
if v:
svg += getSVG(o,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp)
svg += getSVG.getSVG(o,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp)
else:
svg = getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp)
svg = getSVG.getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp)
result += '<g id="' + obj.Name + '"'
result += ' transform="'
result += 'rotate('+str(obj.Rotation)+','+str(obj.X)+','+str(obj.Y)+') '

View File

@@ -32,6 +32,7 @@ import FreeCAD as App
import DraftVecUtils
import draftutils.utils as utils
import draftutils.groups as u_groups
import draftutils.gui_utils as gui_utils
from draftutils.translate import translate
@@ -155,7 +156,7 @@ class Shape2DView(DraftObject):
if hasattr(obj.Base,"OnlySolids"):
onlysolids = obj.Base.OnlySolids
import Arch, Part, Drawing
objs = utils.get_group_contents(objs,walls=True)
objs = u_groups.get_group_contents(objs, walls=True)
objs = gui_utils.remove_hidden(objs)
shapes = []
if hasattr(obj,"FuseArch") and obj.FuseArch:
@@ -246,7 +247,7 @@ class Shape2DView(DraftObject):
elif obj.Base.isDerivedFrom("App::DocumentObjectGroup"):
shapes = []
objs = utils.get_group_contents(obj.Base)
objs = u_groups.get_group_contents(obj.Base)
for o in objs:
if hasattr(o,'Shape'):
if o.Shape:

View File

@@ -0,0 +1,328 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * (c) 2009, 2010 *
# * Yorik van Havre <yorik@uncreated.net>, Ken Cline <cline@frii.com> *
# * (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""Provides utility functions for managing groups in the Draft Workbench.
The functions here are also used in the Arch Workbench as some of
the objects created with this workbench work like groups.
"""
## @package groups
# \ingroup DRAFT
# \brief Provides utility functions for managing groups in the Draft Workbench.
import FreeCAD as App
import draftutils.utils as utils
from draftutils.translate import _tr
from draftutils.messages import _msg, _err
def get_group_names(doc=None):
"""Return a list of names of existing groups in the document.
Parameters
----------
doc: App::Document, optional
It defaults to `None`.
A document on which to search group names.
It if is `None` it will search the current document.
Returns
-------
list of str
A list of names of objects that are "groups".
These are objects derived from `App::DocumentObjectGroup`
or which are of types `'Floor'`, `'Building'`, or `'Site'`
from the Arch Workbench.
Otherwise, return an empty list.
"""
if not doc:
found, doc = utils.find_doc(App.activeDocument())
if not found:
_err(_tr("No active document. Aborting."))
return []
glist = []
for obj in doc.Objects:
if (obj.isDerivedFrom("App::DocumentObjectGroup")
or utils.get_type(obj) in ("Floor", "Building", "Site")):
glist.append(obj.Name)
return glist
def getGroupNames():
"""Return a list of group names. DEPRECATED."""
utils.use_instead("get_group_names")
return get_group_names()
def ungroup(obj):
"""Remove the object from any group to which it belongs.
A "group" is any object returned by `get_group_names`.
Parameters
----------
obj: App::DocumentObject or str
Any type of object.
If it is a string, it must be the `Label` of that object.
Since a label is not guaranteed to be unique in a document,
it will use the first object found with this label.
"""
if isinstance(obj, str):
obj_str = obj
found, obj = utils.find_object(obj, doc=App.activeDocument())
if not found:
_msg("obj: {}".format(obj_str))
_err(_tr("Wrong input: object not in document."))
return None
doc = obj.Document
for name in get_group_names():
group = doc.getObject(name)
if obj in group.Group:
# The list of objects cannot be modified directly,
# so a new list is created, this new list is modified,
# and then it is assigned over the older list.
objects = group.Group
objects.remove(obj)
group.Group = objects
def get_windows(obj):
"""Return the windows and rebars inside a host.
Parameters
----------
obj: App::DocumentObject
A scripted object of type `'Wall'` or `'Structure'`
(Arch Workbench).
This will be searched for objects of type `'Window'` and `'Rebar'`,
and clones of them, and the found elements will be added
to the output list.
The function will search recursively all elements under `obj.OutList`,
in case the windows and rebars are nested under other walls
and structures.
Returns
-------
list
A list of all found windows and rebars in `obj`.
If `obj` is itself a `'Window'` or a `'Rebar'`, or a clone of them,
it will return the same `obj` element.
"""
out = []
if utils.get_type(obj) in ("Wall", "Structure"):
for o in obj.OutList:
out.extend(get_windows(o))
for i in obj.InList:
if (utils.get_type(i) == "Window"
or utils.is_clone(obj, "Window")):
if hasattr(i, "Hosts"):
if obj in i.Hosts:
out.append(i)
elif (utils.get_type(i) == "Rebar"
or utils.is_clone(obj, "Rebar")):
if hasattr(i, "Host"):
if obj == i.Host:
out.append(i)
elif (utils.get_type(obj) in ("Window", "Rebar")
or utils.is_clone(obj, ["Window", "Rebar"])):
out.append(obj)
return out
def get_group_contents(objectslist,
walls=False, addgroups=False,
spaces=False, noarchchild=False):
"""Return a list of objects from expanding the input groups.
The function accepts any type of object, although it is most useful
with "groups", as it is meant to unpack the objects inside these groups.
Parameters
----------
objectslist: list
If any object in the list is a group, its contents (`obj.Group`)
are extracted and added to the output list.
The "groups" are objects derived from `App::DocumentObjectGroup`,
but they can also be `'App::Part'`, or `'Building'`, `'BuildingPart'`,
`'Space'`, and `'Site'` from the Arch Workbench.
Single items that aren't groups are added to the output list
as is.
walls: bool, optional
It defaults to `False`.
If it is `True`, Wall and Structure objects (Arch Workbench)
are treated as groups; they are scanned for Window, Door,
and Rebar objects, and these are added to the output list.
addgroups: bool, optional
It defaults to `False`.
If it is `True`, the group itself is kept as part of the output list.
spaces: bool, optional
It defaults to `False`.
If it is `True`, Arch Spaces are treated as groups,
and are added to the output list.
noarchchild: bool, optional
It defaults to `False`.
If it is `True`, the objects inside Building and BuildingParts
(Arch Workbench) aren't added to the output list.
Returns
-------
list
The list of objects from each group present in `objectslist`,
plus any other individual object given in `objectslist`.
"""
newlist = []
if not isinstance(objectslist, list):
objectslist = [objectslist]
for obj in objectslist:
if obj:
if (obj.isDerivedFrom("App::DocumentObjectGroup")
or (utils.get_type(obj) in ("Building", "BuildingPart",
"Space", "Site")
and hasattr(obj, "Group"))):
if utils.get_type(obj) == "Site":
if obj.Shape:
newlist.append(obj)
if obj.isDerivedFrom("Drawing::FeaturePage"):
# Skip if the group is a Drawing page
# Note: the Drawing workbench is obsolete
newlist.append(obj)
else:
if addgroups or (spaces
and utils.get_type(obj) == "Space"):
newlist.append(obj)
if (noarchchild
and utils.get_type(obj) in ("Building",
"BuildingPart")):
pass
else:
newlist.extend(get_group_contents(obj.Group,
walls, addgroups))
else:
# print("adding ", obj.Name)
newlist.append(obj)
if walls:
newlist.extend(get_windows(obj))
# Clean possible duplicates
cleanlist = []
for obj in newlist:
if obj not in cleanlist:
cleanlist.append(obj)
return cleanlist
def getGroupContents(objectslist,
walls=False, addgroups=False,
spaces=False, noarchchild=False):
"""Return a list of objects from groups. DEPRECATED."""
utils.use_instead("get_group_contents")
return get_group_contents(objectslist,
walls, addgroups,
spaces, noarchchild)
def get_movable_children(objectslist, recursive=True):
"""Return a list of objects with child objects that move with a host.
Builds a list of objects with all child objects (`obj.OutList`)
that have their `MoveWithHost` attribute set to `True`.
This function is mostly useful for Arch Workbench objects.
Parameters
----------
objectslist: list of App::DocumentObject
A single scripted object or list of objects.
recursive: bool, optional
It defaults to `True`, in which case the function
is called recursively to also extract the children of children
objects.
Otherwise, only direct children of the input objects
are added to the output list.
Returns
-------
list
List of children objects that have their `MoveWithHost` attribute
set to `True`.
"""
added = []
if not isinstance(objectslist, list):
objectslist = [objectslist]
for obj in objectslist:
# Skips some objects that should never move their children
if utils.get_type(obj) not in ("Clone", "SectionPlane",
"Facebinder", "BuildingPart"):
children = obj.OutList
if (hasattr(obj, "Proxy") and obj.Proxy
and hasattr(obj.Proxy, "getSiblings")
and utils.get_type(obj) != "Window"):
# children.extend(obj.Proxy.getSiblings(obj))
pass
for child in children:
if hasattr(child, "MoveWithHost") and child.MoveWithHost:
if hasattr(obj, "CloneOf"):
if obj.CloneOf:
if obj.CloneOf.Name != child.Name:
added.append(child)
else:
added.append(child)
else:
added.append(child)
if recursive:
added.extend(get_movable_children(children))
return added
def getMovableChildren(objectslist, recursive=True):
"""Return a list of objects with child objects. DEPRECATED."""
utils.use_instead("get_movable_children")
return get_movable_children(objectslist, recursive)

View File

@@ -591,52 +591,6 @@ def get_clone_base(obj, strict=False):
getCloneBase = get_clone_base
def get_group_names():
"""Return a list of names of existing groups in the document.
Returns
-------
list of str
A list of names of objects that are "groups".
These are objects derived from `'App::DocumentObjectGroup'`
or which are of types `'Floor'`, `'Building'`, or `'Site'`
(from the Arch Workbench).
Otherwise, return an empty list.
"""
glist = []
doc = App.ActiveDocument
for obj in doc.Objects:
if (obj.isDerivedFrom("App::DocumentObjectGroup")
or getType(obj) in ("Floor", "Building", "Site")):
glist.append(obj.Name)
return glist
getGroupNames = get_group_names
def ungroup(obj):
"""Remove the object from any group to which it belongs.
A "group" is any object returned by `get_group_names`.
Parameters
----------
obj : App::DocumentObject
Any type of scripted object.
"""
for name in getGroupNames():
group = App.ActiveDocument.getObject(name)
if obj in group.Group:
# The list of objects cannot be modified directly,
# so a new list is created, this new list is modified,
# and then it is assigned over the older list.
objects = group.Group
objects.remove(obj)
group.Group = objects
def shapify(obj):
"""Transform a parametric object into a static, non-parametric shape.
@@ -693,139 +647,6 @@ def shapify(obj):
return newobj
def get_windows(obj):
"""Return the windows and rebars inside a host.
Parameters
----------
obj : App::DocumentObject
A scripted object of type `'Wall'` or `'Structure'`
(Arch Workbench).
This will be searched for objects of type `'Window'` and `'Rebar'`,
and clones of them, and the found elements will be added
to the output list.
The function will search recursively all elements under `obj.OutList`,
in case the windows and rebars are nested under other walls
and structures.
Returns
-------
list
A list of all found windows and rebars in `obj`.
If `obj` is itself a `'Window'` or a `'Rebar'`, or a clone of them,
it will return the same `obj` element.
"""
out = []
if getType(obj) in ("Wall", "Structure"):
for o in obj.OutList:
out.extend(get_windows(o))
for i in obj.InList:
if getType(i) in ("Window") or isClone(obj, "Window"):
if hasattr(i, "Hosts"):
if obj in i.Hosts:
out.append(i)
elif getType(i) in ("Rebar") or isClone(obj, "Rebar"):
if hasattr(i, "Host"):
if obj == i.Host:
out.append(i)
elif (getType(obj) in ("Window", "Rebar")
or isClone(obj, ["Window", "Rebar"])):
out.append(obj)
return out
getWindows = get_windows
def get_group_contents(objectslist,
walls=False, addgroups=False,
spaces=False, noarchchild=False):
"""Return a list of objects from expanding the input groups.
The function accepts any type of object, although it is most useful
with "groups", as it is meant to unpack the objects inside these groups.
Parameters
----------
objectslist : list
If any object in the list is a group, its contents (`obj.Group`)
are extracted and added to the output list.
The "groups" are objects derived from `'App::DocumentObjectGroup'`,
but they can also be `'App::Part'`, or `'Building'`, `'BuildingPart'`,
`'Space'`, and `'Site'` from the Arch Workbench.
Single items that aren't groups are added to the output list
as is.
walls : bool, optional
It defaults to `False`.
If it is `True`, Wall and Structure objects (Arch Workbench)
are treated as groups; they are scanned for Window, Door,
and Rebar objects, and these are added to the output list.
addgroups : bool, optional
It defaults to `False`.
If it is `True`, the group itself is kept as part of the output list.
spaces : bool, optional
It defaults to `False`.
If it is `True`, Arch Spaces are treated as groups,
and are added to the output list.
noarchchild : bool, optional
It defaults to `False`.
If it is `True`, the objects inside Building and BuildingParts
(Arch Workbench) aren't added to the output list.
Returns
-------
list
The list of objects from each group present in `objectslist`,
plus any other individual object given in `objectslist`.
"""
newlist = []
if not isinstance(objectslist, list):
objectslist = [objectslist]
for obj in objectslist:
if obj:
if (obj.isDerivedFrom("App::DocumentObjectGroup")
or (getType(obj) in ("Building", "BuildingPart",
"Space", "Site")
and hasattr(obj, "Group"))):
if getType(obj) == "Site":
if obj.Shape:
newlist.append(obj)
if obj.isDerivedFrom("Drawing::FeaturePage"):
# skip if the group is a page
newlist.append(obj)
else:
if addgroups or (spaces and getType(obj) == "Space"):
newlist.append(obj)
if (noarchchild
and getType(obj) in ("Building", "BuildingPart")):
pass
else:
newlist.extend(getGroupContents(obj.Group,
walls, addgroups))
else:
# print("adding ", obj.Name)
newlist.append(obj)
if walls:
newlist.extend(getWindows(obj))
# Clean possible duplicates
cleanlist = []
for obj in newlist:
if obj not in cleanlist:
cleanlist.append(obj)
return cleanlist
getGroupContents = get_group_contents
def print_shape(shape):
"""Print detailed information of a topological shape.
@@ -1056,64 +877,6 @@ def get_DXF(obj,direction=None):
getDXF = get_DXF
def get_movable_children(objectslist, recursive=True):
"""Return a list of objects with child objects that move with a host.
Builds a list of objects with all child objects (`obj.OutList`)
that have their `MoveWithHost` attribute set to `True`.
This function is mostly useful for Arch Workbench objects.
Parameters
----------
objectslist : list of App::DocumentObject
A single scripted object or list of objects.
recursive : bool, optional
It defaults to `True`, in which case the function
is called recursively to also extract the children of children
objects.
Otherwise, only direct children of the input objects
are added to the output list.
Returns
-------
list
List of children objects that have their `MoveWithHost` attribute
set to `True`.
"""
added = []
if not isinstance(objectslist, list):
objectslist = [objectslist]
for obj in objectslist:
# Skips some objects that should never move their children
if getType(obj) not in ("Clone", "SectionPlane",
"Facebinder", "BuildingPart"):
children = obj.OutList
if hasattr(obj, "Proxy"):
if obj.Proxy:
if (hasattr(obj.Proxy, "getSiblings")
and getType(obj) not in ("Window")):
# children.extend(obj.Proxy.getSiblings(obj))
pass
for child in children:
if hasattr(child, "MoveWithHost"):
if child.MoveWithHost:
if hasattr(obj, "CloneOf"):
if obj.CloneOf:
if obj.CloneOf.Name != child.Name:
added.append(child)
else:
added.append(child)
else:
added.append(child)
if recursive:
added.extend(getMovableChildren(children))
return added
getMovableChildren = get_movable_children
def filter_objects_for_modifiers(objects, isCopied=False):
filteredObjects = []
for obj in objects:

View File

@@ -26,7 +26,7 @@
# \ingroup DRAFT
# \brief This module provides the view provider code for the Draft Clone object.
import draftutils.utils as utils
import draftutils.groups as groups
class ViewProviderClone:
@@ -53,7 +53,7 @@ class ViewProviderClone:
def resetColors(self, vobj):
colors = []
for o in utils.get_group_contents(vobj.Object.Objects):
for o in groups.get_group_contents(vobj.Object.Objects):
if o.isDerivedFrom("Part::Feature"):
if len(o.ViewObject.DiffuseColor) > 1:
colors.extend(o.ViewObject.DiffuseColor)

View File

@@ -3599,7 +3599,7 @@ def export(objectslist, filename, nospline=False, lwPoly=False):
if dxfLibrary:
global exportList
exportList = objectslist
exportList = Draft.getGroupContents(exportList)
exportList = Draft.get_group_contents(exportList)
nlist = []
exportLayers = []