ui(parameters): Rebuild MAParameters UI for Unity 2022

This commit is contained in:
bd_ 2024-01-23 19:41:11 +09:00
parent 07d61b25b2
commit 7df80797d6
24 changed files with 668 additions and 29 deletions

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 21089a5ec87c4e4fa1616376cbb8fbd7
timeCreated: 1664847495

View File

@ -12,6 +12,7 @@ namespace nadena.dev.modular_avatar.core.editor
private static Dictionary<Type, Action<VisualElement>> _localizers =
new Dictionary<Type, Action<VisualElement>>();
[Obsolete("Use UIElementLocalizer instead")]
public static VisualElement Localize(this VisualTreeAsset asset)
{
var root = asset.CloneTree();

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5b0bd0302666483e9fb9572cc5df36e1
timeCreated: 1706005296

View File

@ -0,0 +1,186 @@
#if MA_VRCSDK3_AVATARS && UNITY_2022_1_OR_NEWER
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.modular_avatar.core.editor.Parameters;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;
using static nadena.dev.modular_avatar.core.editor.Localization;
using Debug = System.Diagnostics.Debug;
namespace nadena.dev.modular_avatar.core.editor
{
[CustomEditor(typeof(ModularAvatarParameters))]
internal class AvatarParametersEditor : MAEditorBase
{
[SerializeField] private StyleSheet uss;
[SerializeField] private VisualTreeAsset uxml;
private ListView listView, unregisteredListView;
private List<DetectedParameter> detectedParameters = new List<DetectedParameter>();
protected override void OnInnerInspectorGUI()
{
throw new System.NotImplementedException();
}
protected override VisualElement CreateInnerInspectorGUI()
{
var root = uxml.CloneTree();
UI.Localize(root);
root.styleSheets.Add(uss);
/*
var listView = new ListView();
listView.BindProperty(serializedObject.FindProperty(nameof(ModularAvatarParameters.parameters)));
listView.itemHeight = 20;
listView.style.flexGrow = 1.0f;
listView.selectionType = SelectionType.Single;
listView.makeItem = () => new TextElement();
listView.bindItem = (elem, i) => ((TextElement) elem).text = $"Item {i}";
root.Q<VisualElement>("ListViewContainer").Add(listView);
*/
listView = root.Q<ListView>("Parameters");
/*listView.makeItem = () => new TextElement();
listView.bindItem = (elem, i) => ((TextElement) elem).text = $"Item {i}";
*/
listView.itemHeight = 100;
#if UNITY_2022_1_OR_NEWER
listView.showBoundCollectionSize = false;
listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;
#endif
unregisteredListView = root.Q<ListView>("UnregisteredParameters");
unregisteredListView.showBoundCollectionSize = false;
unregisteredListView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;
unregisteredListView.makeItem = () =>
{
var row = new VisualElement();
row.AddToClassList("DetectedParameter");
return row;
};
unregisteredListView.bindItem = (elem, i) =>
{
var parameter = detectedParameters[i];
elem.Clear();
var button = new Button();
button.text = "merge_parameter.ui.add_button";
button.AddToClassList("ndmf-tr");
UI.Localize(button);
var label = new Label();
label.text = parameter.OriginalName;
elem.Add(button);
elem.Add(label);
if (parameter.Source != null)
{
var tex = EditorGUIUtility.FindTexture("d_Search Icon");
var sourceButton = new Button();
sourceButton.AddToClassList("SourceButton");
sourceButton.text = "";
var image = new Image();
sourceButton.Add(image);
image.image = tex;
sourceButton.clicked += () =>
{
EditorGUIUtility.PingObject(parameter.Source);
};
elem.Add(sourceButton);
}
button.clicked += () =>
{
detectedParameters.RemoveAt(i);
var target = (ModularAvatarParameters)this.target;
target.parameters.Add(new ParameterConfig()
{
internalParameter = false,
nameOrPrefix = parameter.OriginalName,
isPrefix = parameter.IsPrefix,
remapTo = "",
syncType = parameter.syncType,
defaultValue = parameter.defaultValue,
saved = parameter.saved,
});
EditorUtility.SetDirty(target);
PrefabUtility.RecordPrefabInstancePropertyModifications(target);
unregisteredListView.RefreshItems();
listView.RefreshItems();
listView.selectedIndex = target.parameters.Count - 1;
};
};
unregisteredListView.itemsSource = detectedParameters;
var unregisteredFoldout = root.Q<Foldout>("UnregisteredFoldout");
unregisteredFoldout.RegisterValueChangedCallback(evt =>
{
if (evt.newValue)
{
DetectParameters();
}
});
root.Bind(serializedObject);
listView.itemsRemoved += _ =>
{
if (unregisteredFoldout.value)
{
// We haven't committed the removal to the backing object yet, so defer this one frame to allow that to
// happen.
EditorApplication.delayCall += DetectParameters;
}
};
return root;
}
private void DetectParameters()
{
var known = new HashSet<string>();
var knownPB = new HashSet<string>();
var target = (ModularAvatarParameters)this.target;
foreach (var parameter in target.parameters)
{
if (parameter.isPrefix)
{
knownPB.Add(parameter.nameOrPrefix);
}
else
{
known.Add(parameter.nameOrPrefix);
}
}
var detected = ParameterPolicy.ProbeParameters(target.gameObject);
detectedParameters.Clear();
detectedParameters.AddRange(
detected.Values
.Where(p => p.IsPrefix ? !knownPB.Contains(p.OriginalName) : !known.Contains(p.OriginalName))
.OrderBy(p => p.OriginalName)
);
unregisteredListView.RefreshItems();
}
}
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 21089a5ec87c4e4fa1616376cbb8fbd7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- uss: {fileID: 7433441132597879392, guid: d72e507abb5be28499d149b3c22f80bc, type: 3}
- uxml: {fileID: 9197481963319205126, guid: 00e4e2766c4ae9f4687e98ed34685b4f, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,5 @@
#if MA_VRCSDK3_AVATARS
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
@ -12,22 +11,10 @@ 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,
};
}
#if !UNITY_2022_1_OR_NEWER
[CustomEditor(typeof(ModularAvatarParameters))]
internal class AvatarParametersEditor : MAEditorBase
#endif
internal class AvatarParametersEditor2019 : MAEditorBase
{
/**********************************************************************
* | Field name | Remap to / config |

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7fd14c3a2e157c4dba0955d7d64cf5c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,83 @@
#if MA_VRCSDK3_AVATARS && UNITY_2022_1_OR_NEWER
using System;
using nadena.dev.ndmf.localization;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace nadena.dev.modular_avatar.core.editor.Parameters
{
[CustomPropertyDrawer(typeof(ParameterConfig))]
internal class ParameterConfigDrawer : PropertyDrawer
{
[SerializeField] private StyleSheet uss;
[SerializeField] private VisualTreeAsset uxml;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var rootPath = "Packages/nadena.dev.modular-avatar/Editor/Inspector/Parameters";
var uss = AssetDatabase.LoadAssetAtPath<StyleSheet>(rootPath + "/Parameters.uss");
var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(rootPath + "/ParameterConfigDrawer.uxml");
var root = uxml.CloneTree();
Localization.UI.Localize(root);
root.styleSheets.Add(uss);
var foldout = root.Q<Foldout>();
var foldoutLabel = foldout?.Q<Label>();
if (foldoutLabel != null)
{
foldoutLabel.bindingPath = "nameOrPrefix";
}
var miniDisplay = root.Q<VisualElement>("MiniDisplay");
miniDisplay.RemoveFromHierarchy();
foldoutLabel.parent.Add(miniDisplay);
miniDisplay.styleSheets.Add(uss);
var isPrefixProp = root.Q<PropertyField>("isPrefix");
bool isPrefix = false;
Action evaluateMiniDisplay = () =>
{
miniDisplay.style.display = (isPrefix || foldout.value) ? DisplayStyle.None : DisplayStyle.Flex;
};
foldout.RegisterValueChangedCallback(evt => evaluateMiniDisplay());
isPrefixProp.RegisterValueChangeCallback(evt =>
{
var value = evt.changedProperty.boolValue;
if (value)
{
root.AddToClassList("ParameterConfig__isPrefix");
}
else
{
root.RemoveFromClassList("ParameterConfig__isPrefix");
}
isPrefix = value;
evaluateMiniDisplay();
});
var remapTo = root.Q<PropertyField>("remapTo");
var remapToPlaceholder = root.Q<TextField>("remapToPlaceholder");
remapToPlaceholder.SetEnabled(false);
remapToPlaceholder.labelElement.AddToClassList("ndmf-tr");
root.Q<PropertyField>("internalParameter").RegisterValueChangeCallback(evt =>
{
remapTo.style.display = evt.changedProperty.boolValue ? DisplayStyle.None : DisplayStyle.Flex;
remapToPlaceholder.style.display = evt.changedProperty.boolValue ? DisplayStyle.Flex : DisplayStyle.None;
});
return root;
}
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 633daf89a52e492a9b55aa31e60ec080
timeCreated: 1706005304

View File

@ -0,0 +1,28 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:engine="UnityEditor.UIElements" editor="UnityEditor.UIElements" ma="nadena.dev.modular_avatar.core.editor" editor-extension-mode="False">
<ui:VisualElement name="MiniDisplay">
<ui:Label text="merge_parameter.ui.defaultValue" class="ndmf-tr"/>
<ui:FloatField binding-path="defaultValue"/>
<ui:Label text="merge_parameter.ui.saved" class="ndmf-tr"/>
<ui:Toggle binding-path="saved"/>
</ui:VisualElement>
<ui:Foldout name="ParameterConfigRoot" text="(placeholder)" value="false">
<engine:PropertyField binding-path="nameOrPrefix" label="merge_parameter.ui.name" name="f-name" class="ndmf-tr ParameterConfig__isPrefix_falseOnly" />
<engine:PropertyField binding-path="nameOrPrefix" label="merge_parameter.ui.prefix" name="f-prefix" class="ndmf-tr ParameterConfig__isPrefix_trueOnly" />
<engine:PropertyField binding-path="remapTo" label="merge_parameter.ui.remapTo" name="remapTo" class="ndmf-tr" />
<ui:TextField label="##merge_parameter.ui.remapTo" text="merge_parameter.ui.remapTo.automatic" name="remapToPlaceholder" enabled="false" class="ndmf-tr unity-base-field__aligned" />
<engine:PropertyField binding-path="defaultValue" name="defaultValue" label="merge_parameter.ui.defaultValue" class="ndmf-tr ParameterConfig__isPrefix_falseOnly"/>
<engine:PropertyField binding-path="saved" label="merge_parameter.ui.saved" class="ndmf-tr ParameterConfig__isPrefix_falseOnly" />
<ui:Foldout text="merge_parameter.ui.details" class="ndmf-tr" value="false">
<engine:PropertyField binding-path="internalParameter" label="merge_parameter.ui.internalParameter" name="internalParameter" class="ndmf-tr" />
<engine:PropertyField binding-path="isPrefix" label="merge_parameter.ui.isPrefix" name="isPrefix" class="ndmf-tr" />
<engine:PropertyField binding-path="syncType" label="merge_parameter.ui.syncType" class="ParameterConfig__isPrefix_falseOnly ndmf-tr" />
<engine:PropertyField binding-path="localOnly" label="merge_parameter.ui.localOnly" class="ParameterConfig__isPrefix_falseOnly ndmf-tr" />
</ui:Foldout>
</ui:Foldout>
</ui:UXML>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bdea2a4cbb794433bdc6dd734e19d29c
timeCreated: 1706008148

View File

@ -0,0 +1,21 @@
#if MA_VRCSDK3_AVATARS
using System;
using UnityEditor;
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,
};
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4d7600669e964ade9c83db369a44e076
timeCreated: 1706008016

View File

@ -0,0 +1,90 @@
VisualElement {}
.ParameterConfig__isPrefix_falseOnly {
display: flex;
}
.ParameterConfig__isPrefix_trueOnly {
display: none;
}
.ParameterConfig__isPrefix .ParameterConfig__isPrefix_falseOnly {
display: none;
}
.ParameterConfig__isPrefix .ParameterConfig__isPrefix_trueOnly {
display: flex;
}
#defaultValueGroup {
display: flex;
flex-direction: row;
}
#defaultValueGroup > .unity-base-field__input {
flex-grow: 1;
}
#defaultValueGroup > .unity-base-field__input > * {
flex-grow: 1;
}
#MiniDisplay {
flex-direction: row;
align-self: flex-end;
}
#MiniDisplay > * {
align-self: center;
}
#MiniDisplay > FloatField {
max-width: 60px;
flex-grow: 0;
margin-right: 10px;
}
#MiniDisplay > FloatField TextElement {
margin-left: 0px;
}
#MiniDisplay > Toggle {
margin-right: 5px;
}
#ParameterConfigRoot > Toggle .unity-toggle__text {
flex-grow: 1;
}
#UnregisteredParameters #unity-list-view__footer {
display: none;
}
#UnregisteredParameters Label {
align-self: center;
}
.DetectedParameter {
flex-direction: row;
margin-top: 2px;
margin-bottom: 2px;
}
.DetectedParameter > Label {
flex-grow: 1;
}
.SourceButton {
flex-grow:0;
align-self: flex-end;
height: 24px;
width: 24px;
padding: 1px;
}
/* Vertically align the reorder handle with the foldout chevron */
#Parameters #unity-list-view__reorderable-handle {
padding-top: 0;
justify-content: center;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d72e507abb5be28499d149b3c22f80bc
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<UXML
xmlns:ui="UnityEngine.UIElements"
xmlns:editor="UnityEditor.UIElements"
xmlns:ma="nadena.dev.modular_avatar.core.editor"
>
<ui:VisualElement name="ListViewContainer">
<ui:ListView virtualization-method="DynamicHeight"
reorder-mode="Animated"
reorderable="true"
show-add-remove-footer="true"
show-border="true"
show-foldout-header="false"
name="Parameters"
item-height="100"
binding-path="parameters"
style="flex-grow: 1;"
/>
</ui:VisualElement>
<ui:Foldout text="merge_parameter.ui.unregistered_foldout" name="UnregisteredFoldout" value="false" class="ndmf-tr">
<!-- The show-add-remove-footer property here somehow also controls the background color
of the ListView UI (???). As such, we turn it on here, to get the right theme background color,
but then hide the actual footer in USS.
-->
<ui:ListView
reorderable="false"
show-add-remove-footer="true"
show-border="true"
show-foldout-header="false"
name="UnregisteredParameters"
style="flex-grow: 1;"
/>
</ui:Foldout>
<ma:LanguageSwitcherElement/>
</UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 00e4e2766c4ae9f4687e98ed34685b4f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -41,6 +41,7 @@ namespace nadena.dev.modular_avatar.core.editor
internal static string OverrideLanguage { get; set; } = null;
public static Localizer L { get; private set; }
public static UIElementLocalizer UI;
static Localization()
{
@ -57,6 +58,7 @@ namespace nadena.dev.modular_avatar.core.editor
});
L = localizer;
UI = new UIElementLocalizer(L);
LanguagePrefs.RegisterLanguageChangeCallback(typeof(Localization), _ => OnLangChange?.Invoke());
}

