From f264f0fd41155656e96ba0a80057a6cca845c503 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 2 May 2017 19:22:49 -0300 Subject: [PATCH] Arch Multimaterial --- src/Mod/Arch/ArchCommands.py | 6 +- src/Mod/Arch/ArchComponent.py | 97 +- src/Mod/Arch/ArchMaterial.py | 294 +++++- src/Mod/Arch/ArchPanel.py | 128 ++- src/Mod/Arch/ArchProfile.py | 7 +- src/Mod/Arch/ArchWall.py | 129 ++- src/Mod/Arch/ArchWindow.py | 30 +- src/Mod/Arch/InitGui.py | 2 +- src/Mod/Arch/Resources/Arch.qrc | 2 + .../Resources/icons/Arch_Material_Multi.svg | 857 ++++++++++++++++++ .../Arch/Resources/ui/ArchMultiMaterial.ui | 95 ++ src/Mod/Arch/importDAE.py | 16 +- src/Mod/Arch/importIFC.py | 41 +- src/Mod/Arch/importOBJ.py | 11 +- 14 files changed, 1579 insertions(+), 136 deletions(-) create mode 100644 src/Mod/Arch/Resources/icons/Arch_Material_Multi.svg create mode 100644 src/Mod/Arch/Resources/ui/ArchMultiMaterial.ui diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 01057d5612..012783fdce 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -220,9 +220,9 @@ def cloneComponent(obj): c.CloneOf = obj c.Placement = obj.Placement c.Label = obj.Label - if hasattr(obj,"BaseMaterial"): - if obj.BaseMaterial: - c.BaseMaterial = obj.BaseMaterial + if hasattr(obj,"Material"): + if obj.Material: + c.Material = obj.Material if hasattr(obj,"IfcAttributes"): if obj.IfcAttributes: c.IfcAttributes = obj.IfcAttributes diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 4ae43b4849..e3da39e0d1 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -316,7 +316,7 @@ class Component: obj.addProperty("App::PropertyString","Description","Arch",QT_TRANSLATE_NOOP("App::Property","An optional description for this component")) obj.addProperty("App::PropertyString","Tag","Arch",QT_TRANSLATE_NOOP("App::Property","An optional tag for this component")) obj.addProperty("App::PropertyMap","IfcAttributes","Arch",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes")) - obj.addProperty("App::PropertyLink","BaseMaterial","Material",QT_TRANSLATE_NOOP("App::Property","A material for this object")) + obj.addProperty("App::PropertyLink","Material","Arch",QT_TRANSLATE_NOOP("App::Property","A material for this object")) obj.addProperty("App::PropertyEnumeration","Role","Arch",QT_TRANSLATE_NOOP("App::Property","The role of this object")) obj.addProperty("App::PropertyBool","MoveWithHost","Arch",QT_TRANSLATE_NOOP("App::Property","Specifies if this object must move together when its host is moved")) obj.addProperty("App::PropertyLink","IfcProperties","Arch",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes")) @@ -346,13 +346,16 @@ class Component: if state: self.Type = state + def onDocumentRestored(self,obj): + if hasattr(obj,"BaseMaterial"): + if not hasattr(obj,"Material"): + obj.addProperty("App::PropertyLink","Material","Arch",QT_TRANSLATE_NOOP("App::Property","A material for this object")) + obj.Material = obj.BaseMaterial + obj.removeProperty("BaseMaterial") + print("Migrated old BaseMaterial property -> Material in ",obj.Label) + def onChanged(self,obj,prop): - if prop == "BaseMaterial": - if hasattr(obj,"BaseMaterial"): - if obj.BaseMaterial: - if Draft.getType(obj.BaseMaterial) != "Material": - obj.BaseMaterial = None - print("Removing bad BaseMaterial link in ",obj.Name) + return def clone(self,obj): "if this object is a clone, sets the shape. Returns True if this is the case" @@ -441,21 +444,29 @@ class Component: def rebase(self,shape): import DraftGeomUtils,math - if hasattr(shape,"CenterOfMass"): - v = shape.CenterOfMass + if not isinstance(shape,list): + shape = [shape] + if hasattr(shape[0],"CenterOfMass"): + v = shape[0].CenterOfMass else: - v = shape.BoundBox.Center - n = DraftGeomUtils.getNormal(shape) + v = shape[0].BoundBox.Center + n = DraftGeomUtils.getNormal(shape[0]) r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n) if round(r.Angle,8) == round(math.pi,8): r = FreeCAD.Rotation() - shape = shape.copy() - shape.translate(v.negative()) - shape.rotate(FreeCAD.Vector(0,0,0),r.inverted().Axis,math.degrees(r.inverted().Angle)) + shapes = [] + for s in shape: + s = s.copy() + s.translate(v.negative()) + s.rotate(FreeCAD.Vector(0,0,0),r.inverted().Axis,math.degrees(r.inverted().Angle)) + shapes.append(s) p = FreeCAD.Placement() p.Base = v p.Rotation = r - return (shape,p) + if len(shapes) == 1: + return (shapes[0],p) + else: + return(shapes,p) def hideSubobjects(self,obj,prop): "Hides subobjects when a subobject lists change" @@ -512,7 +523,10 @@ class Component: if base.Solids and f.Solids: if placement: f.Placement = f.Placement.multiply(placement) - base = base.cut(f) + if len(base.Solids) > 1: + base = Part.makeCompound([sol.cut(f) for sol in base.Solids]) + else: + base = base.cut(f) elif o.isDerivedFrom("Part::Feature"): if o.Shape: @@ -545,14 +559,20 @@ class Component: if base.Solids and f.Solids: if placement: f.Placement = f.Placement.multiply(placement) - base = base.cut(f) + if len(base.Solids) > 1: + base = Part.makeCompound([sol.cut(f) for sol in base.Solids]) + else: + base = base.cut(f) elif (Draft.getType(o) == "Roof") or (Draft.isClone(o,"Roof")): # roofs define their own special subtraction volume f = o.Proxy.getSubVolume(o) if f: if base.Solids and f.Solids: - base = base.cut(f) + if len(base.Solids) > 1: + base = Part.makeCompound([sol.cut(f) for sol in base.Solids]) + else: + base = base.cut(f) elif o.isDerivedFrom("Part::Feature"): if o.Shape: @@ -562,7 +582,10 @@ class Component: if placement: s.Placement = s.Placement.multiply(placement) try: - base = base.cut(s) + if len(base.Solids) > 1: + base = Part.makeCompound([sol.cut(s) for sol in base.Solids]) + else: + base = base.cut(s) except Part.OCCError: print("Arch: unable to cut object ",o.Name, " from ", obj.Name) return base @@ -666,14 +689,15 @@ class ViewProviderComponent: def updateData(self,obj,prop): #print(obj.Name," : updating ",prop) - if prop == "BaseMaterial": - if obj.BaseMaterial: - if 'DiffuseColor' in obj.BaseMaterial.Material: - if "(" in obj.BaseMaterial.Material['DiffuseColor']: - c = tuple([float(f) for f in obj.BaseMaterial.Material['DiffuseColor'].strip("()").split(",")]) - if obj.ViewObject: - if obj.ViewObject.ShapeColor != c: - obj.ViewObject.ShapeColor = c + if prop == "Material": + if obj.Material: + if hasattr(obj.Material,"Material"): + if 'DiffuseColor' in obj.Material.Material: + if "(" in obj.Material.Material['DiffuseColor']: + c = tuple([float(f) for f in obj.Material.Material['DiffuseColor'].strip("()").split(",")]) + if obj.ViewObject: + if obj.ViewObject.ShapeColor != c: + obj.ViewObject.ShapeColor = c elif prop == "Shape": if obj.Base: if obj.Base.isDerivedFrom("Part::Compound"): @@ -683,12 +707,17 @@ class ViewProviderComponent: obj.ViewObject.update() #self.onChanged(obj.ViewObject,"ShapeColor") elif prop == "CloneOf": - if obj.CloneOf and not(obj.BaseMaterial): - if obj.ViewObject.DiffuseColor != obj.CloneOf.ViewObject.DiffuseColor: - if len(obj.CloneOf.ViewObject.DiffuseColor) > 1: - obj.ViewObject.DiffuseColor = obj.CloneOf.ViewObject.DiffuseColor - obj.ViewObject.update() - #self.onChanged(obj.ViewObject,"ShapeColor") + if obj.CloneOf: + mat = None + if hasattr(obj,"Material"): + if obj.Material: + mat = obj.Material + if not mat: + if obj.ViewObject.DiffuseColor != obj.CloneOf.ViewObject.DiffuseColor: + if len(obj.CloneOf.ViewObject.DiffuseColor) > 1: + obj.ViewObject.DiffuseColor = obj.CloneOf.ViewObject.DiffuseColor + obj.ViewObject.update() + #self.onChanged(obj.ViewObject,"ShapeColor") return def getIcon(self): @@ -769,7 +798,7 @@ class ViewProviderComponent: if c.getNumChildren() > 0: if c.getChild(0).getName() == "HiRes": num = 1 - print "getting node ",num," for ",self.Object.Label + #print "getting node ",num," for ",self.Object.Label c.whichChild = num break self.hiresgroup.addChild(self.meshnode) diff --git a/src/Mod/Arch/ArchMaterial.py b/src/Mod/Arch/ArchMaterial.py index df6d44f308..55300e0880 100644 --- a/src/Mod/Arch/ArchMaterial.py +++ b/src/Mod/Arch/ArchMaterial.py @@ -37,7 +37,7 @@ else: __title__ = "Arch Material Management" __author__ = "Yorik van Havre" __url__ = "http://www.freecadweb.org" - + ## @package ArchMaterial # \ingroup ARCH # \brief The Material object and tools @@ -68,6 +68,17 @@ def getMaterialContainer(): return obj +def makeMultiMaterial(name="MultiMaterial"): + '''makeMultiMaterial(name): makes an Material object''' + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",name) + obj.Label = name + _ArchMultiMaterial(obj) + if FreeCAD.GuiUp: + _ViewProviderArchMultiMaterial(obj.ViewObject) + getMaterialContainer().addObject(obj) + return obj + + def getDocumentMaterials(): '''getDocumentMaterials(): returns all the arch materials of the document''' for obj in FreeCAD.ActiveDocument.Objects: @@ -84,7 +95,7 @@ class _CommandArchMaterial: "the Arch Material command definition" def GetResources(self): return {'Pixmap': 'Arch_Material_Group', - 'MenuText': QT_TRANSLATE_NOOP("Arch_Material","Set material..."), + 'MenuText': QT_TRANSLATE_NOOP("Arch_Material","Material"), 'Accel': "M, T", 'ToolTip': QT_TRANSLATE_NOOP("Arch_Material","Creates or edits the material definition of a selected object.")} @@ -95,8 +106,38 @@ class _CommandArchMaterial: FreeCADGui.Control.closeDialog() FreeCADGui.doCommand("mat = Arch.makeMaterial()") for obj in sel: - if hasattr(obj,"BaseMaterial"): - FreeCADGui.doCommand("FreeCAD.ActiveDocument."+obj.Name+".BaseMaterial = mat") + if hasattr(obj,"Material"): + FreeCADGui.doCommand("FreeCAD.ActiveDocument."+obj.Name+".Material = mat") + FreeCADGui.doCommandGui("mat.ViewObject.startEditing()") + FreeCAD.ActiveDocument.commitTransaction() + + def IsActive(self): + if FreeCAD.ActiveDocument: + return True + else: + return False + + +class _CommandArchMultiMaterial: + + "the Arch MultiMaterial command definition" + + def GetResources(self): + return {'Pixmap': 'Arch_Material_Multi', + 'MenuText': QT_TRANSLATE_NOOP("Arch_MultiMaterial","Multi-Material"), + 'Accel': "M, T", + 'ToolTip': QT_TRANSLATE_NOOP("Arch_MultiMaterial","Creates or edits multi-materials")} + + def Activated(self): + sel = FreeCADGui.Selection.getSelection() + FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create multi-material")) + FreeCADGui.addModule("Arch") + FreeCADGui.Control.closeDialog() + FreeCADGui.doCommand("mat = Arch.makeMultiMaterial()") + for obj in sel: + if hasattr(obj,"Material"): + if not obj.isDerivedFrom("App::MaterialObject"): + FreeCADGui.doCommand("FreeCAD.ActiveDocument."+obj.Name+".Material = mat") FreeCADGui.doCommandGui("mat.ViewObject.startEditing()") FreeCAD.ActiveDocument.commitTransaction() @@ -108,7 +149,9 @@ class _CommandArchMaterial: class _ArchMaterialContainer: + "The Material Container" + def __init__(self,obj): self.Type = "MaterialContainer" obj.Proxy = self @@ -118,6 +161,7 @@ class _ArchMaterialContainer: class _ViewProviderArchMaterialContainer: + "A View Provider for the Material Container" def __init__(self,vobj): @@ -128,7 +172,9 @@ class _ViewProviderArchMaterialContainer: class _ArchMaterial: + "The Material object" + def __init__(self,obj): self.Type = "Material" obj.Proxy = self @@ -137,7 +183,7 @@ class _ArchMaterial: obj.addProperty("App::PropertyString","ProductURL","Arch",QT_TRANSLATE_NOOP("App::Property","An URL where to find information about this material")) obj.addProperty("App::PropertyPercent","Transparency","Arch",QT_TRANSLATE_NOOP("App::Property","The transparency value of this material")) obj.addProperty("App::PropertyColor","Color","Arch",QT_TRANSLATE_NOOP("App::Property","The color of this material")) - + def onChanged(self,obj,prop): d = None if prop == "Material": @@ -213,20 +259,21 @@ class _ArchMaterial: if FreeCADGui: # not sure why this is needed, but it is... FreeCADGui.ActiveDocument.resetEdit() - + def execute(self,obj): - if obj.Material: + if obj.Material: if FreeCAD.GuiUp: if "DiffuseColor" in obj.Material: c = tuple([float(f) for f in obj.Material['DiffuseColor'].strip("()").split(",")]) for p in obj.InList: - if hasattr(p,"BaseMaterial"): - if p.BaseMaterial.Name == obj.Name: + if hasattr(p,"Material"): + if p.Material.Name == obj.Name: p.ViewObject.ShapeColor = c return class _ViewProviderArchMaterial: + "A View Provider for the Material object" def __init__(self,vobj): @@ -261,7 +308,9 @@ class _ViewProviderArchMaterial: class _ArchMaterialTaskPanel: - '''The editmode TaskPanel for MechanicalMaterial objects''' + + '''The editmode TaskPanel for Arch Material objects''' + def __init__(self,obj=None): self.cards = None self.existingmaterials = [] @@ -340,7 +389,7 @@ class _ArchMaterialTaskPanel: import importFCMat self.material = importFCMat.read(self.cards[card]) self.setFields() - + def fromExisting(self,index): "sets the contents from an existing material" if index > 0: @@ -374,7 +423,7 @@ class _ArchMaterialTaskPanel: if self.cards: for k in sorted(self.cards.keys()): self.form.comboBox_MaterialsInDir.addItem(k) - + def fillExistingCombo(self): "fills the existing materials combo" self.existingmaterials = [] @@ -384,7 +433,7 @@ class _ArchMaterialTaskPanel: self.existingmaterials.append(obj) for m in self.existingmaterials: self.form.comboBox_FromExisting.addItem(m.Label) - + def openEditor(self): "opens the full material editor from the material module" @@ -405,5 +454,224 @@ class _ArchMaterialTaskPanel: QtGui.QDesktopServices.openUrl(baseurl) +class _ArchMultiMaterial: + + "The MultiMaterial object" + + def __init__(self,obj): + self.Type = "MultiMaterial" + obj.Proxy = self + obj.addProperty("App::PropertyString","Description","Arch",QT_TRANSLATE_NOOP("App::Property","A description for this material")) + obj.addProperty("App::PropertyStringList","Names","Arch",QT_TRANSLATE_NOOP("App::Property","The list of layer names")) + obj.addProperty("App::PropertyLinkList","Materials","Arch",QT_TRANSLATE_NOOP("App::Property","The list of layer materials")) + obj.addProperty("App::PropertyFloatList","Thicknesses","Arch",QT_TRANSLATE_NOOP("App::Property","The list of layer thicknesses")) + + +class _ViewProviderArchMultiMaterial: + + "A View Provider for the MultiMaterial object" + + def __init__(self,vobj): + vobj.Proxy = self + + def getIcon(self): + return ":/icons/Arch_Material_Multi.svg" + + def setEdit(self,vobj,mode=0): + taskd = _ArchMultiMaterialTaskPanel(vobj.Object) + FreeCADGui.Control.showDialog(taskd) + return True + + def unsetEdit(self,vobj,mode=0): + FreeCADGui.Control.closeDialog() + return True + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def doubleClicked(self,vobj): + self.setEdit(vobj) + + def isShow(self): + return True + + +class MultiMaterialDelegate(QtGui.QStyledItemDelegate): + def __init__(self, parent=None, *args): + self.mats = [] + for obj in FreeCAD.ActiveDocument.Objects: + if obj.isDerivedFrom("App::MaterialObject"): + self.mats.append(obj) + QtGui.QStyledItemDelegate.__init__(self, parent, *args) + + def createEditor(self,parent,option,index): + if index.column() == 1: + editor = QtGui.QComboBox(parent) + elif index.column() == 2: + ui = FreeCADGui.UiLoader() + editor = ui.createWidget("Gui::InputField") + editor.setSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Minimum) + editor.setParent(parent) + else: + editor = QtGui.QLineEdit(parent) + return editor + + def setEditorData(self, editor, index): + if index.column() == 1: + idx = -1 + for i,m in enumerate(self.mats): + editor.addItem(m.Label) + if m.Label == index.data(): + idx = i + editor.setCurrentIndex(idx) + else: + QtGui.QStyledItemDelegate.setEditorData(self, editor, index) + + def setModelData(self, editor, model, index): + if index.column() == 1: + if editor.currentIndex() == -1: + model.setData(index, "") + else: + model.setData(index, self.mats[editor.currentIndex()].Label) + else: + QtGui.QStyledItemDelegate.setModelData(self, editor, model, index) + + +class _ArchMultiMaterialTaskPanel: + + '''The editmode TaskPanel for MultiMaterial objects''' + + def __init__(self,obj=None): + self.obj = obj + self.form = FreeCADGui.PySideUic.loadUi(":/ui/ArchMultiMaterial.ui") + self.model = QtGui.QStandardItemModel() + self.model.setHorizontalHeaderLabels([translate("Arch","Name"),translate("Arch","Material"),translate("Arch","Thickness")]) + self.form.tree.setModel(self.model) + self.form.tree.setUniformRowHeights(True) + self.form.tree.setItemDelegate(MultiMaterialDelegate()) + QtCore.QObject.connect(self.form.chooseCombo, QtCore.SIGNAL("currentIndexChanged(int)"), self.fromExisting) + QtCore.QObject.connect(self.form.addButton,QtCore.SIGNAL("pressed()"),self.addLayer) + QtCore.QObject.connect(self.form.upButton,QtCore.SIGNAL("pressed()"),self.upLayer) + QtCore.QObject.connect(self.form.downButton,QtCore.SIGNAL("pressed()"),self.downLayer) + QtCore.QObject.connect(self.form.delButton,QtCore.SIGNAL("pressed()"),self.delLayer) + self.fillExistingCombo() + self.fillData() + + def fillData(self,obj=None): + if not obj: + obj = self.obj + if obj: + self.model.clear() + self.model.setHorizontalHeaderLabels([translate("Arch","Name"),translate("Arch","Material"),translate("Arch","Thickness")]) + for i in range(len(obj.Names)): + item1 = QtGui.QStandardItem(obj.Names[i]) + item2 = QtGui.QStandardItem(obj.Materials[i].Label) + item3 = QtGui.QStandardItem(FreeCAD.Units.Quantity(obj.Thicknesses[i],FreeCAD.Units.Length).getUserPreferred()[0]) + self.model.appendRow([item1,item2,item3]) + self.form.nameField.setText(obj.Label) + + def fillExistingCombo(self): + "fills the existing multimaterials combo" + import Draft + self.existingmaterials = [] + for obj in FreeCAD.ActiveDocument.Objects: + if Draft.getType(obj) == "MultiMaterial": + if obj != self.obj: + self.existingmaterials.append(obj) + for m in self.existingmaterials: + self.form.chooseCombo.addItem(m.Label) + + def fromExisting(self,index): + "sets the contents from an existing material" + if index > 0: + if index <= len(self.existingmaterials): + m = self.existingmaterials[index-1] + if m: + self.fillData(m) + + def addLayer(self): + item1 = QtGui.QStandardItem(translate("Arch","New layer")) + item2 = QtGui.QStandardItem() + item3 = QtGui.QStandardItem() + self.model.appendRow([item1,item2,item3]) + + def delLayer(self): + sel = self.form.tree.selectedIndexes() + if sel: + row = sel[0].row() + if row >= 0: + self.model.takeRow(row) + + def moveLayer(self,mvt=0): + sel = self.form.tree.selectedIndexes() + if sel and mvt: + row = sel[0].row() + if row >= 0: + if row+mvt >= 0: + data = self.model.takeRow(row) + self.model.insertRow(row+mvt,data) + ind = self.model.index(row+mvt,0) + self.form.tree.setCurrentIndex(ind) + + def upLayer(self): + self.moveLayer(mvt=-1) + + def downLayer(self): + self.moveLayer(mvt=1) + + def accept(self): + if self.obj: + mats = [] + for m in FreeCAD.ActiveDocument.Objects: + if m.isDerivedFrom("App::MaterialObject"): + mats.append(m) + names = [] + materials = [] + thicknesses = [] + for row in range(self.model.rowCount()): + name = self.model.item(row,0).text() + mat = None + ml = self.model.item(row,1).text() + for m in mats: + if m.Label == ml: + mat = m + d = self.model.item(row,2).text() + try: + d = float(d) + except: + thick = FreeCAD.Units.Quantity(d).Value + else: + thick = FreeCAD.Units.Quantity(d,FreeCAD.Units.Length).Value + if round(thick,32) == 0: + thick = 0.0 + if name and mat: + names.append(name) + materials.append(mat) + thicknesses.append(thick) + self.obj.Names = names + self.obj.Materials = materials + self.obj.Thicknesses = thicknesses + if self.form.nameField.text(): + self.obj.Label = self.form.nameField.text() + return True + + if FreeCAD.GuiUp: FreeCADGui.addCommand('Arch_Material',_CommandArchMaterial()) + FreeCADGui.addCommand('Arch_MultiMaterial',_CommandArchMultiMaterial()) + + class _ArchMaterialToolsCommand: + + def GetCommands(self): + return tuple(['Arch_Material','Arch_MultiMaterial']) + def GetResources(self): + return { 'MenuText': QT_TRANSLATE_NOOP("Arch_MaterialTools",'Material tools'), + 'ToolTip': QT_TRANSLATE_NOOP("Arch_MaterialTools",'Material tools') + } + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + FreeCADGui.addCommand('Arch_MaterialTools', _ArchMaterialToolsCommand()) diff --git a/src/Mod/Arch/ArchPanel.py b/src/Mod/Arch/ArchPanel.py index 451eab9e0a..5a262ecce3 100644 --- a/src/Mod/Arch/ArchPanel.py +++ b/src/Mod/Arch/ArchPanel.py @@ -401,7 +401,21 @@ class _Panel(ArchComponent.Component): elif obj.Base.isDerivedFrom("Part::Feature"): if not obj.Base.Shape.Solids: return - + layers = [] + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Materials"): + varwidth = 0 + restwidth = thickness - sum(obj.Material.Thicknesses) + if restwidth > 0: + varwidth = [t for t in obj.Material.Thicknesses if t == 0] + if varwidth: + varwidth = restwidth/len(varwidth) + for t in obj.Material.Thicknesses: + if t: + layers.append(t) + elif varwidth: + layers.append(varwidth) # creating base shape pl = obj.Placement base = None @@ -420,13 +434,26 @@ class _Panel(ArchComponent.Component): baseprofile = base if not normal: normal = baseprofile.Faces[0].normalAt(0,0).multiply(thickness) - base = base.extrude(normal) + if layers: + layeroffset = 0 + shps = [] + for l in layers: + n = Vector(normal).normalize().multiply(l) + b = base.extrude(n) + if layeroffset: + o = Vector(normal).normalize().multiply(layeroffset) + b.translate(o) + shps.append(b) + layeroffset += l + base = Part.makeCompound(shps) + else: + base = base.extrude(normal) elif base.Wires: fm = False if hasattr(obj,"FaceMaker"): if obj.FaceMaker != "None": try: - base = Part.makeFace(base.Wires,"Part::FaceMaker"+str(obj.FaceMaker)) + baseprofile = Part.makeFace(base.Wires,"Part::FaceMaker"+str(obj.FaceMaker)) fm = True except: FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n") @@ -438,9 +465,22 @@ class _Panel(ArchComponent.Component): closed = False if closed: baseprofile = ArchCommands.makeFace(base.Wires) - if not normal: - normal = baseprofile.normalAt(0,0).multiply(thickness) - base = baseprofile.extrude(normal) + if not normal: + normal = baseprofile.normalAt(0,0).multiply(thickness) + if layers: + layeroffset = 0 + shps = [] + for l in layers: + n = Vector(normal).normalize().multiply(l) + b = baseprofile.extrude(n) + if layeroffset: + o = Vector(normal).normalize().multiply(layeroffset) + b.translate(o) + shps.append(b) + layeroffset += l + base = Part.makeCompound(shps) + else: + base = baseprofile.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: @@ -448,17 +488,38 @@ class _Panel(ArchComponent.Component): if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: - if not normal: - normal = Vector(0,0,1).multiply(thickness) - l2 = length/2 or 0.5 - w2 = width/2 or 0.5 - v1 = Vector(-l2,-w2,0) - v2 = Vector(l2,-w2,0) - v3 = Vector(l2,w2,0) - v4 = Vector(-l2,w2,0) - base = Part.makePolygon([v1,v2,v3,v4,v1]) - baseprofile = Part.Face(base) - base = baseprofile.extrude(normal) + if layers: + shps = [] + layeroffset = 0 + for l in layers: + if normal: + n = Vector(normal).normalize().multiply(l) + else: + n = Vector(0,0,1).multiply(l) + l2 = length/2 or 0.5 + w2 = width/2 or 0.5 + v1 = Vector(-l2,-w2,layeroffset) + v2 = Vector(l2,-w2,layeroffset) + v3 = Vector(l2,w2,layeroffset) + v4 = Vector(-l2,w2,layeroffset) + base = Part.makePolygon([v1,v2,v3,v4,v1]) + basepofile = Part.Face(base) + base = baseprofile.extrude(n) + shps.append(base) + layeroffset += l + base = Part.makeCompound(shps) + else: + if not normal: + normal = Vector(0,0,1).multiply(thickness) + l2 = length/2 or 0.5 + w2 = width/2 or 0.5 + v1 = Vector(-l2,-w2,0) + v2 = Vector(l2,-w2,0) + v3 = Vector(l2,w2,0) + v4 = Vector(-l2,w2,0) + base = Part.makePolygon([v1,v2,v3,v4,v1]) + baseprofile = Part.Face(base) + base = baseprofile.extrude(normal) if hasattr(obj,"Area"): if baseprofile: @@ -539,12 +600,13 @@ class _Panel(ArchComponent.Component): if base: if not base.isNull(): if base.isValid() and base.Solids: - if base.Volume < 0: - base.reverse() - if base.Volume < 0: - FreeCAD.Console.PrintError(translate("Arch","Couldn't compute a shape")) - return - base = base.removeSplitter() + if len(base.Solids) == 1: + if base.Volume < 0: + base.reverse() + if base.Volume < 0: + FreeCAD.Console.PrintError(translate("Arch","Couldn't compute a shape")) + return + base = base.removeSplitter() obj.Shape = base if not pl.isNull(): obj.Placement = pl @@ -565,6 +627,26 @@ class _ViewProviderPanel(ArchComponent.ViewProviderComponent): return ":/icons/Arch_Panel_Clone.svg" return ":/icons/Arch_Panel_Tree.svg" + def updateData(self,obj,prop): + if prop in ["Placement","Shape"]: + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Materials"): + if len(obj.Material.Materials) == len(obj.Shape.Solids): + cols = [] + for i,mat in enumerate(obj.Material.Materials): + c = obj.ViewObject.ShapeColor + c = (c[0],c[1],c[2],obj.ViewObject.Transparency/100.0) + if 'DiffuseColor' in mat.Material: + if "(" in mat.Material['DiffuseColor']: + c = tuple([float(f) for f in mat.Material['DiffuseColor'].strip("()").split(",")]) + if 'Transparency' in mat.Material: + c = (c[0],c[1],c[2],float(mat.Material['Transparency'])) + cols.extend([c for j in range(len(obj.Shape.Solids[i].Faces))]) + if obj.ViewObject.DiffuseColor != cols: + obj.ViewObject.DiffuseColor = cols + ArchComponent.ViewProviderComponent.updateData(self,obj,prop) + class PanelView: "A Drawing view for Arch Panels" diff --git a/src/Mod/Arch/ArchProfile.py b/src/Mod/Arch/ArchProfile.py index 18ee3dfa84..3635061ada 100644 --- a/src/Mod/Arch/ArchProfile.py +++ b/src/Mod/Arch/ArchProfile.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD, Draft, Part, os +import FreeCAD, Draft, os from FreeCAD import Vector import csv @@ -115,6 +115,7 @@ class _ProfileC(_Profile): _Profile.__init__(self,obj,profile) def execute(self,obj): + import Part pl = obj.Placement c1=Part.Circle() c1.Radius=obj.OutDiameter.Value @@ -137,6 +138,7 @@ class _ProfileH(_Profile): _Profile.__init__(self,obj,profile) def execute(self,obj): + import Part pl = obj.Placement p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0) p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0) @@ -165,6 +167,7 @@ class _ProfileR(_Profile): _Profile.__init__(self,obj,profile) def execute(self,obj): + import Part pl = obj.Placement p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0) p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0) @@ -186,6 +189,7 @@ class _ProfileRH(_Profile): _Profile.__init__(self,obj,profile) def execute(self,obj): + import Part pl = obj.Placement p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0) p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0) @@ -213,6 +217,7 @@ class _ProfileU(_Profile): _Profile.__init__(self,obj,profile) def execute(self,obj): + import Part pl = obj.Placement p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0) p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 049a5999bc..081763bc55 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -449,9 +449,17 @@ class _Wall(ArchComponent.Component): extdata = self.getExtrusionData(obj) if extdata: base = extdata[0] - base.Placement = extdata[2].multiply(base.Placement) extv = extdata[2].Rotation.multVec(extdata[1]) - base = base.extrude(extv) + if isinstance(base,list): + shps = [] + for b in base: + b.Placement = extdata[2].multiply(b.Placement) + b = b.extrude(extv) + shps.append(b) + base = Part.makeCompound(shps) + else: + base.Placement = extdata[2].multiply(base.Placement) + base = base.extrude(extv) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): @@ -524,6 +532,22 @@ class _Wall(ArchComponent.Component): base = None placement = None basewires = None + # build wall layers + layers = [] + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Materials"): + varwidth = 0 + restwidth = width - sum(obj.Material.Thicknesses) + if restwidth > 0: + varwidth = [t for t in obj.Material.Thicknesses if t == 0] + if varwidth: + varwidth = restwidth/len(varwidth) + for t in obj.Material.Thicknesses: + if t: + layers.append(t) + elif varwidth: + layers.append(varwidth) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: @@ -556,8 +580,11 @@ class _Wall(ArchComponent.Component): elif len(obj.Base.Shape.Edges) == 1: basewires = [Part.Wire(obj.Base.Shape.Edges)] if basewires and width: + if (len(basewires) == 1) and layers: + basewires = [basewires[0] for l in layers] + layeroffset = 0 baseface = None - for wire in basewires: + for i,wire in enumerate(basewires): e = wire.Edges[0] if isinstance(e.Curve,Part.Circle): dvec = e.Vertexes[0].Point.sub(e.Curve.Center) @@ -567,45 +594,87 @@ class _Wall(ArchComponent.Component): dvec.normalize() sh = None if obj.Align == "Left": - dvec.multiply(width) - if obj.Offset.Value: - dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value) + off = obj.Offset.Value + if layers: + off = off+layeroffset + dvec.multiply(layers[i]) + layeroffset += layers[i] + else: + dvec.multiply(width) + if off: + dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Right": - dvec.multiply(width) dvec = dvec.negative() - if obj.Offset.Value: - dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value) + off = obj.Offset.Value + if layers: + off = off+layeroffset + dvec.multiply(layers[i]) + layeroffset += layers[i] + else: + dvec.multiply(width) + if off: + dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Center": - dvec.multiply(width/2) - w1 = DraftGeomUtils.offsetWire(wire,dvec) - dvec = dvec.negative() - w2 = DraftGeomUtils.offsetWire(wire,dvec) + if layers: + off = width/2-layeroffset + d1 = Vector(dvec).multiply(off) + w1 = DraftGeomUtils.offsetWire(wire,d1) + layeroffset += layers[i] + off = width/2-layeroffset + d1 = Vector(dvec).multiply(off) + w2 = DraftGeomUtils.offsetWire(wire,d1) + else: + dvec.multiply(width/2) + w1 = DraftGeomUtils.offsetWire(wire,dvec) + dvec = dvec.negative() + w2 = DraftGeomUtils.offsetWire(wire,dvec) sh = DraftGeomUtils.bind(w1,w2) if sh: sh.fix(0.1,0,1) # fixes self-intersecting wires f = Part.Face(sh) if baseface: - baseface = baseface.fuse(f) + if layers: + baseface.append(f) + else: + baseface = baseface.fuse(f) else: - baseface = f + if layers: + baseface = [f] + else: + baseface = f if baseface: base,placement = self.rebase(baseface) else: - l2 = length/2 or 0.5 - w2 = width/2 or 0.5 - v1 = Vector(-l2,-w2,0) - v2 = Vector(l2,-w2,0) - v3 = Vector(l2,w2,0) - v4 = Vector(-l2,w2,0) - base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])) + if layers: + totalwidth = sum(layers) + offset = 0 + base = [] + for l in layers: + l2 = length/2 or 0.5 + w1 = -totalwidth/2 + offset + w2 = w1 + l + v1 = Vector(-l2,w1,0) + v2 = Vector(l2,w1,0) + v3 = Vector(l2,w2,0) + v4 = Vector(-l2,w2,0) + base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))) + offset += l + else: + l2 = length/2 or 0.5 + w2 = width/2 or 0.5 + v1 = Vector(-l2,-w2,0) + v2 = Vector(l2,-w2,0) + v3 = Vector(l2,w2,0) + v4 = Vector(-l2,w2,0) + base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])) placement = FreeCAD.Placement() if base and placement: extrusion = normal.multiply(height) @@ -650,6 +719,22 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent): if prop in ["Placement","Shape"]: if obj.ViewObject.DisplayMode == "Footprint": obj.ViewObject.Proxy.setDisplayMode("Footprint") + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Materials"): + if len(obj.Material.Materials) == len(obj.Shape.Solids): + cols = [] + for i,mat in enumerate(obj.Material.Materials): + c = obj.ViewObject.ShapeColor + c = (c[0],c[1],c[2],obj.ViewObject.Transparency/100.0) + if 'DiffuseColor' in mat.Material: + if "(" in mat.Material['DiffuseColor']: + c = tuple([float(f) for f in mat.Material['DiffuseColor'].strip("()").split(",")]) + if 'Transparency' in mat.Material: + c = (c[0],c[1],c[2],float(mat.Material['Transparency'])) + cols.extend([c for j in range(len(obj.Shape.Solids[i].Faces))]) + if obj.ViewObject.DiffuseColor != cols: + obj.ViewObject.DiffuseColor = cols ArchComponent.ViewProviderComponent.updateData(self,obj,prop) def getDisplayModes(self,vobj): diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index eeefc21848..571972f13d 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -647,8 +647,6 @@ class _Window(ArchComponent.Component): obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of this window (for preset windows only)")) obj.addProperty("App::PropertyVector","Normal","Arch",QT_TRANSLATE_NOOP("App::Property","The normal direction of this window")) obj.addProperty("App::PropertyInteger","Preset","Arch","") - obj.addProperty("App::PropertyLink","PanelMaterial","Material",QT_TRANSLATE_NOOP("App::Property","A material for this object")) - obj.addProperty("App::PropertyLink","GlassMaterial","Material",QT_TRANSLATE_NOOP("App::Property","A material for this object")) obj.addProperty("App::PropertyArea","Area","Arch",QT_TRANSLATE_NOOP("App::Property","The area of this window")) obj.addProperty("App::PropertyLength","LouvreWidth","Louvres",QT_TRANSLATE_NOOP("App::Property","the width of louvre elements")) obj.addProperty("App::PropertyLength","LouvreSpacing","Louvres",QT_TRANSLATE_NOOP("App::Property","the space between louvre elements")) @@ -1045,14 +1043,28 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent): colors = [] base = obj.ViewObject.ShapeColor for i in range(len(solids)): - ccol = base + ccol = None + name = obj.WindowParts[(i*5)] typeidx = (i*5)+1 - if typeidx < len(obj.WindowParts): - typ = obj.WindowParts[typeidx] - if typ == WindowPartTypes[2]: # transparent parts - ccol = ArchCommands.getDefaultColor("WindowGlass") - for f in solids[i].Faces: - colors.append(ccol) + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Materials"): + if obj.Material.Names: + if name in obj.Material.Names: + mat = obj.Material.Materials[obj.Material.Names.index(name)] + if 'DiffuseColor' in mat.Material: + if "(" in mat.Material['DiffuseColor']: + ccol = tuple([float(f) for f in mat.Material['DiffuseColor'].strip("()").split(",")]) + if 'Transparency' in mat.Material: + ccol = (ccol[0],ccol[1],ccol[2],float(mat.Material['Transparency'])) + if not ccol: + if typeidx < len(obj.WindowParts): + typ = obj.WindowParts[typeidx] + if typ == WindowPartTypes[2]: # transparent parts + ccol = ArchCommands.getDefaultColor("WindowGlass") + if not ccol: + ccol = base + colors.extend([ccol for f in solids[i].Faces]) #print("colors: ",colors) if colors: obj.ViewObject.DiffuseColor = colors diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 920382b415..f151045e54 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -38,7 +38,7 @@ class ArchWorkbench(Workbench): "Arch_Window","Arch_Roof","Arch_Axis", "Arch_SectionPlane","Arch_Space","Arch_Stairs", "Arch_PanelTools","Arch_Equipment", - "Arch_Frame","Arch_Material","Arch_Schedule","Arch_PipeTools", + "Arch_Frame","Arch_MaterialTools","Arch_Schedule","Arch_PipeTools", "Arch_CutPlane","Arch_Add","Arch_Remove","Arch_Survey"] self.utilities = ["Arch_Component","Arch_CloneComponent","Arch_SplitMesh","Arch_MeshToShape", "Arch_SelectNonSolidMeshes","Arch_RemoveShape", diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc index df9f1d47aa..16adbb5261 100644 --- a/src/Mod/Arch/Resources/Arch.qrc +++ b/src/Mod/Arch/Resources/Arch.qrc @@ -63,6 +63,7 @@ icons/Arch_Component_Clone.svg icons/Arch_Material.svg icons/Arch_Material_Group.svg + icons/Arch_Material_Multi.svg icons/Arch_Schedule.svg icons/ArchWorkbench.svg ui/preferences-arch.ui @@ -70,6 +71,7 @@ ui/preferences-ifc.ui ui/preferences-dae.ui ui/ArchMaterial.ui + ui/ArchMultiMaterial.ui ui/ArchSchedule.ui icons/Arch_Pipe.svg icons/Arch_Pipe_Tree.svg diff --git a/src/Mod/Arch/Resources/icons/Arch_Material_Multi.svg b/src/Mod/Arch/Resources/icons/Arch_Material_Multi.svg new file mode 100644 index 0000000000..d368454650 --- /dev/null +++ b/src/Mod/Arch/Resources/icons/Arch_Material_Multi.svg @@ -0,0 +1,857 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + [Yorik van Havre] + + + Arch_Material_Group + 2015-04-19 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Arch/Resources/icons/Arch_Material_Group.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Arch/Resources/ui/ArchMultiMaterial.ui b/src/Mod/Arch/Resources/ui/ArchMultiMaterial.ui new file mode 100644 index 0000000000..0152462eab --- /dev/null +++ b/src/Mod/Arch/Resources/ui/ArchMultiMaterial.ui @@ -0,0 +1,95 @@ + + + Form + + + + 0 + 0 + 384 + 395 + + + + Multimaterial definition + + + + + + + Copy existing... + + + + + + + + Edit definition + + + + + + + + Name: + + + + + + + + + + + + Composition: + + + + + + + + + + + + Add + + + + + + + Up + + + + + + + Down + + + + + + + Del + + + + + + + + + + + + + diff --git a/src/Mod/Arch/importDAE.py b/src/Mod/Arch/importDAE.py index 27ad151463..22a28fe5d7 100644 --- a/src/Mod/Arch/importDAE.py +++ b/src/Mod/Arch/importDAE.py @@ -224,16 +224,16 @@ def export(exportList,filename,tessellation=1): input_list.addInput(1, 'NORMAL', "#cubenormals-array"+str(objind)) matnode = None matref = "materialref" - if hasattr(obj,"BaseMaterial"): - if obj.BaseMaterial: - if hasattr(obj.BaseMaterial,"Material"): - if "DiffuseColor" in obj.BaseMaterial.Material: - kd = tuple([float(k) for k in obj.BaseMaterial.Material["DiffuseColor"].strip("()").split(",")]) - effect = collada.material.Effect("effect_"+obj.BaseMaterial.Name, [], "phong", diffuse=kd, specular=(1,1,1)) - mat = collada.material.Material("mat_"+obj.BaseMaterial.Name, obj.BaseMaterial.Name, effect) + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Material"): + if "DiffuseColor" in obj.Material.Material: + kd = tuple([float(k) for k in obj.Material.Material["DiffuseColor"].strip("()").split(",")]) + effect = collada.material.Effect("effect_"+obj.Material.Name, [], "phong", diffuse=kd, specular=(1,1,1)) + mat = collada.material.Material("mat_"+obj.Material.Name, obj.Material.Name, effect) colmesh.effects.append(effect) colmesh.materials.append(mat) - matref = "ref_"+obj.BaseMaterial.Name + matref = "ref_"+obj.Material.Name matnode = collada.scene.MaterialNode(matref, mat, inputs=[]) if not matnode: if FreeCAD.GuiUp: diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index b84be1f8ec..caad1fd66c 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -949,8 +949,8 @@ def insert(filename,docname,skip=[],only=[],root=None): for o,m in mattable.items(): if m == material.id(): if o in objects: - if hasattr(objects[o],"BaseMaterial"): - objects[o].BaseMaterial = mat + if hasattr(objects[o],"Material"): + objects[o].Material = mat if DEBUG and materials: print("done") @@ -1319,11 +1319,13 @@ def export(exportList,filename): for m in Arch.getDocumentMaterials(): relobjs = [] for o in m.InList: - if hasattr(o,"BaseMaterial"): - if o.BaseMaterial: - if o.BaseMaterial.Name == m.Name: - if o.Name in products: - relobjs.append(products[o.Name]) + if hasattr(o,"Material"): + if o.Material: + if o.Material.isDerivedFrom("App::MaterialObject"): + # TODO : support multimaterials too + if o.Material.Name == m.Name: + if o.Name in products: + relobjs.append(products[o.Name]) if relobjs: mat = ifcfile.createIfcMaterial(m.Label.encode("utf8")) materials[m.Label] = mat @@ -1592,14 +1594,18 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess pl = extdata[2] if not isinstance(pl,list): pl = [pl] - if (len(p) != len(ev)) or (len(p) != len(pl)): - raise ValueError("importIFC: Extrusion data length mismatch: "+obj.Label) for i in range(len(p)): pi = p[i] pi.scale(0.001) - evi = ev[i] + if i < len(ev): + evi = ev[i] + else: + evi = ev[-1] evi.multiply(0.001) - pli = pl[i] + if i < len(pl): + pli = pl[i] + else: + pli = pl[-1] pli.Base = pli.Base.multiply(0.001) pstr = str([v.Point for v in p[i].Vertexes]) if pstr in profiledefs: @@ -1807,9 +1813,9 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess # apparently not needed, no harm in having both. # but they must have the same name for revit to see them #m = False - #if hasattr(obj,"BaseMaterial"): - # if obj.BaseMaterial: - # if "Color" in obj.BaseMaterial.Material: + #if hasattr(obj,"Material"): + # if obj.Material: + # if "Color" in obj.Material.Material: # m = True #if not m: rgb = obj.ViewObject.ShapeColor[:3] @@ -1817,9 +1823,10 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess psa = surfstyles[rgb] else: m = None - if hasattr(obj,"BaseMaterial"): - if obj.BaseMaterial: - m = obj.BaseMaterial.Label.encode("utf8") + if hasattr(obj,"Material"): + if obj.Material: + if obj.Material.isDerivedFrom("App::MaterialObject"): + m = obj.Material.Label.encode("utf8") col = ifcfile.createIfcColourRgb(None,rgb[0],rgb[1],rgb[2]) ssr = ifcfile.createIfcSurfaceStyleRendering(col,None,None,None,None,None,None,None,"FLAT") iss = ifcfile.createIfcSurfaceStyle(m,"BOTH",[ssr]) diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py index a7ed7368b4..371e3b50be 100644 --- a/src/Mod/Arch/importOBJ.py +++ b/src/Mod/Arch/importOBJ.py @@ -164,11 +164,12 @@ def export(exportList,filename): # write material m = False - if hasattr(obj,"BaseMaterial"): - if obj.BaseMaterial: - outfile.write("usemtl " + obj.BaseMaterial.Name + "\n") - materials.append(obj.BaseMaterial) - m = True + if hasattr(obj,"Material"): + if obj.Material: + if hasattr(obj.Material,"Material"): + outfile.write("usemtl " + obj.Material.Name + "\n") + materials.append(obj.Material) + m = True if not m: if FreeCAD.GuiUp: if hasattr(obj.ViewObject,"ShapeColor") and hasattr(obj.ViewObject,"Transparency"):