[ArchStructure] Variant PropertrySet Support in ArchSketch
Now, user can create : - Variant Layout / combination of ArchStructure (Slab) in addition to ArchWall and CurtainWall based on same ArchSketch, with another PropertySet - Variant Properties / layer of ArchWall on same ArchSketch with different Width, Offset, Material, Height etc. to create Layers, Composite walls etc. (Layout, Layer, Combination, Composite, Elemented etc.) FreeCAD Forum Discussion: - https://forum.freecad.org/viewtopic.php?t=87721&start=130#p794785
This commit is contained in:
committed by
Yorik van Havre
parent
4666fe8a5b
commit
ec451f9eba
@@ -715,6 +715,9 @@ class _Structure(ArchComponent.Component):
|
||||
if not "FaceMaker" in pl:
|
||||
obj.addProperty("App::PropertyEnumeration","FaceMaker","Structure",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object"))
|
||||
obj.FaceMaker = ["None","Simple","Cheese","Bullseye"]
|
||||
if not "ArchSketchData" in pl:
|
||||
obj.addProperty("App::PropertyBool","ArchSketchData","Structure",QT_TRANSLATE_NOOP("App::Property","Use Base ArchSketch (if used) data (e.g. widths, aligns, offsets) instead of Wall's properties"))
|
||||
obj.ArchSketchData = True
|
||||
if not "ArchSketchEdges" in pl: # PropertyStringList
|
||||
obj.addProperty("App::PropertyStringList","ArchSketchEdges","Structure",QT_TRANSLATE_NOOP("App::Property","Selected edges (or group of edges) of the base ArchSketch, to use in creating the shape of this BIM Structure (instead of using all the Base shape's edges by default). Input are index numbers of edges or groups."))
|
||||
else:
|
||||
@@ -726,13 +729,59 @@ class _Structure(ArchComponent.Component):
|
||||
obj.removeProperty("ArchSketchEdges")
|
||||
obj.addProperty("App::PropertyStringList","ArchSketchEdges","Structure",QT_TRANSLATE_NOOP("App::Property","Selected edges (or group of edges) of the base ArchSketch, to use in creating the shape of this BIM Structure (instead of using all the Base shape's edges by default). Input are index numbers of edges or groups."))
|
||||
obj.ArchSketchEdges = newStrValue
|
||||
if not hasattr(obj,"ArchSketchPropertySet"):
|
||||
obj.addProperty("App::PropertyEnumeration","ArchSketchPropertySet","Structure",QT_TRANSLATE_NOOP("App::Property","Select User Defined PropertySet to use in creating variant shape, with same ArchSketch "))
|
||||
obj.ArchSketchPropertySet = ['Default']
|
||||
if not hasattr(self,"ArchSkPropSetPickedUuid"):
|
||||
self.ArchSkPropSetPickedUuid = ''
|
||||
if not hasattr(self,"ArchSkPropSetListPrev"):
|
||||
self.ArchSkPropSetListPrev = []
|
||||
|
||||
self.Type = "Structure"
|
||||
|
||||
|
||||
def dumps(self): # Supercede Arch.Component.dumps()
|
||||
dump = super().dumps()
|
||||
if not isinstance(dump, tuple):
|
||||
dump = (dump,) #Python Tuple With One Item
|
||||
dump = dump + (self.ArchSkPropSetPickedUuid, self.ArchSkPropSetListPrev)
|
||||
return dump
|
||||
|
||||
|
||||
def loads(self,state):
|
||||
super().loads(state) # do nothing as of 2024.11.28
|
||||
if state == None:
|
||||
return
|
||||
elif state[0] == 'S': # state[1] == 't', behaviour before 2024.11.28
|
||||
return
|
||||
elif state[0] == 'Structure':
|
||||
self.ArchSkPropSetPickedUuid = state[1]
|
||||
self.ArchSkPropSetListPrev = state[2]
|
||||
elif state[0] != 'Structure': # model before merging super.dumps/loads()
|
||||
self.ArchSkPropSetPickedUuid = state[0]
|
||||
self.ArchSkPropSetListPrev = state[1]
|
||||
|
||||
|
||||
def onDocumentRestored(self,obj):
|
||||
|
||||
ArchComponent.Component.onDocumentRestored(self,obj)
|
||||
self.setProperties(obj)
|
||||
|
||||
if hasattr(obj,"ArchSketchData") and obj.ArchSketchData and Draft.getType(obj.Base) == "ArchSketch":
|
||||
if hasattr(obj,"ArchSketchEdges"):
|
||||
obj.setEditorMode("ArchSketchEdges", ["ReadOnly"])
|
||||
if hasattr(obj,"ArchSketchPropertySet"):
|
||||
obj.setEditorMode("ArchSketchPropertySet", 0)
|
||||
else:
|
||||
if hasattr(obj,"ArchSketchEdges"):
|
||||
obj.setEditorMode("ArchSketchEdges", 0)
|
||||
if hasattr(obj,"ArchSketchPropertySet"):
|
||||
obj.setEditorMode("ArchSketchPropertySet", ["ReadOnly"])
|
||||
|
||||
# set a flag to indicate onDocumentRestored() is run
|
||||
self.onDocRestoredDone = True
|
||||
|
||||
|
||||
def execute(self,obj):
|
||||
|
||||
"creates the structure shape"
|
||||
@@ -746,6 +795,39 @@ class _Structure(ArchComponent.Component):
|
||||
|
||||
base = None
|
||||
pl = obj.Placement
|
||||
|
||||
# PropertySet support
|
||||
propSetPickedUuidPrev = self.ArchSkPropSetPickedUuid
|
||||
propSetListPrev = self.ArchSkPropSetListPrev
|
||||
propSetSelectedNamePrev = obj.ArchSketchPropertySet
|
||||
propSetSelectedNameCur = None
|
||||
propSetListCur = None
|
||||
if Draft.getType(obj.Base) == "ArchSketch":
|
||||
baseProxy = obj.Base.Proxy
|
||||
if hasattr(baseProxy,"getPropertySet"):
|
||||
# get full list of PropertySet
|
||||
propSetListCur = baseProxy.getPropertySet(obj.Base)
|
||||
# get updated name (if any) of the selected PropertySet
|
||||
propSetSelectedNameCur = baseProxy.getPropertySet(obj.Base,
|
||||
propSetUuid=propSetPickedUuidPrev)
|
||||
if propSetSelectedNameCur: # True if selection is not deleted
|
||||
if propSetListPrev != propSetListCur:
|
||||
obj.ArchSketchPropertySet = propSetListCur
|
||||
obj.ArchSketchPropertySet = propSetSelectedNameCur
|
||||
self.ArchSkPropSetListPrev = propSetListCur
|
||||
#elif propSetListPrev == propSetListCur:
|
||||
#pass #nothing to do in this case
|
||||
# but if below, though (propSetListPrev == propSetListCur)
|
||||
elif propSetSelectedNamePrev != propSetSelectedNameCur:
|
||||
obj.ArchSketchPropertySet = propSetSelectedNameCur
|
||||
else: # True if selection is deleted
|
||||
if propSetListCur:
|
||||
if propSetListPrev != propSetListCur:
|
||||
obj.ArchSketchPropertySet = propSetListCur
|
||||
obj.ArchSketchPropertySet = 'Default'
|
||||
#else: # Seems no need ...
|
||||
#obj.PropertySet = 'Default'
|
||||
|
||||
extdata = self.getExtrusionData(obj)
|
||||
|
||||
if extdata:
|
||||
@@ -851,19 +933,52 @@ class _Structure(ArchComponent.Component):
|
||||
# ArchSketch feature :
|
||||
# Get base shape wires, and faceMaker, for Structure (slab. etc.) from Base Objects if they store and provide by getStructureBaseShapeWires()
|
||||
# (thickness, normal/extrusion, length, width, baseface maybe for later) of structure (slab etc.)
|
||||
structureBaseShapeWires = None
|
||||
baseShapeWires = None #baseSlabWires / baseSlabOpeningWires = None
|
||||
structureBaseShapeWires = []
|
||||
baseShapeWires = [] #baseSlabWires / baseSlabOpeningWires = None
|
||||
faceMaker = None
|
||||
if hasattr(obj.Base, 'Proxy'):
|
||||
if hasattr(obj.Base.Proxy, 'getStructureBaseShapeWires'):
|
||||
structureBaseShapeWires = obj.Base.Proxy.getStructureBaseShapeWires(obj.Base, archsketchEdges=obj.ArchSketchEdges)
|
||||
# provide selected edges, or groups, in obj.ArchSketchEdges for processing in getStructureBaseShapeWires() (getSortedClusters) as override
|
||||
# returned a {dict} ( or a [list] )
|
||||
# get slab wires; use original wires if structureBaseShapeWires() provided none
|
||||
if structureBaseShapeWires: # would be false (none) if both base ArchSketch and obj do not have the edges stored / inputted by user
|
||||
# if structureBaseShapeWires is {dict}
|
||||
baseShapeWires = structureBaseShapeWires.get('slabWires')
|
||||
faceMaker = structureBaseShapeWires.get('faceMaker')
|
||||
|
||||
if hasattr(obj.Base, 'Proxy') and obj.ArchSketchData and \
|
||||
hasattr(obj.Base.Proxy, 'getStructureBaseShapeWires'):
|
||||
propSetUuid = self.ArchSkPropSetPickedUuid
|
||||
|
||||
# provide selected edges, or groups, in obj.ArchSketchEdges for processing in getStructureBaseShapeWires() (getSortedClusters) as override
|
||||
structureBaseShapeWires = obj.Base.Proxy.getStructureBaseShapeWires(obj.Base,
|
||||
propSetUuid=propSetUuid)
|
||||
# get slab wires; use original wires if structureBaseShapeWires() provided none
|
||||
if structureBaseShapeWires: # would be false (none) if both base ArchSketch and obj do not have the edges stored / inputted by user
|
||||
# if structureBaseShapeWires is {dict}
|
||||
baseShapeWires = structureBaseShapeWires.get('slabWires')
|
||||
faceMaker = structureBaseShapeWires.get('faceMaker')
|
||||
elif obj.Base.isDerivedFrom("Sketcher::SketchObject"):
|
||||
skGeom = obj.Base.GeometryFacadeList
|
||||
skGeomEdges = []
|
||||
skPlacement = obj.Base.Placement # Get Sketch's placement to restore later
|
||||
# Get ArchSketch edges to construct ArchStructure
|
||||
# No need to test obj.ArchSketchData ...
|
||||
for ig, geom in enumerate(skGeom):
|
||||
# Construction mode edges should be ignored if
|
||||
# ArchSketchEdges, otherwise, ArchSketchEdges data
|
||||
# needs to take out those in Construction before
|
||||
# using as parameters.
|
||||
if (not obj.ArchSketchEdges and not geom.Construction) or str(ig) in obj.ArchSketchEdges:
|
||||
# support Line, Arc, Circle, Ellipse for Sketch
|
||||
# as Base at the moment
|
||||
if isinstance(geom.Geometry, (Part.LineSegment,
|
||||
Part.Circle, Part.ArcOfCircle,
|
||||
Part.Ellipse)):
|
||||
skGeomEdgesI = geom.Geometry.toShape()
|
||||
skGeomEdges.append(skGeomEdgesI)
|
||||
clusterTransformed = []
|
||||
for cluster in Part.getSortedClusters(skGeomEdges):
|
||||
edgesTransformed = []
|
||||
for edge in cluster:
|
||||
edge.Placement = edge.Placement.multiply(skPlacement)
|
||||
edgesTransformed.append(edge)
|
||||
clusterTransformed.append(edgesTransformed)
|
||||
for clusterT in clusterTransformed:
|
||||
baseShapeWires.append(Part.Wire(clusterT))
|
||||
faceMaker = 'Bullseye'
|
||||
|
||||
if not baseShapeWires:
|
||||
baseShapeWires = obj.Base.Shape.Wires
|
||||
if faceMaker or (obj.FaceMaker != "None"):
|
||||
@@ -936,14 +1051,14 @@ class _Structure(ArchComponent.Component):
|
||||
if obj.Normal.Length:
|
||||
normal = Vector(obj.Normal).normalize()
|
||||
else:
|
||||
normal = baseface.Faces[0].normalAt(0, 0) ## TODO to use ArchSketch's 'normal' for consistency
|
||||
normal = baseface.Faces[0].normalAt(0, 0) # TODO to use ArchSketch's 'normal' for consistency
|
||||
base = None
|
||||
placement = None
|
||||
inverse_placement = None
|
||||
if len(baseface.Faces) > 1:
|
||||
base = []
|
||||
placement = []
|
||||
hint = baseface.Faces[0].normalAt(0, 0) ## TODO anything to do ?
|
||||
hint = baseface.Faces[0].normalAt(0, 0) # TODO anything to do ?
|
||||
for f in baseface.Faces:
|
||||
bf, pf = self.rebase(f, hint)
|
||||
base.append(bf)
|
||||
@@ -976,6 +1091,12 @@ class _Structure(ArchComponent.Component):
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
|
||||
# check the flag indicating if onDocumentRestored() has been run; if
|
||||
# not, no further code is run - as getExtrusionData() below return
|
||||
# error when some properties are not added by onDocumentRestored()
|
||||
if not hasattr(self,"onDocRestoredDone"):
|
||||
return
|
||||
|
||||
if hasattr(obj,"IfcType"):
|
||||
IfcType = obj.IfcType
|
||||
else:
|
||||
@@ -1017,6 +1138,26 @@ class _Structure(ArchComponent.Component):
|
||||
obj.Nodes = self.nodes
|
||||
ArchComponent.Component.onChanged(self,obj,prop)
|
||||
|
||||
if (prop == "ArchSketchPropertySet"
|
||||
and Draft.getType(obj.Base) == "ArchSketch"):
|
||||
baseProxy = obj.Base.Proxy
|
||||
if hasattr(baseProxy,"getPropertySet"):
|
||||
uuid = baseProxy.getPropertySet(obj,
|
||||
propSetName=obj.ArchSketchPropertySet)
|
||||
self.ArchSkPropSetPickedUuid = uuid
|
||||
if (hasattr(obj,"ArchSketchData") and obj.ArchSketchData
|
||||
and Draft.getType(obj.Base) == "ArchSketch"):
|
||||
if hasattr(obj,"ArchSketchEdges"):
|
||||
obj.setEditorMode("ArchSketchEdges", ["ReadOnly"])
|
||||
if hasattr(obj,"ArchSketchPropertySet"):
|
||||
obj.setEditorMode("ArchSketchPropertySet", 0)
|
||||
else:
|
||||
if hasattr(obj,"ArchSketchEdges"):
|
||||
obj.setEditorMode("ArchSketchEdges", 0)
|
||||
if hasattr(obj,"ArchSketchPropertySet"):
|
||||
obj.setEditorMode("ArchSketchPropertySet", ["ReadOnly"])
|
||||
|
||||
|
||||
def getNodeEdges(self,obj):
|
||||
|
||||
"returns a list of edges from structural nodes"
|
||||
|
||||
Reference in New Issue
Block a user