feat: add support for local-only parameters to Parameters component (#275)
* feat: add support for local parameters * docs: update parameters docs
@ -11,6 +11,20 @@ using Debug = System.Diagnostics.Debug;
|
||||
|
||||
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))]
|
||||
internal class AvatarParametersEditor : MAEditorBase
|
||||
{
|
||||
@ -258,9 +272,11 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
var margin = 20;
|
||||
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);
|
||||
rightHalf.xMax = rect.xMax;
|
||||
var rightHalfTop = new Rect(rect.x + leftHalf.width + halfMargin, rect.y, leftHalf.width, elemHeight);
|
||||
rightHalfTop.xMax = rect.xMax;
|
||||
var rightHalfSyncControlField = rightHalfTop;
|
||||
rightHalfSyncControlField.y += _devMode ? elemHeight : 0;
|
||||
|
||||
@ -326,6 +342,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
if (isSynced)
|
||||
{
|
||||
var localOnly = elem.FindPropertyRelative(nameof(ParameterConfig.localOnly));
|
||||
var saved = elem.FindPropertyRelative(nameof(ParameterConfig.saved));
|
||||
|
||||
var savedContents = new GUIContent(G("params.saved"));
|
||||
@ -340,12 +357,26 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
rightHalfDefaultValue.width -= savedPos.width;
|
||||
//savedPos.x -= savedSize.x + checkboxPad * 2;
|
||||
|
||||
|
||||
EditorGUI.LabelField(savedPos, savedContents);
|
||||
savedPos.x += savedLabelWidth + checkboxPad;
|
||||
savedPos.width -= savedLabelWidth - checkboxPad * 2;
|
||||
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 label = new GUIContent(G("params.default"));
|
||||
var labelSize = EditorStyles.label.CalcSize(label);
|
||||
@ -420,8 +451,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
private void DrawHeader(Rect rect)
|
||||
{
|
||||
var leftHalf = new Rect(rect.x, rect.y, rect.width / 2, rect.height);
|
||||
var rightHalf = new Rect(rect.x + rect.width / 2, 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 + leftHalf.width, rect.y, rect.width / 2, rect.height);
|
||||
|
||||
EditorGUI.LabelField(leftHalf, G("params.fieldname"));
|
||||
if (!_devMode) EditorGUI.LabelField(rightHalf, G("params.remapto"));
|
||||
|
@ -11,19 +11,24 @@
|
||||
"menuinstall.showcontents": "Show menu contents",
|
||||
"menuinstall.showcontents.notselected": "No menu selected",
|
||||
"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_uncompressed" : "The icon set in the menu is not set for compression.",
|
||||
"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.srcmenu": "Menu to Install",
|
||||
"params.autodetect_header": " Autodetected Parameters ",
|
||||
"params.internal": "Internal",
|
||||
"params.pb_prefix": "PhysBones Prefix",
|
||||
"params.syncmode": "Sync Mode",
|
||||
"params.syncmode": "Param type",
|
||||
"params.saved": "Saved",
|
||||
"params.synced": "Synced",
|
||||
"params.default": "Default value",
|
||||
"params.fieldname": "Field name",
|
||||
"params.remapto": "Remap to",
|
||||
"params.remapto.tooltip": "Enter a new name for this parameter here to resolve name conflicts",
|
||||
"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.tooltip": "The armature (or subtree) to merge this object into",
|
||||
"merge_armature.prefix": "Prefix",
|
||||
|
@ -9,19 +9,24 @@
|
||||
"menuinstall.showcontents": "メニュー内容を表示",
|
||||
"menuinstall.showcontents.notselected": "メニューが選択されていません",
|
||||
"menuinstall.devoptions": "プレハブ開発者向け設定",
|
||||
"menuinstall.menu_icon_too_large" : "メニューに設定されているアイコンが256ピクセルより大きすぎます。",
|
||||
"menuinstall.menu_icon_uncompressed" : "メニューに設定されているアイコンが圧縮設定されていません。",
|
||||
"menuinstall.menu_icon_too_large": "メニューに設定されているアイコンが256ピクセルより大きすぎます。",
|
||||
"menuinstall.menu_icon_uncompressed": "メニューに設定されているアイコンが圧縮設定されていません。",
|
||||
"menuinstall.srcmenu": "インストールされるメニュー",
|
||||
"params.autodetect_header": " 自動検出されたパラメーター ",
|
||||
"params.internal": "内部値",
|
||||
"params.pb_prefix": "PhysBones前置詞",
|
||||
"params.syncmode": "同期モード",
|
||||
"params.syncmode": "パラメーター型",
|
||||
"params.saved": "保存する",
|
||||
"params.synced": "同期する",
|
||||
"params.default": "初期値",
|
||||
"params.fieldname": "パラメーター名",
|
||||
"params.remapto": "変更後の名前",
|
||||
"params.remapto.tooltip": "ここに新しい名前を入れることで、名前かぶりを解消できます",
|
||||
"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.tooltip": "このオブジェクトを統合先のアーマチュアに統合します",
|
||||
"merge_armature.prefix": "前置詞",
|
||||
|
@ -480,6 +480,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
valueType = type,
|
||||
defaultValue = parameterConfig.defaultValue,
|
||||
saved = parameterConfig.saved,
|
||||
networkSynced = !parameterConfig.localOnly
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,15 @@ namespace nadena.dev.modular_avatar.core
|
||||
public string remapTo;
|
||||
public bool internalParameter, isPrefix;
|
||||
public ParameterSyncType syncType;
|
||||
public bool localOnly;
|
||||
public float defaultValue;
|
||||
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
|
||||
{
|
||||
NotSynced,
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 13 KiB |
@ -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).
|
||||
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.
|
||||
Finally, you can mark parameters as being unsynced to save on bandwidth, if desired.
|
||||
|
||||
### 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.
|
||||
* 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.
|
||||
|
||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 16 KiB |
@ -20,7 +20,7 @@ VRChatの標準パラメーター以外のパラメーターを使ったアセ
|
||||
|
||||
Parametersコンポーネントで名前かぶりを避けるためにパラメーター名を変えたり、アバター読み込みでパラメーターの値が保存されるかを設定できます。
|
||||
複数のアセットのパラメーターを同じにすることで、同じ値を共有させて、同時にアニメーションさせることができます。
|
||||
また、被る名前を変えることで干渉を避けることもできます。
|
||||
また、被る名前を変えることで干渉を避けることもできます。 そして、同期する・しないかも設定できます。
|
||||
|
||||
### プレハブ開発者向け
|
||||
|
||||
@ -29,7 +29,7 @@ Parametersコンポーネントで名前かぶりを避けるためにパラメ
|
||||
パラメーターには以下の設定があります。
|
||||
* 内部値 - パラメーターを非表示にし、ユニークな名前に自動変更します
|
||||
* PhysBones前置詞 - この値がPhysBoneのparameter欄に設定されるもので、いくつかのサブパラメーターのくくりであることを示します。
|
||||
* 同期モード - 同期されるかどうかと、同期される値の種別を指定します
|
||||
* パラメーター型 - Expressions Parametersに登録されるかどうかと、値の型を指定します
|
||||
|
||||
Parametersコンポーネントは、入れ子式(ネスト状)で使うことができます。複雑なアセットをサブプレハブから構築し、名前かぶりを避けつつ同じプレハブを複数回使ったりすることもできます。
|
||||
|
||||
|