Draft: Fixed Move & Rotate continue mode

This commit is contained in:
Yorik van Havre
2017-07-26 12:51:52 -03:00
parent 6df816170a
commit 352accabd9
5 changed files with 213 additions and 17 deletions

View File

@@ -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):

View File

@@ -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>

View File

@@ -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"

View File

@@ -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
#---------------------------------------------------------------------------

View File

@@ -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"