import colorsys import os import json from tempfile import NamedTemporaryFile import gradio as gr import pandas as pd import MiracleCacheTools parameters_list_path = "data/cdiParametersList.json" parameters_groups_data_path = "data/cdiParametersGroupsData.json" EXP_DATA_TEMP_LIST_LENGTH = 16 parameter_preset_files = [] for root, dirs, files in os.walk("data/parameter_presets"): for file in files: if file.endswith(".json"): parameter_preset_files.append(os.path.join(root, file)) def numInputCheck(num, min, max): if num < min: num = min if num > max: num = max return num def RGBInputProcess(r, g, b): r = round(numInputCheck(r, 0, 255)) g = round(numInputCheck(g, 0, 255)) b = round(numInputCheck(b, 0, 255)) # RGB to HEX color_hex = f"#{r:02X}{g:02X}{b:02X}" # RGB to HLS hls = colorsys.rgb_to_hls(r/255.0, g/255.0, b/255.0) hls_h = round(hls[0] * 360) hls_l = round(hls[1] * 100) hls_s = round(hls[2] * 100) # RGB to HSV hsv = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0) hsv_h = round(hsv[0] * 360) hsv_s = round(hsv[1] * 100) hsv_v = round(hsv[2] * 100) return color_hex, color_hex, hls_h, hls_l, hls_s, hsv_h, hsv_s, hsv_v def HLSInputProcess(h, l, s): h = round(numInputCheck(h, 0, 360)) l = round(numInputCheck(l, 0, 100)) s = round(numInputCheck(s, 0, 100)) # HLS to RGB rgb = colorsys.hls_to_rgb(h/360.0, l/100.0, s/100.0) rgb_r = round(rgb[0] * 255) rgb_g = round(rgb[1] * 255) rgb_b = round(rgb[2] * 255) # RGB to HEX color_hex = f"#{rgb_r:02X}{rgb_g:02X}{rgb_b:02X}" # RGB to HSV hsv = colorsys.rgb_to_hsv(rgb_r/255.0, rgb_g/255.0, rgb_b/255.0) hsv_h = round(hsv[0] * 360) hsv_s = round(hsv[1] * 100) hsv_v = round(hsv[2] * 100) return color_hex, color_hex, rgb_r, rgb_g, rgb_b, hsv_h, hsv_s, hsv_v def HSVInputProcess(h, s, v): h = round(numInputCheck(h, 0, 360)) s = round(numInputCheck(s, 0, 100)) v = round(numInputCheck(v, 0, 100)) # HSV to RGB rgb = colorsys.hsv_to_rgb(h/360.0, s/100.0, v/100.0) rgb_r = round(rgb[0] * 255) rgb_g = round(rgb[1] * 255) rgb_b = round(rgb[2] * 255) # RGB to HEX color_hex = f"#{rgb_r:02X}{rgb_g:02X}{rgb_b:02X}" # RGB to HLS hls = colorsys.rgb_to_hls(rgb_r/255.0, rgb_g/255.0, rgb_b/255.0) hls_h = round(hls[0] * 360) hls_l = round(hls[1] * 100) hls_s = round(hls[2] * 100) return color_hex, color_hex, rgb_r, rgb_g, rgb_b, hls_h, hls_l, hls_s def colorInputProcess(color_str): #print(f"color_str: {color_str}") r, g, b = MiracleCacheTools.colorStringProcessRGB(color_str) # RGB to HEX color_hex = f"#{r:02X}{g:02X}{b:02X}" # RGB to HLS hls = colorsys.rgb_to_hls(r/255.0, g/255.0, b/255.0) hls_h = round(hls[0] * 360) hls_l = round(hls[1] * 100) hls_s = round(hls[2] * 100) # RGB to HSV hsv = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0) hsv_h = round(hsv[0] * 360) hsv_s = round(hsv[1] * 100) hsv_v = round(hsv[2] * 100) return color_hex, r, g, b, hls_h, hls_l, hls_s, hsv_h, hsv_s, hsv_v def parameterPresetFileSelectUpdate(parameter_preset_file_select_type): if parameter_preset_file_select_type == "选择已有文件": return gr.Dropdown(value=None, interactive=True), gr.File(value=None, interactive=False) elif parameter_preset_file_select_type == "上传本地文件": return gr.Dropdown(value=None, interactive=False), gr.File(value=None, interactive=True) else: return gr.Dropdown(value=None, interactive=False), gr.File(value=None, interactive=False) def parameterPresetFileProcess(parameter_preset_file): with open(parameter_preset_file, "r", encoding="utf8") as file: data = json.load(file) parameter_preset_list = list(data) return gr.Dropdown(choices=parameter_preset_list), data def processButton0201Click(parameter_preset, expression_acceptor_file, expression_donor_file, parameter_preset_data): if parameter_preset is None: raise ValueError("parameter preset not found") if expression_acceptor_file is None: raise ValueError("expression acceptor not found") if expression_donor_file is None: raise ValueError("expression donor not found") with open(expression_acceptor_file, "r", encoding="utf8") as file: data_acceptor = json.load(file) with open(expression_donor_file, "r", encoding="utf8") as file: data_donor = json.load(file) parameters_list = list(parameter_preset_data[parameter_preset]) data_result = MiracleCacheTools.expressionParametersMigration(parameters_list, data_acceptor, data_donor) with NamedTemporaryFile(suffix=".exp3.json", delete=False, mode="w", encoding="utf8") as file: json.dump(data_result, file, ensure_ascii=False, indent=4) result_file_path = file.name return result_file_path def useButton0202Click(select_type, file_select, file_upload): if select_type == "选择已有文件": if file_select is None: raise ValueError("parameter preset file not found") file = file_select elif select_type == "上传本地文件": if file_upload is None: raise ValueError("parameter preset file not found") file = file_upload else: raise ValueError(f"unknown select type : {select_type}") with open(file, "r", encoding="utf8") as f: data = json.load(f) return data def useButton0202aClick(file_upload): if file_upload is None: raise ValueError("parameters list update file not found") with open(file_upload, "r", encoding="utf8") as file: data_raw = json.load(file) data_result = MiracleCacheTools.cdiParametersListGet(data_raw) data_result_df = MiracleCacheTools.parametersListTextGet(data_result) return data_result, data_result_df def addButton0202Click(data_raw, name, params, parameters_list_df): if name is None: raise ValueError("parameter preset name is empty") if params is None: params = [] name = name.strip() if name == "": raise ValueError("parameter preset name is empty") if name in data_raw: raise ValueError(f"Duplicate parameter preset name found: {name}") pdata = {} for param in params: pid = parameters_list_df[parameters_list_df["text"]==param].reset_index(drop=True)["id"][0] pname = parameters_list_df[parameters_list_df["text"]==param].reset_index(drop=True)["name"][0] pdata[pid] = {"Name": pname} data_raw[name] = pdata.copy() return data_raw, "", [] def deleteButton0202Click(data_raw, delete_list): if delete_list is None: delete_list = [] for name in delete_list: if name in data_raw: del data_raw[name] return data_raw, [] def saveButton0202Click(data_raw): with NamedTemporaryFile(suffix=".json", delete=False, mode="w", encoding="utf8") as file: json.dump(data_raw, file, ensure_ascii=False) result_file_path = file.name return result_file_path def updateParametersGroupsDataByCdiFile(file_upload): if file_upload is None: raise ValueError("parameters groups data update file not found") with open(file_upload, "r", encoding="utf8") as file: data_raw = json.load(file) data_result = MiracleCacheTools.cdiParametersGroupsDataGet(data_raw) data_result_df = MiracleCacheTools.parametersListTextGet(data_result) return data_result, data_result_df def processButton0203bClick(parameters_groups, expression_acceptor_file, expression_donor_file, parameters_groups_data, parameters_groups_dataframe): if parameters_groups is None: parameters_groups = [] if expression_acceptor_file is None: raise ValueError("expression acceptor not found") if expression_donor_file is None: raise ValueError("expression donor not found") with open(expression_acceptor_file, "r", encoding="utf8") as file: data_acceptor = json.load(file) with open(expression_donor_file, "r", encoding="utf8") as file: data_donor = json.load(file) groups = {} for gtext in parameters_groups: gid = parameters_groups_dataframe[parameters_groups_dataframe["text"]==gtext].reset_index(drop=True)["id"][0] groups[gid] = parameters_groups_data[gid] data_result = MiracleCacheTools.expressionParametersMigrationByGroups(groups, data_acceptor, data_donor) with NamedTemporaryFile(suffix=".exp3.json", delete=False, mode="w", encoding="utf8") as file: json.dump(data_result, file, ensure_ascii=False, indent=4) result_file_path = file.name return result_file_path def multipleExpressionsParametersMigration(expression_donor_files, parameters_groups, expression_data_temp_list, parameters_groups_data, parameters_groups_dataframe): if parameters_groups is None: return expression_data_temp_list elif len(parameters_groups) == 0: return expression_data_temp_list if expression_donor_files is None: return expression_data_temp_list elif len(expression_donor_files) == 0: return expression_data_temp_list data_result = expression_data_temp_list[-1] data_list_result = expression_data_temp_list.copy() groups = {} for gtext in parameters_groups: gid = parameters_groups_dataframe[parameters_groups_dataframe["text"]==gtext].reset_index(drop=True)["id"][0] groups[gid] = parameters_groups_data[gid] for expression_donor_file in expression_donor_files: with open(expression_donor_file, "r", encoding="utf8") as file: data_donor = json.load(file) data_result = MiracleCacheTools.expressionParametersMigrationByGroups(groups, data_result, data_donor) data_list_result.append(data_result.copy()) if len(data_list_result) > EXP_DATA_TEMP_LIST_LENGTH: data_list_result = data_list_result[-EXP_DATA_TEMP_LIST_LENGTH:] return data_list_result def multipleExpressionsParametersOverlay(expression_donor_files, parameters_groups, expression_data_temp_list, parameters_groups_data, parameters_groups_dataframe): if parameters_groups is None: return expression_data_temp_list elif len(parameters_groups) == 0: return expression_data_temp_list if expression_donor_files is None: return expression_data_temp_list elif len(expression_donor_files) == 0: return expression_data_temp_list data_result = expression_data_temp_list[-1] data_list_result = expression_data_temp_list.copy() groups = {} for gtext in parameters_groups: gid = parameters_groups_dataframe[parameters_groups_dataframe["text"]==gtext].reset_index(drop=True)["id"][0] groups[gid] = parameters_groups_data[gid] for expression_donor_file in expression_donor_files: with open(expression_donor_file, "r", encoding="utf8") as file: data_donor = json.load(file) data_result = MiracleCacheTools.expressionParametersOverlayByGroups(groups, data_result, data_donor) data_list_result.append(data_result.copy()) if len(data_list_result) > EXP_DATA_TEMP_LIST_LENGTH: data_list_result = data_list_result[-EXP_DATA_TEMP_LIST_LENGTH:] return data_list_result def expressionDataTempListAppendEmptyExpressionsDict(expression_data_temp_list): expression_data_temp_list.append({"Type": "Live2D Expression", "Parameters": []}) if len(expression_data_temp_list) > EXP_DATA_TEMP_LIST_LENGTH: expression_data_temp_list = expression_data_temp_list[-EXP_DATA_TEMP_LIST_LENGTH:] return expression_data_temp_list def saveButton0204bClick(data_raw_list): data_raw = data_raw_list[-1] with NamedTemporaryFile(suffix=".exp3.json", delete=False, mode="w", encoding="utf8") as file: json.dump(data_raw, file, ensure_ascii=False) result_file_path = file.name return result_file_path def expressionDataTempListStateChange(expression_data_temp_list): expression_data = expression_data_temp_list[-1] if len(expression_data_temp_list) <= 1: back_interactive = False else: back_interactive = True return gr.JSON(value=expression_data), gr.Button(interactive=back_interactive) with gr.Blocks(title="MiracleCacheTools") as demo: gr.Markdown("## 奇迹缓缓辅助工具箱") with gr.Tab("颜色空间换算"): comment_01 = gr.Markdown("注意事项:
滑块监听事件为其输入值的改变,快速拖动可能会出现数值更新不及时的bug。(程序缓不过来了)
调色时建议先通过点击确定大概位置,再缓慢微移滑块。") RGB_hex = gr.Textbox(value="#000000", label="十六进制RGB值", interactive=False) with gr.Row(): with gr.Column(scale=1): gr.Markdown("**RGB**") RGB_r = gr.Slider(0, 255, value=0, step=1, label="R(红色)") RGB_g = gr.Slider(0, 255, value=0, step=1, label="G(绿色)") RGB_b = gr.Slider(0, 255, value=0, step=1, label="B(蓝色)") with gr.Column(scale=1): gr.Markdown("**HLS**") HLS_h = gr.Slider(0, 360, value=0, step=1, label="H(色相)") HLS_l = gr.Slider(0, 100, value=0, step=1, label="L(亮度)") HLS_s = gr.Slider(0, 100, value=0, step=1, label="S(饱和度)") with gr.Column(scale=1): gr.Markdown("**HSV**") HSV_h = gr.Slider(0, 360, value=0, step=1, label="H(色相)") HSV_s = gr.Slider(0, 100, value=0, step=1, label="S(饱和度)") HSV_v = gr.Slider(0, 100, value=0, step=1, label="V(明度)") with gr.Row(): with gr.Column(scale=1): color = gr.ColorPicker(value="#000000", label="调色板", scale=1) gr.Markdown("右侧可上传参考图片,配合调色板的吸管工具使用。
试验性功能,请谨慎使用。") image_sample = gr.Image(value=None, label="参考图片", interactive=True, scale=3) RGB_r.input( fn=RGBInputProcess, inputs=[RGB_r, RGB_g, RGB_b], outputs=[color, RGB_hex, HLS_h, HLS_l, HLS_s, HSV_h, HSV_s, HSV_v] ) RGB_g.input( fn=RGBInputProcess, inputs=[RGB_r, RGB_g, RGB_b], outputs=[color, RGB_hex, HLS_h, HLS_l, HLS_s, HSV_h, HSV_s, HSV_v] ) RGB_b.input( fn=RGBInputProcess, inputs=[RGB_r, RGB_g, RGB_b], outputs=[color, RGB_hex, HLS_h, HLS_l, HLS_s, HSV_h, HSV_s, HSV_v] ) HLS_h.input( fn=HLSInputProcess, inputs=[HLS_h, HLS_l, HLS_s], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HSV_h, HSV_s, HSV_v] ) HLS_l.input( fn=HLSInputProcess, inputs=[HLS_h, HLS_l, HLS_s], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HSV_h, HSV_s, HSV_v] ) HLS_s.input( fn=HLSInputProcess, inputs=[HLS_h, HLS_l, HLS_s], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HSV_h, HSV_s, HSV_v] ) HSV_h.input( fn=HSVInputProcess, inputs=[HSV_h, HSV_s, HSV_v], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HLS_h, HLS_l, HLS_s] ) HSV_s.input( fn=HSVInputProcess, inputs=[HSV_h, HSV_s, HSV_v], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HLS_h, HLS_l, HLS_s] ) HSV_v.input( fn=HSVInputProcess, inputs=[HSV_h, HSV_s, HSV_v], outputs=[color, RGB_hex, RGB_r, RGB_g, RGB_b, HLS_h, HLS_l, HLS_s] ) color.input( fn=colorInputProcess, inputs=[color], outputs=[RGB_hex, RGB_r, RGB_g, RGB_b, HLS_h, HLS_l, HLS_s, HSV_h, HSV_s, HSV_v] ) with gr.Tab("表情参数批量迁移"): with open(parameters_list_path, "r", encoding="utf8") as file: parameters_list_dict = json.load(file) parameters_list_dict_state = gr.State(parameters_list_dict) parameters_list_df_state = gr.State(MiracleCacheTools.parametersListTextGet(parameters_list_dict)) ## 此处参数分组表格和参数表格使用同一个函数获取 with open(parameters_groups_data_path, "r", encoding="utf8") as file: parameters_groups_data_dict = json.load(file) parameters_groups_data_dict_state = gr.State(parameters_groups_data_dict) parameters_groups_data_df_state = gr.State(MiracleCacheTools.parametersListTextGet(parameters_groups_data_dict)) gr.Markdown("表情参数批量迁移,试验性功能,请谨慎使用。
实际效果为,根据参考的参数列表,将参数施主的表情参数复制到参数受主中,覆盖原有表情参数或新增表情参数。(详见下方的详细说明)
参数列表应随奇迹缓缓一齐更新。
工具不会处理数据文件可能存在的格式问题,请自行确保数据文件格式正确并备份原始数据。") with gr.Tab("使用参数预设"): parameter_preset_data_state = gr.State({}) with gr.Row(): with gr.Column(scale=1): gr.Markdown("#### 参数预设文件") gr.Markdown("选择或上传参数预设文件并选择参数预设") parameter_preset_file_select_type = gr.Radio(choices=["选择已有文件", "上传本地文件"], value="选择已有文件", label="参数预设文件选择方式", interactive=True) parameter_preset_file_select = gr.Dropdown(choices=parameter_preset_files, value=None, multiselect=False, label="选择参数预设文件", interactive=True) parameter_preset_file_upload = gr.File(file_types=[".json"], label="上传参数预设文件", interactive=False) parameter_preset = gr.Dropdown(choices=[], value=None, multiselect=False, label="选择参数预设", interactive=True) with gr.Column(scale=1): expression_acceptor_file = gr.File(file_types=[".json"], label="上传参数受主文件", interactive=True) expression_donor_file = gr.File(file_types=[".json"], label="上传参数施主文件", interactive=True) with gr.Row(): process_button_0201 = gr.Button("处理", variant="primary") clear_button_0201 = gr.Button("清空", variant="primary") output_file_0201 = gr.File(label="输出文件", interactive=False) gr.Markdown("#### 使用方法:") gr.Markdown("1. 选择或上传参数预设文件,选择参数预设。
2. 上传参数受主文件和参数施主文件。") gr.Markdown("#### 原理说明:") gr.Markdown("遍历预设列表中的参数。
若其存在于施主文件中,则将其复制到受主文件中,覆盖原有参数或新增参数。
若其不存在于施主文件中,则删去受主文件中的该参数(若存在)。") parameter_preset_file_select_type.change( fn=parameterPresetFileSelectUpdate, inputs=[parameter_preset_file_select_type], outputs=[parameter_preset_file_select, parameter_preset_file_upload] ) parameter_preset_file_select.input( fn=parameterPresetFileProcess, inputs=[parameter_preset_file_select], outputs=[parameter_preset, parameter_preset_data_state] ) parameter_preset_file_upload.upload( fn=parameterPresetFileProcess, inputs=[parameter_preset_file_upload], outputs=[parameter_preset, parameter_preset_data_state] ) process_button_0201.click( fn=processButton0201Click, inputs=[parameter_preset, expression_acceptor_file, expression_donor_file, parameter_preset_data_state], outputs=[output_file_0201] ) clear_button_0201.click( fn=lambda : ["选择已有文件", [], None, [], None, None], outputs=[parameter_preset_file_select_type, parameter_preset_file_select, parameter_preset_file_upload, parameter_preset, expression_acceptor_file, expression_donor_file] ) with gr.Tab("自定义参数预设"): parameter_preset_0202_state = gr.State({}) with gr.Row(): with gr.Column(scale=1): gr.Markdown("#### 参数预设模板文件") gr.Markdown("选择或上传参数预设文件并以其作为参数预设模板") parameter_preset_file_select_type_0202 = gr.Radio(choices=["选择已有文件", "上传本地文件"], value="选择已有文件", label="参数预设文件选择方式", interactive=True) parameter_preset_file_select_0202 = gr.Dropdown(choices=parameter_preset_files, value=None, multiselect=False, label="选择参数预设文件", interactive=True) parameter_preset_file_upload_0202 = gr.File(file_types=[".json"], label="上传参数预设文件", interactive=False) with gr.Row(): use_button_0202 = gr.Button("使用参数预设模板", variant="primary") clear_button_0202 = gr.Button("清空", variant="primary") gr.Markdown("#### 参数列表更新") gr.Markdown("默认使用现有参数列表
可上传『.cdi3.json』文件以更新参数列表") parameters_list_update_file = gr.File(file_types=[".json"], show_label=False) with gr.Row(): use_button_0202a = gr.Button("更新参数列表", variant="primary") with gr.Column(scale=1): gr.Markdown("#### 添加参数预设") gr.Markdown("注意,预设名称不可与现有的重复。") parameter_preset_name = gr.Textbox(value="", label="参数预设名称", interactive=True) parameter_preset_parameters = gr.Dropdown(choices=parameters_list_df_state.value["text"].to_list(), value=None, multiselect=True, label="选择预设参数", interactive=True, info="参数过多时,下拉框存在局限,后续将进行优化。") with gr.Row(): add_button_0202 = gr.Button("添加参数预设", variant="primary") clear_button_0202b = gr.Button("清空", variant="primary") gr.Markdown("#### 删除参数预设") parameter_preset_delete = gr.Dropdown(choices=list(parameter_preset_0202_state.value), value=None, multiselect=True, label="选择要删除的参数预设", interactive=True) with gr.Row(): delete_button_0202 = gr.Button("删除参数预设", variant="primary") clear_button_0202c = gr.Button("清空", variant="primary") gr.Markdown("#### 参数预设预览") parameter_preset_preview = gr.Dataframe(MiracleCacheTools.parameterPresetDataFramePreviewGet(parameter_preset_0202_state.value), headers=["预设名称", "参数列表"], interactive=False, label="参数预设预览") gr.Markdown("#### 参数预设保存") save_button_0202 = gr.Button("保存参数预设文件", variant="primary") output_file_0202 = gr.File(label="输出文件", interactive=False) parameter_preset_file_select_type_0202.change( fn=parameterPresetFileSelectUpdate, inputs=[parameter_preset_file_select_type_0202], outputs=[parameter_preset_file_select_0202, parameter_preset_file_upload_0202] ) use_button_0202.click( fn=useButton0202Click, inputs=[parameter_preset_file_select_type_0202, parameter_preset_file_select_0202, parameter_preset_file_upload_0202], outputs=[parameter_preset_0202_state] ) clear_button_0202.click( fn=lambda :["选择已有文件", [], None], outputs=[parameter_preset_file_select_type_0202, parameter_preset_file_select_0202, parameter_preset_file_upload_0202] ) use_button_0202a.click( fn=useButton0202aClick, inputs=[parameters_list_update_file], outputs=[parameters_list_dict_state, parameters_list_df_state] ) add_button_0202.click( fn=addButton0202Click, inputs=[parameter_preset_0202_state, parameter_preset_name, parameter_preset_parameters, parameters_list_df_state], outputs=[parameter_preset_0202_state, parameter_preset_name, parameter_preset_parameters] ) clear_button_0202b.click( fn=lambda : ["", []], outputs=[parameter_preset_name, parameter_preset_parameters] ) delete_button_0202.click( fn=deleteButton0202Click, inputs=[parameter_preset_0202_state, parameter_preset_delete], outputs=[parameter_preset_0202_state, parameter_preset_delete] ) clear_button_0202c.click( fn=lambda : [[]], outputs=[parameter_preset_delete] ) save_button_0202.click( fn=saveButton0202Click, inputs=[parameter_preset_0202_state], outputs=[output_file_0202] ) parameters_list_df_state.change( fn=lambda df:gr.Dropdown(choices=df["text"].to_list()), inputs=[parameters_list_df_state], outputs=[parameter_preset_parameters] ) parameter_preset_0202_state.change( fn=lambda preset:[gr.Dataframe(MiracleCacheTools.parameterPresetDataFramePreviewGet(preset)), gr.Dropdown(choices=list(preset))], inputs=[parameter_preset_0202_state], outputs=[parameter_preset_preview, parameter_preset_delete] ) with gr.Tab("使用原生参数分组"): gr.Markdown("使用原生的参数分组作为参考的参数列表。
分组可多选。") with gr.Row(): with gr.Column(scale=1): parameters_groups_select_0203 = gr.Dropdown(choices=parameters_groups_data_df_state.value["text"].to_list(), value=None, multiselect=True, interactive=True, label="选择参数分组") with gr.Row(): all_button_0203 = gr.Button("全选", variant="primary") #clear_button_0203 = gr.Button("清空", variant="primary") gr.Markdown("#### 参数分组数据更新") gr.Markdown("默认使用现有参数分组数据
可上传『.cdi3.json』文件以更新参数分组数据") parameters_groups_data_update_file = gr.File(file_types=[".json"], show_label=False) with gr.Row(): use_button_0203a = gr.Button("更新参数分组", variant="primary") with gr.Column(scale=1): expression_acceptor_file_0203 = gr.File(file_types=[".json"], label="上传参数受主文件", interactive=True) expression_donor_file_0203 = gr.File(file_types=[".json"], label="上传参数施主文件", interactive=True) with gr.Row(): process_button_0203b = gr.Button("处理", variant="primary") clear_button_0203b = gr.Button("清空", variant="primary") output_file_0203 = gr.File(label="输出文件", interactive=False) all_button_0203.click( fn=lambda df: gr.Dropdown(value=df["text"].to_list()), inputs=[parameters_groups_data_df_state], outputs=[parameters_groups_select_0203] ) use_button_0203a.click( fn=updateParametersGroupsDataByCdiFile, inputs=[parameters_groups_data_update_file], outputs=[parameters_groups_data_dict_state, parameters_groups_data_df_state] ) process_button_0203b.click( fn=processButton0203bClick, inputs=[parameters_groups_select_0203, expression_acceptor_file_0203, expression_donor_file_0203, parameters_groups_data_dict_state, parameters_groups_data_df_state], outputs=[output_file_0203] ) clear_button_0203b.click( fn=lambda:[[], None, None], outputs=[parameters_groups_select_0203, expression_acceptor_file_0203, expression_donor_file_0203] ) with gr.Tab("多表情参数迁移叠加"): expression_data_temp_list_state = gr.State([{"Type": "Live2D Expression", "Parameters": []}]) gr.Markdown("此工具不再限定参数来源为一个参数施主文件和一个参数受主文件,现在可以将多个表情里指定的参数迁移到目标中。") gr.Markdown("新表情的参数会覆盖原有的同名参数,目前有『迁移』『叠加』两种操作。
『迁移』和之前一样会删掉参考列表中原表情有而新表情没有的参数,『叠加』则不会。
当参数列表包含所有相关参数时,其『迁移』结果新表情将会完全覆盖原表情,『叠加』结果则类似于VTS的表情叠加。") gr.Markdown("右侧可预览暂存的表情数据,点击保存按钮可将其保存为json文件。
可以撤回处理操作,目前至多支持16步。") with gr.Row(): with gr.Column(scale=1): gr.Markdown("#### 表情参数迁移") gr.Markdown("上传参数施主文件并选择参数分组。") expression_donor_files = gr.Files(file_types=[".json"], label="上传参数施主文件", interactive=True) parameters_groups_select_0204 = gr.Dropdown(choices=parameters_groups_data_df_state.value["text"].to_list(), value=None, multiselect=True, interactive=True, label="选择参数分组") with gr.Row(): all_button_0204a = gr.Button("全选", variant="primary") clear_button_0204a = gr.Button("清空", variant="primary") with gr.Row(): migration_button_0204a = gr.Button("迁移", variant="primary") overlay_button_0204a = gr.Button("叠加", variant="primary") gr.Markdown("#### 参数分组数据更新") gr.Markdown("默认使用现有参数分组数据
可上传『.cdi3.json』文件以更新参数分组数据") parameters_groups_data_update_file_0204 = gr.File(file_types=[".json"], show_label=False, interactive=True) with gr.Row(): use_button_0204 = gr.Button("更新参数分组", variant="primary") with gr.Column(scale=1): expression_data_temp_preview_json = gr.JSON(value=expression_data_temp_list_state.value[-1], label="暂存表情数据预览") with gr.Row(): back_button_0204b = gr.Button("撤回", variant="primary", interactive=False) clear_button_0204b = gr.Button("清空", variant="primary") save_button_0204b = gr.Button("保存", variant="primary") output_file_0204 = gr.File(label="输出文件", interactive=False) all_button_0204a.click( fn=lambda df: gr.Dropdown(value=df["text"].to_list()), inputs=[parameters_groups_data_df_state], outputs=[parameters_groups_select_0204] ) clear_button_0204a.click( fn=lambda :[[], []], outputs=[expression_donor_files, parameters_groups_select_0204] ) migration_button_0204a.click( fn=multipleExpressionsParametersMigration, inputs=[expression_donor_files, parameters_groups_select_0204, expression_data_temp_list_state, parameters_groups_data_dict_state, parameters_groups_data_df_state], outputs=[expression_data_temp_list_state] ) overlay_button_0204a.click( fn=multipleExpressionsParametersOverlay, inputs=[expression_donor_files, parameters_groups_select_0204, expression_data_temp_list_state, parameters_groups_data_dict_state, parameters_groups_data_df_state], outputs=[expression_data_temp_list_state] ) use_button_0204.click( fn=updateParametersGroupsDataByCdiFile, inputs=[parameters_groups_data_update_file_0204], outputs=[parameters_groups_data_dict_state, parameters_groups_data_df_state] ) back_button_0204b.click( fn=lambda lst: lst[:-1], inputs=[expression_data_temp_list_state], outputs=[expression_data_temp_list_state] ) clear_button_0204b.click( fn=expressionDataTempListAppendEmptyExpressionsDict, inputs=[expression_data_temp_list_state], outputs=[expression_data_temp_list_state] ) save_button_0204b.click( fn=saveButton0204bClick, inputs=[expression_data_temp_list_state], outputs=[output_file_0204] ) expression_data_temp_list_state.change( fn=expressionDataTempListStateChange, inputs=[expression_data_temp_list_state], outputs=[expression_data_temp_preview_json, back_button_0204b] ) ## ??? parameters_groups_data_df_state.change( fn=lambda df: (gr.Dropdown(choices=df["text"].to_list()), gr.Dropdown(choices=df["text"].to_list())), inputs=[parameters_groups_data_df_state], outputs=[parameters_groups_select_0203, parameters_groups_select_0204] ) demo.launch()