def exportSMURFScene(entities, path): """Exports an arranged scene into SMURFS. It will export only entities with a valid entity/name, and entity/type property. Args: selected_only(bool): If True only selected entities get exported. subfolder(bool): If True the models are exported into separate subfolders entities: path: Returns: """ log("Exporting scene to " + path + '.smurfs', "INFO") with open(path + '.smurfs', 'w') as outputfile: sceneinfo = ("# SMURF scene created at " + path + " " + datetime.now().strftime("%Y%m%d_%H:%M") + "\n") log(sceneinfo, "INFO") sceneinfo += "# created with Phobos " + version + " - " + repository + "\n\n" ioUtils.securepath(path) outputfile.write(sceneinfo) entitiesdict = roundFloatsInDict( {'entities': entities}, ioUtils.getExpSettings().decimalPlaces) outputfile.write(yaml.dump(entitiesdict))
def exportSMURFScene(entities, path): """Exports an arranged scene into SMURFS. It will export only entities with a valid entity/name, and entity/type property. Args: selected_only(bool): If True only selected entities get exported. subfolder(bool): If True the models are exported into separate subfolders entities: path: Returns: """ log("Exporting scene to " + path + '.smurfs', "INFO") with open(path + '.smurfs', 'w') as outputfile: sceneinfo = ( "# SMURF scene created at " + path + " " + datetime.now().strftime("%Y%m%d_%H:%M") + "\n" ) log(sceneinfo, "INFO") sceneinfo += "# created with Phobos " + version + " - " + repository + "\n\n" ioUtils.securepath(path) outputfile.write(sceneinfo) entitiesdict = roundFloatsInDict( {'entities': entities}, ioUtils.getExpSettings().decimalPlaces ) outputfile.write(yaml.dump(entitiesdict))
def exportSMURFScene(entities, path): """Exports an arranged scene into SMURFS. It will export only entities with a valid entity/name, and entity/type property. :param selected_only: If True only selected entities get exported. :type selected_only: bool :param subfolder: If True the models are exported into separate subfolders :type subfolder: bool """ # TODO path consistency (Windows) with open(path + '.smurfs', 'w') as outputfile: sceneinfo = "# SMURF scene created at " + path + " " + datetime.now( ).strftime("%Y%m%d_%H:%M") + "\n" log(sceneinfo, "INFO") sceneinfo += "# created with Phobos " + version + " - https://github.com/rock-simulation/phobos\n\n" securepath(path) log("Exporting scene to " + path + '.smurfs', "INFO") outputfile.write(sceneinfo) epsilon = 10**(-bpy.data.worlds[0].phobosexportsettings.decimalPlaces ) # TODO: implement this separately entitiesdict = epsilonToZero( {'entities': entities}, epsilon, bpy.data.worlds[0].phobosexportsettings.decimalPlaces) outputfile.write(yaml.dump(entitiesdict))
def execute(self, context): roots = ioUtils.getExportModels() if not roots: log("No properly defined models selected or present in scene.", 'ERROR') return {'CANCELLED'} elif not self.exportall: roots = [ root for root in roots if root['modelname'] == self.modelname ] if len(roots) > 1: log( "Ambiguous model definitions: " + self.modelname + " exists " + str(len(roots)) + " times.", "ERROR") return {'CANCELLED'} for root in roots: # setup paths exportpath = ioUtils.getExportPath() if not securepath(exportpath): log("Could not secure path to export to.", "ERROR") continue log("Export path: " + exportpath, "DEBUG") ioUtils.exportModel(models.deriveModelDictionary(root), exportpath) # select all exported models after export is done if ioUtils.getExpSettings().selectedOnly: for root in roots: objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist, clear=False) else: bpy.ops.object.select_all(action='DESELECT') for root in roots: sUtils.selectObjects(list([root]), False) bpy.ops.phobos.select_model() # report success to user log("Export successful.", "INFO") return {'FINISHED'}
def exportModel(root, export_path, entitytypes=None, model=None): # derive model model = models.buildModelDictionary(root) if not model: model = models.buildModelDictionary(root) # export model in selected formats if entitytypes is None: entitytypes = entities.entity_types for entitytype in entitytypes: typename = "export_entity_" + entitytype # check if format exists and should be exported if not getattr(bpy.data.worlds[0], typename, False): continue # format exists and is exported: if ioUtils.getExpSettings().structureExport: model_path = os.path.join(export_path, entitytype) else: model_path = export_path securepath(model_path) try: entities.entity_types[entitytype]['export'](model, model_path) log( "Export model: " + model['name'] + ' as ' + entitytype + " to " + model_path, "DEBUG") except KeyError: log( "No export function available for selected model type: " + entitytype, "ERROR") continue # TODO: Move mesh export to individual formats? This is practically SMURF # export meshes in selected formats i = 1 mt = len([ m for m in meshes.mesh_types if getattr(bpy.data.worlds[0], "export_mesh_" + m) ]) mc = len(model['meshes']) n = mt * mc for meshtype in meshes.mesh_types: mesh_path = ioUtils.getOutputMeshpath(export_path, meshtype) try: typename = "export_mesh_" + meshtype if getattr(bpy.data.worlds[0], typename): securepath(mesh_path) for meshname in model['meshes']: meshes.mesh_types[meshtype]['export']( model['meshes'][meshname], mesh_path) display.setProgress( i / n, 'Exporting ' + meshname + '.' + meshtype + '...') i += 1 except KeyError: log( "No export function available for selected mesh function: " + meshtype, "ERROR") print(sys.exc_info()[0]) display.setProgress(0) # TODO: Move texture export to individual formats? This is practically SMURF # TODO: Also, this does not properly take care of textures embedded in a .blend file # export textures if ioUtils.getExpSettings().exportTextures: for materialname in model['materials']: mat = model['materials'][materialname] for texturetype in [ 'diffuseTexture', 'normalTexture', 'displacementTexture' ]: if texturetype in mat: sourcepath = os.path.join( os.path.expanduser(bpy.path.abspath('//')), mat[texturetype]) if os.path.isfile(sourcepath): texture_path = securepath( os.path.join(export_path, 'textures')) log("Exporting textures to " + texture_path, "INFO") try: shutil.copy( sourcepath, os.path.join( texture_path, os.path.basename(mat[texturetype]))) except shutil.SameFileError: log("{} already in place".format(texturetype), "INFO")
def deriveEntity(entity, outpath, savetosubfolder): """This function handles a heightmap entity in a scene to export it :param smurf: The heightmap root object. :type smurf: bpy.types.Object :param outpath: The path to export to. :type outpath: str :param savetosubfolder: If True data will be exported into subfolders. :type savetosubfolder: bool :return: dict - An entry for the scenes entitiesList """ heightmap = entity # determine outpath for the heightmap export heightmap_outpath = securepath( os.path.join(outpath, structure_subfolder ) if savetosubfolder else outpath) log("Exporting " + heightmap["entity/name"] + " as a heightmap entity", "INFO") entitypose = models.deriveObjectPose(heightmap) heightmapMesh = sUtils.getImmediateChildren(heightmap)[0] if bpy.data.worlds[0].heightmapMesh: exMesh = heightmapMesh.to_mesh(bpy.context.scene, True, "PREVIEW") exMesh.name = "hm_" + heightmap["entity/name"] oldMesh = heightmapMesh.data heightmapMesh.data = exMesh heightmapMesh.modifiers["displace_heightmap"].show_render = False heightmapMesh.modifiers["displace_heightmap"].show_viewport = False if bpy.data.worlds[0].useObj: iUtils.exportObj(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".obj") elif bpy.data.worlds[0].useStl: iUtils.exportStl(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".stl") elif bpy.data.worlds[0].useDae: iUtils.exportDae(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".dae") else: log("No mesh export type checked! Aborting heightmap export.", "ERROR", __name__ + ".handleScene_heightmap") return {} heightmapMesh.modifiers["displace_heightmap"].show_render = True heightmapMesh.modifiers["displace_heightmap"].show_viewport = True heightmapMesh.data = oldMesh bpy.data.meshes.remove(exMesh) entry = { "name": heightmap["entity/name"], "type": "mesh", "file": filename, "anchor": heightmap["anchor"] if "anchor" in heightmap else "none", "position": entitypose["translation"], "rotation": entitypose["rotation_quaternion"] } else: imagepath = os.path.abspath( os.path.join( os.path.split(bpy.data.filepath)[0], heightmap["image"])) shutil.copy2(imagepath, heightmap_outpath) entry = { "name": heightmap["entity/name"], "type": "heightmap", "file": os.path.join("heightmaps", os.path.basename(imagepath)), "anchor": heightmap["anchor"] if "anchor" in heightmap else "none", "width": heightmapMesh.dimensions[1], "length": heightmapMesh.dimensions[0], "height": heightmapMesh.modifiers["displace_heightmap"].strength, "position": entitypose["translation"], "rotation": entitypose["rotation_quaternion"] } return entry
def bakeModel(objlist, modelname, posename="", decimate_type='COLLAPSE', decimate_parameter=0.1): """This function gets a list of objects and creates a single, simplified mesh from it and exports it to .stl. Args: objlist(list: list): The list of blender objects to join and export as simplified stl file. modelname(str): The new models name and filename. posename: (Default value = "") decimate_type: (Default value = 'COLLAPSE') decimate_parameter: (Default value = 0.1) objlist: Returns: """ if bpy.context.scene.phobosexportsettings.relativePath: # CHECK careful with path consistency (Windows) outpath = securepath( os.path.expanduser( os.path.join(bpy.path.abspath("//"), bpy.context.scene.phobosexportsettings.path))) else: # CHECK careful with path consistency (Windows) outpath = securepath( os.path.expanduser(bpy.context.scene.phobosexportsettings.path)) # TODO delete me? # bake_outpath = securepath(os.path.join(outpath, modelname) if savetosubfolder else outpath) bake_outpath = outpath if bpy.context.scene.phobosexportsettings.structureExport: securepath(os.path.join(bake_outpath, 'bakes')) bake_outpath = os.path.join(bake_outpath, 'bakes/') export_name = modelname + '_' + posename visuals = [ o for o in objlist if ("phobostype" in o and o.phobostype == "visual") ] if len(visuals) > 0: log("Baking model to " + bake_outpath, "INFO") sUtils.selectObjects(visuals, active=0) log("Copying objects for joining...", "INFO") bpy.ops.object.duplicate(linked=False, mode='TRANSLATION') log("Joining...", "INFO") bpy.ops.object.join() obj = bpy.context.active_object log("Deleting vertices...", "INFO") bpy.ops.object.editmode_toggle() bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() log("Adding modifier...", "INFO") bpy.ops.object.modifier_add(type='DECIMATE') bpy.context.object.modifiers["Decimate"].decimate_type = decimate_type if decimate_type == 'COLLAPSE': bpy.context.object.modifiers["Decimate"].ratio = decimate_parameter elif decimate_type == 'UNSUBDIV': bpy.context.object.modifiers[ "Decimate"].iterations = decimate_parameter elif decimate_type == 'DISSOLVE': bpy.context.object.modifiers[ "Decimate"].angle_limit = decimate_parameter log("Applying modifier...", "INFO") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Decimate") obj.name = export_name + ".obj" # TODO use_selection might cause bugs, depending on Blender version bpy.ops.export_scene.obj(filepath=os.path.join(bake_outpath, obj.name), use_selection=True) obj.hide_render = True previewfile = export_name bUtils.createPreview(visuals, export_path=bake_outpath, modelname=modelname, previewfile=previewfile) obj.select = True bpy.ops.object.delete() log("Done baking...", "INFO") else: log("No visuals to bake!", "WARNING")
def execute(self, context): """ Args: context: Returns: """ roots = ioUtils.getExportModels() if not roots: log("No properly defined models selected or present in scene.", 'ERROR') return {'CANCELLED'} elif not self.exportall: roots = [ root for root in roots if nUtils.getModelName(root) == self.modelname ] if len(roots) > 1: log( "Ambiguous model definitions: " + self.modelname + " exists " + str(len(roots)) + " times.", "ERROR", ) return {'CANCELLED'} for root in roots: # setup paths exportpath = ioUtils.getExportPath() if not securepath(exportpath): log("Could not secure path to export to.", "ERROR") continue log("Export path: " + exportpath, "DEBUG") ioUtils.exportModel(models.deriveModelDictionary(root), exportpath) # select all exported models after export is done if ioUtils.getExpSettings().selectedOnly: for root in roots: objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist, clear=False) else: bpy.ops.object.select_all(action='DESELECT') for root in roots: sUtils.selectObjects(list([root]), False) bpy.ops.phobos.select_model() # TODO: Move mesh export to individual formats? This is practically SMURF # export meshes in selected formats # for meshtype in meshes.mesh_types: # mesh_path = ioUtils.getOutputMeshpath(meshtype) # try: # typename = "export_mesh_" + meshtype # if getattr(bpy.data.worlds[0], typename): # securepath(mesh_path) # for meshname in model['meshes']: # meshes.mesh_types[meshtype]['export'](model['meshes'][meshname], mesh_path) # except KeyError: # log("No export function available for selected mesh function: " + meshtype, # "ERROR", "ExportModelOperator") # print(sys.exc_info()[0]) # TODO: Move texture export to individual formats? This is practically SMURF # export textures # if ioUtils.textureExportEnabled(): # texture_path = '' # for materialname in model['materials']: # mat = model['materials'][materialname] # for texturetype in ['diffuseTexture', 'normalTexture', 'displacementTexture']: # if texturetype in mat: # texpath = os.path.join(os.path.expanduser(bpy.path.abspath('//')), mat[texturetype]) # if os.path.isfile(texpath): # if texture_path == '': # texture_path = securepath(os.path.join(export_path, 'textures')) # log("Exporting textures to " + texture_path, "INFO", "ExportModelOperator") # try: # shutil.copy(texpath, os.path.join(texture_path, os.path.basename(mat[texturetype]))) # except shutil.SameFileError: # log("{} already in place".format(texturetype), "INFO", "ExportModelOperator") # report success to user log("Export successful.", "INFO", end="\n\n") return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ roots = ioUtils.getExportModels() if not roots: log("No properly defined models selected or present in scene.", 'ERROR') return {'CANCELLED'} elif not self.exportall: roots = [root for root in roots if nUtils.getModelName(root) == self.modelname] if len(roots) > 1: log( "Ambiguous model definitions: " + self.modelname + " exists " + str(len(roots)) + " times.", "ERROR", ) return {'CANCELLED'} for root in roots: # setup paths exportpath = ioUtils.getExportPath() if not securepath(exportpath): log("Could not secure path to export to.", "ERROR") continue log("Export path: " + exportpath, "DEBUG") ioUtils.exportModel(models.deriveModelDictionary(root), exportpath) # select all exported models after export is done if ioUtils.getExpSettings().selectedOnly: for root in roots: objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist, clear=False) else: bpy.ops.object.select_all(action='DESELECT') for root in roots: sUtils.selectObjects(list([root]), False) bpy.ops.phobos.select_model() # TODO: Move mesh export to individual formats? This is practically SMURF # export meshes in selected formats # for meshtype in meshes.mesh_types: # mesh_path = ioUtils.getOutputMeshpath(meshtype) # try: # typename = "export_mesh_" + meshtype # if getattr(bpy.data.worlds[0], typename): # securepath(mesh_path) # for meshname in model['meshes']: # meshes.mesh_types[meshtype]['export'](model['meshes'][meshname], mesh_path) # except KeyError: # log("No export function available for selected mesh function: " + meshtype, # "ERROR", "ExportModelOperator") # print(sys.exc_info()[0]) # TODO: Move texture export to individual formats? This is practically SMURF # export textures # if ioUtils.textureExportEnabled(): # texture_path = '' # for materialname in model['materials']: # mat = model['materials'][materialname] # for texturetype in ['diffuseTexture', 'normalTexture', 'displacementTexture']: # if texturetype in mat: # texpath = os.path.join(os.path.expanduser(bpy.path.abspath('//')), mat[texturetype]) # if os.path.isfile(texpath): # if texture_path == '': # texture_path = securepath(os.path.join(export_path, 'textures')) # log("Exporting textures to " + texture_path, "INFO", "ExportModelOperator") # try: # shutil.copy(texpath, os.path.join(texture_path, os.path.basename(mat[texturetype]))) # except shutil.SameFileError: # log("{} already in place".format(texturetype), "INFO", "ExportModelOperator") # report success to user log("Export successful.", "INFO", end="\n\n") return {'FINISHED'}
def deriveEntity(entity, outpath): """This function handles a heightmap entity in a scene to export it Args: smurf(bpy.types.Object): The heightmap root object. outpath(str): The path to export to. savetosubfolder(bool): If True data will be exported into subfolders. entity: Returns: : dict - An entry for the scenes entitiesList """ heightmap = entity # determine outpath for the heightmap export heightmap_outpath = securepath(os.path.join(outpath, structure_subfolder)) log("Exporting " + heightmap["entity/name"] + " as a heightmap entity", "INFO") entitypose = models.deriveObjectPose(heightmap) heightmapMesh = sUtils.getImmediateChildren(heightmap)[0] if bpy.data.window_managers[0].heightmapMesh: exMesh = heightmapMesh.to_mesh(bpy.context.scene, True, "PREVIEW") exMesh.name = "hm_" + heightmap["entity/name"] oldMesh = heightmapMesh.data heightmapMesh.data = exMesh heightmapMesh.modifiers["displace_heightmap"].show_render = False heightmapMesh.modifiers["displace_heightmap"].show_viewport = False # CHECK are the heightmaps exported to the right directory? if bpy.data.window_managers[0].useObj: ioUtils.exportObj(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".obj") elif bpy.data.window_managers[0].useStl: ioUtils.exportStl(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".stl") elif bpy.data.window_managers[0].useDae: ioUtils.exportDae(heightmap_outpath, heightmapMesh) filename = os.path.join("heightmaps", exMesh.name + ".dae") else: log("No mesh export type checked! Aborting heightmap export.", "ERROR") return {} heightmapMesh.modifiers["displace_heightmap"].show_render = True heightmapMesh.modifiers["displace_heightmap"].show_viewport = True heightmapMesh.data = oldMesh bpy.data.meshes.remove(exMesh) entry = { "name": heightmap["entity/name"], "type": "mesh", "file": filename, "anchor": heightmap["anchor"] if "anchor" in heightmap else "none", "position": entitypose["translation"], "rotation": entitypose["rotation_quaternion"], } else: imagepath = os.path.abspath( os.path.join(os.path.split(bpy.data.filepath)[0], heightmap["image"]) ) shutil.copy2(imagepath, heightmap_outpath) entry = { "name": heightmap["entity/name"], "type": "heightmap", "file": os.path.join("heightmaps", os.path.basename(imagepath)), "anchor": heightmap["anchor"] if "anchor" in heightmap else "none", "width": heightmapMesh.dimensions[1], "length": heightmapMesh.dimensions[0], "height": heightmapMesh.modifiers["displace_heightmap"].strength, "position": entitypose["translation"], "rotation": entitypose["rotation_quaternion"], } return entry
def bakeModel(objlist, modelname, posename="", decimate_type='COLLAPSE', decimate_parameter=0.1): """This function gets a list of objects and creates a single, simplified mesh from it and exports it to .stl. Args: objlist(list: list): The list of blender objects to join and export as simplified stl file. modelname(str): The new models name and filename. posename: (Default value = "") decimate_type: (Default value = 'COLLAPSE') decimate_parameter: (Default value = 0.1) objlist: Returns: """ if bpy.context.scene.phobosexportsettings.relativePath: # CHECK careful with path consistency (Windows) outpath = securepath( os.path.expanduser( os.path.join(bpy.path.abspath("//"), bpy.context.scene.phobosexportsettings.path) ) ) else: # CHECK careful with path consistency (Windows) outpath = securepath(os.path.expanduser(bpy.context.scene.phobosexportsettings.path)) # TODO delete me? # bake_outpath = securepath(os.path.join(outpath, modelname) if savetosubfolder else outpath) bake_outpath = outpath if bpy.context.scene.phobosexportsettings.structureExport: securepath(os.path.join(bake_outpath, 'bakes')) bake_outpath = os.path.join(bake_outpath, 'bakes/') export_name = modelname + '_' + posename visuals = [o for o in objlist if ("phobostype" in o and o.phobostype == "visual")] if len(visuals) > 0: log("Baking model to " + bake_outpath, "INFO") sUtils.selectObjects(visuals, active=0) log("Copying objects for joining...", "INFO") bpy.ops.object.duplicate(linked=False, mode='TRANSLATION') log("Joining...", "INFO") bpy.ops.object.join() obj = bpy.context.active_object log("Deleting vertices...", "INFO") bpy.ops.object.editmode_toggle() bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() log("Adding modifier...", "INFO") bpy.ops.object.modifier_add(type='DECIMATE') bpy.context.object.modifiers["Decimate"].decimate_type = decimate_type if decimate_type == 'COLLAPSE': bpy.context.object.modifiers["Decimate"].ratio = decimate_parameter elif decimate_type == 'UNSUBDIV': bpy.context.object.modifiers["Decimate"].iterations = decimate_parameter elif decimate_type == 'DISSOLVE': bpy.context.object.modifiers["Decimate"].angle_limit = decimate_parameter log("Applying modifier...", "INFO") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Decimate") obj.name = export_name + ".obj" # TODO use_selection might cause bugs, depending on Blender version bpy.ops.export_scene.obj(filepath=os.path.join(bake_outpath, obj.name), use_selection=True) obj.hide_render = True previewfile = export_name bUtils.createPreview( visuals, export_path=bake_outpath, modelname=modelname, previewfile=previewfile ) obj.select = True bpy.ops.object.delete() log("Done baking...", "INFO") else: log("No visuals to bake!", "WARNING")
def deriveEntity(entity, outpath, savetosubfolder): """Derives the dictionary for a SMURF entity from the phobos model dictionary. :param entity: The smurf root object. :type entity: bpy.types.Object :param outpath: The path to export the smurf to. :type outpath: str :param savetosubfolder: If True the export path has a subfolder for this smurf entity. :type savetosubfolder: bool :return: dict - An entry for the scenes entitiesList """ smurf = entity # determine outpath for the smurf export # differentiate between full model and baked reference if "entity/isReference" in smurf: bpy.ops.scene.reload_models_and_poses_operator() modelsPosesColl = bpy.context.user_preferences.addons[ "phobos"].preferences.models_poses for robot_model in modelsPosesColl: if (smurf["modelname"] == robot_model.robot_name) and (smurf["entity/pose"] == robot_model.label): entitypose = models.deriveObjectPose(smurf) entry = models.initObjectProperties(smurf, 'entity', ['link', 'joint', 'motor']) entry.pop("isReference") entry['file'] = os.path.join( os.path.relpath(robot_model.path, outpath), smurf["modelname"] + ".smurf") if 'parent' not in entry and 'joint/type' in smurf and smurf[ 'joint/type'] == 'fixed': entry['parent'] = 'world' entry["position"] = entitypose["translation"] entry["rotation"] = entitypose["rotation_quaternion"] ''' with open(os.path.join(os.path.dirname(defs.__file__), "RobotLib.yml"), "r") as f: robots = yaml.load(f.read()) sourcepath = robots[smurf["modelname"]] for filename in os.listdir(sourcepath): fullpath = os.path.join(sourcepath, filename) if os.path.isfile(fullpath): shutil.copy2(fullpath, os.path.join(smurf_outpath, filename)) else: # remove old folders to prevent errors in copytree shutil.rmtree(os.path.join(smurf_outpath, filename), True) shutil.copytree(fullpath, os.path.join(smurf_outpath, filename)) ''' else: smurf_outpath = securepath( os.path.join(outpath, entity["modelname"] ) if savetosubfolder else outpath) log("smurf_outpath: " + outpath, "DEBUG", "exportSMURFsScene") log( "Exporting " + smurf["entity/name"] + " as a smurf entity to " + smurf_outpath, "INFO", "deriveSMURFEntity", "\n\n") subfolder = smurf["modelname"] if savetosubfolder else "" sUtils.selectObjects(sUtils.getChildren(smurf), clear=True) # re-select for mesh export model, objectlist = models.buildModelDictionary(smurf) export( model, objectlist, smurf_outpath) # FIXME: this is the export function from entities! entitypose = models.deriveObjectPose(smurf) entry = models.initObjectProperties(smurf, 'entity', ['link', 'joint', 'motor']) entry['file'] = (os.path.join(subfolder, smurf["modelname"] + ".smurf") if os.path.isfile(smurf_outpath) else os.path.join( subfolder, "smurf", smurf["modelname"] + ".smurf")) if 'parent' not in entry and 'joint/type' in smurf and smurf[ 'joint/type'] == 'fixed': entry['parent'] = 'world' entry["position"] = entitypose["translation"] entry["rotation"] = entitypose["rotation_quaternion"] return entry