Spaces:
Sleeping
Sleeping
| 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("注意事项:<br>滑块监听事件为其输入值的改变,快速拖动可能会出现数值更新不及时的bug。(程序缓不过来了)<br>调色时建议先通过点击确定大概位置,再缓慢微移滑块。") | |
| 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("右侧可上传参考图片,配合调色板的吸管工具使用。<br>试验性功能,请谨慎使用。") | |
| 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("表情参数批量迁移,试验性功能,请谨慎使用。<br>实际效果为,根据参考的参数列表,将参数施主的表情参数复制到参数受主中,覆盖原有表情参数或新增表情参数。(详见下方的详细说明)<br>参数列表应随奇迹缓缓一齐更新。<br>工具不会处理数据文件可能存在的格式问题,请自行确保数据文件格式正确并备份原始数据。") | |
| 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. 选择或上传参数预设文件,选择参数预设。<br>2. 上传参数受主文件和参数施主文件。") | |
| gr.Markdown("#### 原理说明:") | |
| gr.Markdown("遍历预设列表中的参数。<br>若其存在于施主文件中,则将其复制到受主文件中,覆盖原有参数或新增参数。<br>若其不存在于施主文件中,则删去受主文件中的该参数(若存在)。") | |
| 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("默认使用现有参数列表<br>可上传『.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("使用原生的参数分组作为参考的参数列表。<br>分组可多选。") | |
| 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("默认使用现有参数分组数据<br>可上传『.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("新表情的参数会覆盖原有的同名参数,目前有『迁移』『叠加』两种操作。<br>『迁移』和之前一样会删掉参考列表中原表情有而新表情没有的参数,『叠加』则不会。<br>当参数列表包含所有相关参数时,其『迁移』结果新表情将会完全覆盖原表情,『叠加』结果则类似于VTS的表情叠加。") | |
| gr.Markdown("右侧可预览暂存的表情数据,点击保存按钮可将其保存为json文件。<br>可以撤回处理操作,目前至多支持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("默认使用现有参数分组数据<br>可上传『.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() | |