def convert_windows_path(attr): """ Fix windows paths in one path attribute. Args: attr (OfAttr): Attribute to modify. Returns: bool: Whether the attribute was modified """ path = attr.get_string() attr_name = attr.get_name() item_name = attr.get_parent_object().get_name() if path: result = re.sub(LETTER_RX, "", path).replace("\\", "/") if result == path: ix.log_info("Path OK: {}.{} {}".format(item_name, attr_name, path)) else: attr.set_string(result) ix.log_info( "Conformed: {}.{} {} -> {}".format(item_name, attr_name, path, result) ) return True return False
def main(): """ Prepare this project to be rendered. """ desc = "Prepare a Clarisse project file for rendering on Conductor" parser = argparse.ArgumentParser(description=desc) parser.add_argument( "-convert_windows_paths", action="store_true", default=True, help="If this was submitted from windows, strip drive letters.", ) parser.add_argument( "-range", nargs=2, type=int, help="Ensure image ranges are turned on." ) parser.add_argument("-images", nargs="+", type=str, help="Image object names.") options, _ = parser.parse_known_args() ix.log_info("convert_windows_paths {}".format(options.convert_windows_paths)) resolve_contexts() # strip regular drive letters AFTER resolving contexts so we catch any paths # that were inside contexts. if options.convert_windows_paths: convert_windows_paths() if options.range and options.images: start, end = options.range force_image_ranges(start, end, options.images) ensure_image_directories(options.images)
def Search_replace(self, sender, evtid): ix.begin_command_batch('Undo Search_replace') Selected_Hierarchy = Hierarchy_checkbox.get_value() oldtext = oldtext_lineEdit.get_text() newtext = newtext_lineEdit.get_text() counter = 0 for i in range( ix.selection.get_count() ): selected_obj = str(ix.selection[i]) selected_obj_name = selected_obj.split('/') if len(oldtext) != 0 : new_name = selected_obj_name[-1].replace( oldtext , newtext ) ix.cmds.RenameItem( selected_obj , new_name ) if str(selected_obj_name[-1]) != new_name: counter += 1 if Selected_Hierarchy : if ix.selection[i].is_context(): Hierarchy_list = Hierarchy_lister( ix.selection[i] , True , True ) for iii in range(len(Hierarchy_list)): selected_obj_name = Hierarchy_list[iii].split('/') if len(oldtext) != 0 : new_name = selected_obj_name[-1].replace( oldtext , newtext ) ix.cmds.RenameItem( Hierarchy_list[iii] , new_name ) if str(selected_obj_name[-1]) != new_name: counter += 1 ix.log_info ( str(counter) + " Object has been renamed" + " -- from renamer" ) ix.end_command_batch()
def write_render_package(self): """ Write a package suitable for rendering. A render package is a project file with a special name. """ app = ix.application clarisse_window = app.get_event_window() self._before_write_package() current_filename = app.get_current_project_filename() current_window_title = clarisse_window.get_title() package_file = self.render_package_path.posix_path() with cu.disabled_app(): success = ix.application.save_project(package_file) ix.application.set_current_project_filename(current_filename) clarisse_window.set_title(current_window_title) self._after_write_package() if not success: ix.log_error( "Failed to export render package {}".format(package_file)) ix.log_info("Wrote package to {}".format(package_file)) return package_file
def add_prefix(self, sender, evtid): ix.begin_command_batch('Undo Add Prefix') Selected_Hierarchy = Hierarchy_checkbox.get_value() string_Prefix = Prefix_lineEdit.get_text() counter = 0 for i in range(ix.selection.get_count()): selected_obj = str(ix.selection[i]) selected_obj_name = selected_obj.split('/') if len(string_Prefix) != 0: new_name = (string_Prefix + str(selected_obj_name[-1])) ix.cmds.RenameItem(selected_obj, new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 if Selected_Hierarchy: if ix.selection[i].is_context(): Hierarchy_list = Hierarchy_lister( ix.selection[i], True, True) for iii in range(len(Hierarchy_list)): selected_obj_name = Hierarchy_list[iii].split('/') new_name = (string_Prefix + str(selected_obj_name[-1])) ix.cmds.RenameItem(Hierarchy_list[iii], new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 ix.log_info( str(counter) + " Object has been added your Prefix" + " -- from AWA renamer") ix.end_command_batch()
def Filereader_Renamer(self, sender, evtid): ix.begin_command_batch('Undo Filereader Rename') Selected_Hierarchy = Hierarchy_checkbox.get_value() file_suffix = file_suffix_checkbox.get_value() object_type_suffix = object_type_suffix_checkbox.get_value() counter = 0 for i in range(ix.selection.get_count() ): selected_obj = str(ix.selection[i]) selected_obj_name = selected_obj.split('/') #True Type if ix.selection[i].is_context() is False : object_type_fullname = ix.selection[i].get_class_name() if object_type_fullname in dict_suffix_short: #has dirctory if len( str( ix.selection[i].attrs.filename) ) > 2 : filename_full_path = ix.selection[i].attrs.filename #print (filename_full_path[0]) file_name_and_extension = os.path.splitext( os.path.split( str(filename_full_path[0]) )[1]) #print (file_name_and_extension) new_name = file_name_and_extension[0] if file_suffix : new_name = new_name + "_" + file_name_and_extension[1][ 1: ] if object_type_suffix : new_name = new_name + "_" + dict_suffix_short.get(object_type_fullname) ix.cmds.RenameItem( selected_obj , new_name ) if str(selected_obj_name[-1]) != new_name : counter += 1 if Selected_Hierarchy : if ix.selection[i].is_context(): Hierarchy_list = Hierarchy_lister( ix.selection[i] , True , True ) for iii in range(len(Hierarchy_list)): selected_obj_name = str(Hierarchy_list[iii]).split('/') #True Type if Hierarchy_list[iii].is_context() is False : object_type_fullname = Hierarchy_list[iii].get_class_name() if object_type_fullname in dict_suffix_short: #has dirctory if len( str( Hierarchy_list[iii].attrs.filename) ) > 2 : filename_full_path = Hierarchy_list[iii].attrs.filename #print (filename_full_path[0]) file_name_and_extension = os.path.splitext( os.path.split( str(filename_full_path[0]) )[1]) #print (file_name_and_extension) new_name = file_name_and_extension[0] if file_suffix : new_name = new_name + "_" + file_name_and_extension[1][ 1: ] if object_type_suffix : new_name = new_name + "_" + dict_suffix_short.get(object_type_fullname) ix.cmds.RenameItem( Hierarchy_list[iii] , new_name ) if str(selected_obj_name[-1]) != new_name : counter += 1 ix.log_info (str(counter) + " Object has been renamed" + " -- from AWA renamer") ix.end_command_batch()
def convert_windows_paths(): """ Fix windows paths in regular path attrs. """ attrs = ix.api.OfAttr.get_path_attrs() total = len(list(attrs)) ix.log_info("Stripping drive letters for {:d} paths".format(total)) count = 0 for attr in attrs: if convert_windows_path(attr): count += 1 ix.log_info("Done conforming {:d} of {:d} paths".format(count, total))
def _get_qt(): # check which versions of Qt are loaded pyqt4 = 1 if sys.modules.has_key("PyQt4") else 0 pyqt5 = 1 if sys.modules.has_key("PyQt5") else 0 pyside = 1 if sys.modules.has_key("PySide") else 0 pyside2 = 1 if sys.modules.has_key("PySide2") else 0 # get the number of loaded versions loaded_qt_versions = pyqt4 + pyqt5 + pyside + pyside2 # if no version of Qt is loaded, or if multiple ones are, # throw an exception if loaded_qt_versions == 0: raise Exception("pyqt_clarisse - no known Qt module found. Try importing PyQt4/5 or PySide/2 **before** importing pyqt_clarisse") elif loaded_qt_versions > 1: raise Exception("pyqt_clarisse - more than one Qt module loaded ! Load only one of PyQt4/5 or PySide/2 before importing pyqt_clarisse") # here we can actually load the correct version of Qt and # return its QtCore and QtGui parts. if pyqt4 == 1: ix.log_info("Python: using PyQt4 Qt bindings.") from PyQt4 import QtCore, QtGui return QtCore, QtGui elif pyqt5 == 1: ix.log_info("Python: using PyQt5 Qt bindings.") from PyQt5 import QtCore, QtWidgets return QtCore, QtWidgets elif pyside == 1: ix.log_info("Python: using PySide Qt bindings.") from PySide import QtCore, QtGui return QtCore, QtGui elif pyside2 == 1: ix.log_info("Python: using PySide2 Qt bindings.") from PySide2 import QtCore, QtWidgets return QtCore, QtWidgets
def _copy_system_dependencies_to_temp(self): """ Copy over all system dependencies to a tmp folder. Wrapper scripts, config files etc. The clarisse.cfg file is special. See ../clarisse_config.py """ for entry in deps.system_dependencies(): if os.path.isfile(entry["src"]): if entry["src"].endswith(".cfg"): safe_config = ccfg.legalize(entry["src"]) with open(entry["dest"], "w") as dest: dest.write(safe_config) ix.log_info("Copy with mods {} to {}".format( entry["src"], entry["dest"])) else: ix.log_info("Copy {} to {}".format(entry["src"], entry["dest"])) shutil.copy(entry["src"], entry["dest"])
def ensure_image_directories(images): """ Create directories in preparation for image output. Clarisse fails to render if the destination directories don't exist. Args: images (list): Clarisse paths to all images """ ix.log_info("Ensure directories exist for images") directories = [] for image_path in images: image = ix.get_item(image_path) directory = os.path.dirname(image.get_attribute("save_as").get_string()) directories.append(directory) sys.stdout.write("{} save to disk at: {}\n".format(image_path, directory)) mkdir_p(directories)
def submit(self): """ Submit all jobs. Returns: list: list of response dictionaries, containing response codes and descriptions. """ submission_args = self.get_args() self.write_render_package() do_submission, submission_args = self.legalize_upload_paths( submission_args) results = [] if do_submission: for job_args in submission_args: try: remote_job = conductor_submit.Submit(job_args) response, response_code = remote_job.main() results.append({ "code": response_code, "response": response }) except BaseException: results.append({ "code": "undefined", "response": "".join(traceback.format_exception(*sys.exc_info())), }) for result in results: ix.log_info(result) else: return [{ "code": "undefined", "response": "Submission cancelled by user" }] self._after_submit() return results
def surface_maps(asset, selectedVariants): # explode variants variantLabels, variantConfigs = assetexchange_shared.asset.explode_variants( 'Primary', selectedVariants) # iterate variant config for variantConfig in variantConfigs: # get all maps and convert to dictionary by map type object_list = assetexchange_shared.asset.filter_objects_by_variant_config( asset, 'Primary', variantLabels, variantConfig) surface_maps = { surface_map["type"]: surface_map for surface_map in object_list } shader_name = asset['uid'].split(".")[1] shader_type = "disney" map_maps(shader_name, surface_maps, shader_type) ix.log_info("Basic shader setup created.")
def environment_hdri(asset, selectedVariants): # explode variants variantLabels, variantConfigs = assetexchange_shared.asset.explode_variants( 'Primary', selectedVariants) # iterate variant config for variantConfig in variantConfigs: # get environment map object_list = assetexchange_shared.asset.filter_objects_by_variant_config( asset, 'Primary', variantLabels, variantConfig) if len(object_list) == 0: return env_map = object_list[0] # clarisse run import ix.log_info("Ninja works. Does iFX stuff.") asset_name = asset['uid'] path_to_asset = env_map["file"]["path"] asset_name = asset_name.split(".")[1] create_dome(asset_name, path_to_asset) ix.log_info("Run done.")
def submit(self): """Submit all jobs. Collect their responses and show them in the log. """ self.write_render_package() results = [] for job_args in self.get_args(): try: remote_job = conductor_submit.Submit(job_args) response, response_code = remote_job.main() results.append({"code": response_code, "response": response}) except BaseException: results.append({"code": "undefined", "response": "".join( traceback.format_exception(*sys.exc_info()))}) for result in results: ix.log_info(result) if self.delete_render_package: if os.path.exists(self.render_package): os.remove(self.render_package)
def create_dome(name, path_to_hdri_map): ix.log_info("Creating HDRI Dome, you can Undo.") create_env = None ix.begin_command_batch("AssetNinjaImportHdri") clean_name = str(name) mapfile = ix.cmds.CreateObject(clean_name, 'TextureMapFile') mapfile.attrs.projection = 5 path_to_hdri_map = str(path_to_hdri_map) mapfile.attrs.filename = path_to_hdri_map mapfile.attrs.interpolation_mode = 1 mapfile.attrs.mipmap_filtering_mode = 1 mapfile.attrs.color_space_auto_detect = False mapfile.attrs.file_color_space = 'linear' mapfile.attrs.pre_multiplied = False ibl_name = "IBL_" + clean_name light = ix.cmds.CreateObject(ibl_name, 'LightPhysicalEnvironment') ix.cmds.SetTexture([light.get_full_name() + ".color"], mapfile.get_full_name()) if create_env: env = ix.cmds.CreateObject('ibl_env', 'GeometrySphere') env_mat = ix.cmds.CreateObject('ibl_mat', 'MaterialMatte') env.attrs.override_material = env_mat env.attrs.unseen_by_camera = True env.attrs.cast_shadows = False env.attrs.receive_shadows = False env.attrs.is_emitter = False env.attrs.radius = 500001 env.attrs.unseen_by_rays = True env.attrs.unseen_by_reflections = True env.attrs.unseen_by_refractions = True env.attrs.unseen_by_gi = True env.attrs.unseen_by_sss = True ix.cmds.SetTexture([env_mat.get_full_name() + ".color"], mapfile.get_full_name()) ix.cmds.SetTexture([light.get_full_name() + ".parent"], env.get_full_name()) ix.end_command_batch() ix.log_info("Dome IBL Done.")
def force_image_ranges(start, end, images): """ Ensure the sequence attributes on image ranges are valid. Clarisse doesn't respect frame range overrides, so we make sure the image ranges are covered. Args: start (int): first frame end (int): last frame images (list): Clarisse paths to all images """ ix.log_info( "Ensuring image ranges are on for the sequence {}:{}".format(start, end) ) for image_path in images: image = ix.get_item(image_path) ix.log_info("Setting range for: {} ".format(image.get_name())) image.get_attribute("first_frame").set_long(start) image.get_attribute("last_frame").set_long(end) image.get_attribute("frame_step").set_long(1)
def _get_qt(): """ This function will check loaded modules to try and guess which version was loaded. In case no version or multiple ones were loaded, it will log an error and return nothing. @note This function is "private" and shouldn't be used directly by anthing other than this module. @returns The QApplication and QEventLoop classes as a pair """ # check which versions of Qt are loaded pyqt4 = 1 if "PyQt4" in sys.modules else 0 pyqt5 = 1 if "PyQt5" in sys.modules else 0 pyside = 1 if "PySide" in sys.modules else 0 pyside2 = 1 if "PySide2" in sys.modules else 0 # get the number of loaded versions loaded_qt_versions = pyqt4 + pyqt5 + pyside + pyside2 # if no version of Qt is loaded, or if multiple ones are, throw an exception if loaded_qt_versions == 0: raise Exception("QtHelper - no known Qt module found. Try importing PyQt4/5 or PySide/2 **before** importing QtHelper") elif loaded_qt_versions > 1: raise Exception("QtHelper - more than one Qt module loaded! Load **only** one of PyQt4/5 or PySide/2 before importing QtHelper") # here we can actually load the correct version of Qt and return its QtCore and QtGui parts. if pyqt4 == 1: ix.log_info("Python: using PyQt4 Qt bindings.") from PyQt4 import QtCore, QtGui return QtGui.QApplication, QtCore.QEventLoop elif pyqt5 == 1: ix.log_info("Python: using PyQt5 Qt bindings.") from PyQt5 import QtCore, QtWidgets return QtWidgets.QApplication, QtCore.QEventLoop elif pyside == 1: ix.log_info("Python: using PySide Qt bindings.") from PySide import QtCore, QtGui return QtGui.QApplication, QtCore.QEventLoop elif pyside2 == 1: ix.log_info("Python: using PySide2 Qt bindings.") from PySide2 import QtCore, QtWidgets return QtWidgets.QApplication, QtCore.QEventLoop
def map_maps(shader_name, surface_maps, shader): ix.log_info("Creating Basic shader setup.") shader_name = str(shader_name) default_ctx = ix.cmds.CreateContext(shader_name, "Global", "project://scene") if shader == "disney": material = ix.cmds.CreateObject(shader_name, "MaterialPhysicalDisneyPrincipled", "Global", default_ctx) if "Diffuse" in surface_maps: diffuse = str(surface_maps["Diffuse"]["file"]["path"]) channel_name = shader_name + "_Diffuse" tx = ix.cmds.CreateObject(channel_name, 'TextureMapFile', default_ctx) tx.attrs.filename = diffuse tx.attrs.color_space_auto_detect = 0 tx.attrs.mipmap_filtering_mode = 1 tx.attrs.file_color_space = 'Clarisse|sRGB' set_tex = str(default_ctx) + "/" + str(shader_name) ix.cmds.SetTexture([set_tex + ".base_color"], set_tex + "_Diffuse") if "Albedo" in surface_maps: albedo = str(surface_maps["Albedo"]["file"]["path"]) channel_name = shader_name + "_Albedo" tx = ix.cmds.CreateObject(channel_name, 'TextureMapFile', default_ctx) tx.attrs.filename = albedo tx.attrs.color_space_auto_detect = 0 tx.attrs.mipmap_filtering_mode = 1 tx.attrs.file_color_space = 'Clarisse|sRGB' set_tex = str(default_ctx) + "/" + str(shader_name) ix.cmds.SetTexture([set_tex + ".base_color"], set_tex + "_Albedo") if "Roughness" in surface_maps: rough = str(surface_maps["Roughness"]["file"]["path"]) channel_name = shader_name + "_Roughness" tx = ix.cmds.CreateObject(channel_name, 'TextureMapFile', default_ctx) tx.attrs.filename = rough tx.attrs.color_space_auto_detect = 0 tx.attrs.mipmap_filtering_mode = 1 tx.attrs.file_color_space = 'linear' set_tex = str(default_ctx) + "/" + str(shader_name) ix.cmds.SetTexture([set_tex + ".roughness"], set_tex + "_Roughness") ix.cmds.SetValues( [set_tex + "_Roughness.single_channel_file_behavior"], ["1"]) ix.cmds.SetValues([set_tex + ".specular"], ["0.2"]) if "Normal" in surface_maps: normal = str(surface_maps["Normal"]["file"]["path"]) channel_name = shader_name + "_Normal" tx = ix.cmds.CreateObject(channel_name, 'TextureMapFile', default_ctx) tx.attrs.filename = normal tx.attrs.color_space_auto_detect = 0 tx.attrs.mipmap_filtering_mode = 1 tx.attrs.file_color_space = 'linear' txnrm_util = ix.cmds.CreateObject(channel_name + "_nrm", "TextureNormalMap", default_ctx) set_tex = str(default_ctx) + "/" + str(shader_name) ix.cmds.SetTexture([set_tex + ".normal_input"], set_tex + "_Normal_nrm") ix.cmds.SetTexture([set_tex + "_Normal_nrm.input"], set_tex + "_Normal") if "Displacement" in surface_maps: displacement = str(surface_maps["Displacement"]["file"]["path"]) channel_name = shader_name + "_Displacement" tx = ix.cmds.CreateObject(channel_name, 'TextureMapFile', default_ctx) displ_node = ix.cmds.CreateObject(channel_name + "_displacement", "Displacement", default_ctx) tx.attrs.filename = displacement tx.attrs.color_space_auto_detect = 0 tx.attrs.mipmap_filtering_mode = 1 tx.attrs.file_color_space = 'linear' tx.attrs.use_raw_data = "1" ix.cmds.SetTexture( [set_tex + "_Displacement_displacement.front_value"], set_tex + "_Displacement") ix.cmds.SetValues( [set_tex + "_Displacement.single_channel_file_behavior"], ["1"]) ix.cmds.SetValues( [set_tex + "_Displacement_displacement.front_value"], ["0.07"])
def combiner_group_Renamer(self, sender, evtid): ix.begin_command_batch('Undo Combiner Group Rename') Selected_Hierarchy = Hierarchy_checkbox.get_value() object_type_suffix = combiner_group_object_type_suffix_checkbox.get_value( ) counter = 0 for i in range(ix.selection.get_count()): selected_obj = str(ix.selection[i]) selected_obj_name = selected_obj.split('/') if ix.selection[i].is_context() is False: object_type_fullname = ix.selection[i].get_class_name() #True Type #SceneObjectCombiner if object_type_fullname == "SceneObjectCombiner": #has dirctory if len(str(ix.selection[i].attrs.objects)) > 1: First_Ref_Path = str(ix.selection[i].attrs.objects[0]) new_name = First_Ref_Path.split('/')[-1] if object_type_suffix == 1: new_name = new_name + "_" + "Combiner" ix.cmds.RenameItem(selected_obj, new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 #True Type #SceneObjectCombiner if object_type_fullname == "Group": #has dirctory if len(str(ix.selection[i].attrs.inclusion_items)) > 1: First_Ref_Path = str( ix.selection[i].attrs.inclusion_items[0]) new_name = First_Ref_Path.split('/')[-1] if object_type_suffix == 1: new_name = new_name + "_" + "Group" ix.cmds.RenameItem(selected_obj, new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 if Selected_Hierarchy: if ix.selection[i].is_context(): Hierarchy_list = Hierarchy_lister(ix.selection[i], True, True) for iii in range(len(Hierarchy_list)): selected_obj_name = str(Hierarchy_list[iii]).split('/') if Hierarchy_list[iii].is_context() is False: object_type_fullname = Hierarchy_list[ iii].get_class_name() #True Type #SceneObjectCombiner if object_type_fullname == "SceneObjectCombiner": #has dirctory if len(str(Hierarchy_list[iii].attrs.objects) ) > 1: First_Ref_Path = str( Hierarchy_list[iii].attrs.objects[0]) new_name = First_Ref_Path.split('/')[-1] if object_type_suffix == 1: new_name = new_name + "_" + "Combiner" ix.cmds.RenameItem(Hierarchy_list[iii], new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 #True Type #SceneObjectCombiner if object_type_fullname == "Group": if len( str(Hierarchy_list[iii].attrs. inclusion_items)) > 1: First_Ref_Path = str( Hierarchy_list[iii].attrs. inclusion_items[0]) new_name = First_Ref_Path.split('/')[-1] if object_type_suffix == 1: new_name = new_name + "_" + "Group" ix.cmds.RenameItem(Hierarchy_list[iii], new_name) if str(selected_obj_name[-1]) != new_name: counter += 1 ix.log_info( str(counter) + " Object has been renamed" + " -- from AWA renamer") ix.end_command_batch()
def do_export(): # extensions = 'All Known Files...\t*.{zip}\nZip Archive (*.zip)\t*.{zip}\n' extensions = 'All Known Files...\t*' dest_dir = '/var/tmp' if platform.system() == "Windows": dest_dir = ix.api.GuiWidget.save_file(ix.application, '', 'Select temp folder',extensions) # if dest_file[-4:] == ".zip": dest_file = dest_file[:-4] # dest_dir = os.path.dirname(dest_file) # if dest_file == '' or not os.path.isdir(dest_dir): # if dest_file == '': # pass # cancel # else: # ix.log_error("The specified directory is invalid") # return # else: ix.enable_command_history() ix.begin_command_batch("ExportRenderPackage()") # first we flatten all contexts make_all_context_local() # then we gather all external file resources unique_files = {} attrs = ix.api.OfAttr.get_path_attrs() new_file_list = [] attr_list = [] scene_info = {"output_path": ""} for i in range(attrs.get_count()): # deduplicating file_path = attrs[i].get_string() if not os.path.isfile(file_path): # Find the output path... if attrs[i].get_name() == "save_as": scene_info['output_path'] = os.path.dirname(file_path) print("Skipping file %s" % file_path) continue attr_list.append(attrs[i].get_full_name()) if not file_path in unique_files: # de-windoify path new_file_path = os.path.abspath(file_path).replace("\\", '/').replace(':', '').replace('\\\\', '/') # getting the absolute path of the file new_file_path = "$PDIR/" + new_file_path unique_files[file_path] = new_file_path new_file_list.append(new_file_path) else: new_file_list.append(unique_files[file_path]) # updating attribute path with new filename ix.enable_command_history() ix.cmds.SetValues(attr_list, new_file_list) ix.log_info("saving project file...") ix.application.check_for_events() name = ix.application.get_current_project_filename() name = os.path.basename(name) if name == '': name = "Untitled.project" if name.endswith(".project"): name = name[:-8] + ".render" else: name += ".render" # generating temp folder in Clarisse temp directory gen_tempdir = tempfile.mkdtemp('', '', dest_dir) # ix.application.export_context_as_project(gen_tempdir + '/' + name, ix.application.get_factory().get_root()) ix.application.export_render_archive(gen_tempdir + '/' + name) # restoring file attributes with original paths # copying files in new directory # return_files = [gen_tempdir + '/' + name] scene_info["scene_file"] = "%s/%s" % (gen_tempdir, name) scene_info["dependencies"] = [gen_tempdir + '/' + name] for file_path in unique_files: target = unique_files[file_path][5:] target_dir = gen_tempdir + os.path.dirname(target) if not os.path.isdir(target_dir): os.makedirs(target_dir) ix.log_info("copying file '" + file_path + "'..." ) ix.application.check_for_events() new_path = gen_tempdir + target scene_info["dependencies"].append(new_path) if platform.system == "Windows": shutil.copyfile(file_path, new_path) else: os.symlink(file_path, new_path) # The stuff that is commented out packages the dependencies into an archive # this is something we do not support at the moment, but I'm leaving around # for future reference... # ix.log_info("building archive...") ix.application.check_for_events() # shutil.make_archive(dest_file, 'zip', gen_tempdir) # ix.log_info("cleaning temporary files...") # ix.application.check_for_events() # shutil.rmtree(gen_tempdir) # ix.log_info("Package successfully exported in '" + dest_file + ".zip'.") ix.end_command_batch() # # restore original state ix.application.get_command_manager().undo() ix.disable_command_history() print("Dependencies: ") for filename in scene_info["dependencies"]: print("\t%s" % filename) return scene_info