def set_property_tree(self, asset): if isinstance(asset, unreal.MaterialInterface): data = self.get_material_property(asset) elif isinstance(asset, unreal.Blueprint): pass else: toast(u"不支持资产") return data_list = [{ "property": group, "value": "", "children": [{ "bg_color": QtGui.QColor("transparent"), "property": prop, "property_checked": QtCore.Qt.Unchecked, "value": value, } for prop, value in props.items()], } for group, props in data.items()] self.property_model.set_data_list(data_list) self.source = asset self.state.source_eanble = True self.state.lable_visible = True self.state.lable_text = asset.get_name()
def transfer_property(self): for i, asset in enumerate(self.asset_model.get_data_list()): if not asset.get("destination_checked"): continue # NOTE 选择 Asset_List 的资产 更新颜色 index = self.asset_model.index(i, 0) model = self.Asset_List.selectionModel() model.setCurrentIndex(index, model.SelectCurrent) property_list = [ prop.get("property") for grp in self.property_model.get_data_list() for prop in grp.get("children") # NOTE 过滤没有勾选的资源 if prop.get("bg_color") == QtGui.QColor("green") and prop.get("property_checked") ] # NOTE 传递属性 asset = asset.get("asset") if isinstance(asset, type(self.source)): self.transfer_material_property(asset, property_list) else: raise RuntimeError(u"%s 和复制源类型不匹配" % asset.get_name()) toast("传递完成", 'success')
def add_selected_assets(self): data_list = self.model.get_data_list() tooltip_list = [ data.get("asset").get_path_name() for data in data_list ] asset_list = [ asset for asset in util_lib.get_selected_assets() if asset.get_path_name() not in tooltip_list ] if not asset_list: toast(u"请选择资产") return # NOTE 确保不添加重复的 item data_list.extend([{ 'bg_color': QtGui.QColor("transparent"), 'asset': asset, u"原名称": asset.get_name(), u"新名称": "", u"文件类型": type(asset).__name__, } for asset in asset_list]) self.update_table() self.model.set_data_list(data_list)
def get_destination(self): if not self.source: toast(u"请拾取复制源") return data_list = self.asset_model.get_data_list() tooltip_list = [ data.get("asset").get_path_name() for data in data_list ] assets = [ asset for asset in util_lib.get_selected_assets() if isinstance(asset, type(self.source)) and asset.get_path_name() not in tooltip_list ] if not assets: toast(u"请选择匹配的资产") return data_list.extend([ { "bg_color": QtGui.QColor("transparent"), "asset": asset, "destination": asset.get_name(), # NOTE 默认勾选 "destination_checked": QtCore.Qt.Checked, } for asset in assets if not asset is self.source ]) self.asset_model.set_data_list(data_list)
def add_selected_actors(self): data_list = self.model.get_data_list() tooltip_list = [ data.get("asset").get_path_name() for data in data_list ] actor_list = [ actor for actor in level_lib.get_selected_level_actors() if actor.get_path_name() not in tooltip_list ] if not actor_list: toast(u"请选择Actor") return data_list.extend([{ 'bg_color': QtGui.QColor("transparent"), 'asset': actor, u"原名称": actor.get_actor_label(), u"新名称": "", u"文件类型": type(actor).__name__, } for actor in actor_list]) self.update_table() self.model.set_data_list(data_list)
def export_setting(self): path, _ = QFileDialog.getSaveFileName(self, caption=u"输出设置", filter=u"ini (*.ini)") if not path: return copyfile(self.settings.fileName(), path) toast(u"导出成功", "info")
def read_config(self, text=True): self.ini_file = self.Config_LE.text() if not os.path.exists(self.ini_file): toast(u"配置路径不存在") self.Config_LE.setText("") return # print(self.ini_file) self.config = ConfigParser() if six.PY2 else ConfigParser(strict=False) self.config.read(self.ini_file) section = "MovieSceneCaptureUIInstance AutomatedLevelSequenceCapture" option = "Settings" try: capture_settings = self.config.get(section, option) except: return capture_settings_dict = self.json_config[section][option] capture_settings = capture_settings[1:-1] pattern = re.compile("\((.+?)\)") value_list = [] for i, match in enumerate(pattern.findall(capture_settings)): capture_settings = capture_settings.replace(match, "$$%s$$" % i) value_list.append(match) # NOTE 设置 for pair in capture_settings.split(","): k, v = pair.split("=") v = value_list[int(v[3])] if v.startswith("($$") else v k = capture_settings_dict.get(k) if not k: continue elif k == "output_directory": self.Output_LE.setText(v[6:-1].replace("\\\\", "\\")) if text else None elif text and k == "output_format": self.FileName_LE.setText(v[1:-1]) if text else None elif k == "game_mode_override": if v == "None": continue v = v.split('"')[1] v = unreal.load_class(None, v) self.capture_settings.set_editor_property(k, v) elif k == "custom_frame_rate": numerator, denominator = v.split(",") numerator = numerator.split("=")[1] denominator = denominator.split("=")[1] v = unreal.FrameRate(int(numerator), int(denominator)) self.capture_settings.set_editor_property(k, v) elif k == "resolution": x, y = v.split(",") x = x.split("=")[1] y = y.split("=")[1] v = unreal.CaptureResolution(int(x), int(y)) self.capture_settings.set_editor_property(k, v) else: v = ast.literal_eval(v) self.capture_settings.set_editor_property(k, v)
def open_item(self): if not self.check_item(): return project = sys_lib.get_project_content_directory() path = self.item_path.replace("/Game/", project) path = os.path.dirname(path) if os.path.exists(path): os.startfile(path) else: toast(u"当前选择元素路径不存在")
def get_source(self): assets = util_lib.get_selected_assets() if len(assets) < 1: toast(u"请选择一个资产") return asset = assets[0] self.set_property_tree(asset) self.asset_model.set_data_list([]) self.property_model_sort.sort(0, QtCore.Qt.AscendingOrder)
def browse_file(self): path, _ = QtWidgets.QFileDialog.getOpenFileName( self, caption=u"获取 Unreal 用户配置文件", filter="ini (*.ini);;所有文件 (*)" ) if not os.path.exists(path): toast(u"配置路径不存在") return self.Config_LE.setText(path)
def locate_item_location(self): data_list = self.model.get_data_list() index = self.Table_View.selectionModel().currentIndex() if not index: toast(u"没有选择元素进行定位") return asset = data_list[index.row()]["asset"] path = asset.get_path_name() if asset_lib.does_asset_exist(path): asset_lib.sync_browser_to_objects([path]) else: toast(u"元素不存在")
def locate_asset_location(self): data_list = self.asset_model.get_data_list() index = self.Asset_List.selectionModel().currentIndex() if not index or not data_list: toast(u"没有元素可定位") return asset = data_list[index.row()]["asset"] path = asset.get_path_name() if asset_lib.does_asset_exist(path): asset_lib.sync_browser_to_objects([path]) else: toast(u"元素不存在")
def main(): # NOTE 保存对象 check = editor_util.save_dirty_packages_with_dialog(True, True) if not check: toast(u"保存失败") return uproject = paths.get_project_file_path() editor = sys.executable # NOTE 启动当前引擎 subprocess.Popen([editor, uproject, "-skipcompile"], shell=True) # NOTE 退出引擎 sys_lib.quit_editor()
def import_setting(self): path, _ = QFileDialog.getOpenFileName(self, caption=u"获取设置", filter=u"ini (*.ini)") # NOTE 如果文件不存在则返回空 if not path or not os.path.exists(path): return self.settings = QtCore.QSettings(path, QtCore.QSettings.IniFormat) self.settings.sync() self.load_settings() name = "%s.ini" % self.__class__.__name__ self.settings = QtCore.QSettings(name, QtCore.QSettings.IniFormat) self.save_settings() toast(u"加载成功", "info")
def get_selected_actors(self, click=False): actors = level_lib.get_selected_level_actors() if click: if not actors: toast(u"请选择一个物体") return actor = actors[0] self.Align_LE.setText(actor.get_path_name()) return if len(actors) < 2: msg = u"请选择两个物体" toast(msg) raise RuntimeError(msg) return actors[-1], actors[:-1]
def get_asset(self): selected_asset = [ a for a in unreal.EditorUtilityLibrary.get_selected_assets() for cls_type in self.class_filter if isinstance(a, cls_type) ] if not selected_asset: toast(u"请选择下列类型\n %s" % ("\n".join([c.__name__ for c in self.class_filter]))) return selected_asset = selected_asset[0] count = self.USelector.count() for i in range(count): text = self.USelector.itemText(i) if text == selected_asset.get_path_name(): self.USelector.setCurrentIndex(i) break
def locate_file_location(self): data_list = self.model.get_data_list() index = self.Table_View.selectionModel().currentIndex() if not index: toast(u"没有选择元素进行定位") return asset = data_list[index.row()]["asset"] path = asset.get_path_name() # path = os.path.splitext(path)[0] project = sys_lib.get_project_content_directory() path = path.replace("/Game/", project) path = os.path.dirname(path) if os.path.exists(path): os.startfile(path) else: toast(u"当前选择元素路径不存在")
def __init__(self, parent=None): super(SequencerRenderTool, self).__init__() DIR = os.path.dirname(__file__) ui_path = os.path.join(DIR, "render_tool.ui") loadUi(ui_path, self) name = "%s.ini" % self.__class__.__name__ self.settings = QtCore.QSettings(name, QtCore.QSettings.IniFormat) cb_list = self.settings.value("cb_list") cb_list = cb_list if isinstance(cb_list, list) else [cb_list] if cb_list else [] self.json_config = read_json() self.ini_file = posixpath.join( project_dir, "Saved", "Config", "Windows", "EditorPerProjectUserSettings.ini", ) self.ini_file = self.ini_file if os.path.exists(self.ini_file) else "" for cb in self.Pass_Container.findChildren(QtWidgets.QCheckBox): if cb.objectName() in cb_list: cb.setChecked(True) cb.clicked.connect(self.dump_settings) self.Select_BTN.clicked.connect(partial(cb.setChecked, True)) self.Toggle_BTN.clicked.connect(cb.toggle) self.NonSelect_BTN.clicked.connect(partial(cb.setChecked, False)) self.Select_BTN.clicked.connect(self.dump_settings) self.Toggle_BTN.clicked.connect(self.dump_settings) self.NonSelect_BTN.clicked.connect(self.dump_settings) self.Proctocol_Combo.currentIndexChanged.connect(self.dump_settings) self.Proctocol_Combo.currentIndexChanged.connect(self.combo_changed) self.Config_LE.setText(self.ini_file) self.Config_Browse_BTN.clicked.connect(self.browse_file) self.Browse_BTN.clicked.connect(self.browse_directory) self.Render_BTN.clicked.connect(self.batch_render) self.Locate_BTN.clicked.connect( lambda: os.startfile(self.Output_LE.text()) if os.path.exists(self.Output_LE.text()) else toast(u"输出目录的路径不存在") ) self.Config_BTN.clicked.connect(self.read_config) self.Help_Action.triggered.connect( lambda: webbrowser.open_new_tab( "http://wiki.l0v0.com/unreal/PyToolkit/#/render/1_render_tool" ) ) self.capture_settings = unreal.MovieSceneCaptureSettings() self.read_config() index = self.settings.value("index") self.Proctocol_Combo.setCurrentIndex(int(index)) if index else None
def batch_render(self): # NOTE 获取当前选择的 LevelSequence sequence_list = [ asset for asset in unreal.EditorUtilityLibrary.get_selected_assets() if isinstance(asset, unreal.LevelSequence) ] if not sequence_list: toast(u"请选择一个 \n LevelSequence") return self.ini_file = self.Config_LE.text() if not os.path.exists(self.ini_file): toast(u"配置路径不存在") self.Config_LE.setText("") return self.output_directory = self.Output_LE.text() if not os.access(self.output_directory, os.W_OK): toast(u"当前输出路径非法") return elif not os.path.exists(self.output_directory): # NOTE 路径不存在则创建文件夹 os.makedirs(self.output_directory) elif os.path.isfile(self.output_directory): # NOTE 如果传入文件路径则获取目录 self.output_directory = os.path.dirname(self.output_directory) self.render(sequence_list, 0)
def render(self, sequence_list, i): progress = (i / len(sequence_list)) * 100 self.ProgressBar.setValue(progress) # NOTE 如果超出数组则退出执行 if i >= len(sequence_list): # NOTE 输出完成 打开输出文件夹的路径 os.startfile(self.output_directory) toast(u"渲染完成~", "info") print("渲染完成") return # NOTE 设置全局变量才起作用! global on_finished_callback sequence = sequence_list[i] self.capture = self.setup_capture() self.capture.set_editor_property( "level_sequence_asset", unreal.SoftObjectPath(sequence.get_path_name()) ) on_finished_callback = unreal.OnRenderMovieStopped( lambda s: self.render(sequence_list, i + 1) ) unreal.SequencerTools.render_movie(self.capture, on_finished_callback)
def batch_render(output_directory="C:/render", output_format="{sequence}"): # NOTE 获取当前选择的 LevelSequence sequence_list = [ asset for asset in unreal.EditorUtilityLibrary.get_selected_assets() if isinstance(asset, unreal.LevelSequence) ] if not sequence_list: toast(u"请选择一个 LevelSequence") return if not os.access(output_directory, os.W_OK): toast(u"当前输出路径非法") return elif not os.path.exists(output_directory): # NOTE 路径不存在则创建文件夹 os.makedirs(output_directory) elif os.path.isfile(output_directory): # NOTE 如果传入文件路径则获取目录 output_directory = os.path.dirname(output_directory) render(sequence_list, 0, output_directory, output_format)
def check_item(self): if not asset_lib.does_asset_exist(self.item_path): toast(u"资源路径不存在") return False return True