diff --git a/src/Mod/Arch/ArchBuildingPart.py b/src/Mod/Arch/ArchBuildingPart.py index 2895f88bac..6b0a9d192c 100644 --- a/src/Mod/Arch/ArchBuildingPart.py +++ b/src/Mod/Arch/ArchBuildingPart.py @@ -164,14 +164,14 @@ class BuildingPart: obj.addProperty("App::PropertyEnumeration","IfcRole","Component",QT_TRANSLATE_NOOP("App::Property","The role of this object")) import ArchComponent obj.IfcRole = ArchComponent.IfcRoles - if not "CloneOf" in pl: - obj.addProperty("App::PropertyLink","CloneOf","Component",QT_TRANSLATE_NOOP("App::Property","The object this component is cloning")) if not "Description" in pl: obj.addProperty("App::PropertyString","Description","Component",QT_TRANSLATE_NOOP("App::Property","An optional description for this component")) if not "Tag" in pl: obj.addProperty("App::PropertyString","Tag","Component",QT_TRANSLATE_NOOP("App::Property","An optional tag for this component")) if not "IfcAttributes" in pl: obj.addProperty("App::PropertyMap","IfcAttributes","Component",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes")) + if not "Shape" in pl: + obj.addProperty("Part::PropertyPartShape","Shape","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The shape of this object")) self.Type = "BuildingPart" def onDocumentRestored(self,obj): @@ -197,28 +197,42 @@ class BuildingPart: for child in obj.Group: if Draft.getType(child) in ["Wall","Structure"]: if not child.Height.Value: + #print("Executing ",child.Label) child.Proxy.execute(child) elif prop == "Placement": if hasattr(self,"oldPlacement"): if self.oldPlacement: - v = FreeCAD.Vector(0,0,1) deltap = obj.Placement.Base.sub(self.oldPlacement.Base) if deltap.Length == 0: deltap = None - deltar = FreeCAD.Rotation(self.oldPlacement.Rotation.multVec(v),obj.Placement.Rotation.multVec(v)) - if deltar.Angle < 0.001: + deltar = self.oldPlacement.Rotation.multiply(obj.Placement.Rotation) + #print "Rotation",deltar.Axis,deltar.Angle + if deltar.Angle < 0.0001: deltar = None for child in obj.Group: if ((not hasattr(child,"MoveWithHost")) or child.MoveWithHost) and hasattr(child,"Placement"): - print "moving ",child.Label + #print "moving ",child.Label if deltap: child.Placement.move(deltap) if deltar: - child.Placement.Rotation = child.Placement.Rotation.multiply(deltar) + #child.Placement.Rotation = child.Placement.Rotation.multiply(deltar) - not enough, child must also move + # use shape methods to obtain a correct placement + import Part,math + shape = Part.Shape() + shape.Placement = child.Placement + shape.rotate(DraftVecUtils.tup(obj.Placement.Base), DraftVecUtils.tup(deltar.Axis), math.degrees(deltar.Angle)) + child.Placement = shape.Placement def execute(self,obj): - pass + # gather all the child shapes into a compound + shapes = [] + for o in obj.Group: + if o.isDerivedFrom("Part::Feature") and o.Shape and (not o.Shape.isNull()): + shapes.append(o.Shape) + if shapes: + import Part + obj.Shape = Part.makeCompound(shapes) def getSpaces(self,obj): @@ -278,6 +292,9 @@ class ViewProviderBuildingPart: vobj.addProperty("App::PropertyFloatList","ViewData","BuildingPart",QT_TRANSLATE_NOOP("App::Property","Camera position data associated with this object")) if not "RestoreView" in pl: vobj.addProperty("App::PropertyBool","RestoreView","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If set, the view stored in this object will be restored on double-click")) + if not "DiffuseColor" in pl: + vobj.addProperty("App::PropertyColorList","DiffuseColor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The individual face colors")) + def onDocumentRestored(self,vobj): @@ -342,6 +359,18 @@ class ViewProviderBuildingPart: if prop in ["Placement","LevelOffset"]: self.onChanged(obj.ViewObject,"OverrideUnit") + elif prop == "Shape": + # gather all the child shapes + cols = [] + for o in obj.Group: + if o.isDerivedFrom("Part::Feature") and o.Shape and (not o.Shape.isNull()): + if len(o.ViewObject.DiffuseColor) == len(o.Shape.Faces): + cols.extend(o.ViewObject.DiffuseColor) + else: + c = o.ViewObject.ShapeColor[:3]+(obj.ViewObject.Transparency/100.0,) + for i in range(len(o.Shape.Faces)): + cols.append(c) + obj.ViewObject.DiffuseColor = cols def onChanged(self,vobj,prop): diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 98c0757d69..7b2a8e5e25 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -508,7 +508,7 @@ class Component: "if this object is a clone, sets the shape. Returns True if this is the case" if hasattr(obj,"CloneOf"): if obj.CloneOf: - if (Draft.getType(obj.CloneOf) == Draft.getType(obj)) or (Draft.getType(obj) == "Component"): + if (Draft.getType(obj.CloneOf) == Draft.getType(obj)) or (Draft.getType(obj) in ["Component","BuildingPart"]): pl = obj.Placement obj.Shape = obj.CloneOf.Shape.copy() obj.Placement = pl @@ -1071,8 +1071,23 @@ class ViewProviderComponent: menu.addAction(action1) def toggleSubcomponents(self): + FreeCADGui.runCommand("Arch_ToggleSubs") + def areDifferentColors(self,a,b): + + if len(a) != len(b): + return True + for i in range(len(a)): + if abs(sum(a[i]) - sum(b[i])) > 0.00001: + return True + return False + + def colorize(self,obj,force=False): + + if obj.CloneOf: + if self.areDifferentColors(obj.ViewObject.DiffuseColor,obj.CloneOf.ViewObject.DiffuseColor) or force: + obj.ViewObject.DiffuseColor = obj.CloneOf.ViewObject.DiffuseColor class ArchSelectionObserver: diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index e41445d3ab..076d7d2a9e 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -578,7 +578,7 @@ class _Structure(ArchComponent.Component): normal = None if not height: for p in obj.InList: - if Draft.getType(p) == "Floor": + if Draft.getType(p) in ["Floor","BuildingPart"]: if p.Height.Value: height = p.Height.Value base = None diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index e0e8deedc6..ea40618fb4 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -750,7 +750,7 @@ class _Wall(ArchComponent.Component): height = obj.Height.Value if not height: for p in obj.InList: - if Draft.getType(p) == "Floor": + if Draft.getType(p) in ["Floor","BuildingPart"]: if p.Height.Value: height = p.Height.Value if not height: diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index a25d62c0b2..e8c705f32a 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -1451,15 +1451,6 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent): if self.areDifferentColors(colors,obj.ViewObject.DiffuseColor) or force: obj.ViewObject.DiffuseColor = colors - def areDifferentColors(self,a,b): - - if len(a) != len(b): - return True - for i in range(len(a)): - if abs(sum(a[i]) - sum(b[i])) > 0.00001: - return True - return False - class _ArchWindowTaskPanel: diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 67c56acf9f..f78788c292 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -649,7 +649,7 @@ def getMovableChildren(objectslist,recursive=True): if not isinstance(objectslist,list): objectslist = [objectslist] for obj in objectslist: - if not (getType(obj) in ["Clone","SectionPlane","Facebinder"]): + if not (getType(obj) in ["Clone","SectionPlane","Facebinder","BuildingPart"]): # objects that should never move their children children = obj.OutList if hasattr(obj,"Proxy"): @@ -3118,8 +3118,10 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5): return obj def makeShapeString(String,FontFile,Size = 100,Tracking = 0): + '''ShapeString(Text,FontFile,Height,Track): Turns a text string into a Compound Shape''' + if not FreeCAD.ActiveDocument: FreeCAD.Console.PrintError("No active document. Aborting\n") return @@ -3140,11 +3142,13 @@ def makeShapeString(String,FontFile,Size = 100,Tracking = 0): return obj def clone(obj,delta=None,forcedraft=False): + '''clone(obj,[delta,forcedraft]): makes a clone of the given object(s). The clone is an exact, linked copy of the given object. If the original object changes, the final object changes too. Optionally, you can give a delta Vector to move the clone from the original position. If forcedraft is True, the resulting object is a Draft clone even if the input object is an Arch object.''' + prefix = getParam("ClonePrefix","") if prefix: prefix = prefix.strip()+" " @@ -3153,14 +3157,18 @@ def clone(obj,delta=None,forcedraft=False): if (len(obj) == 1) and obj[0].isDerivedFrom("Part::Part2DObject"): cl = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Clone2D") cl.Label = prefix + obj[0].Label + " (2D)" - elif (len(obj) == 1) and hasattr(obj[0],"CloneOf") and (not forcedraft): + elif (len(obj) == 1) and (hasattr(obj[0],"CloneOf") or (getType(obj[0]) == "BuildingPart")) and (not forcedraft): # arch objects can be clones import Arch - cl = getattr(Arch,"make"+obj[0].Proxy.Type)() + if getType(obj[0]) == "BuildingPart": + cl = Arch.makeComponent() + else: + cl = getattr(Arch,"make"+obj[0].Proxy.Type)() base = getCloneBase(obj[0]) cl.Label = prefix + base.Label cl.CloneOf = base - cl.Placement = obj[0].Placement + if getType(obj[0]) != "BuildingPart": + cl.Placement = obj[0].Placement try: cl.Role = base.Role cl.Description = base.Description @@ -3169,7 +3177,7 @@ def clone(obj,delta=None,forcedraft=False): pass if gui: cl.ViewObject.DiffuseColor = base.ViewObject.DiffuseColor - if obj[0].Proxy.Type == "Window": + if getType(obj[0]) in ["Window","BuildingPart"]: from DraftGui import todo todo.delay(Arch.recolorize,cl) select(cl) @@ -6103,7 +6111,7 @@ class _PointArray(_DraftObject): obj.addProperty("App::PropertyLink","Base","Draft",QT_TRANSLATE_NOOP("App::Property","Base")).Base = bobj obj.addProperty("App::PropertyLink","PointList","Draft",QT_TRANSLATE_NOOP("App::Property","PointList")).PointList = ptlst obj.addProperty("App::PropertyInteger","Count","Draft",QT_TRANSLATE_NOOP("App::Property","Count")).Count = 0 - obj.setEditorMode("Count", 1) + obj.setEditorMode("Count", 1) def execute(self, obj): import Part @@ -6118,18 +6126,18 @@ class _PointArray(_DraftObject): pls = opl.Links elif hasattr(opl, 'Components'): pls = opl.Components - + base = [] i = 0 if hasattr(obj.Base, 'Shape'): for pts in pls: - #print pts # inspect the objects + #print pts # inspect the objects if hasattr(pts, 'X') and hasattr(pts, 'Y') and hasattr(pts, 'Y'): nshape = obj.Base.Shape.copy() if hasattr(pts, 'Placement'): place = pts.Placement nshape.translate(place.Base) - nshape.rotate(place.Base, place.Rotation.Axis, place.Rotation.Angle * 180 / math.pi ) + nshape.rotate(place.Base, place.Rotation.Axis, place.Rotation.Angle * 180 / math.pi ) nshape.translate(Base.Vector(pts.X,pts.Y,pts.Z)) i += 1 base.append(nshape) @@ -6314,7 +6322,7 @@ class _ViewProviderDraftArray(_ViewProviderDraft): if hasattr(self.Object,"ArrayType"): return ":/icons/Draft_Array.svg" elif hasattr(self.Object,"PointList"): - return ":/icons/Draft_PointArray.svg" + return ":/icons/Draft_PointArray.svg" return ":/icons/Draft_PathArray.svg" def resetColors(self, vobj): @@ -6494,7 +6502,7 @@ class _Facebinder(_DraftObject): obj.addProperty("App::PropertyBool","RemoveSplitter","Draft",QT_TRANSLATE_NOOP("App::Property","Specifies if splitter lines must be removed")) obj.addProperty("App::PropertyDistance","Extrusion","Draft",QT_TRANSLATE_NOOP("App::Property","An optional extrusion value to be applied to all faces")) obj.addProperty("App::PropertyBool","Sew","Draft",QT_TRANSLATE_NOOP("App::Property","This specifies if the shapes sew")) - + def execute(self,obj): import Part