Skip to content

Commit 70853bb

Browse files
committed
Enhance Live2D parameter handling and update reset logic
- Modified the motion manager update function to accept arguments for better error handling. - Updated the parameter editor to display unknown parameters by default. - Implemented a new function to retrieve parameter ranges and default values, improving flexibility for different model types. - Adjusted the parameter reset logic to use initial values or model defaults, ensuring a more accurate reset process.
1 parent fd2a4d8 commit 70853bb

2 files changed

Lines changed: 94 additions & 11 deletions

File tree

static/live2d-model.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ Live2DManager.prototype.installMouthOverride = function() {
429429
const origMotionManagerUpdate = internalModel.motionManager.update.bind(internalModel.motionManager);
430430
this._origMotionManagerUpdate = origMotionManagerUpdate;
431431

432-
internalModel.motionManager.update = () => {
432+
internalModel.motionManager.update = (...args) => {
433433
// 检查 coreModel 是否仍然有效(在调用原始方法之前检查)
434434
if (!coreModel || !this.currentModel || !this.currentModel.internalModel || !this.currentModel.internalModel.coreModel) {
435435
return; // 如果模型已销毁,直接返回
@@ -451,7 +451,7 @@ Live2DManager.prototype.installMouthOverride = function() {
451451
// 先调用原始的 motionManager.update(添加错误处理)
452452
if (origMotionManagerUpdate) {
453453
try {
454-
origMotionManagerUpdate();
454+
origMotionManagerUpdate(...args);
455455
} catch (e) {
456456
// SDK 内部 motion 在异步加载期间可能会抛出 getParameterIndex 错误
457457
// 这是 pixi-live2d-display 的已知问题,静默忽略即可

templates/live2d_parameter_editor.html

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@
533533
return false;
534534
}
535535
}
536-
// 默认隐藏未知参数(保守策略
536+
// 不匹配则默认显示(包括未知参数
537537
return true;
538538
}
539539

@@ -842,6 +842,63 @@
842842
}
843843
}
844844

845+
// 获取参数的范围和默认值
846+
function getParameterRange(coreModel, index) {
847+
let min = -1;
848+
let max = 1;
849+
let defaultVal = undefined;
850+
851+
try {
852+
// 优先尝试 getParameterDefaultValueByIndex (Live2DManager 中使用的标准方法)
853+
// Live2DManager.js 中确认使用了此方法,应该是最可靠的获取默认值方式
854+
if (typeof coreModel.getParameterDefaultValueByIndex === 'function') {
855+
defaultVal = coreModel.getParameterDefaultValueByIndex(index);
856+
}
857+
858+
// Try Cubism 2 style (Standard SDK)
859+
if (typeof coreModel.getParamMin === 'function') {
860+
min = coreModel.getParamMin(index);
861+
max = coreModel.getParamMax(index);
862+
if (defaultVal === undefined) defaultVal = coreModel.getParamDefaultValue(index);
863+
}
864+
// Try Cubism 4 JS Wrapper style (pixi-live2d-display / Internal Model)
865+
else if (coreModel.parameters && coreModel.parameters.minimumValues) {
866+
min = coreModel.parameters.minimumValues[index];
867+
max = coreModel.parameters.maximumValues ? coreModel.parameters.maximumValues[index] : 1;
868+
if (defaultVal === undefined && coreModel.parameters.defaultValues) {
869+
defaultVal = coreModel.parameters.defaultValues[index];
870+
}
871+
}
872+
// Try Cubism 4 Standard Emscripten binding style
873+
else if (typeof coreModel.getParameterMinimumValues === 'function') {
874+
// Note: In some bindings these return arrays or pointers, not values by index directly usually
875+
// But let's check if getParameterMinimumValue exists
876+
if (typeof coreModel.getParameterMinimumValue === 'function') {
877+
min = coreModel.getParameterMinimumValue(index);
878+
max = coreModel.getParameterMaximumValue(index);
879+
if (defaultVal === undefined) defaultVal = coreModel.getParameterDefaultValue(index);
880+
}
881+
}
882+
// Fallback: check if we can access the arrays directly on the coreModel (some custom bindings)
883+
else if (coreModel._parameterMinimumValues) {
884+
min = coreModel._parameterMinimumValues[index];
885+
max = coreModel._parameterMaximumValues ? coreModel._parameterMaximumValues[index] : 1;
886+
if (defaultVal === undefined && coreModel._parameterDefaultValues) {
887+
defaultVal = coreModel._parameterDefaultValues[index];
888+
}
889+
}
890+
} catch (e) {
891+
console.warn('Error getting parameter range:', e);
892+
}
893+
894+
// Validate values
895+
if (typeof min !== 'number' || isNaN(min)) min = -1;
896+
if (typeof max !== 'number' || isNaN(max)) max = 1;
897+
if (defaultVal === undefined || typeof defaultVal !== 'number' || isNaN(defaultVal)) defaultVal = 0;
898+
899+
return { min, max, default: defaultVal };
900+
}
901+
845902
// 显示参数列表(按分组,显示所有参数)
846903
function displayParameters() {
847904
if (!live2dModel || !live2dModel.internalModel || !live2dModel.internalModel.coreModel) {
@@ -956,7 +1013,16 @@
9561013
for (const { id: paramId, name: paramName, index: i } of groupedParams[groupName]) {
9571014
try {
9581015
const currentValue = coreModel.getParameterValueByIndex(i);
959-
const initialValue = initialParameters[paramId] || 0;
1016+
1017+
// 获取参数范围
1018+
const range = getParameterRange(coreModel, i);
1019+
let minValue = range.min;
1020+
let maxValue = range.max;
1021+
const initialValue = initialParameters[paramId] !== undefined ? initialParameters[paramId] : range.default;
1022+
1023+
// 确保当前值在范围内 (或者至少如果当前值超出范围,扩展范围以包含它)
1024+
if (currentValue < minValue) minValue = currentValue;
1025+
if (currentValue > maxValue) maxValue = currentValue;
9601026

9611027
const paramItem = document.createElement('div');
9621028
paramItem.className = 'parameter-item';
@@ -982,16 +1048,16 @@
9821048
const slider = document.createElement('input');
9831049
slider.type = 'range';
9841050
slider.className = 'parameter-slider';
985-
slider.min = '-1';
986-
slider.max = '1';
1051+
slider.min = minValue;
1052+
slider.max = maxValue;
9871053
slider.step = '0.01';
9881054
slider.value = currentValue;
9891055

9901056
const input = document.createElement('input');
9911057
input.type = 'number';
9921058
input.className = 'parameter-input';
993-
input.min = '-1';
994-
input.max = '1';
1059+
input.min = minValue;
1060+
input.max = maxValue;
9951061
input.step = '0.01';
9961062
input.value = currentValue;
9971063

@@ -1003,7 +1069,7 @@
10031069
const numValue = parseFloat(value);
10041070
if (isNaN(numValue)) return;
10051071

1006-
const clampedValue = Math.max(-1, Math.min(1, numValue));
1072+
const clampedValue = Math.max(minValue, Math.min(maxValue, numValue));
10071073
try {
10081074
coreModel.setParameterValueByIndex(i, clampedValue);
10091075
valueSpan.textContent = clampedValue.toFixed(3);
@@ -1055,10 +1121,27 @@
10551121
const coreModel = live2dModel.internalModel.coreModel;
10561122
const paramCount = coreModel.getParameterCount();
10571123

1058-
// 将所有参数重置为零
1124+
// 将所有参数重置为加载时的初始值
10591125
for (let i = 0; i < paramCount; i++) {
10601126
try {
1061-
coreModel.setParameterValueByIndex(i, 0);
1127+
let paramId = null;
1128+
try {
1129+
paramId = coreModel.getParameterId(i);
1130+
} catch (e) {
1131+
paramId = `param_${i}`;
1132+
}
1133+
1134+
let resetValue = 0;
1135+
// 优先使用加载时记录的初始值
1136+
if (initialParameters && initialParameters[paramId] !== undefined) {
1137+
resetValue = initialParameters[paramId];
1138+
} else {
1139+
// 降级到使用模型定义的默认值
1140+
const range = getParameterRange(coreModel, i);
1141+
resetValue = range.default;
1142+
}
1143+
1144+
coreModel.setParameterValueByIndex(i, resetValue);
10621145
} catch (e) {
10631146
console.warn(`重置参数索引 ${i} 失败:`, e);
10641147
}

0 commit comments

Comments
 (0)