feat: add support for local-only parameters to Parameters component (#275)

* feat: add support for local parameters

* docs: update parameters docs
This commit is contained in:
bd_ 2023-04-15 17:06:35 +09:00 committed by GitHub
parent ab3b05752a
commit 9dc44d8ccc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 61 additions and 13 deletions

View File

@ -11,6 +11,20 @@ using Debug = System.Diagnostics.Debug;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
[CustomPropertyDrawer(typeof(ParameterSyncType))]
internal class ParameterSyncTypeDrawer : EnumDrawer<ParameterSyncType>
{
protected override string localizationPrefix => "params.syncmode";
protected override Array enumValues => new object[]
{
ParameterSyncType.NotSynced,
ParameterSyncType.Bool,
ParameterSyncType.Float,
ParameterSyncType.Int,
};
}
[CustomEditor(typeof(ModularAvatarParameters))] [CustomEditor(typeof(ModularAvatarParameters))]
internal class AvatarParametersEditor : MAEditorBase internal class AvatarParametersEditor : MAEditorBase
{ {
@ -258,9 +272,11 @@ namespace nadena.dev.modular_avatar.core.editor
var margin = 20; var margin = 20;
var halfMargin = margin / 2; var halfMargin = margin / 2;
var leftHalf = new Rect(rect.x, rect.y, rect.width / 2 - halfMargin, elemHeight); var leftHalf = new Rect(rect.x, rect.y, rect.width * 0.3f - halfMargin, elemHeight);
var rightHalf = new Rect(rect.x + leftHalf.width + halfMargin, rect.y, leftHalf.width, elemHeight); var rightHalf = new Rect(rect.x + leftHalf.width + halfMargin, rect.y, leftHalf.width, elemHeight);
rightHalf.xMax = rect.xMax;
var rightHalfTop = new Rect(rect.x + leftHalf.width + halfMargin, rect.y, leftHalf.width, elemHeight); var rightHalfTop = new Rect(rect.x + leftHalf.width + halfMargin, rect.y, leftHalf.width, elemHeight);
rightHalfTop.xMax = rect.xMax;
var rightHalfSyncControlField = rightHalfTop; var rightHalfSyncControlField = rightHalfTop;
rightHalfSyncControlField.y += _devMode ? elemHeight : 0; rightHalfSyncControlField.y += _devMode ? elemHeight : 0;
@ -326,6 +342,7 @@ namespace nadena.dev.modular_avatar.core.editor
if (isSynced) if (isSynced)
{ {
var localOnly = elem.FindPropertyRelative(nameof(ParameterConfig.localOnly));
var saved = elem.FindPropertyRelative(nameof(ParameterConfig.saved)); var saved = elem.FindPropertyRelative(nameof(ParameterConfig.saved));
var savedContents = new GUIContent(G("params.saved")); var savedContents = new GUIContent(G("params.saved"));
@ -340,12 +357,26 @@ namespace nadena.dev.modular_avatar.core.editor
rightHalfDefaultValue.width -= savedPos.width; rightHalfDefaultValue.width -= savedPos.width;
//savedPos.x -= savedSize.x + checkboxPad * 2; //savedPos.x -= savedSize.x + checkboxPad * 2;
EditorGUI.LabelField(savedPos, savedContents); EditorGUI.LabelField(savedPos, savedContents);
savedPos.x += savedLabelWidth + checkboxPad; savedPos.x += savedLabelWidth + checkboxPad;
savedPos.width -= savedLabelWidth - checkboxPad * 2; savedPos.width -= savedLabelWidth - checkboxPad * 2;
saved.boolValue = EditorGUI.Toggle(savedPos, saved.boolValue); saved.boolValue = EditorGUI.Toggle(savedPos, saved.boolValue);
var syncedContents = new GUIContent(G("params.synced"));
var syncedStyle = EditorStyles.toggle;
var syncedSize = syncedStyle.CalcSize(syncedContents);
var syncedLabelWidth = EditorStyles.label.CalcSize(syncedContents).x;
var syncedPos = rightHalfDefaultValue;
syncedPos.width = syncedSize.x + checkboxPad * 2;
rightHalfDefaultValue.x += syncedPos.width;
rightHalfDefaultValue.width -= syncedPos.width;
EditorGUI.LabelField(syncedPos, syncedContents);
syncedPos.x += syncedLabelWidth + checkboxPad;
syncedPos.width -= syncedLabelWidth - checkboxPad * 2;
localOnly.boolValue = !EditorGUI.Toggle(syncedPos, !localOnly.boolValue);
var defaultValueProp = elem.FindPropertyRelative(nameof(ParameterConfig.defaultValue)); var defaultValueProp = elem.FindPropertyRelative(nameof(ParameterConfig.defaultValue));
var label = new GUIContent(G("params.default")); var label = new GUIContent(G("params.default"));
var labelSize = EditorStyles.label.CalcSize(label); var labelSize = EditorStyles.label.CalcSize(label);
@ -420,8 +451,8 @@ namespace nadena.dev.modular_avatar.core.editor
private void DrawHeader(Rect rect) private void DrawHeader(Rect rect)
{ {
var leftHalf = new Rect(rect.x, rect.y, rect.width / 2, rect.height); var leftHalf = new Rect(rect.x, rect.y, rect.width * 0.3f, rect.height);
var rightHalf = new Rect(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height); var rightHalf = new Rect(rect.x + leftHalf.width, rect.y, rect.width / 2, rect.height);
EditorGUI.LabelField(leftHalf, G("params.fieldname")); EditorGUI.LabelField(leftHalf, G("params.fieldname"));
if (!_devMode) EditorGUI.LabelField(rightHalf, G("params.remapto")); if (!_devMode) EditorGUI.LabelField(rightHalf, G("params.remapto"));

View File

@ -11,19 +11,24 @@
"menuinstall.showcontents": "Show menu contents", "menuinstall.showcontents": "Show menu contents",
"menuinstall.showcontents.notselected": "No menu selected", "menuinstall.showcontents.notselected": "No menu selected",
"menuinstall.devoptions": "Prefab Developer Options", "menuinstall.devoptions": "Prefab Developer Options",
"menuinstall.menu_icon_too_large" : "The icon set in the menu is too large than 256 pixels.", "menuinstall.menu_icon_too_large": "The icon set in the menu is too large than 256 pixels.",
"menuinstall.menu_icon_uncompressed" : "The icon set in the menu is not set for compression.", "menuinstall.menu_icon_uncompressed": "The icon set in the menu is not set for compression.",
"menuinstall.srcmenu": "Menu to Install", "menuinstall.srcmenu": "Menu to Install",
"params.autodetect_header": " Autodetected Parameters ", "params.autodetect_header": " Autodetected Parameters ",
"params.internal": "Internal", "params.internal": "Internal",
"params.pb_prefix": "PhysBones Prefix", "params.pb_prefix": "PhysBones Prefix",
"params.syncmode": "Sync Mode", "params.syncmode": "Param type",
"params.saved": "Saved", "params.saved": "Saved",
"params.synced": "Synced",
"params.default": "Default value", "params.default": "Default value",
"params.fieldname": "Field name", "params.fieldname": "Field name",
"params.remapto": "Remap to", "params.remapto": "Remap to",
"params.remapto.tooltip": "Enter a new name for this parameter here to resolve name conflicts", "params.remapto.tooltip": "Enter a new name for this parameter here to resolve name conflicts",
"params.devmode": "Show Prefab Developer Options", "params.devmode": "Show Prefab Developer Options",
"params.syncmode.NotSynced": "Animator Only",
"params.syncmode.Int": "Int",
"params.syncmode.Float": "Float",
"params.syncmode.Bool": "Bool",
"merge_armature.merge_target": "Merge Target", "merge_armature.merge_target": "Merge Target",
"merge_armature.merge_target.tooltip": "The armature (or subtree) to merge this object into", "merge_armature.merge_target.tooltip": "The armature (or subtree) to merge this object into",
"merge_armature.prefix": "Prefix", "merge_armature.prefix": "Prefix",

View File

@ -9,19 +9,24 @@
"menuinstall.showcontents": "メニュー内容を表示", "menuinstall.showcontents": "メニュー内容を表示",
"menuinstall.showcontents.notselected": "メニューが選択されていません", "menuinstall.showcontents.notselected": "メニューが選択されていません",
"menuinstall.devoptions": "プレハブ開発者向け設定", "menuinstall.devoptions": "プレハブ開発者向け設定",
"menuinstall.menu_icon_too_large" : "メニューに設定されているアイコンが256ピクセルより大きすぎます。", "menuinstall.menu_icon_too_large": "メニューに設定されているアイコンが256ピクセルより大きすぎます。",
"menuinstall.menu_icon_uncompressed" : "メニューに設定されているアイコンが圧縮設定されていません。", "menuinstall.menu_icon_uncompressed": "メニューに設定されているアイコンが圧縮設定されていません。",
"menuinstall.srcmenu": "インストールされるメニュー", "menuinstall.srcmenu": "インストールされるメニュー",
"params.autodetect_header": " 自動検出されたパラメーター ", "params.autodetect_header": " 自動検出されたパラメーター ",
"params.internal": "内部値", "params.internal": "内部値",
"params.pb_prefix": "PhysBones前置詞", "params.pb_prefix": "PhysBones前置詞",
"params.syncmode": "同期モード", "params.syncmode": "パラメーター型",
"params.saved": "保存する", "params.saved": "保存する",
"params.synced": "同期する",
"params.default": "初期値", "params.default": "初期値",
"params.fieldname": "パラメーター名", "params.fieldname": "パラメーター名",
"params.remapto": "変更後の名前", "params.remapto": "変更後の名前",
"params.remapto.tooltip": "ここに新しい名前を入れることで、名前かぶりを解消できます", "params.remapto.tooltip": "ここに新しい名前を入れることで、名前かぶりを解消できます",
"params.devmode": "プレハブ開発者向け設定を表示", "params.devmode": "プレハブ開発者向け設定を表示",
"params.syncmode.NotSynced": "Animatorのみ",
"params.syncmode.Int": "Int",
"params.syncmode.Float": "Float",
"params.syncmode.Bool": "Bool",
"merge_armature.merge_target": "統合先", "merge_armature.merge_target": "統合先",
"merge_armature.merge_target.tooltip": "このオブジェクトを統合先のアーマチュアに統合します", "merge_armature.merge_target.tooltip": "このオブジェクトを統合先のアーマチュアに統合します",
"merge_armature.prefix": "前置詞", "merge_armature.prefix": "前置詞",

View File

@ -480,6 +480,7 @@ namespace nadena.dev.modular_avatar.core.editor
valueType = type, valueType = type,
defaultValue = parameterConfig.defaultValue, defaultValue = parameterConfig.defaultValue,
saved = parameterConfig.saved, saved = parameterConfig.saved,
networkSynced = !parameterConfig.localOnly
}; };
} }

View File

@ -12,10 +12,15 @@ namespace nadena.dev.modular_avatar.core
public string remapTo; public string remapTo;
public bool internalParameter, isPrefix; public bool internalParameter, isPrefix;
public ParameterSyncType syncType; public ParameterSyncType syncType;
public bool localOnly;
public float defaultValue; public float defaultValue;
public bool saved; public bool saved;
} }
/**
* This enum is a bit poorly named, having been introduced before local-only parameters were a thing. In actuality,
* this is the parameter type - NotSynced indicates the parameter should not be registered in Expression Parameters.
*/
public enum ParameterSyncType public enum ParameterSyncType
{ {
NotSynced, NotSynced,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -21,6 +21,7 @@ The Parameters component should be used when you're building a prefab which make
The parameters component on prefabs can be used to rename parameters to avoid conflicts, and to adjust whether synced parameters are saved across avatar reloads (and their default value). The parameters component on prefabs can be used to rename parameters to avoid conflicts, and to adjust whether synced parameters are saved across avatar reloads (and their default value).
By renaming multiple prefab parameters to be the same, you can make them all share the same state and animate at the same time. By renaming multiple prefab parameters to be the same, you can make them all share the same state and animate at the same time.
Alternately, by changing conflicting names to be different, you can resolve prefab conflicts. Alternately, by changing conflicting names to be different, you can resolve prefab conflicts.
Finally, you can mark parameters as being unsynced to save on bandwidth, if desired.
### Prefab developers ### Prefab developers
@ -30,7 +31,7 @@ Each parameter can be configured with the following options:
* Internal - Hides the parameter, and automatically renames the parameter with a unique name. * Internal - Hides the parameter, and automatically renames the parameter with a unique name.
* PhysBones Prefix - Indicates this is a parameter passed to a PhysBone "parameter" field (and thus it really references a number of sub-parameters) * PhysBones Prefix - Indicates this is a parameter passed to a PhysBone "parameter" field (and thus it really references a number of sub-parameters)
* Sync Mode - Indicates if a parameter is synced, and if so what its type is * Param type - Indicates what type a parameter is, or if it's only present on the animator (and not the Expressions Parameters asset)
Parameters components can be nested. This lets you build up a complex prefab out of sub-prefabs, some which may be added multiple times, and while avoiding parameter name conflicts. Parameters components can be nested. This lets you build up a complex prefab out of sub-prefabs, some which may be added multiple times, and while avoiding parameter name conflicts.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -20,7 +20,7 @@ VRChatの標準パラメーター以外のパラメーターを使ったアセ
Parametersコンポーネントで名前かぶりを避けるためにパラメーター名を変えたり、アバター読み込みでパラメーターの値が保存されるかを設定できます。 Parametersコンポーネントで名前かぶりを避けるためにパラメーター名を変えたり、アバター読み込みでパラメーターの値が保存されるかを設定できます。
複数のアセットのパラメーターを同じにすることで、同じ値を共有させて、同時にアニメーションさせることができます。 複数のアセットのパラメーターを同じにすることで、同じ値を共有させて、同時にアニメーションさせることができます。
また、被る名前を変えることで干渉を避けることもできます。 また、被る名前を変えることで干渉を避けることもできます。 そして、同期する・しないかも設定できます。
### プレハブ開発者向け ### プレハブ開発者向け
@ -29,7 +29,7 @@ Parametersコンポーネントで名前かぶりを避けるためにパラメ
パラメーターには以下の設定があります。 パラメーターには以下の設定があります。
* 内部値 - パラメーターを非表示にし、ユニークな名前に自動変更します * 内部値 - パラメーターを非表示にし、ユニークな名前に自動変更します
* PhysBones前置詞 - この値がPhysBoneのparameter欄に設定されるもので、いくつかのサブパラメーターのくくりであることを示します。 * PhysBones前置詞 - この値がPhysBoneのparameter欄に設定されるもので、いくつかのサブパラメーターのくくりであることを示します。
* 同期モード - 同期されるかどうかと、同期される値の種別を指定します * パラメーター型 - Expressions Parametersに登録されるかどうかと、値の型を指定します
Parametersコンポーネントは、入れ子式ネスト状で使うことができます。複雑なアセットをサブプレハブから構築し、名前かぶりを避けつつ同じプレハブを複数回使ったりすることもできます。 Parametersコンポーネントは、入れ子式ネスト状で使うことができます。複雑なアセットをサブプレハブから構築し、名前かぶりを避けつつ同じプレハブを複数回使ったりすることもできます。