Draft: Fixed Move & Rotate continue mode
This commit is contained in:
@@ -730,6 +730,19 @@ def pruneIncluded(objectslist,strict=False):
|
||||
newlist.append(obj)
|
||||
return newlist
|
||||
|
||||
def getAllChildren(objectlist):
|
||||
"getAllChildren(objectlist): returns all the children of all the object sin the list"
|
||||
obs = []
|
||||
for o in objectlist:
|
||||
if not o in obs:
|
||||
obs.append(o)
|
||||
if o.OutList:
|
||||
l = getAllChildren(o.OutList)
|
||||
for c in l:
|
||||
if not c in obs:
|
||||
obs.append(c)
|
||||
return obs
|
||||
|
||||
class _SurveyObserver:
|
||||
"an observer for the survey() function"
|
||||
def __init__(self,callback):
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>456</width>
|
||||
<height>666</height>
|
||||
<height>699</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -490,6 +490,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_19">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_13">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, all FreeCAD object properties will be stored inside the exported objects, allowing to recreate a full parametric model on reimport.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export full FreeCAD parametric model</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>IfcExportFreeCADProperties</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -139,7 +139,7 @@ def getPreferences():
|
||||
global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS
|
||||
global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES
|
||||
global FORCE_BREP, IMPORT_PROPERTIES, STORE_UID, SERIALIZE
|
||||
global SPLIT_LAYERS, EXPORT_2D
|
||||
global SPLIT_LAYERS, EXPORT_2D, FULL_PARAMETRIC
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False):
|
||||
import FreeCADGui
|
||||
@@ -165,6 +165,7 @@ def getPreferences():
|
||||
SERIALIZE = p.GetBool("ifcSerialize",False)
|
||||
SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False)
|
||||
EXPORT_2D = p.GetBool("ifcExport2D",True)
|
||||
FULL_PARAMETRIC = p.GetBool("IfcExportFreeCADProperties",False)
|
||||
|
||||
|
||||
def explore(filename=None):
|
||||
@@ -355,8 +356,8 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
FreeCAD.ActiveDocument = doc
|
||||
|
||||
if DEBUG: print("done.")
|
||||
|
||||
global ROOT_ELEMENT
|
||||
|
||||
global ROOT_ELEMENT, parametrics
|
||||
|
||||
if root:
|
||||
ROOT_ELEMENT = root
|
||||
@@ -395,6 +396,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
structshapes = {} # { id:shaoe } only used for merge mode
|
||||
mattable = {} # { objid:matid }
|
||||
sharedobjects = {} # { representationmapid:object }
|
||||
parametrics = [] # a list of imported objects whose parametric relationships need processing after all objects have been created
|
||||
for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
|
||||
additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
|
||||
for r in ifcfile.by_type("IfcRelAggregates"):
|
||||
@@ -478,6 +480,16 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
guid = product.GlobalId
|
||||
ptype = product.is_a()
|
||||
if DEBUG: print(count+1,"/",len(products)," creating object #",pid," : ",ptype,end="")
|
||||
|
||||
# checking for full FreeCAD parametric definition, overriding everything else
|
||||
if pid in properties.keys():
|
||||
if "FreeCADPropertySet" in properties[pid].keys():
|
||||
if DEBUG: print(" restoring from parametric definition")
|
||||
obj = createFromProperties(properties[pid],ifcfile)
|
||||
if obj:
|
||||
objects[pid] = obj
|
||||
continue
|
||||
|
||||
name = str(ptype[3:])
|
||||
if product.Name:
|
||||
name = product.Name.encode("utf8")
|
||||
@@ -872,7 +884,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
if DEBUG: print("adding ",len(cobs), " object(s) to ", objects[host].Label)
|
||||
Arch.addComponents(cobs,objects[host])
|
||||
if DEBUG: FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
if DEBUG: print("done.")
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
@@ -918,7 +930,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
count += 1
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
if DEBUG and annotations: print("done.")
|
||||
|
||||
# Materials
|
||||
@@ -954,6 +966,12 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
|
||||
if DEBUG and materials: print("done")
|
||||
|
||||
# restore links from full parametric definitions
|
||||
for p in parametrics:
|
||||
l = FreeCAD.ActiveDocument.getObject(p[2])
|
||||
if l:
|
||||
setattr(p[0],p[1],l)
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
@@ -1020,6 +1038,8 @@ def export(exportList,filename):
|
||||
annotations.append(obj)
|
||||
objectslist = [obj for obj in objectslist if not obj in annotations]
|
||||
objectslist = Arch.pruneIncluded(objectslist)
|
||||
if FULL_PARAMETRIC:
|
||||
objectslist = Arch.getAllChildren(objectslist)
|
||||
products = {} # { Name: IfcEntity, ... }
|
||||
surfstyles = {} # { (r,g,b): IfcEntity, ... }
|
||||
clones = {} # { Basename:[Clonename1,Clonename2,...] }
|
||||
@@ -1035,7 +1055,7 @@ def export(exportList,filename):
|
||||
b = Draft.getCloneBase(o,strict=True)
|
||||
if b:
|
||||
clones.setdefault(b.Name,[]).append(o.Name)
|
||||
|
||||
|
||||
#print("clones table: ",clones)
|
||||
#print(objectslist)
|
||||
|
||||
@@ -1234,6 +1254,68 @@ def export(exportList,filename):
|
||||
if not ifcprop:
|
||||
#if DEBUG : print("no ifc properties to export")
|
||||
pass
|
||||
if FULL_PARAMETRIC:
|
||||
# exporting all the object properties
|
||||
FreeCADProps = []
|
||||
FreeCADGuiProps = []
|
||||
FreeCADProps.append(ifcfile.createIfcPropertySingleValue("FreeCADType",None,ifcfile.create_entity("IfcText",obj.TypeId),None))
|
||||
FreeCADProps.append(ifcfile.createIfcPropertySingleValue("FreeCADName",None,ifcfile.create_entity("IfcText",obj.Name),None))
|
||||
for realm,ctx in [("App",obj),("Gui",obj.ViewObject)]:
|
||||
if ctx:
|
||||
for prop in ctx.PropertiesList:
|
||||
if hasattr(ctx,"Proxy"):
|
||||
if ctx.Proxy:
|
||||
if realm == "App":
|
||||
FreeCADProps.append(ifcfile.createIfcPropertySingleValue("FreeCADAppObject",None,ifcfile.create_entity("IfcText",str(ctx.Proxy.__class__)),None))
|
||||
else:
|
||||
FreeCADGuiProps.append(ifcfile.createIfcPropertySingleValue("FreeCADGuiObject",None,ifcfile.create_entity("IfcText",str(ctx.Proxy.__class__)),None))
|
||||
if not(prop in ["IfcProperties","IfcAttributes","Shape","Proxy","ExpressionEngine","AngularDeflection","BoundingBox"]):
|
||||
try:
|
||||
ptype = ctx.getTypeIdOfProperty(prop)
|
||||
except AttributeError:
|
||||
ptype = "Unknown"
|
||||
itype = None
|
||||
ivalue = None
|
||||
if ptype in ["App::PropertyString","App::PropertyEnumeration"]:
|
||||
itype = "IfcText"
|
||||
ivalue = getattr(ctx,prop)
|
||||
elif ptype == "App::PropertyInteger":
|
||||
itype = "IfcInteger"
|
||||
ivalue = getattr(ctx,prop)
|
||||
elif ptype == "App::PropertyFloat":
|
||||
itype = "IfcReal"
|
||||
ivalue = float(getattr(ctx,prop))
|
||||
elif ptype == "App::PropertyBool":
|
||||
itype = "IfcBoolean"
|
||||
ivalue = getattr(ctx,prop)
|
||||
elif ptype in ["App::PropertyVector","App::PropertyPlacement"]:
|
||||
itype = "IfcText"
|
||||
ivalue = str(getattr(ctx,prop))
|
||||
elif ptype in ["App::PropertyLength","App::PropertyDistance"]:
|
||||
itype = "IfcReal"
|
||||
ivalue = float(getattr(ctx,prop).getValueAs("m"))
|
||||
elif ptype == "App::PropertyArea":
|
||||
itype = "IfcReal"
|
||||
ivalue = float(getattr(ctx,prop).getValueAs("m^2"))
|
||||
elif ptype == "App::PropertyLink":
|
||||
t = getattr(ctx,prop)
|
||||
if t:
|
||||
itype = "IfcText"
|
||||
ivalue = "FreeCADLink_" + t.Name
|
||||
else:
|
||||
if DEBUG: print("Unable to encode property ",prop," of type ",ptype)
|
||||
if itype:
|
||||
# TODO add description
|
||||
if realm == "Gui":
|
||||
FreeCADGuiProps.append(ifcfile.createIfcPropertySingleValue("FreeCADGui_"+prop,None,ifcfile.create_entity(itype,ivalue),None))
|
||||
else:
|
||||
FreeCADProps.append(ifcfile.createIfcPropertySingleValue("FreeCAD_"+prop,None,ifcfile.create_entity(itype,ivalue),None))
|
||||
if FreeCADProps:
|
||||
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'FreeCADPropertySet',None,FreeCADProps)
|
||||
ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset)
|
||||
if FreeCADGuiProps:
|
||||
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'FreeCADGuiPropertySet',None,FreeCADGuiProps)
|
||||
ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset)
|
||||
|
||||
count += 1
|
||||
|
||||
@@ -1429,7 +1511,7 @@ def export(exportList,filename):
|
||||
defaulthost = ifcfile.createIfcBuildingStorey(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"Default Storey",'',None,None,None,None,"ELEMENT",None)
|
||||
ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'DefaultStoreyLink','',buildings[0],[defaulthost])
|
||||
ifcfile.createIfcRelContainedInSpatialStructure(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'AnnotationsLink','',annos,defaulthost)
|
||||
|
||||
|
||||
|
||||
if DEBUG: print("writing ",filename,"...")
|
||||
|
||||
@@ -1444,6 +1526,70 @@ def export(exportList,filename):
|
||||
os.remove(templatefile)
|
||||
|
||||
|
||||
def createFromProperties(propsets,ifcfile):
|
||||
"creates a FreeCAD parametric object from a set of properties"
|
||||
obj = None
|
||||
sets = []
|
||||
global parametrics
|
||||
if "FreeCADPropertySet" in propsets.keys():
|
||||
appset = propsets["FreeCADPropertySet"]
|
||||
if "FreeCADType" in appset:
|
||||
if "FreeCADName" in appset:
|
||||
obj = FreeCAD.ActiveDocument.addObject(appset["FreeCADType"],appset["FreeCADName"])
|
||||
if "FreeCADAppObject" in appset:
|
||||
mod,cla = appset["FreeCADAppObject"].split(".")
|
||||
import importlib
|
||||
mod = importlib.import_module(mod)
|
||||
getattr(mod,cla)(obj)
|
||||
sets.append(("App",appset))
|
||||
if FreeCAD.GuiUp:
|
||||
if "FreeCADGuiPropertySet" in propsets.keys():
|
||||
guiset = propsets["FreeCADGuiPropertySet"]
|
||||
if "FreeCADGuiObject" in guiset:
|
||||
mod,cla = guiset["FreeCADGuiObject"].split(".")
|
||||
import importlib
|
||||
mod = importlib.import_module(mod)
|
||||
getattr(mod,cla)(obj.ViewObject)
|
||||
sets.append(("Gui",guiset))
|
||||
if obj and sets:
|
||||
for realm,pset in sets:
|
||||
if realm == "App":
|
||||
target = obj
|
||||
else:
|
||||
target = obj.ViewObject
|
||||
for pid in pset:
|
||||
ient = ifcfile[pid]
|
||||
if ient.is_a("IfcPropertySingleValue"):
|
||||
if ient.Name.startswith("FreeCAD_"):
|
||||
name = ient.Name.split("_")
|
||||
if name in target.PropertiesList:
|
||||
ptype = target.getTypeIdOfProperty(name)
|
||||
if ptype in ["App::PropertyString","App::PropertyEnumeration","App::PropertyInteger","App::PropertyFloat"]:
|
||||
setattr(target,name,ient.NominalValue)
|
||||
elif ptype in ["App::PropertyLength","App:PropertyDistance"]:
|
||||
setattr(target,name,ient.NominalValue*1000)
|
||||
elif ptype == "App::PropertyBool":
|
||||
if ient.NominalValue == ".T.":
|
||||
setattr(target,name,True)
|
||||
else:
|
||||
setattr(target,name,True)
|
||||
elif ptype == "App::PropertyVector":
|
||||
setattr(target,name,FreeCAD.Vector([float(s) for s in ient.NominalValue.split("(")[1].strip(")").split(",")]))
|
||||
elif ptype == "App::PropertyArea":
|
||||
setattr(target,name,ient.NominalValue*1000000)
|
||||
elif ptype == "App::PropertyPlacement":
|
||||
data = ient.NominalValue.split("[")[1].strip("]").split("(")
|
||||
v = FreeCAD.Vector([float(s) for s in data[1].strip(")").split(",")])
|
||||
r = FreeCAD.Rotation([float(s) for s in data[3].strip(")").split(",")])
|
||||
setattr(target,name,FreeCAD.Placement(v,r))
|
||||
elif ptype == "App::PropertyLink":
|
||||
link = ient.NominalValue.split("_")[1]
|
||||
parametrics.append([target,name,link])
|
||||
else:
|
||||
print("Unhandled FreeCAD property:",name," of type:",ptype)
|
||||
return obj
|
||||
|
||||
|
||||
def createCurve(ifcfile,wire):
|
||||
"creates an IfcCompositeCurve from a shape"
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ class todo:
|
||||
QtCore.QTimer.singleShot(0,doTodo).'''
|
||||
itinerary = []
|
||||
commitlist = []
|
||||
afteritinerary = []
|
||||
|
||||
@staticmethod
|
||||
def doTasks():
|
||||
@@ -134,6 +135,17 @@ class todo:
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
FreeCADGui.Snapper.restack()
|
||||
todo.commitlist = []
|
||||
for f, arg in todo.afteritinerary:
|
||||
try:
|
||||
# print("debug: executing",f)
|
||||
if arg:
|
||||
f(arg)
|
||||
else:
|
||||
f()
|
||||
except:
|
||||
wrn = "[Draft.todo.tasks] Unexpected error:", sys.exc_info()[0], "in ", f, "(", arg, ")"
|
||||
FreeCAD.Console.PrintWarning (wrn)
|
||||
todo.afteritinerary = []
|
||||
|
||||
@staticmethod
|
||||
def delay (f, arg):
|
||||
@@ -148,6 +160,13 @@ class todo:
|
||||
QtCore.QTimer.singleShot(0, todo.doTasks)
|
||||
todo.commitlist = cl
|
||||
|
||||
@staticmethod
|
||||
def delayAfter (f, arg):
|
||||
# print("debug: delaying",f)
|
||||
if todo.afteritinerary == []:
|
||||
QtCore.QTimer.singleShot(0, todo.doTasks)
|
||||
todo.afteritinerary.append((f,arg))
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# UNITS handling
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -2319,11 +2319,10 @@ class Move(Modifier):
|
||||
def finish(self,closed=False,cont=False):
|
||||
if self.ghost:
|
||||
self.ghost.finalize()
|
||||
Modifier.finish(self)
|
||||
if cont and self.ui:
|
||||
if self.ui.continueMode:
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.Activated()
|
||||
todo.delayAfter(self.Activated,[])
|
||||
Modifier.finish(self)
|
||||
|
||||
def move(self,delta,copy=False):
|
||||
"moving the real shapes"
|
||||
@@ -2467,7 +2466,7 @@ class Rotate(Modifier):
|
||||
self.step = 0
|
||||
self.center = None
|
||||
self.ui.arcUi()
|
||||
self.ui.isCopy.show()
|
||||
self.ui.modUi()
|
||||
self.ui.setTitle("Rotate")
|
||||
self.arctrack = arcTracker()
|
||||
self.ghost = ghostTracker(self.sel)
|
||||
@@ -2476,17 +2475,16 @@ class Rotate(Modifier):
|
||||
|
||||
def finish(self,closed=False,cont=False):
|
||||
"finishes the arc"
|
||||
Modifier.finish(self)
|
||||
if self.arctrack:
|
||||
self.arctrack.finalize()
|
||||
if self.ghost:
|
||||
self.ghost.finalize()
|
||||
if self.doc:
|
||||
self.doc.recompute()
|
||||
if cont and self.ui:
|
||||
if self.ui.continueMode:
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.Activated()
|
||||
todo.delayAfter(self.Activated,[])
|
||||
Modifier.finish(self)
|
||||
if self.doc:
|
||||
self.doc.recompute()
|
||||
|
||||
def rot (self,angle,copy=False):
|
||||
"rotating the real shapes"
|
||||
|
||||
Reference in New Issue
Block a user