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()