mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-04-12 23:48:59 +08:00
Merge branch 'main' into enhance_a-t_pose_conversion
This commit is contained in:
commit
dcf1151276
2
.github/ProjectRoot/vpm-manifest-2022.json
vendored
2
.github/ProjectRoot/vpm-manifest-2022.json
vendored
@ -19,7 +19,7 @@
|
|||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
},
|
},
|
||||||
"nadena.dev.ndmf": {
|
"nadena.dev.ndmf": {
|
||||||
"version": "1.5.0-rc.7"
|
"version": "1.5.0-rc.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,7 +42,9 @@ namespace nadena.dev.modular_avatar.animation
|
|||||||
throw new Exception("Unknown RuntimeAnimatorContoller type " + controller.GetType());
|
throw new Exception("Unknown RuntimeAnimatorContoller type " + controller.GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
return merger.Finish();
|
var clone = merger.Finish();
|
||||||
|
ObjectRegistry.RegisterReplacedObject(controller, clone);
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void CloneAllControllers(BuildContext context)
|
internal static void CloneAllControllers(BuildContext context)
|
||||||
|
@ -95,7 +95,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var t = (ModularAvatarBoneProxy) targets[i];
|
var t = (ModularAvatarBoneProxy) targets[i];
|
||||||
Undo.RecordObjects(targets, "Set targets");
|
Undo.RecordObjects(targets, "Set targets");
|
||||||
var xform = ((TempObjRef) objRefs[i]).target;
|
var xform = ((TempObjRef) objRefs[i]).target;
|
||||||
if (RuntimeUtil.FindAvatarTransformInParents(xform)?.gameObject != parentAvatar) continue;
|
if (xform != null && RuntimeUtil.FindAvatarTransformInParents(xform)?.gameObject != parentAvatar) continue;
|
||||||
t.target = xform;
|
t.target = xform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
case VisibleHeadAccessoryValidation.ReadyStatus.ParentMarked:
|
case VisibleHeadAccessoryValidation.ReadyStatus.ParentMarked:
|
||||||
EditorGUILayout.HelpBox(Localization.S("fpvisible.normal"), MessageType.Info);
|
EditorGUILayout.HelpBox(Localization.S("fpvisible.normal"), MessageType.Info);
|
||||||
break;
|
break;
|
||||||
|
case VisibleHeadAccessoryValidation.ReadyStatus.NotUnderHead:
|
||||||
|
EditorGUILayout.HelpBox(Localization.S("fpvisible.NotUnderHead"), MessageType.Warning);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
var label = "fpvisible." + status;
|
var label = "fpvisible." + status;
|
||||||
|
@ -18,7 +18,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
return (EditorStyles.label?.lineHeight ?? 0) * 3;
|
return (EditorStyles.label?.lineHeight ?? 0) * 3;
|
||||||
}
|
}
|
||||||
catch (NullReferenceException e)
|
catch (NullReferenceException)
|
||||||
{
|
{
|
||||||
// This can happen in early initialization...
|
// This can happen in early initialization...
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.UIElements;
|
using UnityEditor.UIElements;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -148,7 +147,7 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
|
|||||||
{
|
{
|
||||||
return targetObject?.GetComponent<Renderer>()?.sharedMaterials;
|
return targetObject?.GetComponent<Renderer>()?.sharedMaterials;
|
||||||
}
|
}
|
||||||
catch (MissingComponentException e)
|
catch (MissingComponentException)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,11 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
internal static class ParameterIntrospectionCache
|
internal static class ParameterIntrospectionCache
|
||||||
{
|
{
|
||||||
internal static PropCache<GameObject, ImmutableList<ProvidedParameter>> ProvidedParameterCache = new (GetParametersForObject_miss);
|
internal static PropCache<GameObject, ImmutableList<ProvidedParameter>> ProvidedParameterCache =
|
||||||
|
new("GetParametersForObject", GetParametersForObject_miss);
|
||||||
|
|
||||||
internal static PropCache<GameObject, ImmutableDictionary<(ParameterNamespace, string), ParameterMapping>>
|
internal static PropCache<GameObject, ImmutableDictionary<(ParameterNamespace, string), ParameterMapping>>
|
||||||
ParameterRemappingCache = new(GetParameterRemappingsAt_miss);
|
ParameterRemappingCache = new("GetParameterRemappingsAt", GetParameterRemappingsAt_miss);
|
||||||
|
|
||||||
private static ImmutableList<ProvidedParameter> GetParametersForObject_miss(ComputeContext ctx, GameObject obj)
|
private static ImmutableList<ProvidedParameter> GetParametersForObject_miss(ComputeContext ctx, GameObject obj)
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
createInstaller = false;
|
createInstaller = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (MissingComponentException e)
|
catch (MissingComponentException)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var grouped = ctx.Observe(target,
|
var grouped = ctx.Observe(target,
|
||||||
t => (t.GroupedBones ?? Array.Empty<GameObject>())
|
t => (t.GroupedBones ?? Array.Empty<GameObject>())
|
||||||
.Select(obj => obj.transform)
|
.Select(obj => obj.transform)
|
||||||
.ToHashSet(new ObjectIdentityComparer<Transform>()),
|
.ToHashSet(),
|
||||||
(x, y) => x.SetEquals(y)
|
(x, y) => x.SetEquals(y)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
|
|||||||
.Select(x => mesh.GetBlendShapeName(x))
|
.Select(x => mesh.GetBlendShapeName(x))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
catch (MissingComponentException e)
|
catch (MissingComponentException)
|
||||||
{
|
{
|
||||||
shapeNames = null;
|
shapeNames = null;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
"worldfixed.quest": "This component is not compatible with Android builds and will have no effect.",
|
"worldfixed.quest": "This component is not compatible with Android builds and will have no effect.",
|
||||||
"worldfixed.normal": "This object will be fixed to world unless you fixed to avatar with constraint.",
|
"worldfixed.normal": "This object will be fixed to world unless you fixed to avatar with constraint.",
|
||||||
"fpvisible.normal": "This object will be visible in your first person view.",
|
"fpvisible.normal": "This object will be visible in your first person view.",
|
||||||
"fpvisible.NotUnderHead": "This component has no effect when not placed under the head bone.",
|
"fpvisible.NotUnderHead": "This component has no effect when not placed under the head bone.\nIf this will be placed under the head bone through Bone Proxy etc., this warning can be ignored.",
|
||||||
"fpvisible.quest": "This component is not compatible with Android builds and will have no effect.",
|
"fpvisible.quest": "This component is not compatible with Android builds and will have no effect.",
|
||||||
"fpvisible.InPhysBoneChain": "This object is controlled by a Physics Bone chain and cannot be made visible in first person safely. Select the start of the chain instead.",
|
"fpvisible.InPhysBoneChain": "This object is controlled by a Physics Bone chain and cannot be made visible in first person safely. Select the start of the chain instead.",
|
||||||
"blendshape.mesh": "Mesh",
|
"blendshape.mesh": "Mesh",
|
||||||
@ -241,7 +241,7 @@
|
|||||||
"setup_outfit.err.no_avatar_descriptor": "No avatar descriptor found in {0}'s parents. Make sure your outfit is placed inside your avatar.",
|
"setup_outfit.err.no_avatar_descriptor": "No avatar descriptor found in {0}'s parents. Make sure your outfit is placed inside your avatar.",
|
||||||
"setup_outfit.err.no_animator": "Your avatar does not have an Animator component.",
|
"setup_outfit.err.no_animator": "Your avatar does not have an Animator component.",
|
||||||
"setup_outfit.err.no_hips": "Your avatar does not have a Hips bone. Setup Outfit only works on humanoid avatars.",
|
"setup_outfit.err.no_hips": "Your avatar does not have a Hips bone. Setup Outfit only works on humanoid avatars.",
|
||||||
"setup_outfit.err.no_outfit_hips": "Unable to identify the Hips object for the outfit. Searched for objects containing the following names:",
|
"setup_outfit.err.no_outfit_hips": "Unable to identify the Hips object for the outfit. Searched for objects containing the following names(case-insensitive):",
|
||||||
"move_independently.group-header": "Objects to move together",
|
"move_independently.group-header": "Objects to move together",
|
||||||
"scale_adjuster.scale": "Scale adjustment",
|
"scale_adjuster.scale": "Scale adjustment",
|
||||||
"scale_adjuster.adjust_children": "Adjust position of child objects",
|
"scale_adjuster.adjust_children": "Adjust position of child objects",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"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": "メニューに設定されているアイコンが256x256より大きいです。",
|
||||||
"menuinstall.menu_icon_uncompressed": "メニューに設定されているアイコンが圧縮設定されていません。",
|
"menuinstall.menu_icon_uncompressed": "メニューに設定されているアイコンが圧縮設定されていません。",
|
||||||
"menuinstall.srcmenu": "インストールされるメニュー",
|
"menuinstall.srcmenu": "インストールされるメニュー",
|
||||||
"params.syncmode.NotSynced": "Animatorのみ",
|
"params.syncmode.NotSynced": "Animatorのみ",
|
||||||
@ -31,32 +31,32 @@
|
|||||||
"merge_parameter.ui.name": "パラメーター名",
|
"merge_parameter.ui.name": "パラメーター名",
|
||||||
"merge_parameter.ui.prefix": "PhysBone 接頭辞",
|
"merge_parameter.ui.prefix": "PhysBone 接頭辞",
|
||||||
"merge_parameter.ui.remapTo": "名前を変更",
|
"merge_parameter.ui.remapTo": "名前を変更",
|
||||||
"merge_parameter.ui.remapTo.tooltip": "ここに新しい名前を入れることで、このパラメーターの名前を変更できます。これで名前かぶりを回避したり、あるいはあえて複数のギミックを連動できます。",
|
"merge_parameter.ui.remapTo.tooltip": "ここに新しい名前を入れることで、このパラメーターの名前を変更できます。これで名前かぶりを回避したり、複数のギミックを連動させたりすることができます。",
|
||||||
"merge_parameter.ui.remapTo.automatic": "(自動的に設定)",
|
"merge_parameter.ui.remapTo.automatic": "(自動的に設定)",
|
||||||
"merge_parameter.ui.defaultValue": "初期値",
|
"merge_parameter.ui.defaultValue": "初期値",
|
||||||
"merge_parameter.ui.defaultValue.tooltip": "アバターがリセット、または最初に着た時にこの値が採用されます。",
|
"merge_parameter.ui.defaultValue.tooltip": "アバターをリセットした時、または最初に着た時にこの値が採用されます。",
|
||||||
"merge_parameter.ui.saved": "保存する",
|
"merge_parameter.ui.saved": "保存する",
|
||||||
"merge_parameter.ui.saved.tooltip": "保存されたパラメーターは、アバター変更やワールド移動で保持されます",
|
"merge_parameter.ui.saved.tooltip": "保存されたパラメーターは、アバター変更やワールド移動をしても保持されます",
|
||||||
"merge_parameter.ui.internalParameter": "自動リネーム",
|
"merge_parameter.ui.internalParameter": "自動リネーム",
|
||||||
"merge_parameter.ui.internalParameter.tooltip": "有効にすると、名前かぶりを回避するために自動的に名前を変更します",
|
"merge_parameter.ui.internalParameter.tooltip": "有効にすると、名前かぶりを回避するために自動的に名前を変更します",
|
||||||
"merge_parameter.ui.isPrefix": "PhysBone 接頭辞",
|
"merge_parameter.ui.isPrefix": "PhysBone 接頭辞",
|
||||||
"merge_parameter.ui.syncType": "パラメーター型",
|
"merge_parameter.ui.syncType": "パラメーター型",
|
||||||
"merge_parameter.ui.synced": "同期する",
|
"merge_parameter.ui.synced": "同期する",
|
||||||
"merge_parameter.ui.synced.tooltip": "有効にすると、ネットワーク上同期されます",
|
"merge_parameter.ui.synced.tooltip": "有効にすると、このパラメーターは同期されます",
|
||||||
"merge_parameter.ui.unregistered_foldout": "未登録パラメーター",
|
"merge_parameter.ui.unregistered_foldout": "未登録パラメーター",
|
||||||
"merge_parameter.ui.add_button": "追加",
|
"merge_parameter.ui.add_button": "追加",
|
||||||
"merge_parameter.ui.details": "パラメーターの詳細設定",
|
"merge_parameter.ui.details": "パラメーターの詳細設定",
|
||||||
"merge_parameter.ui.overrideAnimatorDefaults": "アニメーターの初期値を設定",
|
"merge_parameter.ui.overrideAnimatorDefaults": "アニメーターでの初期値を設定",
|
||||||
"merge_armature.merge_target": "統合先",
|
"merge_armature.merge_target": "統合先",
|
||||||
"merge_armature.merge_target.tooltip": "このオブジェクトを統合先のアーマチュアに統合します",
|
"merge_armature.merge_target.tooltip": "このオブジェクトを統合先のアーマチュアに統合します",
|
||||||
"merge_armature.prefix": "接頭辞",
|
"merge_armature.prefix": "接頭辞",
|
||||||
"merge_armature.prefix.tooltip": "マージするボーンに付いている接頭辞",
|
"merge_armature.prefix.tooltip": "統合されるボーンに付いている接頭辞",
|
||||||
"merge_armature.suffix": "接尾辞",
|
"merge_armature.suffix": "接尾辞",
|
||||||
"merge_armature.suffix.tooltip": "マージするボーンに付いている接尾辞",
|
"merge_armature.suffix.tooltip": "統合されるボーンに付いている接尾辞",
|
||||||
"merge_armature.locked": "位置を固定",
|
"merge_armature.locked": "位置を固定",
|
||||||
"merge_armature.locked.tooltip": "このオブジェクトのボーンを統合先のボーンに常に相互的に位置を合わせる。アニメーション制作向け",
|
"merge_armature.locked.tooltip": "このオブジェクトのボーンと統合先のボーンの位置を常に合わせます。アニメーション作成時に便利です。",
|
||||||
"merge_armature.adjust_names": "ボーン名を統合先に合わせる",
|
"merge_armature.adjust_names": "ボーン名を統合先に合わせる",
|
||||||
"merge_armature.adjust_names.tooltip": "統合先のボーン名に合わせて、衣装のボーン名を合わせて変更します。統合先アバターに非対応の衣装導入向け機能です。",
|
"merge_armature.adjust_names.tooltip": "衣装のボーン名をアバターのボーン名に合わせて変更します。アバターに非対応の衣装を導入する時に便利です。",
|
||||||
"merge_armature.mangle_names": "名前かぶりを回避",
|
"merge_armature.mangle_names": "名前かぶりを回避",
|
||||||
"merge_armature.mangle_names.tooltip": "ほかのアセットとの名前かぶりを裂けるため、新規ボーンの名前を自動で変更する",
|
"merge_armature.mangle_names.tooltip": "ほかのアセットとの名前かぶりを裂けるため、新規ボーンの名前を自動で変更する",
|
||||||
"path_mode.Relative": "相対的(このオブジェクトからのパスを使用)",
|
"path_mode.Relative": "相対的(このオブジェクトからのパスを使用)",
|
||||||
@ -66,12 +66,12 @@
|
|||||||
"merge_animator.delete_attached_animator": "付属アニメーターを削除",
|
"merge_animator.delete_attached_animator": "付属アニメーターを削除",
|
||||||
"merge_animator.delete_attached_animator.tooltip": "統合後、このオブジェクトについているアニメーターを削除します",
|
"merge_animator.delete_attached_animator.tooltip": "統合後、このオブジェクトについているアニメーターを削除します",
|
||||||
"merge_animator.path_mode": "パスモード",
|
"merge_animator.path_mode": "パスモード",
|
||||||
"merge_animator.path_mode.tooltip": "アニメーション内のパスを解釈するモード。相対的にすると、このオブジェクトについているアニメーターでアニメーション編集できます",
|
"merge_animator.path_mode.tooltip": "アニメーション内のパスを解釈するモード。相対的にすると、このオブジェクトにつけたアニメーターでアニメーションを編集することができます。",
|
||||||
"merge_animator.match_avatar_write_defaults": "アバターのWrite Defaults設定に合わせる",
|
"merge_animator.match_avatar_write_defaults": "アバターのWrite Defaults設定に合わせる",
|
||||||
"merge_animator.match_avatar_write_defaults.tooltip": "アバターの該当アニメーターのWrite Defaults設定に合わせます。アバター側の設定が矛盾する場合は、統合されるアニメーターのWD値がそのまま採用されます。",
|
"merge_animator.match_avatar_write_defaults.tooltip": "アバターの該当アニメーターのWrite Defaults設定に合わせます。アバター側の設定が矛盾する場合は、統合されるアニメーターのWD値がそのまま採用されます。",
|
||||||
"merge_animator.relative_path_root": "相対的パスのルート",
|
"merge_animator.relative_path_root": "相対的パスのルート",
|
||||||
"merge_animator.relative_path_root.tooltip": "相対的パスはこのオブジェクトを基準に解釈されます。指定がない場合は、このコンポーネントがついているオブジェクトを基準とします。",
|
"merge_animator.relative_path_root.tooltip": "相対的パスはこのオブジェクトを基準に解釈されます。指定がない場合は、このコンポーネントがついているオブジェクトを基準とします。",
|
||||||
"merge_animator.layer_priority": "レイヤー優先度",
|
"merge_animator.layer_priority": "レイヤー統合優先度",
|
||||||
"merge_animator.layer_priority.tooltip": "アニメーターにレイヤーが統合される順番を制御します。低い値から高い値の順に統合されます。マイナスの場合は元々のAvatar Descriptorについているコントローラーより前に統合され、ゼロ以上の場合はそのあとに統合されます。",
|
"merge_animator.layer_priority.tooltip": "アニメーターにレイヤーが統合される順番を制御します。低い値から高い値の順に統合されます。マイナスの場合は元々のAvatar Descriptorについているコントローラーより前に統合され、ゼロ以上の場合はそのあとに統合されます。",
|
||||||
"merge_armature.lockmode": "位置追従モード",
|
"merge_armature.lockmode": "位置追従モード",
|
||||||
"merge_armature.lockmode.not_locked.title": "追従なし",
|
"merge_armature.lockmode.not_locked.title": "追従なし",
|
||||||
@ -81,29 +81,29 @@
|
|||||||
"merge_armature.lockmode.bidirectional.title": "アバター <=====> オブジェクト (双方向)",
|
"merge_armature.lockmode.bidirectional.title": "アバター <=====> オブジェクト (双方向)",
|
||||||
"merge_armature.lockmode.bidirectional.body": "アバターと統合されるアーマチュアは常に同じ位置になります。元のアバターを操作するアニメーションを作る時に便利かもしれません。有効にするためには、統合されるアーマチュアの位置を統合先と同じにしておく必要があります。",
|
"merge_armature.lockmode.bidirectional.body": "アバターと統合されるアーマチュアは常に同じ位置になります。元のアバターを操作するアニメーションを作る時に便利かもしれません。有効にするためには、統合されるアーマチュアの位置を統合先と同じにしておく必要があります。",
|
||||||
"merge_armature.reset_pos": "位置を元アバターに合わせてリセット",
|
"merge_armature.reset_pos": "位置を元アバターに合わせてリセット",
|
||||||
"merge_armature.reset_pos.info": "このコマンドは、衣装のボーンの位置をアバターのボーンの位置に合わせます。非対応衣装を導入するとき、アバウトに合わせるために便利です。",
|
"merge_armature.reset_pos.info": "衣装のボーンの位置をアバターのボーンの位置に合わせます。非対応衣装を導入する際、アバウトに位置を合わせるのに便利です。",
|
||||||
"merge_armature.reset_pos.convert_atpose": "Aポーズ/Tポーズを合わせる",
|
"merge_armature.reset_pos.convert_atpose": "Aポーズ/Tポーズを合わせる",
|
||||||
"merge_armature.reset_pos.adjust_rotation": "回転も合わせる",
|
"merge_armature.reset_pos.adjust_rotation": "回転も合わせる",
|
||||||
"merge_armature.reset_pos.adjust_scale": "スケールも合わせる",
|
"merge_armature.reset_pos.adjust_scale": "スケールも合わせる",
|
||||||
"merge_armature.reset_pos.execute": "実行",
|
"merge_armature.reset_pos.execute": "実行",
|
||||||
"merge_armature.reset_pos.heuristic_scale": "衣装の全体的なスケールをアバターに合わせる",
|
"merge_armature.reset_pos.heuristic_scale": "衣装の全体的なスケールをアバターに合わせる",
|
||||||
"merge_armature.reset_pos.heuristic_scale.tooltip": "腕の長さを参考に、衣装全体のスケールをアバターに合わせます。非対応衣装を導入するときは推奨です。",
|
"merge_armature.reset_pos.heuristic_scale.tooltip": "腕の長さを参考に、衣装全体のスケールをアバターに合わせます。非対応衣装を導入する時にお勧めです。",
|
||||||
"merge_blend_tree.blend_tree": "ブレンドツリー",
|
"merge_blend_tree.blend_tree": "ブレンドツリー",
|
||||||
"merge_blend_tree.path_mode": "パスモード",
|
"merge_blend_tree.path_mode": "パスモード",
|
||||||
"merge_blend_tree.path_mode.tooltip": "アニメーション内のパスを解釈するモード。相対的にすると、このオブジェクトについているアニメーターでアニメーション編集できます",
|
"merge_blend_tree.path_mode.tooltip": "アニメーション内のパスを解釈するモード。相対的にすると、このオブジェクトにつけたアニメーターでアニメーションを編集することができます。",
|
||||||
"merge_blend_tree.relative_path_root": "相対的パスのルート",
|
"merge_blend_tree.relative_path_root": "相対的パスのルート",
|
||||||
"merge_blend_tree.relative_path_root.tooltip": "相対的パスはこのオブジェクトを基準に解釈されます。指定がない場合は、このコンポーネントがついているオブジェクトを基準とします。",
|
"merge_blend_tree.relative_path_root.tooltip": "相対的パスはこのオブジェクトを基準に解釈されます。指定がない場合は、このコンポーネントがついているオブジェクトを基準とします。",
|
||||||
"worldfixed.quest": "このコンポーネントはアンドロイドビルド非対応のため無効となっています。",
|
"worldfixed.quest": "このコンポーネントはアンドロイドビルドに非対応であるため、無効となっています。",
|
||||||
"worldfixed.normal": "このオブジェクトはConstraint等でアバターに追従させない限りワールドに固定されます。",
|
"worldfixed.normal": "このオブジェクトはConstraint等でアバターに追従させない限りワールドに固定されます。",
|
||||||
"fpvisible.normal": "このオブジェクトは一人視点で表示されます。",
|
"fpvisible.normal": "このオブジェクトは一人称視点で表示されます。",
|
||||||
"fpvisible.NotUnderHead": "このコンポーネントはヘッドボーン外では効果がありません。",
|
"fpvisible.NotUnderHead": "このコンポーネントは頭ボーンの配下でないと効果がありません。\n(Bone Proxyなどで頭ボーンの配下に配置される場合は効果あります)",
|
||||||
"fpvisible.quest": "このコンポーネントはアンドロイドビルド非対応のため無効となっています。",
|
"fpvisible.quest": "このコンポーネントはアンドロイドビルドに非対応であるため、無効となっています。",
|
||||||
"fpvisible.InPhysBoneChain": "このオブジェクトはPhysBoneに制御されているため、一人視点で表示できません。PhysBoneの始点を指定してください。",
|
"fpvisible.InPhysBoneChain": "このオブジェクトはPhysBoneで制御されているため、一人称視点でうまく表示させることができません。PhysBoneの始点を指定してください。",
|
||||||
"blendshape.mesh": "メッシュ",
|
"blendshape.mesh": "メッシュ",
|
||||||
"blendshape.source": "元メッシュのブレンドシェープ",
|
"blendshape.source": "元メッシュのブレンドシェイプ",
|
||||||
"blendshape.target": "このメッシュのブレンドシェープ",
|
"blendshape.target": "このメッシュのブレンドシェイプ",
|
||||||
"hint.not_in_avatar": "このコンポーネントが正しく動作するには、アバター内に配置する必要があります。",
|
"hint.not_in_avatar": "このコンポーネントを正しく動作させるには、アバター内に配置する必要があります。",
|
||||||
"boneproxy.err.MovingTarget": "他のモジュラーアバターコンポーネントで移動されるオブジェクトを指定できません。",
|
"boneproxy.err.MovingTarget": "他のモジュラーアバターコンポーネントで移動されるオブジェクトは指定できません。",
|
||||||
"boneproxy.err.NotInAvatar": "アバター内のオブジェクトを指定してください。",
|
"boneproxy.err.NotInAvatar": "アバター内のオブジェクトを指定してください。",
|
||||||
"boneproxy.attachment": "配置モード",
|
"boneproxy.attachment": "配置モード",
|
||||||
"boneproxy.attachment.AsChildAtRoot": "子として・ルートに配置",
|
"boneproxy.attachment.AsChildAtRoot": "子として・ルートに配置",
|
||||||
@ -112,28 +112,28 @@
|
|||||||
"boneproxy.attachment.AsChildKeepRotation": "子として・ワールド向きを維持",
|
"boneproxy.attachment.AsChildKeepRotation": "子として・ワールド向きを維持",
|
||||||
"mesh_settings.header_probe_anchor": "Anchor Override 設定",
|
"mesh_settings.header_probe_anchor": "Anchor Override 設定",
|
||||||
"mesh_settings.inherit_probe_anchor": "設定モード",
|
"mesh_settings.inherit_probe_anchor": "設定モード",
|
||||||
"mesh_settings.probe_anchor": "アンカーオーバーライド",
|
"mesh_settings.probe_anchor": "Anchor Override",
|
||||||
"mesh_settings.probe_anchor.tooltip": "このオブジェクトとその子のレンダラーのAnchor Overrideを設定します。",
|
"mesh_settings.probe_anchor.tooltip": "このオブジェクトとその子のレンダラーのAnchor Overrideを設定します。",
|
||||||
"mesh_settings.header_bounds": "Bounds 設定",
|
"mesh_settings.header_bounds": "Bounds 設定",
|
||||||
"mesh_settings.inherit_bounds": "設定モード",
|
"mesh_settings.inherit_bounds": "設定モード",
|
||||||
"mesh_settings.root_bone": "ルートボーン",
|
"mesh_settings.root_bone": "ルートボーン",
|
||||||
"mesh_settings.root_bone.tooltip": "このオブジェクトとその子のメッシュで設定されるルートボーン。メッシュのバウンズを計算するための参照点として使用されます。",
|
"mesh_settings.root_bone.tooltip": "このオブジェクトとその子のメッシュで設定されるルートボーン。メッシュのBoundsを計算する際の基準として使用されます。",
|
||||||
"mesh_settings.bounds": "バウンズ",
|
"mesh_settings.bounds": "Bounds",
|
||||||
"mesh_settings.bounds.tooltip": "このオブジェクトとその子のメッシュで設定されるバウンズ。画面外のメッシュのレンダリングを省略するかどうかを決定するために使用されます。",
|
"mesh_settings.bounds.tooltip": "このオブジェクトとその子のメッシュで設定されるバウンズ。画面外のメッシュのレンダリングを省略するかどうかを決定するために使用されます。",
|
||||||
"mesh_settings.inherit_mode.Inherit": "継承",
|
"mesh_settings.inherit_mode.Inherit": "継承",
|
||||||
"mesh_settings.inherit_mode.Set": "設定",
|
"mesh_settings.inherit_mode.Set": "設定",
|
||||||
"mesh_settings.inherit_mode.DontSet": "設定しない(メッシュ本体の設定のまま)",
|
"mesh_settings.inherit_mode.DontSet": "設定しない(メッシュ本体の設定のまま)",
|
||||||
"mesh_settings.inherit_mode.SetOrInherit": "親が指定されてる時は継承、または設定",
|
"mesh_settings.inherit_mode.SetOrInherit": "親で指定されている時は継承、それ以外では設定",
|
||||||
"pb_blocker.help": "このオブジェクトは親のPhysBoneから影響を受けなくなります。",
|
"pb_blocker.help": "このオブジェクトは親のPhysBoneから影響を受けなくなります。",
|
||||||
"hint.bad_vrcsdk": "使用中のVRCSDKのバージョンとは互換性がありません。\n\nVRCSDKを更新してみてください。それでもだめでしたら、Modular Avatarにも最新版が出てないかチェックしてください。",
|
"hint.bad_vrcsdk": "使用中のVRCSDKのバージョンとは互換性がありません。\n\nVRCSDKを更新してみてください。それでも駄目な場合、Modular Avatarにも最新版が出ていないか確認してみてください。",
|
||||||
"error.stack_trace": "スタックトレース(バグを報告する時は必ず添付してください!)",
|
"error.stack_trace": "スタックトレース(バグを報告する時は必ず添付してください!)",
|
||||||
"error.merge_armature.circular_dependency": "[MA-0001] Merge Armatureに循環参照があります",
|
"error.merge_armature.circular_dependency": "[MA-0001] Merge Armatureに循環参照があります",
|
||||||
"error.merge_armature.circular_dependency:description": "Merge Armature コンポーネントは、自分自身、または自分の子をマージターゲットとして参照しています。",
|
"error.merge_armature.circular_dependency:description": "Merge Armatureコンポーネントの統合先として、自分自身、または自分の子が参照されています。",
|
||||||
"error.merge_armature.circular_dependency:hint": "Merge Armature は通常、ターゲットフィールドにアバター本体の Armature オブジェクトを指定する必要があります。衣装自体を指定しないでください。",
|
"error.merge_armature.circular_dependency:hint": "通常、Merge Armatureは統合先としてアバター本体のArmatureオブジェクトを指定する必要があります。衣装自体を指定しないように注意してください。",
|
||||||
"error.merge_armature.physbone_on_humanoid_bone": "[MA-0002] ヒューマノイドボーンにPhysBoneコンポーネントを検出",
|
"error.merge_armature.physbone_on_humanoid_bone": "[MA-0002] HumanoidボーンにPhysBoneコンポーネントがついています。",
|
||||||
"error.merge_armature.physbone_on_humanoid_bone:hint": "一部のヒューマノイドボーンは、PhysBonesによって制御されています。 マージ対象の対応するヒューマノイドボーンとは位置が異なるため、適切にマージすることはできません。マージするにはヒューマノイドボーンのPhysBonesを取り除く必要があります。",
|
"error.merge_armature.physbone_on_humanoid_bone:hint": "一部のHumanoidボーンがPhysBoneによって制御されています。対応する統合先のHumanoidボーンと位置が異なるため、適切に統合することができません。統合するにはHumanoidボーンについているPhysBoneを取り除く必要があります。",
|
||||||
"error.merge_blend_tree.missing_tree": "[MA-0009] ブレンドツリーが指定されていません",
|
"error.merge_blend_tree.missing_tree": "[MA-0009] ブレンドツリーが指定されていません",
|
||||||
"error.merge_blend_tree.missing_tree:hint": "Merge Blend Treeが動作するには、どのブレンドツリーを統合するかを指定する必要があります。「ブレンドツリー」欄を設定してみてください。",
|
"error.merge_blend_tree.missing_tree:hint": "Merge Blend Treeが動作するには、どのブレンドツリーを統合するか指定する必要があります。「ブレンドツリー」欄を設定しているかご確認ください。",
|
||||||
"error.internal_error": "[MA-9999] 内部エラーが発生しました:{0}\n以下のオブジェクトの処理中に発生しました:",
|
"error.internal_error": "[MA-9999] 内部エラーが発生しました:{0}\n以下のオブジェクトの処理中に発生しました:",
|
||||||
"error.merge_animator.param_type_mismatch": "[MA-0003] パラメータの型が競合しています",
|
"error.merge_animator.param_type_mismatch": "[MA-0003] パラメータの型が競合しています",
|
||||||
"error.merge_animator.param_type_mismatch:description": "パラメータ {0} には複数の型が指定されています: {1} != {2}",
|
"error.merge_animator.param_type_mismatch:description": "パラメータ {0} には複数の型が指定されています: {1} != {2}",
|
||||||
@ -143,37 +143,37 @@
|
|||||||
"error.rename_params.type_conflict:description": "パラメータ {0} には複数の型が指定されています: {1} != {2}",
|
"error.rename_params.type_conflict:description": "パラメータ {0} には複数の型が指定されています: {1} != {2}",
|
||||||
"error.rename_params.default_value_conflict": "[MA-0007] 初期値の競合",
|
"error.rename_params.default_value_conflict": "[MA-0007] 初期値の競合",
|
||||||
"error.rename_params.default_value_conflict:description": "パラメータ {0} には複数の初期値が指定されています: {1} != {2}",
|
"error.rename_params.default_value_conflict:description": "パラメータ {0} には複数の初期値が指定されています: {1} != {2}",
|
||||||
"error.rename_params.default_value_conflict:hint": "予測不可能な動作を避けるために、MAパラメータコンポーネントのデフォルト値フィールドはパラメーター名毎に一個のコンポーネント以外空白のままにしてください。 複数の値が存在する場合、Modular Avatarは階層順に指定された最初のデフォルト値を選択します。",
|
"error.rename_params.default_value_conflict:hint": "予測不可能な動作を避けるため、MA Parametersコンポーネントの初期値フィールドはパラメーター名毎に1つだけしか指定しないようにし、他のコンポーネントでは空白のままにしてください。複数の値が存在する場合、Modular Avatarは階層順で最初に指定された初期値を採用します。",
|
||||||
"error.replace_object.null_target": "[MA-0008] ターゲットが指定されていません",
|
"error.replace_object.null_target": "[MA-0008] 置き換え先が指定されていません",
|
||||||
"error.replace_object.null_target:hint": "Replace Object には置き換えるべきターゲットオブジェクトが必要です。設定してみてください。",
|
"error.replace_object.null_target:hint": "Replace Objectは置き換え先のオブジェクトを指定する必要があります。",
|
||||||
"validation.blendshape_sync.no_local_renderer": "[MA-1000] このオブジェクトにはSkinned Mesh Rendererがありません。",
|
"validation.blendshape_sync.no_local_renderer": "[MA-1000] このオブジェクトにはSkinned Mesh Rendererがありません。",
|
||||||
"validation.blendshape_sync.no_local_renderer:hint": "Blendshape Syncは同じGameObject上のSkinned Mesh Rendererに作用します。正しいオブジェクトに追加しましたか?",
|
"validation.blendshape_sync.no_local_renderer:hint": "Blendshape Syncは同じGameObject上のSkinned Mesh Rendererに作用します。コンポーネントが正しいオブジェクトに追加されているか確認してください。",
|
||||||
"validation.blendshape_sync.no_local_mesh": "[MA-1001] このオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。",
|
"validation.blendshape_sync.no_local_mesh": "[MA-1001] このオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。",
|
||||||
"validation.blendshape_sync.no_local_mesh:hint": "このオブジェクトの Skinned Mesh Renderer の設定が壊れている可能性があります。 元のプレハブまたはFBXからオブジェクトを再作成してみてください。",
|
"validation.blendshape_sync.no_local_mesh:hint": "このオブジェクトの Skinned Mesh Renderer の設定が壊れている可能性があります。 元のプレハブまたはFBXからオブジェクトを再作成してみてください。",
|
||||||
"validation.blendshape_sync.no_bindings": "[MA-1002] このBlendshape Syncにはバインドが設定されていません。",
|
"validation.blendshape_sync.no_bindings": "[MA-1002] このBlendshape Syncにはバインドが設定されていません。",
|
||||||
"validation.blendshape_sync.no_bindings:hint": "Blendshape Syncは、どのブレンドシェイプを同期するかを知る必要があります。追加するには、「+」ボタンをクリックしてください。",
|
"validation.blendshape_sync.no_bindings:hint": "Blendshape Syncは、どのブレンドシェイプを同期するかを知る必要があります。追加するには、「+」ボタンをクリックしてください。",
|
||||||
"validation.blendshape_sync.missing_local_shape": "[MA-1003] 同期先のメッシュに該当するブレンドシェープ「{0}」がありません。",
|
"validation.blendshape_sync.missing_local_shape": "[MA-1003] 同期先のメッシュにブレンドシェイプ「{0}」がありません。",
|
||||||
"validation.blendshape_sync.missing_local_shape:description": "ローカルブレンドシェイプがありません: {0}",
|
"validation.blendshape_sync.missing_local_shape:description": "ブレンドシェイプ「{0}」がありません。",
|
||||||
"validation.blendshape_sync.missing_local_shape:hint": "ターゲットオブジェクトから値を受け取るように設定されたブレンドシェイプがありません。赤で示されているブレンドシェイプ名を変更してみてください。",
|
"validation.blendshape_sync.missing_local_shape:hint": "値を「受け取る」ように設定されたブレンドシェイプが同期先のメッシュに存在しません。赤で示されているブレンドシェイプ名を変更してみてください。",
|
||||||
"validation.blendshape_sync.missing_target_shape": "[MA-1004] 同期先メッシュにブレンドシェープ「{0}」が見つかりません",
|
"validation.blendshape_sync.missing_target_shape": "[MA-1004] 同期元のメッシュにブレンドシェイプ「{0}」がありません。",
|
||||||
"validation.blendshape_sync.missing_target_shape:description": "ターゲットブレンドシェイプがありません: {0}",
|
"validation.blendshape_sync.missing_target_shape:description": "ブレンドシェイプ「{0}」がありません。",
|
||||||
"validation.blendshape_sync.missing_target_shape:hint": "ローカルオブジェクトに値を「送る」ように設定されたブレンドシェイプがありません。赤で示されているブレンドシェイプ名を変更してみてください。",
|
"validation.blendshape_sync.missing_target_shape:hint": "値を「送る」ように設定されたブレンドシェイプが同期元のメッシュに存在しません。赤で示されているブレンドシェイプ名を変更してみてください。",
|
||||||
"validation.blendshape_sync.no_target": "[MA-1005] このBlendshape Syncには同期元が設定されていないバインドがあります。",
|
"validation.blendshape_sync.no_target": "[MA-1005] このBlendshape Syncには同期元が設定されていないバインドがあります。",
|
||||||
"validation.blendshape_sync.no_target:hint": "どのオブジェクトからBlendshapeを同期するかを教える必要があります。メッシュを設定してみてください。",
|
"validation.blendshape_sync.no_target:hint": "どのオブジェクトからBlendshapeを同期するか指定する必要があります。メッシュを設定してください。",
|
||||||
"validation.blendshape_sync.missing_target_renderer": "[MA-1006] 同期元のオブジェクトにはSkinnedMeshRendererがありません。",
|
"validation.blendshape_sync.missing_target_renderer": "[MA-1006] 同期元のオブジェクトにSkinned Mesh Rendererがありません。",
|
||||||
"validation.blendshape_sync.missing_target_renderer:hint": "Blendshape Syncは、対象オブジェクトのSkinned Mesh Rendererからブレンド形状の値を受け取ります。正しいオブジェクトに追加しましたか?",
|
"validation.blendshape_sync.missing_target_renderer:hint": "Blendshape Syncは、同期元のSkinned Mesh Rendererからブレンドシェイプの値を受け取ります。コンポーネントが正しいオブジェクトに追加されているか確認してください。",
|
||||||
"validation.blendshape_sync.missing_target_mesh": "[MA-1007] 同期元のオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。",
|
"validation.blendshape_sync.missing_target_mesh": "[MA-1007] 同期元のオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。",
|
||||||
"validation.blendshape_sync.missing_target_mesh:hint": "ターゲットオブジェクトの Skinned Mesh Renderer の設定が壊れている可能性があります。 元のプレハブまたはFBXからオブジェクトを再作成してみてください。",
|
"validation.blendshape_sync.missing_target_mesh:hint": "同期元のオブジェクトの Skinned Mesh Renderer の設定が壊れている可能性があります。 元のプレハブまたはFBXからオブジェクトを再作成してみてください。",
|
||||||
"validation.bone_proxy.no_target": "[MA-1100] ターゲットオブジェクトが未設定、もしくは存在しません。",
|
"validation.bone_proxy.no_target": "[MA-1100] ターゲットオブジェクトが未設定であるか、存在しません。",
|
||||||
"validation.bone_proxy.no_target:hint": "ボーンプロキシがどのオブジェクトに追尾するかを知る必要があります。追尾すべきオブジェクトをターゲットフィールドに設定してみてください。",
|
"validation.bone_proxy.no_target:hint": "Bone Proxyはどのオブジェクトに追従させるかを指定する必要があります。追従させたい対象のオブジェクトをターゲット欄に設定してみてください。",
|
||||||
"validation.menu_installer.no_menu": "[MA-1200] インストールするメニューがありません。",
|
"validation.menu_installer.no_menu": "[MA-1200] インストールするメニューがありません。",
|
||||||
"validation.menu_installer.no_menu:hint": "Menu Installer は、どのメニューをインストールするべきか設定する必要があります。 「Prefab開発者向けオプション」内の「インストールするメニュー」フィールドを設定するか、MA Menu Itemコンポーネントを追加してみてください。",
|
"validation.menu_installer.no_menu:hint": "Menu Installer は、どのメニューをインストールするべきか設定する必要があります。 「Prefab開発者向けオプション」内の「インストールするメニュー」フィールドを設定するか、MA Menu Itemコンポーネントを追加してみてください。",
|
||||||
"validation.merge_animator.no_animator": "[MA-1300] Animator Controllerが設定されていません",
|
"validation.merge_animator.no_animator": "[MA-1300] Animator Controllerが未設定であるか、存在しません。",
|
||||||
"validation.merge_animator.no_animator:hint": "Animatorをマージするには、どのアニメーターを統合するかを設定する必要があります。「統合されるアニメーター」を設定してみてください。",
|
"validation.merge_animator.no_animator:hint": "どのアニメーターを統合するか設定する必要があります。「統合されるアニメーター」を設定してみてください。",
|
||||||
"validation.merge_armature.no_target": "[MA-1400] 統合先が未設定、もしくは存在しません。",
|
"validation.merge_armature.no_target": "[MA-1400] 統合先が未設定であるか、存在しません。",
|
||||||
"validation.merge_armature.no_target:hint": "Merge Armatureはどこに統合するか設定する必要があります。「統合先」を設定してみてください。",
|
"validation.merge_armature.no_target:hint": "Merge Armatureはどこに統合するか設定する必要があります。「統合先」を設定してみてください。",
|
||||||
"validation.merge_armature.target_is_child": "[MA-1500] 統合先をこのオブジェクトの子にすることができません",
|
"validation.merge_armature.target_is_child": "[MA-1500] 統合先として自身の子を指定することはできません。",
|
||||||
"validation.merge_armature.target_is_child:hint": "Merge Armature は自身の子に統合できません。「統合先」を別のオブジェクトに設定してみてください。",
|
"validation.merge_armature.target_is_child:hint": "Merge Armatureで自身の子に統合することはできません。「統合先」を別のオブジェクトに設定してみてください。",
|
||||||
"submenu_source.Children": "子オブジェクトから生成",
|
"submenu_source.Children": "子オブジェクトから生成",
|
||||||
"submenu_source.MenuAsset": "Expressions Menu アセットを指定",
|
"submenu_source.MenuAsset": "Expressions Menu アセットを指定",
|
||||||
"menuitem.showcontents": "メニュー内容を表示",
|
"menuitem.showcontents": "メニュー内容を表示",
|
||||||
@ -183,7 +183,7 @@
|
|||||||
"menuitem.prop.type": "タイプ",
|
"menuitem.prop.type": "タイプ",
|
||||||
"menuitem.prop.type.tooltip": "この項目の種別",
|
"menuitem.prop.type.tooltip": "この項目の種別",
|
||||||
"menuitem.prop.value": "パラメーター値",
|
"menuitem.prop.value": "パラメーター値",
|
||||||
"menuitem.prop.value.tooltip": "この項目が操作されたとき、パラメーターが設定される値",
|
"menuitem.prop.value.tooltip": "この項目が操作されたとき、パラメーターに設定される値",
|
||||||
"menuitem.prop.automatic_value": "自動",
|
"menuitem.prop.automatic_value": "自動",
|
||||||
"menuitem.prop.automatic_value.tooltip": "かぶらない値を自動的に割り振る",
|
"menuitem.prop.automatic_value.tooltip": "かぶらない値を自動的に割り振る",
|
||||||
"menuitem.prop.parameter": "パラメーター名",
|
"menuitem.prop.parameter": "パラメーター名",
|
||||||
@ -191,19 +191,19 @@
|
|||||||
"menuitem.prop.submenu_asset": "サブメニューアセット",
|
"menuitem.prop.submenu_asset": "サブメニューアセット",
|
||||||
"menuitem.prop.submenu_asset.tooltip": "サブメニューとして引用するアセット",
|
"menuitem.prop.submenu_asset.tooltip": "サブメニューとして引用するアセット",
|
||||||
"menuitem.prop.submenu_source": "サブメニュー引用元",
|
"menuitem.prop.submenu_source": "サブメニュー引用元",
|
||||||
"menuitem.prop.submenu_source.tooltip": "このサブメニューの内容をどこから引用するべきかを指定",
|
"menuitem.prop.submenu_source.tooltip": "このサブメニューの内容をどこから引用するべきか指定します。",
|
||||||
"menuitem.prop.source_override": "引用元オブジェクト",
|
"menuitem.prop.source_override": "引用元オブジェクト",
|
||||||
"menuitem.prop.source_override.tooltip": "指定した場合は、指定したオブジェクトの子をメニューの内容として指定します。指定されてない場合はこのオブジェクト直下の子を使用します。",
|
"menuitem.prop.source_override.tooltip": "指定した場合、指定したオブジェクトの子をメニューの内容として指定します。指定されてない場合はこのオブジェクト直下の子を使用します。",
|
||||||
"menuitem.prop.is_default": "初期設定にする",
|
"menuitem.prop.is_default": "初期設定にする",
|
||||||
"menuitem.prop.is_default.tooltip": "ONの場合、アバター初期化の際にこのメニューアイテムを選択します",
|
"menuitem.prop.is_default.tooltip": "有効になっていると、アバター初期化の際にこのメニューアイテムを選択した状態にします。",
|
||||||
"menuitem.prop.is_saved": "保存する",
|
"menuitem.prop.is_saved": "保存する",
|
||||||
"menuitem.prop.is_saved.tooltip": "有効になっていると、アバター変更やワールド移動するときこの設定が保持されます。",
|
"menuitem.prop.is_saved.tooltip": "有効になっていると、アバター変更やワールド移動をしてもこの設定が保持されます。",
|
||||||
"menuitem.prop.is_synced": "同期する",
|
"menuitem.prop.is_synced": "同期する",
|
||||||
"menuitem.prop.is_synced.tooltip": "有効の場合はほかのプレイヤーに同期されます。",
|
"menuitem.prop.is_synced.tooltip": "有効になっていると、メニューがほかのプレイヤーに同期されます。",
|
||||||
"menuitem.param.rotation": "回転パラメーター名",
|
"menuitem.param.rotation": "ラジアルメニュー用パラメーター名",
|
||||||
"menuitem.param.rotation.tooltip": "このメニューアイテムの回転に連動するべきパラメーター",
|
"menuitem.param.rotation.tooltip": "このラジアルメニューの操作と連動するべきパラメーター",
|
||||||
"menuitem.param.horizontal": "横パラメーター名",
|
"menuitem.param.horizontal": "横パラメーター名",
|
||||||
"menuitem.param.horizontal.tooltip": "横操作に連動するパラメーター名",
|
"menuitem.param.horizontal.tooltip": "左右操作に連動するパラメーター名",
|
||||||
"menuitem.param.vertical": "縦パラメーター名",
|
"menuitem.param.vertical": "縦パラメーター名",
|
||||||
"menuitem.param.vertical.tooltip": "上下操作に連動するパラメーター名",
|
"menuitem.param.vertical.tooltip": "上下操作に連動するパラメーター名",
|
||||||
"menuitem.label.control_labels_and_params": "表示名・パラメーター",
|
"menuitem.label.control_labels_and_params": "表示名・パラメーター",
|
||||||
@ -219,29 +219,29 @@
|
|||||||
"control_group.foldout.actions": "アクション",
|
"control_group.foldout.actions": "アクション",
|
||||||
"control_group.foldout.menu_items": "関連付けされたメニューアイテム",
|
"control_group.foldout.menu_items": "関連付けされたメニューアイテム",
|
||||||
"control_group.is_saved": "保存する",
|
"control_group.is_saved": "保存する",
|
||||||
"control_group.is_saved.tooltip": "有効になっていると、アバター変更やワールド移動するときこの設定が保持されます。",
|
"control_group.is_saved.tooltip": "有効になっていると、アバター変更やワールド移動をしてもこの設定が保持されます。",
|
||||||
"control_group.is_synced": "同期する",
|
"control_group.is_synced": "同期する",
|
||||||
"control_group.is_synced.tooltip": "有効の場合はほかのプレイヤーに同期されます。",
|
"control_group.is_synced.tooltip": "有効になっていると、メニューがほかのプレイヤーに同期されます。",
|
||||||
"control_group.default_value": "初期値",
|
"control_group.default_value": "初期値",
|
||||||
"control_group.default_value.unset": "(どれも選択されない)",
|
"control_group.default_value.unset": "(どれも選択されない)",
|
||||||
"animation_gen.duplicate_binding": "別々のコントロールグループから、同じパラメーターが操作されています。パラメーター:{0}",
|
"animation_gen.duplicate_binding": "別々のコントロールグループから、同じパラメーターが操作されています。パラメーター:{0}",
|
||||||
"animation_gen.multiple_defaults": "同じコントロールグループに初期設定に指定されたメニューアイテムが複数あります。",
|
"animation_gen.multiple_defaults": "同じコントロールグループに初期設定にするとして指定されたメニューアイテムが複数あります。",
|
||||||
"menuitem.misc.add_item": "メニューアイテムを追加",
|
"menuitem.misc.add_item": "メニューアイテムを追加",
|
||||||
"replace_object.target_object": "上書き先",
|
"replace_object.target_object": "置き換え先",
|
||||||
"setup_outfit.err.header.notarget": "Setup outfit の処理が失敗しました",
|
"setup_outfit.err.header.notarget": "Setup Outfit の処理に失敗しました",
|
||||||
"setup_outfit.err.header": "Setup outfit が「{0}」を処理中に失敗しました。",
|
"setup_outfit.err.header": "Setup Outfit が「{0}」を処理中に失敗しました。",
|
||||||
"setup_outfit.err.unknown": "原因不明のエラーが発生しました。",
|
"setup_outfit.err.unknown": "原因不明のエラーが発生しました。",
|
||||||
"setup_outfit.err.no_selection": "オブジェクトが選択されていません。",
|
"setup_outfit.err.no_selection": "オブジェクトが選択されていません。",
|
||||||
"setup_outfit.err.run_on_avatar_itself": "Setup Outfitはアバター自体ではなく、衣装のほうで実行してください。\n\nキメラアバターを作る場合は、中のほうのAvatar Descriptorを消して、衣装として扱ってください。",
|
"setup_outfit.err.run_on_avatar_itself": "Setup Outfitはアバター自体ではなく、衣装の方で実行してください。\n\nキメラアバターを作る場合は、中の方のAvatar Descriptorを消して、衣装として扱ってください。",
|
||||||
"setup_outfit.err.multiple_avatar_descriptors": "「{0}」とその親に、複数のavatar descriptorを発見しました。\n\nキメラアバターを作る場合は、中のほうのAvatar Descriptorを消して、衣装として扱ってください。",
|
"setup_outfit.err.multiple_avatar_descriptors": "「{0}」とその親で複数のAvatar Descriptorを発見しました。\n\nキメラアバターを作る場合は、中の方のAvatar Descriptorを消して、衣装として扱ってください。",
|
||||||
"setup_outfit.err.no_avatar_descriptor": "「{0}」の親に、avatar descriptorが見つかりませんでした。衣装のオブジェクトをアバターの中に配置してください。",
|
"setup_outfit.err.no_avatar_descriptor": "「{0}」の親にAvatar Descriptorが見つかりませんでした。衣装のオブジェクトをアバターの中に配置してください。",
|
||||||
"setup_outfit.err.no_animator": "アバターにAnimatorコンポーネントがありません。",
|
"setup_outfit.err.no_animator": "アバターにAnimatorコンポーネントがありません。",
|
||||||
"setup_outfit.err.no_hips": "アバターにHipsボーンがありません。なお、Setup Outfitはヒューマノイドアバター以外には対応していません。",
|
"setup_outfit.err.no_hips": "アバターにHipsボーンがありません。なお、Setup OutfitはHumanoidアバター以外には対応していません。",
|
||||||
"setup_outfit.err.no_outfit_hips": "衣装のHipsボーンを発見できませんでした。以下の名前を含むボーンを探しました:",
|
"setup_outfit.err.no_outfit_hips": "衣装のHipsボーンを発見できませんでした。アクセサリー等に対してSetup Outfitを試みた場合は、代わりにBone Proxyコンポーネントを使って配置してみてください。\n以下の名前を含むボーンを(大文字・小文字を区別つけずに)探しました:",
|
||||||
"move_independently.group-header": "一緒に動かすオブジェクト",
|
"move_independently.group-header": "同時に動かすオブジェクト",
|
||||||
"scale_adjuster.scale": "Scale調整値",
|
"scale_adjuster.scale": "Scale調整値",
|
||||||
"scale_adjuster.adjust_children": "子オブジェクトの位置を調整",
|
"scale_adjuster.adjust_children": "子オブジェクトの位置を調整",
|
||||||
"world_fixed_object.err.unsupported_platform": "World Fixed Objectがこのプラットフォームに対応していません",
|
"world_fixed_object.err.unsupported_platform": "World Fixed Objectはこのプラットフォームに対応していません。",
|
||||||
"world_fixed_object.err.unsupported_platform:description": "World Fixed ObjectはAndroid向けビルドには対応していないため、動作しません。",
|
"world_fixed_object.err.unsupported_platform:description": "World Fixed ObjectはAndroid向けビルドには対応していないため、動作しません。",
|
||||||
"ma_info.param_usage_ui.header": "Expressions Parameter 使用状況",
|
"ma_info.param_usage_ui.header": "Expressions Parameter 使用状況",
|
||||||
"ma_info.param_usage_ui.other_objects": "このアバター内の他のオブジェクト",
|
"ma_info.param_usage_ui.other_objects": "このアバター内の他のオブジェクト",
|
||||||
@ -251,8 +251,8 @@
|
|||||||
"reactive_object.inverse": "条件を反転",
|
"reactive_object.inverse": "条件を反転",
|
||||||
"reactive_object.material-setter.set-to": "変更先のマテリアル ",
|
"reactive_object.material-setter.set-to": "変更先のマテリアル ",
|
||||||
"menuitem.misc.add_toggle": "トグルを追加",
|
"menuitem.misc.add_toggle": "トグルを追加",
|
||||||
"ro_sim.open_debugger_button": "リアクションデバッグツールを開く",
|
"ro_sim.open_debugger_button": "Reaction デバッガーを開く",
|
||||||
"ro_sim.window.title": "MA リアクションデバッグツール",
|
"ro_sim.window.title": "MA Reaction デバッガー",
|
||||||
"ro_sim.header.inspecting": "表示中のオブジェクト",
|
"ro_sim.header.inspecting": "表示中のオブジェクト",
|
||||||
"ro_sim.header.clear_overrides": "すべてのオーバーライドを解除",
|
"ro_sim.header.clear_overrides": "すべてのオーバーライドを解除",
|
||||||
"ro_sim.header.object_state": "オブジェクトのアクティブ状態",
|
"ro_sim.header.object_state": "オブジェクトのアクティブ状態",
|
||||||
@ -261,16 +261,17 @@
|
|||||||
"ro_sim.header.override_gameobject_state": "GameObject のアクティブ状態をオーバーライド",
|
"ro_sim.header.override_gameobject_state": "GameObject のアクティブ状態をオーバーライド",
|
||||||
"ro_sim.header.override_menuitem_state": "MenuItem の選択状態をオーバーライト",
|
"ro_sim.header.override_menuitem_state": "MenuItem の選択状態をオーバーライト",
|
||||||
"ro_sim.affected_by.title": "以下のルールに影響されています",
|
"ro_sim.affected_by.title": "以下のルールに影響されています",
|
||||||
"ro_sim.effect_group.controls_obj_state": "オブジェクトのアクティブ状態を設定する➡",
|
"ro_sim.effect_group.component": "Reactive Component",
|
||||||
|
"ro_sim.effect_group.controls_obj_state": "オブジェクトのアクティブ状態を次に設定する➡",
|
||||||
"ro_sim.effect_group.target_component": "コンポーネント",
|
"ro_sim.effect_group.target_component": "コンポーネント",
|
||||||
"ro_sim.effect_group.target_component.tooltip": "Reactive Componentに影響されるコンポーネント",
|
"ro_sim.effect_group.target_component.tooltip": "Reactive Componentに影響されるコンポーネント",
|
||||||
"ro_sim.effect_group.property": "プロパティ",
|
"ro_sim.effect_group.property": "プロパティ",
|
||||||
"ro_sim.effect_group.property.tooltip": "設定されるプロパティ",
|
"ro_sim.effect_group.property.tooltip": "設定されるプロパティ",
|
||||||
"ro_sim.effect_group.value": "値",
|
"ro_sim.effect_group.value": "値",
|
||||||
"ro_sim.effect_group.value.tooltip": "上記 Reactive Component が活性状態の時に設定される値",
|
"ro_sim.effect_group.value.tooltip": "上記の Reactive Component がアクティブな時に設定される値",
|
||||||
"ro_sim.effect_group.material": "マテリアル",
|
"ro_sim.effect_group.material": "マテリアル",
|
||||||
"ro_sim.effect_group.material.tooltip": "上記 Reactive Component が活性状態の時に設定されるマテリアル",
|
"ro_sim.effect_group.material.tooltip": "上記の Reactive Component がアクティブな時に設定されるマテリアル",
|
||||||
"ro_sim.effect_group.rule_inverted": "このルールの条件が反転されています",
|
"ro_sim.effect_group.rule_inverted": "このルールの条件は反転されています",
|
||||||
"ro_sim.effect_group.rule_inverted.tooltip": "このルールは、いずれかの条件が満たされていない場合に適用されます",
|
"ro_sim.effect_group.rule_inverted.tooltip": "このルールは、いずれかの条件が満たされていない場合に適用されます",
|
||||||
"ro_sim.effect_group.conditions": "条件"
|
"ro_sim.effect_group.conditions": "条件"
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,6 @@
|
|||||||
"worldfixed.quest": "이 컴포넌트는 안드로이드 빌드를 대응하지 않습니다.",
|
"worldfixed.quest": "이 컴포넌트는 안드로이드 빌드를 대응하지 않습니다.",
|
||||||
"worldfixed.normal": "이 오브젝트는 Constraint 을 사용하여 아바타에 고정하지 않는 이상 월드축에 고정됩니다.",
|
"worldfixed.normal": "이 오브젝트는 Constraint 을 사용하여 아바타에 고정하지 않는 이상 월드축에 고정됩니다.",
|
||||||
"fpvisible.normal": "이 오브젝트는 일인칭 시점에서 보일 것입니다.",
|
"fpvisible.normal": "이 오브젝트는 일인칭 시점에서 보일 것입니다.",
|
||||||
"fpvisible.NotUnderHead": "Head 본(Bone) 내의 오브젝트가 아닌 경우 작동하지 않습니다.",
|
|
||||||
"fpvisible.quest": "이 컴포넌트는 오큘러스 퀘스트 단독 버전과 호환되지 않으며 영향을 미치지 않습니다.",
|
"fpvisible.quest": "이 컴포넌트는 오큘러스 퀘스트 단독 버전과 호환되지 않으며 영향을 미치지 않습니다.",
|
||||||
"fpvisible.InPhysBoneChain": "이 객체는 Physics Bone 체인에 의해 컨트롤되므로 체인의 세부적인 선택이 불가능합니다. 대신 체인의 시작 부분을 선택하세요.",
|
"fpvisible.InPhysBoneChain": "이 객체는 Physics Bone 체인에 의해 컨트롤되므로 체인의 세부적인 선택이 불가능합니다. 대신 체인의 시작 부분을 선택하세요.",
|
||||||
"blendshape.mesh": "메시",
|
"blendshape.mesh": "메시",
|
||||||
|
@ -94,7 +94,6 @@
|
|||||||
"worldfixed.quest": "此组件未生效,因为它与 Oculus Quest 不兼容。",
|
"worldfixed.quest": "此组件未生效,因为它与 Oculus Quest 不兼容。",
|
||||||
"worldfixed.normal": "当前对象将会固定于世界,除非您使用约束将它绑定在 Avatar 内。",
|
"worldfixed.normal": "当前对象将会固定于世界,除非您使用约束将它绑定在 Avatar 内。",
|
||||||
"fpvisible.normal": "当前对象将在第一人称视角中可见。",
|
"fpvisible.normal": "当前对象将在第一人称视角中可见。",
|
||||||
"fpvisible.NotUnderHead": "此组件未生效,因为它需要放置在 Head 骨骼下。",
|
|
||||||
"fpvisible.quest": "此组件未生效,因为它与 Oculus Quest 不兼容。",
|
"fpvisible.quest": "此组件未生效,因为它与 Oculus Quest 不兼容。",
|
||||||
"fpvisible.InPhysBoneChain": "当前对象由 PhysicsBone 控制,可能无法在第一人称视角中可见;请指定 PhysicsBone 链的起点。",
|
"fpvisible.InPhysBoneChain": "当前对象由 PhysicsBone 控制,可能无法在第一人称视角中可见;请指定 PhysicsBone 链的起点。",
|
||||||
"blendshape.mesh": "网格",
|
"blendshape.mesh": "网格",
|
||||||
@ -227,7 +226,6 @@
|
|||||||
"setup_outfit.err.no_avatar_descriptor": "在 {0} 的父级中找不到 VRC Avatar Descriptor。请确保您的服装放置在 Avatar 内。",
|
"setup_outfit.err.no_avatar_descriptor": "在 {0} 的父级中找不到 VRC Avatar Descriptor。请确保您的服装放置在 Avatar 内。",
|
||||||
"setup_outfit.err.no_animator": "您的 Avatar 没有动画控制器 (Animator) 组件。",
|
"setup_outfit.err.no_animator": "您的 Avatar 没有动画控制器 (Animator) 组件。",
|
||||||
"setup_outfit.err.no_hips": "您的 Avatar 没有 Hips 骨骼。Setup Outfit 只能用于 humanoid Avatars。",
|
"setup_outfit.err.no_hips": "您的 Avatar 没有 Hips 骨骼。Setup Outfit 只能用于 humanoid Avatars。",
|
||||||
"setup_outfit.err.no_outfit_hips": "无法识别服装的 Hips,已搜索包含以下名称的对象:",
|
|
||||||
"move_independently.group-header": "要一起移动的对象",
|
"move_independently.group-header": "要一起移动的对象",
|
||||||
"scale_adjuster.scale": "调整比例",
|
"scale_adjuster.scale": "调整比例",
|
||||||
"scale_adjuster.adjust_children": "调整子级的位置",
|
"scale_adjuster.adjust_children": "调整子级的位置",
|
||||||
|
@ -99,7 +99,6 @@
|
|||||||
"worldfixed.quest": "此元件未生效,因為它與 Android 環境不相容。",
|
"worldfixed.quest": "此元件未生效,因為它與 Android 環境不相容。",
|
||||||
"worldfixed.normal": "當前物件將會固定於世界,除非你使用約束將它綁在 Avatar 內。",
|
"worldfixed.normal": "當前物件將會固定於世界,除非你使用約束將它綁在 Avatar 內。",
|
||||||
"fpvisible.normal": "當前物件將在第一人稱視角中可見。",
|
"fpvisible.normal": "當前物件將在第一人稱視角中可見。",
|
||||||
"fpvisible.NotUnderHead": "此元件未生效,因為它需要放置在 Head 骨骼下。",
|
|
||||||
"fpvisible.quest": "此元件未生效,因為它與 Android 環境不相容。",
|
"fpvisible.quest": "此元件未生效,因為它與 Android 環境不相容。",
|
||||||
"fpvisible.InPhysBoneChain": "當前物件由 Physics Bone 控制,可能無法在第一人稱視角中可見;請指定 Physics Bone 鏈的起點。",
|
"fpvisible.InPhysBoneChain": "當前物件由 Physics Bone 控制,可能無法在第一人稱視角中可見;請指定 Physics Bone 鏈的起點。",
|
||||||
"blendshape.mesh": "網格",
|
"blendshape.mesh": "網格",
|
||||||
@ -239,7 +238,6 @@
|
|||||||
"setup_outfit.err.no_avatar_descriptor": "在 {0} 的父級中找不到 VRC Avatar Descriptor。請確保你的服裝放置在 Avatar 裡。",
|
"setup_outfit.err.no_avatar_descriptor": "在 {0} 的父級中找不到 VRC Avatar Descriptor。請確保你的服裝放置在 Avatar 裡。",
|
||||||
"setup_outfit.err.no_animator": "你的 Avatar 沒有 Animator 元件。",
|
"setup_outfit.err.no_animator": "你的 Avatar 沒有 Animator 元件。",
|
||||||
"setup_outfit.err.no_hips": "你的 Avatar 沒有 Hips 骨骼。Setup Outfit 只能用於 humanoid Avatars。",
|
"setup_outfit.err.no_hips": "你的 Avatar 沒有 Hips 骨骼。Setup Outfit 只能用於 humanoid Avatars。",
|
||||||
"setup_outfit.err.no_outfit_hips": "識別不到服裝的 Hips 骨骼,已搜尋含有以下名稱的骨骼物件:",
|
|
||||||
"move_independently.group-header": "要一起移動的物件",
|
"move_independently.group-header": "要一起移動的物件",
|
||||||
"scale_adjuster.scale": "調整比例",
|
"scale_adjuster.scale": "調整比例",
|
||||||
"scale_adjuster.adjust_children": "調整子級的位置",
|
"scale_adjuster.adjust_children": "調整子級的位置",
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using nadena.dev.modular_avatar.core.menu;
|
using nadena.dev.modular_avatar.core.menu;
|
||||||
using nadena.dev.modular_avatar.editor.ErrorReporting;
|
using nadena.dev.modular_avatar.editor.ErrorReporting;
|
||||||
|
using nadena.dev.ndmf;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
using VRC.SDK3.Avatars.ScriptableObjects;
|
using VRC.SDK3.Avatars.ScriptableObjects;
|
||||||
@ -102,7 +103,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
PushControl(control);
|
PushControl(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_menuToInstallerMap.TryGetValue(expMenu, out var installers))
|
if (_menuToInstallerMap.TryGetValue(ObjectRegistry.GetReference(expMenu), out var installers))
|
||||||
{
|
{
|
||||||
foreach (var installer in installers)
|
foreach (var installer in installers)
|
||||||
{
|
{
|
||||||
@ -311,7 +312,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
// initial validation
|
// initial validation
|
||||||
if (installer.menuToAppend == null && installer.GetComponent<MenuSource>() == null) return;
|
if (installer.menuToAppend == null && installer.GetComponent<MenuSource>() == null) return;
|
||||||
|
|
||||||
var target = installer.installTargetMenu ? (object) installer.installTargetMenu : RootMenuKey;
|
var target = installer.installTargetMenu ? (object) ObjectRegistry.GetReference(installer.installTargetMenu) : RootMenuKey;
|
||||||
if (!_targetMenuToInstaller.TryGetValue(target, out var targets))
|
if (!_targetMenuToInstaller.TryGetValue(target, out var targets))
|
||||||
{
|
{
|
||||||
targets = new List<ModularAvatarMenuInstaller>();
|
targets = new List<ModularAvatarMenuInstaller>();
|
||||||
@ -366,7 +367,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Some menu installers may be bound to the root menu _asset_ directly.
|
// Some menu installers may be bound to the root menu _asset_ directly.
|
||||||
if (menuToInstallerFiltered.TryGetValue(menu, out var installers))
|
if (menuToInstallerFiltered.TryGetValue(ObjectRegistry.GetReference(menu), out var installers))
|
||||||
{
|
{
|
||||||
foreach (var installer in installers)
|
foreach (var installer in installers)
|
||||||
{
|
{
|
||||||
|
@ -236,8 +236,10 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool? ProbeWriteDefaults(AnimatorController controller)
|
internal static bool? ProbeWriteDefaults(AnimatorController controller)
|
||||||
{
|
{
|
||||||
|
if (controller == null) return null;
|
||||||
|
|
||||||
bool hasWDOn = false;
|
bool hasWDOn = false;
|
||||||
bool hasWDOff = false;
|
bool hasWDOff = false;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
var converters = context.AvatarRootObject.GetComponentsInChildren<ModularAvatarConvertConstraints>(true)
|
var converters = context.AvatarRootObject.GetComponentsInChildren<ModularAvatarConvertConstraints>(true)
|
||||||
.Select(c => c.gameObject)
|
.Select(c => c.gameObject)
|
||||||
.ToHashSet(new ObjectIdentityComparer<GameObject>());
|
.ToHashSet();
|
||||||
if (converters.Count == 0) return;
|
if (converters.Count == 0) return;
|
||||||
|
|
||||||
var constraintGameObjects = context.AvatarRootObject.GetComponentsInChildren<IConstraint>(true)
|
var constraintGameObjects = context.AvatarRootObject.GetComponentsInChildren<IConstraint>(true)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
#if MA_VRCSDK3_AVATARS
|
#if MA_VRCSDK3_AVATARS
|
||||||
using VRC.SDK3.Dynamics.PhysBone.Components;
|
using VRC.SDK3.Dynamics.PhysBone.Components;
|
||||||
#endif
|
#endif
|
||||||
@ -123,7 +123,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (MissingComponentException _)
|
catch (MissingComponentException)
|
||||||
{
|
{
|
||||||
// No animator? weird. Move on.
|
// No animator? weird. Move on.
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (!referencedGameObjects.Contains(go))
|
if (!referencedGameObjects.Contains(go))
|
||||||
{
|
{
|
||||||
UnityEngine.Object.DestroyImmediate(go);
|
Object.DestroyImmediate(go);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
ParameterNamespace.Animator,
|
ParameterNamespace.Animator,
|
||||||
_component, PluginDefinition.Instance, _component.AnimatorControllerParameterType)
|
_component, PluginDefinition.Instance, _component.AnimatorControllerParameterType)
|
||||||
{
|
{
|
||||||
|
ExpandTypeOnConflict = true,
|
||||||
WantSynced = _component.isSynced,
|
WantSynced = _component.isSynced,
|
||||||
IsHidden = hidden,
|
IsHidden = hidden,
|
||||||
DefaultValue = _component.isDefault ? _component.Control.value : null
|
DefaultValue = _component.isDefault ? _component.Control.value : null
|
||||||
|
@ -109,7 +109,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
return uxml != null && EditorStyles.label != null;
|
return uxml != null && EditorStyles.label != null;
|
||||||
}
|
}
|
||||||
catch (NullReferenceException _)
|
catch (NullReferenceException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using nadena.dev.ndmf.preview;
|
using nadena.dev.ndmf.preview;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace nadena.dev.modular_avatar.core.editor
|
namespace nadena.dev.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
@ -13,21 +12,25 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
public PropCache<Key, Value> Owner;
|
public PropCache<Key, Value> Owner;
|
||||||
public Key Key;
|
public Key Key;
|
||||||
public Value Value;
|
public Value Value;
|
||||||
|
public string DebugName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly string _debugName;
|
||||||
private readonly Func<ComputeContext, Key, Value> _operator;
|
private readonly Func<ComputeContext, Key, Value> _operator;
|
||||||
private readonly Func<Value, Value, bool> _equalityComparer;
|
private readonly Func<Value, Value, bool> _equalityComparer;
|
||||||
private readonly Dictionary<Key, CacheEntry> _cache = new();
|
private readonly Dictionary<Key, CacheEntry> _cache = new();
|
||||||
|
|
||||||
public PropCache(Func<ComputeContext, Key, Value> operatorFunc, Func<Value, Value, bool> equalityComparer = null)
|
public PropCache(string debugName, Func<ComputeContext, Key, Value> operatorFunc,
|
||||||
|
Func<Value, Value, bool> equalityComparer = null)
|
||||||
{
|
{
|
||||||
|
_debugName = debugName;
|
||||||
_operator = operatorFunc;
|
_operator = operatorFunc;
|
||||||
_equalityComparer = equalityComparer;
|
_equalityComparer = equalityComparer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InvalidateEntry(CacheEntry entry)
|
private static void InvalidateEntry(CacheEntry entry)
|
||||||
{
|
{
|
||||||
var newGenContext = new ComputeContext("PropCache for key " + entry.Key);
|
var newGenContext = new ComputeContext("PropCache/" + entry.DebugName + " key " + entry.Key);
|
||||||
var newValue = entry.Owner._operator(newGenContext, entry.Key);
|
var newValue = entry.Owner._operator(newGenContext, entry.Key);
|
||||||
if (entry.Owner._equalityComparer != null && entry.Owner._equalityComparer(entry.Value, newValue))
|
if (entry.Owner._equalityComparer != null && entry.Owner._equalityComparer(entry.Value, newValue))
|
||||||
{
|
{
|
||||||
@ -44,14 +47,15 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (!_cache.TryGetValue(key, out var entry) || entry.GenerateContext.IsInvalidated)
|
if (!_cache.TryGetValue(key, out var entry) || entry.GenerateContext.IsInvalidated)
|
||||||
{
|
{
|
||||||
var subContext = new ComputeContext("PropCache for key " + key);
|
var subContext = new ComputeContext("PropCache/" + _debugName + " key " + key);
|
||||||
entry = new CacheEntry
|
entry = new CacheEntry
|
||||||
{
|
{
|
||||||
GenerateContext = subContext,
|
GenerateContext = subContext,
|
||||||
ObserverContext = new ComputeContext("Observer for PropCache for key " + key),
|
ObserverContext = new ComputeContext("Observer for PropCache for key " + key),
|
||||||
Owner = this,
|
Owner = this,
|
||||||
Key = key,
|
Key = key,
|
||||||
Value = _operator(subContext, key)
|
Value = _operator(subContext, key),
|
||||||
|
DebugName = _debugName
|
||||||
};
|
};
|
||||||
_cache[key] = entry;
|
_cache[key] = entry;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
Parameter = GetActiveSelfProxy(cursor.gameObject),
|
Parameter = GetActiveSelfProxy(cursor.gameObject),
|
||||||
DebugName = cursor.gameObject.name,
|
DebugName = cursor.gameObject.name,
|
||||||
IsConstant = false,
|
IsConstant = false,
|
||||||
InitialValue = cursor.gameObject.activeSelf ? 1.0f : 0.0f,
|
InitialValue = _computeContext.Observe(cursor.gameObject, go => go.activeSelf) ? 1.0f : 0.0f,
|
||||||
ParameterValueLo = 0.5f,
|
ParameterValueLo = 0.5f,
|
||||||
ParameterValueHi = float.PositiveInfinity,
|
ParameterValueHi = float.PositiveInfinity,
|
||||||
ReferenceObject = cursor.gameObject,
|
ReferenceObject = cursor.gameObject,
|
||||||
@ -228,7 +228,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
if (!objectGroups.TryGetValue(key, out var group))
|
if (!objectGroups.TryGetValue(key, out var group))
|
||||||
{
|
{
|
||||||
group = new AnimatedProperty(key, target.activeSelf ? 1 : 0);
|
var active = _computeContext.Observe(target, t => t.activeSelf);
|
||||||
|
group = new AnimatedProperty(key, active ? 1 : 0);
|
||||||
objectGroups[key] = group;
|
objectGroups[key] = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (_analysisCache == null)
|
if (_analysisCache == null)
|
||||||
{
|
{
|
||||||
_analysisCache = new PropCache<GameObject, AnalysisResult>((ctx, root) =>
|
_analysisCache = new PropCache<GameObject, AnalysisResult>("ROAnalyzer", (ctx, root) =>
|
||||||
{
|
{
|
||||||
var analysis = new ReactiveObjectAnalyzer(ctx);
|
var analysis = new ReactiveObjectAnalyzer(ctx);
|
||||||
analysis.ForcePropertyOverrides = ctx.Observe(ROSimulator.PropertyOverrides, a=>a, (a,b) => false)
|
analysis.ForcePropertyOverrides = ctx.Observe(ROSimulator.PropertyOverrides, a=>a, (a,b) => false)
|
||||||
@ -157,9 +157,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
if (condition.ReferenceObject != null && !toggledObjects.Contains(condition.ReferenceObject))
|
if (condition.ReferenceObject != null && !toggledObjects.Contains(condition.ReferenceObject))
|
||||||
condition.IsConstant = asc.AnimationDatabase.ClipsForPath(asc.PathMappings.GetObjectIdentifier(condition.ReferenceObject)).IsEmpty;
|
condition.IsConstant = asc.AnimationDatabase.ClipsForPath(asc.PathMappings.GetObjectIdentifier(condition.ReferenceObject)).IsEmpty;
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
// Remove redundant active conditions.
|
// Remove redundant active conditions.
|
||||||
int retain = 0;
|
|
||||||
actionGroup.ControllingConditions.RemoveAll(c => c.IsConstant && c.InitiallyActive);
|
actionGroup.ControllingConditions.RemoveAll(c => c.IsConstant && c.InitiallyActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private HashSet<string> activeProps = new();
|
private HashSet<string> activeProps = new();
|
||||||
|
|
||||||
private AnimationClip _initialStateClip;
|
private AnimationClip _initialStateClip;
|
||||||
|
private bool _writeDefaults;
|
||||||
|
|
||||||
public ReactiveObjectPass(ndmf.BuildContext context)
|
public ReactiveObjectPass(ndmf.BuildContext context)
|
||||||
{
|
{
|
||||||
@ -33,6 +34,10 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
internal void Execute()
|
internal void Execute()
|
||||||
{
|
{
|
||||||
|
// Having a WD OFF layer after WD ON layers can break WD. We match the behavior of the existing states,
|
||||||
|
// and if mixed, use WD ON to maximize compatibility.
|
||||||
|
_writeDefaults = MergeAnimatorProcessor.ProbeWriteDefaults(FindFxController().animatorController as AnimatorController) ?? true;
|
||||||
|
|
||||||
var analysis = new ReactiveObjectAnalyzer(context).Analyze(context.AvatarRootObject);
|
var analysis = new ReactiveObjectAnalyzer(context).Analyze(context.AvatarRootObject);
|
||||||
|
|
||||||
var shapes = analysis.Shapes;
|
var shapes = analysis.Shapes;
|
||||||
@ -277,7 +282,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var initial = new AnimationClip();
|
var initial = new AnimationClip();
|
||||||
var initialState = new AnimatorState();
|
var initialState = new AnimatorState();
|
||||||
initialState.motion = initial;
|
initialState.motion = initial;
|
||||||
initialState.writeDefaultValues = false;
|
initialState.writeDefaultValues = _writeDefaults;
|
||||||
initialState.name = "<default>";
|
initialState.name = "<default>";
|
||||||
asm.defaultState = initialState;
|
asm.defaultState = initialState;
|
||||||
|
|
||||||
@ -295,7 +300,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var transitionBuffer = new List<(AnimatorState, List<AnimatorStateTransition>)>();
|
var transitionBuffer = new List<(AnimatorState, List<AnimatorStateTransition>)>();
|
||||||
var entryTransitions = new List<AnimatorTransition>();
|
var entryTransitions = new List<AnimatorTransition>();
|
||||||
|
|
||||||
transitionBuffer.Add((initialState, new List<AnimatorStateTransition>()));
|
var initialStateTransitionList = new List<AnimatorStateTransition>();
|
||||||
|
transitionBuffer.Add((initialState, initialStateTransitionList));
|
||||||
|
|
||||||
foreach (var group in info.actionGroups.Skip(lastConstant))
|
foreach (var group in info.actionGroups.Skip(lastConstant))
|
||||||
{
|
{
|
||||||
@ -315,8 +321,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
var conditions = GetTransitionConditions(asc, group);
|
var conditions = GetTransitionConditions(asc, group);
|
||||||
|
|
||||||
foreach (var (st, transitions) in transitionBuffer)
|
|
||||||
{
|
|
||||||
if (!group.Inverted)
|
if (!group.Inverted)
|
||||||
{
|
{
|
||||||
var transition = new AnimatorStateTransition
|
var transition = new AnimatorStateTransition
|
||||||
@ -327,13 +331,13 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
hasFixedDuration = true,
|
hasFixedDuration = true,
|
||||||
conditions = (AnimatorCondition[])conditions.Clone()
|
conditions = (AnimatorCondition[])conditions.Clone()
|
||||||
};
|
};
|
||||||
transitions.Add(transition);
|
initialStateTransitionList.Add(transition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var cond in conditions)
|
foreach (var cond in conditions)
|
||||||
{
|
{
|
||||||
transitions.Add(new AnimatorStateTransition
|
initialStateTransitionList.Add(new AnimatorStateTransition
|
||||||
{
|
{
|
||||||
isExit = true,
|
isExit = true,
|
||||||
hasExitTime = false,
|
hasExitTime = false,
|
||||||
@ -343,7 +347,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var state = new AnimatorState();
|
var state = new AnimatorState();
|
||||||
|
|
||||||
@ -351,7 +354,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
state.name = group.ControllingConditions[0].DebugName.Replace(".", "_");
|
state.name = group.ControllingConditions[0].DebugName.Replace(".", "_");
|
||||||
|
|
||||||
state.motion = clip;
|
state.motion = clip;
|
||||||
state.writeDefaultValues = false;
|
state.writeDefaultValues = _writeDefaults;
|
||||||
states.Add(new ChildAnimatorState
|
states.Add(new ChildAnimatorState
|
||||||
{
|
{
|
||||||
position = new Vector3(x, y),
|
position = new Vector3(x, y),
|
||||||
@ -527,8 +530,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private void ApplyController(AnimatorStateMachine asm, string layerName)
|
private void ApplyController(AnimatorStateMachine asm, string layerName)
|
||||||
{
|
{
|
||||||
var fx = context.AvatarDescriptor.baseAnimationLayers
|
var fx = FindFxController();
|
||||||
.FirstOrDefault(l => l.type == VRCAvatarDescriptor.AnimLayerType.FX);
|
|
||||||
if (fx.animatorController == null)
|
if (fx.animatorController == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("No FX layer found");
|
throw new InvalidOperationException("No FX layer found");
|
||||||
@ -569,5 +572,13 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
).ToArray();
|
).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VRCAvatarDescriptor.CustomAnimLayer FindFxController()
|
||||||
|
{
|
||||||
|
var fx = context.AvatarDescriptor.baseAnimationLayers
|
||||||
|
.FirstOrDefault(l => l.type == VRCAvatarDescriptor.AnimLayerType.FX);
|
||||||
|
|
||||||
|
return fx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private const string PREFIX = "m_Materials.Array.data[";
|
private const string PREFIX = "m_Materials.Array.data[";
|
||||||
|
|
||||||
private PropCache<Renderer, ImmutableList<(int, Material)>> _cache = new(
|
private PropCache<Renderer, ImmutableList<(int, Material)>> _cache = new(
|
||||||
GetMaterialOverridesForRenderer, Enumerable.SequenceEqual
|
"GetMaterialOverridesForRenderer", GetMaterialOverridesForRenderer, Enumerable.SequenceEqual
|
||||||
);
|
);
|
||||||
|
|
||||||
private static ImmutableList<(int, Material)> GetMaterialOverridesForRenderer(ComputeContext ctx, Renderer r)
|
private static ImmutableList<(int, Material)> GetMaterialOverridesForRenderer(ComputeContext ctx, Renderer r)
|
||||||
|
@ -87,14 +87,15 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
foreach (var (paramName, list) in _mamiByParam)
|
foreach (var (paramName, list) in _mamiByParam)
|
||||||
{
|
{
|
||||||
// Assign automatic values first
|
// Assign automatic values first
|
||||||
float defaultValue;
|
int? defaultValue = null;
|
||||||
if (declaredParams.TryGetValue(paramName, out var p))
|
if (declaredParams.TryGetValue(paramName, out var p))
|
||||||
{
|
{
|
||||||
defaultValue = p.defaultValue;
|
defaultValue = (int) p.defaultValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
defaultValue = list.FirstOrDefault(m => m.isDefault && !m.automaticValue)?.Control?.value ?? 0;
|
var floatDefault = list.FirstOrDefault(m => m.isDefault && !m.automaticValue)?.Control?.value;
|
||||||
|
if (floatDefault.HasValue) defaultValue = (int) floatDefault.Value;
|
||||||
|
|
||||||
if (list.Count == 1 && list[0].isDefault && list[0].automaticValue)
|
if (list.Count == 1 && list[0].isDefault && list[0].automaticValue)
|
||||||
// If we have only a single entry, it's probably an on-off toggle, so we'll implicitly let 1
|
// If we have only a single entry, it's probably an on-off toggle, so we'll implicitly let 1
|
||||||
@ -103,7 +104,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
HashSet<int> usedValues = new();
|
HashSet<int> usedValues = new();
|
||||||
usedValues.Add((int)defaultValue);
|
if (defaultValue.HasValue) usedValues.Add(defaultValue.Value);
|
||||||
|
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
@ -113,6 +114,19 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!defaultValue.HasValue)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
if (!usedValues.Contains(i))
|
||||||
|
{
|
||||||
|
defaultValue = i;
|
||||||
|
usedValues.Add(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var nextValue = 1;
|
var nextValue = 1;
|
||||||
|
|
||||||
var valueType = VRCExpressionParameters.ValueType.Bool;
|
var valueType = VRCExpressionParameters.ValueType.Bool;
|
||||||
@ -125,7 +139,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (mami.isDefault)
|
if (mami.isDefault)
|
||||||
{
|
{
|
||||||
mami.Control.value = defaultValue;
|
mami.Control.value = defaultValue.GetValueOrDefault();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -153,7 +167,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
name = paramName,
|
name = paramName,
|
||||||
valueType = valueType,
|
valueType = valueType,
|
||||||
saved = isSaved,
|
saved = isSaved,
|
||||||
defaultValue = defaultValue,
|
defaultValue = defaultValue.GetValueOrDefault(),
|
||||||
networkSynced = isSynced
|
networkSynced = isSynced
|
||||||
};
|
};
|
||||||
newParameters[paramName] = newParam;
|
newParameters[paramName] = newParam;
|
||||||
|
@ -128,7 +128,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
n_nrm[i] = o_nrm[newToOrigVertIndex[i]];
|
n_nrm[i] = o_nrm[newToOrigVertIndex[i]];
|
||||||
n_tan[i] = o_tan[newToOrigVertIndex[i]];
|
n_tan[i] = o_tan[newToOrigVertIndex[i]];
|
||||||
}
|
}
|
||||||
catch (IndexOutOfRangeException e)
|
catch (IndexOutOfRangeException)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -250,7 +250,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
List<int> n2o = new List<int>(toRetainVertices.Length);
|
List<int> n2o = new List<int>(toRetainVertices.Length);
|
||||||
List<int> o2n = new List<int>(toRetainVertices.Length);
|
List<int> o2n = new List<int>(toRetainVertices.Length);
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < toRetainVertices.Length; j++)
|
for (int j = 0; j < toRetainVertices.Length; j++)
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using nadena.dev.modular_avatar.core.editor.Simulator;
|
|
||||||
using nadena.dev.ndmf.preview;
|
using nadena.dev.ndmf.preview;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
@ -60,8 +59,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PropCache<GameObject, ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>>>
|
private readonly PropCache<GameObject, ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>>>
|
||||||
_blendshapeCache = new(ShapesForAvatar);
|
_blendshapeCache = new("ShapesForAvatar", ShapesForAvatar);
|
||||||
|
|
||||||
private static ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>> ShapesForAvatar(ComputeContext context, GameObject avatarRoot)
|
private static ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>> ShapesForAvatar(ComputeContext context, GameObject avatarRoot)
|
||||||
{
|
{
|
||||||
@ -75,7 +74,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>>.Builder rendererStates =
|
ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>>.Builder rendererStates =
|
||||||
ImmutableDictionary.CreateBuilder<SkinnedMeshRenderer, ImmutableList<(int, float)>>(
|
ImmutableDictionary.CreateBuilder<SkinnedMeshRenderer, ImmutableList<(int, float)>>(
|
||||||
new ObjectIdentityComparer<SkinnedMeshRenderer>()
|
|
||||||
);
|
);
|
||||||
var avatarRootTransform = avatarRoot.transform;
|
var avatarRootTransform = avatarRoot.transform;
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
// these properties in a closure
|
// these properties in a closure
|
||||||
_menuItemOverrideProperty = prop;
|
_menuItemOverrideProperty = prop;
|
||||||
_menuItemOverrideTarget = mami;
|
_menuItemOverrideTarget = mami;
|
||||||
soc.OnStateOverrideChanged += MenuItemOverrideChanged;
|
soc.OnStateOverrideChanged = MenuItemOverrideChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MenuItemOverrideChanged(bool? obj)
|
private void MenuItemOverrideChanged(bool? obj)
|
||||||
@ -319,7 +319,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
|
|
||||||
_propertyOverrideProperty = property;
|
_propertyOverrideProperty = property;
|
||||||
_propertyOverrideTargetValue = targetValue;
|
_propertyOverrideTargetValue = targetValue;
|
||||||
soc.OnStateOverrideChanged += OnParameterOverrideChanged;
|
soc.OnStateOverrideChanged = OnParameterOverrideChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnParameterOverrideChanged(bool? state)
|
private void OnParameterOverrideChanged(bool? state)
|
||||||
@ -539,11 +539,11 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
soc.SetWithoutNotify(menuOverride);
|
soc.SetWithoutNotify(menuOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
soc.OnStateOverrideChanged += value => { UpdateMenuItemOverride(prop, mami, value); };
|
soc.OnStateOverrideChanged = value => { UpdateMenuItemOverride(prop, mami, value); };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
soc.OnStateOverrideChanged += value => UpdatePropertyOverride(prop, value, targetValue);
|
soc.OnStateOverrideChanged = value => UpdatePropertyOverride(prop, value, targetValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
var active = condition.InitiallyActive;
|
var active = condition.InitiallyActive;
|
||||||
|
@ -16,7 +16,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private static StyleSheet uss;
|
private static StyleSheet uss;
|
||||||
private Button btn_disable, btn_default, btn_enable;
|
private Button btn_disable, btn_default, btn_enable;
|
||||||
public event System.Action<bool?> OnStateOverrideChanged;
|
public System.Action<bool?> OnStateOverrideChanged;
|
||||||
|
|
||||||
public StateOverrideController()
|
public StateOverrideController()
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,7 @@ namespace nadena.dev.modular_avatar.core.editor.ScaleAdjuster
|
|||||||
public BoneState parentHint;
|
public BoneState parentHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<Component, BoneState> _bones = new(new ObjectIdentityComparer<Component>());
|
private readonly Dictionary<Component, BoneState> _bones = new();
|
||||||
//private List<BoneState> _states = new List<BoneState>();
|
//private List<BoneState> _states = new List<BoneState>();
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
@ -59,7 +59,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var scaleAdjusters = ctx.GetComponentsByType<ModularAvatarScaleAdjuster>();
|
var scaleAdjusters = ctx.GetComponentsByType<ModularAvatarScaleAdjuster>();
|
||||||
|
|
||||||
var avatarToRenderer =
|
var avatarToRenderer =
|
||||||
new Dictionary<GameObject, HashSet<Renderer>>(new ObjectIdentityComparer<GameObject>());
|
new Dictionary<GameObject, HashSet<Renderer>>();
|
||||||
|
|
||||||
foreach (var root in ctx.GetAvatarRoots())
|
foreach (var root in ctx.GetAvatarRoots())
|
||||||
{
|
{
|
||||||
@ -73,7 +73,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
continue; // nested avatar descriptor
|
continue; // nested avatar descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
var renderers = new HashSet<Renderer>(new ObjectIdentityComparer<Renderer>());
|
var renderers = new HashSet<Renderer>();
|
||||||
avatarToRenderer.Add(root, renderers);
|
avatarToRenderer.Add(root, renderers);
|
||||||
|
|
||||||
foreach (var renderer in root.GetComponentsInChildren<Renderer>())
|
foreach (var renderer in root.GetComponentsInChildren<Renderer>())
|
||||||
@ -97,6 +97,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
internal class ScaleAdjusterPreviewNode : IRenderFilterNode
|
internal class ScaleAdjusterPreviewNode : IRenderFilterNode
|
||||||
{
|
{
|
||||||
|
private readonly HashSet<Transform> _knownProxies = new();
|
||||||
|
|
||||||
private readonly GameObject SourceAvatarRoot;
|
private readonly GameObject SourceAvatarRoot;
|
||||||
private readonly GameObject VirtualAvatarRoot;
|
private readonly GameObject VirtualAvatarRoot;
|
||||||
|
|
||||||
@ -110,12 +112,12 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private readonly Dictionary<Transform, Transform> _shadowBoneMap;
|
private readonly Dictionary<Transform, Transform> _shadowBoneMap;
|
||||||
|
|
||||||
// Map from bones found in initial proxy state to shadow bones (with scale adjuster bones substituted)
|
// Map from bones found in initial proxy state to shadow bones (with scale adjuster bones substituted)
|
||||||
private readonly Dictionary<Transform, Transform> _finalBonesMap = new(new ObjectIdentityComparer<Transform>());
|
private readonly Dictionary<Transform, Transform> _finalBonesMap = new();
|
||||||
|
|
||||||
private readonly Dictionary<ModularAvatarScaleAdjuster, Transform> _scaleAdjusters =
|
private readonly Dictionary<ModularAvatarScaleAdjuster, Transform> _scaleAdjusters =
|
||||||
new(new ObjectIdentityComparer<ModularAvatarScaleAdjuster>());
|
new();
|
||||||
|
|
||||||
private Dictionary<Renderer, Transform[]> _rendererBoneStates = new(new ObjectIdentityComparer<Renderer>());
|
private Dictionary<Renderer, Transform[]> _rendererBoneStates = new();
|
||||||
|
|
||||||
public ScaleAdjusterPreviewNode(ComputeContext context, RenderGroup group,
|
public ScaleAdjusterPreviewNode(ComputeContext context, RenderGroup group,
|
||||||
IEnumerable<(Renderer, Renderer)> proxyPairs)
|
IEnumerable<(Renderer, Renderer)> proxyPairs)
|
||||||
@ -167,7 +169,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private HashSet<Transform> GetSourceBonesSet(ComputeContext context, List<(Renderer, Renderer)> proxyPairs)
|
private HashSet<Transform> GetSourceBonesSet(ComputeContext context, List<(Renderer, Renderer)> proxyPairs)
|
||||||
{
|
{
|
||||||
var bonesSet = new HashSet<Transform>(new ObjectIdentityComparer<Transform>());
|
var bonesSet = new HashSet<Transform>();
|
||||||
foreach (var (_, r) in proxyPairs)
|
foreach (var (_, r) in proxyPairs)
|
||||||
{
|
{
|
||||||
if (r == null) continue;
|
if (r == null) continue;
|
||||||
@ -230,6 +232,9 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (SourceAvatarRoot == null) return Task.FromResult<IRenderFilterNode>(null);
|
if (SourceAvatarRoot == null) return Task.FromResult<IRenderFilterNode>(null);
|
||||||
|
|
||||||
|
// Clean any destroyed objects out of _knownProxies to avoid growing this set indefinitely
|
||||||
|
_knownProxies.RemoveWhere(p => p == null);
|
||||||
|
|
||||||
var proxyPairList = proxyPairs.ToList();
|
var proxyPairList = proxyPairs.ToList();
|
||||||
|
|
||||||
if (!GetSourceBonesSet(context, proxyPairList).SetEquals(_shadowBoneMap.Keys))
|
if (!GetSourceBonesSet(context, proxyPairList).SetEquals(_shadowBoneMap.Keys))
|
||||||
@ -243,7 +248,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private Dictionary<Transform, Transform> CreateShadowBones(Transform[] srcBones)
|
private Dictionary<Transform, Transform> CreateShadowBones(Transform[] srcBones)
|
||||||
{
|
{
|
||||||
var srcToDst = new Dictionary<Transform, Transform>(new ObjectIdentityComparer<Transform>());
|
var srcToDst = new Dictionary<Transform, Transform>();
|
||||||
|
|
||||||
for (var i = 0; i < srcBones.Length; i++) GetShadowBone(srcBones[i]);
|
for (var i = 0; i < srcBones.Length; i++) GetShadowBone(srcBones[i]);
|
||||||
|
|
||||||
@ -339,7 +344,15 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
if (proxy == null) return;
|
if (proxy == null) return;
|
||||||
|
|
||||||
var curParent = proxy.transform.parent ?? original.transform.parent;
|
var curParent = proxy.transform.parent ?? original.transform.parent;
|
||||||
if (_finalBonesMap.TryGetValue(curParent, out var newRoot)) proxy.transform.SetParent(newRoot, false);
|
if (_finalBonesMap.TryGetValue(curParent, out var newRoot))
|
||||||
|
{
|
||||||
|
// We need to remember this proxy so we can avoid destroying it when we destroy VirtualAvatarRoot
|
||||||
|
// in Dispose
|
||||||
|
|
||||||
|
_knownProxies.Add(proxy.transform);
|
||||||
|
|
||||||
|
proxy.transform.SetParent(newRoot, false);
|
||||||
|
}
|
||||||
|
|
||||||
var smr = proxy as SkinnedMeshRenderer;
|
var smr = proxy as SkinnedMeshRenderer;
|
||||||
if (smr == null) return;
|
if (smr == null) return;
|
||||||
@ -351,6 +364,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
foreach (var proxy in _knownProxies)
|
||||||
|
{
|
||||||
|
if (proxy != null && proxy.IsChildOf(VirtualAvatarRoot.transform))
|
||||||
|
{
|
||||||
|
proxy.transform.SetParent(null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Object.DestroyImmediate(VirtualAvatarRoot);
|
Object.DestroyImmediate(VirtualAvatarRoot);
|
||||||
|
|
||||||
_srcBones.Dispose();
|
_srcBones.Dispose();
|
||||||
|
@ -390,7 +390,13 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private static bool ValidateSetupOutfit(GameObject gameObj)
|
private static bool ValidateSetupOutfit(GameObject gameObj)
|
||||||
{
|
{
|
||||||
Object obj;
|
if (gameObj == null)
|
||||||
|
{
|
||||||
|
errorHeader = S("setup_outfit.err.header.notarget");
|
||||||
|
errorMessageGroups = new string[] { S("setup_outfit.err.no_selection") };
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
errorHeader = S_f("setup_outfit.err.header", gameObj.name);
|
errorHeader = S_f("setup_outfit.err.header", gameObj.name);
|
||||||
var xform = gameObj.transform;
|
var xform = gameObj.transform;
|
||||||
|
|
||||||
|
@ -205,6 +205,13 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
|
|
||||||
Transform iter = newTarget;
|
Transform iter = newTarget;
|
||||||
|
|
||||||
|
if (newTarget == null)
|
||||||
|
{
|
||||||
|
boneReference = HumanBodyBones.LastBone;
|
||||||
|
subPath = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (newTarget == avatarTransform)
|
if (newTarget == avatarTransform)
|
||||||
{
|
{
|
||||||
boneReference = HumanBodyBones.LastBone;
|
boneReference = HumanBodyBones.LastBone;
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#region
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
namespace nadena.dev.modular_avatar
|
|
||||||
{
|
|
||||||
internal class ObjectIdentityComparer<T> : IEqualityComparer<T>
|
|
||||||
{
|
|
||||||
public bool Equals(T x, T y)
|
|
||||||
{
|
|
||||||
return (object)x == (object)y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHashCode(T obj)
|
|
||||||
{
|
|
||||||
if (obj == null) return 0;
|
|
||||||
return RuntimeHelpers.GetHashCode(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e674cbd75db24fb2b238674cd7010edb
|
|
||||||
timeCreated: 1709448428
|
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using nadena.dev.ndmf;
|
using nadena.dev.ndmf;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -28,6 +29,11 @@ namespace modular_avatar_tests
|
|||||||
return transformMaskElements.SequenceEqual(other.transformMaskElements);
|
return transformMaskElements.SequenceEqual(other.transformMaskElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(humanoidMaskElements, transformMaskElements);
|
||||||
|
}
|
||||||
|
|
||||||
public static ExtractedMask FromAvatarMask(AvatarMask mask)
|
public static ExtractedMask FromAvatarMask(AvatarMask mask)
|
||||||
{
|
{
|
||||||
var so = new SerializedObject(mask);
|
var so = new SerializedObject(mask);
|
||||||
|
@ -19,7 +19,7 @@ namespace UnitTests.PropCacheTest
|
|||||||
int seq = 0;
|
int seq = 0;
|
||||||
|
|
||||||
Dictionary<int, List<WeakReference<ComputeContext>>> invalidators = new();
|
Dictionary<int, List<WeakReference<ComputeContext>>> invalidators = new();
|
||||||
PropCache<int,int> cache = new PropCache<int, int>((ctx, k) =>
|
PropCache<int,int> cache = new PropCache<int, int>("test", (ctx, k) =>
|
||||||
{
|
{
|
||||||
Debug.Log("Generating value for " + k);
|
Debug.Log("Generating value for " + k);
|
||||||
if (!invalidators.TryGetValue(k, out var list))
|
if (!invalidators.TryGetValue(k, out var list))
|
||||||
|
@ -48,13 +48,18 @@ namespace UnitTests.ReactiveComponent.ParameterAssignment
|
|||||||
{
|
{
|
||||||
TestAssignments(new[] { (false, 2.0f), (true, 0.0f), (true, 0.0f) }, new[] { 2.0f, 1.0f, 3.0f }, null);
|
TestAssignments(new[] { (false, 2.0f), (true, 0.0f), (true, 0.0f) }, new[] { 2.0f, 1.0f, 3.0f }, null);
|
||||||
TestAssignments(new[] { (false, 2.7f), (true, 0.0f), (true, 0.0f) }, new[] { 2.7f, 1.0f, 3.0f }, null);
|
TestAssignments(new[] { (false, 2.7f), (true, 0.0f), (true, 0.0f) }, new[] { 2.7f, 1.0f, 3.0f }, null);
|
||||||
|
TestAssignments(new[] { (true, 1.0f), (false, 0.0f) }, new[] { 2.0f, 0.0f }, null, overrideExpectedDefaultValue: 1.0f);
|
||||||
|
TestAssignments(new[] { (true, 1.0f), (false, 0.0f) }, new[] { 1.0f, 0.0f }, 0);
|
||||||
|
TestAssignments(new[] { (true, 1.0f), (false, 0.0f) }, new[] { 1.0f, 0.0f }, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAssignments(
|
void TestAssignments(
|
||||||
(bool, float)[] assignments,
|
(bool, float)[] assignments,
|
||||||
float[] expectedAssignments,
|
float[] expectedAssignments,
|
||||||
int? defaultIndex = null,
|
int? defaultIndex = null,
|
||||||
Action<List<ModularAvatarMenuItem>> customize = null
|
Action<List<ModularAvatarMenuItem>> customize = null,
|
||||||
|
float? overrideExpectedDefaultValue = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var root = CreateRoot("root");
|
var root = CreateRoot("root");
|
||||||
@ -103,7 +108,7 @@ namespace UnitTests.ReactiveComponent.ParameterAssignment
|
|||||||
Assert.AreEqual(expected, mami.Control.value);
|
Assert.AreEqual(expected, mami.Control.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedDefaultValue = defaultIndex.HasValue ? expectedAssignments[defaultIndex.Value] : 0;
|
var expectedDefaultValue = overrideExpectedDefaultValue ?? (defaultIndex.HasValue ? expectedAssignments[defaultIndex.Value] : 0);
|
||||||
Assert.AreEqual(expectedDefaultValue, avDesc.expressionParameters.parameters.Single().defaultValue);
|
Assert.AreEqual(expectedDefaultValue, avDesc.expressionParameters.parameters.Single().defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,18 @@ designed for a specific avatar.
|
|||||||
|
|
||||||
## Manually configuring Mesh Settings
|
## Manually configuring Mesh Settings
|
||||||
|
|
||||||
When you add Mesh Settings to a game object, initially it is configured to do nothing. By setting either
|
When you add Mesh Settings to a game object, initially it is configured to do nothing. In order for the settings
|
||||||
"Anchor Override Mode" or "Bounds Override Mode" to "Set", you can configure the anchor override or bounds
|
component to have any effect, you need to change the "Anchor Override Mode" and/or "Bounds Override Mode". These
|
||||||
for all meshes under that game object. Alternately, by setting the mode to "Don't set", you can exclude
|
support the following options:
|
||||||
these meshes from the influence of Mesh Settings higher up on the hierarchy.
|
|
||||||
|
- Inherit: This component does nothing for this setting; it will inherit values set in parent Mesh Settings.
|
||||||
|
- Set: This component sets the corresponding setting on any meshes on its GameObject or its children.
|
||||||
|
- Don't set: This component _blocks_ any parent Mesh Settings from having an effect. Meshes will remain at their default
|
||||||
|
settings.
|
||||||
|
- Set or inherit: If there is a parent Mesh Settings in Set mode, it will be used. If no parent Mesh Settings applies,
|
||||||
|
then this component's settings will be used. This is useful for outfit prefabs, to ensure that any avatar-wide
|
||||||
|
settings
|
||||||
|
take precedence.
|
||||||
|
|
||||||
When configuring bounds, the bounding box will be determined relative to the transform you specify as the
|
When configuring bounds, the bounding box will be determined relative to the transform you specify as the
|
||||||
"Root Bone". Note that bounds only affects Skinned Mesh Renderers, but Anchor Override also impacts other
|
"Root Bone". Note that bounds only affects Skinned Mesh Renderers, but Anchor Override also impacts other
|
||||||
|
@ -22,5 +22,3 @@ Just attach a Visible Head Accessory component under a child of the Head bone. T
|
|||||||
|
|
||||||
The component will automatically generate a clone of the Head bone, which is connected to the real head bone using a parent constraint.
|
The component will automatically generate a clone of the Head bone, which is connected to the real head bone using a parent constraint.
|
||||||
Only one constraint will be generated, even if multiple Visible Head Accessory components are used. As such, the performance impact of this component is the same whether you use one or dozens.
|
Only one constraint will be generated, even if multiple Visible Head Accessory components are used. As such, the performance impact of this component is the same whether you use one or dozens.
|
||||||
|
|
||||||
Due to technical limitations on the Quest, this component has no effect when building for Quest standalone.
|
|
||||||
|
@ -21,9 +21,16 @@ Mesh Settingsコンポーネントを使用すると、特定のゲームオブ
|
|||||||
|
|
||||||
## Mesh Settingsの手動設定
|
## Mesh Settingsの手動設定
|
||||||
|
|
||||||
ゲームオブジェクトにMesh Settingsを追加すると、最初は何も効果がありません。Anchor Overrideの設定モードまたはBounds Override
|
ゲームオブジェクトにMesh Settingsを追加すると、最初は何も効果がありません。効果を発揮するには、まずは「Anchor Override
|
||||||
の設定モードを「設定」に設定することで、そのゲームオブジェクトの下にあるすべてのメッシュのアンカーオーバーライドまたはバウンズ
|
設定」あるいは
|
||||||
を設定できます。また、モードを「設定しない」に設定することで、これらのメッシュを階層の上位にあるMesh Settingsの影響から除外できます。
|
「Bounds 設定」で「設定モード」を変更する必要があります。以下の選択しがあります。
|
||||||
|
|
||||||
|
- 継承:このコンポーネントはこの設定に対して何もしません。親のMesh Settingsで設定された値を継承します。
|
||||||
|
- 設定:このコンポーネントは、そのゲームオブジェクトとその子にあるメッシュの対応する設定を設定します。
|
||||||
|
- 設定しない:このコンポーネントは、親のMesh Settingsの影響を受けないようにします。メッシュはデフォルトの設定のままです。
|
||||||
|
- 親が継承された時は継承、または設定:親のMesh Settingsが設定モードにある場合、それが使用されます。親のMesh
|
||||||
|
Settingsが適用されない場合、
|
||||||
|
このコンポーネントの設定が使用されます。衣装プレハブなどに、アバター全体の設定が優先されるようにするために便利です。
|
||||||
|
|
||||||
バウンズを設定する場合、バウンディングボックスは「Root Bone」として指定したトランスフォームに対して相対的に決定されます。
|
バウンズを設定する場合、バウンディングボックスは「Root Bone」として指定したトランスフォームに対して相対的に決定されます。
|
||||||
また、バウンズはSkinned Mesh Rendererのみに影響しますが、Anchor OverrideはMesh RendererやLine Rendererなどの他のタイプの
|
また、バウンズはSkinned Mesh Rendererのみに影響しますが、Anchor OverrideはMesh RendererやLine Rendererなどの他のタイプの
|
||||||
|
@ -22,5 +22,3 @@ Headボーンの子にVisible Head Accessoryコンポーネントを付けるだ
|
|||||||
|
|
||||||
このコンポーネントは自動的にHeadボーンを複製し、Parent Constraintで本物のHeadボーンに追従させます。
|
このコンポーネントは自動的にHeadボーンを複製し、Parent Constraintで本物のHeadボーンに追従させます。
|
||||||
複数のVisible Head Accessoryコンポーネントを使っても、Constraintは一つだけです。なので、複数のボーンを指定しても、その分重くなることはありません。
|
複数のVisible Head Accessoryコンポーネントを使っても、Constraintは一つだけです。なので、複数のボーンを指定しても、その分重くなることはありません。
|
||||||
|
|
||||||
技術的な制約により、Quest単体では動作できません。Quest向けのビルドはつけたままにしてもいいが、効果は発揮しません。
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "nadena.dev.modular-avatar",
|
"name": "nadena.dev.modular-avatar",
|
||||||
"displayName": "Modular Avatar",
|
"displayName": "Modular Avatar",
|
||||||
"version": "1.10.0-rc.6",
|
"version": "1.10.0-rc.9",
|
||||||
"unity": "2022.3",
|
"unity": "2022.3",
|
||||||
"description": "A suite of tools for assembling your avatar out of reusable components",
|
"description": "A suite of tools for assembling your avatar out of reusable components",
|
||||||
"author": {
|
"author": {
|
||||||
@ -16,6 +16,6 @@
|
|||||||
},
|
},
|
||||||
"vpmDependencies": {
|
"vpmDependencies": {
|
||||||
"com.vrchat.avatars": ">=3.7.0",
|
"com.vrchat.avatars": ">=3.7.0",
|
||||||
"nadena.dev.ndmf": ">=1.5.0-rc.7 <2.0.0-a"
|
"nadena.dev.ndmf": ">=1.5.0-rc.10 <2.0.0-a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user