def get_selected_actors(self): actors = level_lib.get_selected_level_actors() if len(actors) < 2: msg = u"请选择两个场景物体" toast(msg) raise RuntimeError(msg) return actors[-2], actors[-1]
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 oepn_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 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 self.config = ConfigParser() self.config.read(self.ini_file) section = "MovieSceneCaptureUIInstance AutomatedLevelSequenceCapture" option = "Settings" capture_settings = self.config.get(section, option) 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 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 align_l_up(self): base, target = self.get_selected_actors() info = level_lib.get_level_viewport_camera_info() if not info: toast(u"无法获取摄像机信息") return cam_location, cam_rotation = info origin, extent = base.get_actor_bounds(True) line = cam_location - origin line.normalize() x_val = line.dot(unreal.Vector(1, 0, 0)) y_val = line.dot(unreal.Vector(0, 1, 0)) z_val = line.dot(unreal.Vector(0, 0, 1)) # NOTE 正对 X 轴 if x_val > 0.5: pass
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 __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 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