View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using nadena.dev.ndmf.localization;
using UnityEngine.UIElements;
namespace nadena.dev.modular_avatar.core.editor
{
internal class UIElementLocalizer
{
private static Dictionary<Type, Func<VisualElement, Action>> _localizers =
new Dictionary<Type, Func<VisualElement, Action>>();
private readonly Localizer _localizer;
public UIElementLocalizer(Localizer localizer)
{
_localizer = localizer;
}
internal void Localize(VisualElement elem)
{
WalkTree(elem);
}
private void WalkTree(VisualElement elem)
{
var ty = elem.GetType();
if (elem.ClassListContains("ndmf-tr"))
{
var op = GetLocalizationOperation(ty);
if (op != null)
{
var action = op(elem);
LanguagePrefs.RegisterLanguageChangeCallback(elem, _elem => action());
action();
}
}
foreach (var child in elem.Children())
{
WalkTree(child);
}
}
private Func<VisualElement, Action> GetLocalizationOperation(Type ty)
{
if (!_localizers.TryGetValue(ty, out var action))
{
PropertyInfo m_label = ty.GetProperty("text") ?? ty.GetProperty("label");
if (m_label == null)
{
action = null;
}
else
{
action = elem =>
{
var key = m_label.GetValue(elem) as string;
if (key != null)
{
return () =>
{
var new_label = _localizer.GetLocalizedString(key);
if (!_localizer.TryGetLocalizedString(key + ":tooltip", out var tooltip))
{
tooltip = null;
}
m_label.SetValue(elem, new_label);
elem.tooltip = tooltip;
};
}
else
{
return () => { };
}
};
}
_localizers[ty] = action;
}
return action;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 37429a0f4f1d4d6e9dc4b27577082ed1
timeCreated: 1706179997

View File

@ -14,6 +14,13 @@
"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.syncmode.NotSynced": "Animator Only",
"params.syncmode.Int": "Int",
"params.syncmode.Float": "Float",
"params.syncmode.Bool": "Bool",
"params.__comment__": "=== Unity 2019 only strings ===",
"params.autodetect_header": " Autodetected Parameters ",
"params.internal": "Internal",
"params.pb_prefix": "PhysBones Prefix",
@ -25,10 +32,26 @@
"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",
"params.__comment1__": "=== Unity 2022 only strings ===",
"merge_parameter.ui.name": "Parameter name",
"merge_parameter.ui.prefix": "PhysBone prefix name",
"merge_parameter.ui.remapTo": "Change name to",
"merge_parameter.ui.remapTo.tooltip": "Enter a new name here to rename this parameter or prefix. This can be used to resolve name conflicts, or to link up multiple gimmicks.",
"merge_parameter.ui.defaultValue": "Default",
"merge_parameter.ui.defaultValue.tooltip": "This parameter will be set to this value when the avatar is reset or initially worn",
"merge_parameter.ui.saved": "Saved",
"merge_parameter.ui.saved.tooltip": "If set, this parameter's value will be saved when you change avatars or worlds",
"merge_parameter.ui.internalParameter": "Auto Rename",
"merge_parameter.ui.internalParameter.tooltip": "If set, this parameter will be automatically renamed to avoid conflicts with other parameters",
"merge_parameter.ui.isPrefix": "Is PhysBone Prefix",
"merge_parameter.ui.syncType": "Parameter type",
"merge_parameter.ui.localOnly": "Local Only",
"merge_parameter.ui.localOnly.tooltip": "If set, this parameter will not be synced across the network",
"merge_parameter.ui.unregistered_foldout": "Unregistered Parameters",
"merge_parameter.ui.add_button": "Add",
"merge_parameter.ui.details": "Parameter Configuration",
"merge_armature.merge_target": "Merge Target",
"merge_armature.merge_target.tooltip": "The armature (or subtree) to merge this object into",
"merge_armature.prefix": "Prefix",

View File

@ -13,6 +13,13 @@
"menuinstall.menu_icon_too_large": "メニューに設定されているアイコンが256ピクセルより大きすぎます。",
"menuinstall.menu_icon_uncompressed": "メニューに設定されているアイコンが圧縮設定されていません。",
"menuinstall.srcmenu": "インストールされるメニュー",
"params.syncmode.NotSynced": "Animatorのみ",
"params.syncmode.Int": "Int",
"params.syncmode.Float": "Float",
"params.syncmode.Bool": "Bool",
"params.__comment__": "=== Unity 2019 only strings ===",
"params.autodetect_header": " 自動検出されたパラメーター ",
"params.internal": "内部値",
"params.pb_prefix": "PhysBones前置詞",
@ -24,10 +31,26 @@
"params.remapto": "変更後の名前",
"params.remapto.tooltip": "ここに新しい名前を入れることで、名前かぶりを解消できます",
"params.devmode": "プレハブ開発者向け設定を表示",
"params.syncmode.NotSynced": "Animatorのみ",
"params.syncmode.Int": "Int",
"params.syncmode.Float": "Float",
"params.syncmode.Bool": "Bool",
"params.__comment1__": "=== Unity 2022 only strings ===",
"merge_parameter.ui.name": "パラメーター名",
"merge_parameter.ui.prefix": "PhysBone 前置詞名",
"merge_parameter.ui.remapTo": "名前を変更",
"merge_parameter.ui.remapTo.tooltip": "ここに新しい名前を入れることで、このパラメーターの名前を変更できます。これで名前かぶりを回避したり、あるいはあえて複数のギミックを連動できます。",
"merge_parameter.ui.defaultValue": "初期値",
"merge_parameter.ui.defaultValue.tooltip": "アバターがリセット、または最初に着た時にこの値が採用されます。",
"merge_parameter.ui.saved": "保存する",
"merge_parameter.ui.saved.tooltip": "保存されたパラメーターは、アバター変更やワールド移動で保持されます",
"merge_parameter.ui.internalParameter": "自動リネーム",
"merge_parameter.ui.internalParameter.tooltip": "有効にすると、名前かぶりを回避するために自動的に名前を変更します",
"merge_parameter.ui.isPrefix": "PhysBone 前置詞名",
"merge_parameter.ui.syncType": "パラメーター型",
"merge_parameter.ui.localOnly": "ローカルのみ",
"merge_parameter.ui.localOnly.tooltip": "有効にすると、ネットワーク上同期されなくなります",
"merge_parameter.ui.unregistered_foldout": "未登録パラメーター",
"merge_parameter.ui.add_button": "追加",
"merge_parameter.ui.details": "パラメーターの詳細設定",
"merge_armature.merge_target": "統合先",
"merge_armature.merge_target.tooltip": "このオブジェクトを統合先のアーマチュアに統合します",
"merge_armature.prefix": "前置詞",

View File

@ -3,8 +3,10 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Serialization;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects;
using VRC.SDK3.Dynamics.Contact.Components;
@ -20,6 +22,8 @@ namespace nadena.dev.modular_avatar.core.editor
public float defaultValue;
public bool saved;
[FormerlySerializedAs("source")] public Object Source;
public string MapKey => IsPrefix ? OriginalName + "*" : OriginalName;
}
@ -96,6 +100,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
OriginalName = bone.parameter,
IsPrefix = true,
Source = bone,
};
parameters[param.MapKey] = param;
@ -112,6 +117,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
OriginalName = contact.parameter,
IsPrefix = false,
Source = contact,
};
parameters[param.MapKey] = param;
@ -169,7 +175,8 @@ namespace nadena.dev.modular_avatar.core.editor
var param = new DetectedParameter()
{
OriginalName = name,
IsPrefix = false
IsPrefix = false,
Source = menu,
};
parameters[param.MapKey] = param;
}
@ -271,7 +278,8 @@ namespace nadena.dev.modular_avatar.core.editor
var param = new DetectedParameter()
{
OriginalName = parameterName,
IsPrefix = false
IsPrefix = false,
Source = controller
};
parameters[param.MapKey] = param;
}
@ -318,6 +326,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
IsPrefix = false,
OriginalName = name,
Source = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GetAssetPath(blendTree))
});
}
}
@ -343,6 +352,7 @@ namespace nadena.dev.modular_avatar.core.editor
syncType = map.syncType,
defaultValue = map.defaultValue,
saved = map.saved,
Source = parametersComponent,
};
newParams[param.MapKey] = param;
continue;

View File

@ -14,6 +14,7 @@ namespace nadena.dev.modular_avatar.core
public bool localOnly;
public float defaultValue;
public bool saved;
public bool? hasDefaultValue;
}
/**