def readTextureCSV(self): #TODO: search for texture in directory and link to that if it exists (swap in materials csv?) #TODO: figure out how to mark a texture as used in the surfaces directory in blender. Can do in UE4 try: with open(self.textureCSVPath, mode='r') as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') line_count = 0 parameterNames = [] for row in csv_reader: if line_count == 0: unreal.log("Parameters To Import: " + " | ".join(row)) parameterNames = row line_count += 1 else: #Add texture to import list self.createTexture( filepath=row[1], importLocation=self.UETextureDirectory, overwrite=row[4], textureName=row[0]) line_count += 1 unreal.log('Processed ' + str(line_count - 1) + ' textures') unreal.EditorAssetLibrary.save_directory( self.UETextureDirectory) except Exception: unreal.log_warning("Issue reading texture csv file")
def _import_to_content_browser(self, path, sg_publish_data): """ Import the asset into the Unreal Content Browser. :param path: Path to file. :param sg_publish_data: Shotgun data dictionary with all the standard publish fields. """ unreal.log("File to import: {}".format(path)) if not os.path.exists(path): raise Exception("File not found on disk - '%s'" % path) destination_path, destination_name = self._get_destination_path_and_name( sg_publish_data) asset_path = _unreal_import_fbx_asset(path, destination_path, destination_name) if asset_path: self._set_asset_metadata(asset_path, sg_publish_data) # Focus the Unreal Content Browser on the imported asset asset_paths = [] asset_paths.append(asset_path) unreal.EditorAssetLibrary.sync_browser_to_objects(asset_paths)
def move_assets_to_path(root, name, assets): """ Moving (renaming) list of asset paths to new destination. Args: root (str): root of the path (eg. `/Game`) name (str): name of destination directory (eg. `Foo` ) assets (list of str): list of asset paths Returns: str: folder name Example: This will get paths of all assets under `/Game/Test` and move them to `/Game/NewTest`. If `/Game/NewTest` already exists, then resulting path will be `/Game/NewTest1` >>> assets = unreal.EditorAssetLibrary.list_assets("/Game/Test") >>> move_assets_to_path("/Game", "NewTest", assets) NewTest """ eal = unreal.EditorAssetLibrary name = create_folder(root, name) unreal.log(assets) for asset in assets: loaded = eal.load_asset(asset) eal.rename_asset(asset, "{}/{}/{}".format(root, name, loaded.get_name())) return name
def init_qt_app(self): self.logger.debug("%s: Initializing QtApp for Unreal", self) from sgtk.platform.qt5 import QtWidgets if not QtWidgets.QApplication.instance(): self._qt_app = QtWidgets.QApplication(sys.argv) self._qt_app.setQuitOnLastWindowClosed(False) unreal.log("Created QApplication instance: {0}".format( self._qt_app)) def _app_tick(dt): QtWidgets.QApplication.processEvents() tick_handle = unreal.register_slate_post_tick_callback(_app_tick) def _app_quit(): unreal.unregister_slate_post_tick_callback(tick_handle) QtWidgets.QApplication.instance().aboutToQuit.connect(_app_quit) else: self._qt_app = QtWidgets.QApplication.instance() # Make the QApplication use the dark theme. Must be called after the QApplication is instantiated self._initialize_dark_look_and_feel()
def check_asset_name(self, asset_data): package_name = unreal.StringLibrary.conv_name_to_string( asset_data.package_name) if isinstance(package_name, unicode): unreal.log('package name has unicode: {}'.format( package_name.encode('utf-8')))
def _execute_callback(self, callback): """ Execute the callback right away """ unreal.log("_execute_callback called with {0}".format(callback.__str__())) self._callback = callback self._execute_within_exception_trap()
def _unreal_import_fbx_asset(input_path, destination_path, destination_name): """ Import an FBX into Unreal Content Browser :param input_path: The fbx file to import :param destination_path: The Content Browser path where the asset will be placed :param destination_name: The asset name to use; if None, will use the filename without extension """ tasks = [] tasks.append( _generate_fbx_import_task(input_path, destination_path, destination_name)) unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks(tasks) first_imported_object = None for task in tasks: unreal.log("Import Task for: {}".format(task.filename)) for object_path in task.imported_object_paths: unreal.log("Imported object: {}".format(object_path)) if not first_imported_object: first_imported_object = object_path return first_imported_object
def load_positions_from_backup(): print('load_positions_from_backup') actors = get_all_actors() saved_positions = get_saved_positions() unreal.log(type(actors)) unreal.log(type(saved_positions)) for actor in actors: actor.set_actor_location(saved_positions[""], False, False)
def run(): # Create the processor with preconfigured inputs global _g_processor _g_processor = ProcessHDAExample(get_test_hda(), node_inputs=build_inputs()) # Activate the processor, this will starts instantiation, and then cook if not _g_processor.activate(): unreal.log_warning('Activation failed.') else: unreal.log('Activated!')
def _execute_deferred(self, callback): """ Execute the callback deferred The primary purpose of this method is to detach the executing code from the menu invocation """ unreal.log("{0} _execute_deferred called with {1}".format(self, callback.__str__())) self._callback = callback from sgtk.platform.qt5 import QtCore QtCore.QTimer.singleShot(0, self._execute_within_exception_trap)
def _post_init(self): """ Equivalent to __init__ but will also be called from C++ """ engine = sgtk.platform.current_engine() engine.unreal_sg_engine = self unreal.log( "ShotgunEngineWrapper._post_init: unreal_sg_engine {} with tk-unreal {}" .format(self, engine))
def process(self): name = self.data["subset"] selection = [] if (self.options or {}).get("useSelection"): sel_objects = unreal.EditorUtilityLibrary.get_selected_assets() selection = [a.get_path_name() for a in sel_objects] unreal.log("selection: {}".format(selection)) instantiate(self.root, name, self.data, selection, self.suffix)
def shutdown(self): from sgtk.platform.qt5 import QtWidgets engine = sgtk.platform.current_engine() if engine is not None: unreal.log("Shutting down %s" % self.__class__.__name__) # destroy_engine of tk-unreal will take care of closing all dialogs that are still opened engine.destroy() QtWidgets.QApplication.instance().quit() QtWidgets.QApplication.processEvents()
def getCutNumber(self, fbxfile): """ 파일네임에서 s00_c000 의 규칙을 갖는 스트링 찾기. :type fbxfile: str :rtype: str """ filename = os.path.basename(fbxfile) p = re.compile("s\d+_c\d+") scene_cut = p.findall(filename) unreal.log(fbxfile) return scene_cut
def get_shotgrid_menu_items(self): """ Returns the list of available menu items to populate the SG menu in Unreal. """ menu_items = [] engine = sgtk.platform.current_engine() menu_items = self.create_menu(engine) unreal.log("get_shotgrid_menu_items returned: {0}".format(menu_items.__str__())) return menu_items
def RenderSequence(path): capture_settings = unreal.AutomatedLevelSequenceCapture() capture_settings.level_sequence_asset = unreal.SoftObjectPath(path) try: unreal.SequencerTools.render_movie(capture_settings, unreal.OnRenderMovieStopped()) return True except Exception as e: print("Python Caught Exception:") print(e) return False unreal.log("Render Sequence...")
def importHierarchyCSV(self): try: newname = self.fbxName.partition('.')[0] if newname[ 0: 3] == "SM_": #todo if there are any other prefixes in the future, test for them newname = "ASH_" + newname[3:] elif newname[ 0: 4] == "CAM_": #todo if there are any other prefixes in the future, test for them newname = "ASH_" + newname[4:] elif newname[ 0: 4] == "LGT_": #todo if there are any other prefixes in the future, test for them newname = "ASH_" + newname[4:] else: newname = "ASH_" + newname asset_name = newname import_tasks = [] factory = unreal.CSVImportFactory() csvPath = self.rootImportFolder + asset_name + '.csv' #todo at some point fix the hierarchy name so it is unique per import factory.script_factory_can_import(csvPath) # AssetImportTask = unreal.AssetImportTask() AssetImportTask.set_editor_property('filename', csvPath) AssetImportTask.set_editor_property('factory', factory) AssetImportTask.set_editor_property('destination_path', self.UEMeshDirectory) AssetImportTask.set_editor_property('automated', True) #self.automateImports) importSettings = unreal.CSVImportSettings() #importSettings.set_editor_property('import_row_struct',True) path_to_asset = '/OVFPPlugin/generalResources/blenderToUnrealAdgBridge/B2UADGBrige_MeshHierarcyCSV' #.B2UADGBrige_MeshHierarcyCSV' asset_reg = unreal.AssetRegistryHelpers.get_asset_registry() #CSVstruct = asset_reg.get_asset_by_object_path(path_to_asset) CSVstruct = unreal.load_asset(path_to_asset) #unreal.log_warning(str(CSVstruct)) factory.automated_import_settings.import_row_struct = CSVstruct #AssetImportTask.set_editor_property('save', False) import_tasks.append(AssetImportTask) #do the import self.AssetTools.import_asset_tasks(import_tasks) unreal.EditorAssetLibrary.save_directory( self.UEMeshDirectory) #save directory we imported into except Exception: unreal.log("Issue with hierarcy file")
def check_directory(self, directory): for ignore in self.ignore_paths: if directory.startswith(ignore): return if unreal.EditorAssetLibrary.does_directory_exist(directory): # get_assets_by_pathは/で終わる場合PackageNameとして認識しないので変換 directory_name = unreal.Paths.normalize_directory_name(directory) if len(unreal.AssetRegistryHelpers.get_asset_registry(). get_assets_by_path(directory_name, True)) == 0: # uassetではないアセットが存在する場合はDeleteに失敗する unreal.EditorAssetLibrary.delete_directory(directory) unreal.log('delete: {}'.format(directory.encode('utf-8')))
def _execute_within_exception_trap(self): """ Execute the callback and log any exception that gets raised which may otherwise have been swallowed by the deferred execution of the callback. """ if self._callback is not None: try: unreal.log("_execute_within_exception_trap: trying callback {0}".format(self._callback.__str__())) self._callback() except Exception, e: current_engine = sgtk.platform.current_engine() current_engine.logger.exception("An exception was raised from Toolkit") self._callback = None
def check_asset(self, asset_data): package_name = unreal.StringLibrary.conv_name_to_string( asset_data.package_name) if len( unreal.EditorAssetLibrary.find_package_referencers_for_asset( package_name, False)) == 0: asset_name = unreal.StringLibrary.conv_name_to_string( asset_data.asset_name) asset_class = asset_data.asset_class unreal.log('[{0}] {1} {2}'.format(asset_class, asset_name.encode('utf-8'), package_name.encode('utf-8')))
def get_shotgun_menu_items(self): """ Returns the list of available menu items to populate the SG menu in Unreal. """ menu_items = [] engine = sgtk.platform.current_engine() menu_items = self.create_menu(engine) unreal.log_warning("get_shotgun_menu_items is deprecated, get_shotgrid_menu_items should be used instead.") unreal.log("get_shotgun_menu_items returned: {0}".format(menu_items.__str__())) return menu_items
def execute_command(self, command_name): """ Callback to execute the menu item selected in the SG menu in Unreal. """ engine = sgtk.platform.current_engine() unreal.log("execute_command called for {0}".format(command_name)) if command_name in engine.commands: unreal.log("execute_command: Command {0} found.".format(command_name)) command = engine.commands[command_name] command_callback = command["callback"] command_callback = self._get_command_override(engine, command_name, command_callback) self._execute_callback(command_callback)
def rename_assets(search_pattern, replace_pattern, use_case): # instances of unreal classes system_lib = unreal.SystemLibrary() editor_util = unreal.EditorUtilityLibrary() string_lib = unreal.StringLibrary() # get the selected assets selected_assets = editor_util.get_selected_assets() num_assets = len(selected_assets) replaced = 0 unreal.log("Selected {} asset/s".format(num_assets)) # loop over each asset and rename for asset in selected_assets: asset_name = system_lib.get_object_name(asset) # check if the asset name contains the to be replaced text if string_lib.contains(asset_name, search_pattern, use_case=use_case): search_case = unreal.SearchCase.CASE_SENSITIVE if use_case else unreal.SearchCase.IGNORE_CASE replaced_name = string_lib.replace(asset_name, search_pattern, replace_pattern, search_case=search_case) editor_util.rename_asset(asset, replaced_name) replaced += 1 unreal.log("Replaced {} with {}".format(asset_name, replaced_name)) else: unreal.log("{} did not match the search pattern, was skipped".format(asset_name)) unreal.log("Replaced {} of {} assets".format(replaced, num_assets))
def check_asset_data(self, asset_data): package_name = unreal.StringLibrary.conv_name_to_string( asset_data.package_name) texture_obj = asset_data.get_asset() size_x = texture_obj.blueprint_get_size_x() size_y = texture_obj.blueprint_get_size_y() invalid_x = size_x % 4 != 0 invalid_y = size_y % 4 != 0 if invalid_x or invalid_y: unreal.log('unable to compress: [{}x{}] {}'.format( size_x, size_y, package_name.encode('utf-8')))
def init_qt_app(self): self.logger.debug("%s: Initializing QtApp for Unreal", self) from sgtk.platform.qt5 import QtWidgets if not QtWidgets.QApplication.instance(): self._qt_app = QtWidgets.QApplication(sys.argv) self._qt_app.setQuitOnLastWindowClosed(False) unreal.log("Created QApplication instance: {0}".format( self._qt_app)) else: self._qt_app = QtWidgets.QApplication.instance() # Make the QApplication use the dark theme. Must be called after the QApplication is instantiated self._initialize_dark_look_and_feel()
def _emit_log_message(self, handler, record): """ Called by the engine to log messages in Unreal script editor. All log messages from the toolkit logging namespace will be passed to this method. :param handler: Log handler that this message was dispatched from. Its default format is "[levelname basename] message". :type handler: :class:`~python.logging.LogHandler` :param record: Standard python logging record. :type record: :class:`~python.logging.LogRecord` """ msg = handler.format(record) # Assuming the Unreal Editor has a message dialog, you would call # here a method that allows to send text to that console. Note that # this method can be called from any thread that uses Toolkit logging. unreal.log("{0}".format(msg))
def launch_nxt_in_ue(): os.environ[NXT_DCC_ENV_VAR] = 'unreal' existing = QtWidgets.QApplication.instance() if existing: unreal.log('Found existing QApp') else: unreal.log('Building new QApp for nxt') existing = nxt_editor._new_qapp() global __NXT_WINDOW if __NXT_WINDOW: __NXT_WINDOW.show() __NXT_WINDOW.raise_() else: __NXT_WINDOW = nxt_editor.show_new_editor() __NXT_WINDOW.close_signal.connect(existing.exit) atexit.register(__NXT_WINDOW.close)
def _sc_test_file_strings(): unreal.log("\nTesting source control file strings.") # File strings used in source control commands can be: # - export text path (often stored on clipboard) file1 = _sc_get_file_from_state( r"Texture2D'/Engine/EditorResources/S_Actor.S_Actor'") # - asset file2 = _sc_get_file_from_state(r"/Engine/EditorResources/S_Actor.S_Actor") # - long package name file3 = _sc_get_file_from_state(r"/Engine/EditorResources/S_Actor") # - relative path file4 = _sc_get_file_from_state(r"Content/EditorResources/S_Actor.uasset") # - fully qualified path (just use result of relative path) file5 = _sc_get_file_from_state(file4) # All the resolved file paths should be the same same_paths = file1 == file2 == file3 == file4 == file5 unreal.log( "The resolved file paths are all the same: {0}".format(same_paths))
def readMaterialInstanceCSV(self): try: with open(self.materialInstanceCSVPath, mode='r') as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') line_count = 0 parameterNames = [] for row in csv_reader: if line_count == 0: unreal.log("Parameters To Import: " + " | ".join(row)) parameterNames = row line_count += 1 else: self.createMaterialInstance(NewMatName = row[1],parameterNames = parameterNames, parameters = row) #unreal.log("row:" + str(line_count) + " :".join(row)) line_count += 1 unreal.log('Processed ' + str(line_count-1) + ' materials') #TODO: search for textures before import unreal.EditorAssetLibrary.save_directory(self.UEMaterialDirectory) except Exception: unreal.log_warning("Issue reading material csv file")
def do_import(self): import_task = unreal.AssetImportTask() import_task.filename = self.asset_data.get("fbx_file_path") import_task.destination_path = self.asset_data.get("game_path") import_task.automated = not bool(self.asset_data.get("advanced_ui_import")) import_task.replace_existing = True import_task.save = False#self.asset_data.get("file_save") # abc import options if self.asset_data.get("abc_import"): options = self.abc_import_option() else: options = self.fbx_import_option() # assign the options object to the import task and import the asset import_task.options = options unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([import_task]) skeleton_asset_name = os.path.splitext(options.get_editor_property("skeleton").get_path_name())[0] unreal.log(skeleton_asset_name) unreal.EditorAssetLibrary.save_asset(skeleton_asset_name)