diff --git a/Editor/Inspector/MaterialSetter/MaterialSetter.uxml b/Editor/Inspector/MaterialSetter/MaterialSetter.uxml index d5b38020..ea0ee768 100644 --- a/Editor/Inspector/MaterialSetter/MaterialSetter.uxml +++ b/Editor/Inspector/MaterialSetter/MaterialSetter.uxml @@ -2,6 +2,8 @@ xmlns:ma="nadena.dev.modular_avatar.core.editor"> + + - - \ No newline at end of file diff --git a/Editor/Inspector/MaterialSetter/MaterialSetterStyles.uss b/Editor/Inspector/MaterialSetter/MaterialSetterStyles.uss index a29ce1e3..8b429bd5 100644 --- a/Editor/Inspector/MaterialSetter/MaterialSetterStyles.uss +++ b/Editor/Inspector/MaterialSetter/MaterialSetterStyles.uss @@ -32,4 +32,16 @@ #f-material-index-int { display: none; +} + +#f-material { + flex-grow: 1; +} + +.horizontal > Label { + align-self: center; +} + +#f-object > * { + margin-left: 0; } \ No newline at end of file diff --git a/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.cs b/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.cs index dc376550..ca9697c0 100644 --- a/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.cs +++ b/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.cs @@ -28,9 +28,43 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger var f_material_index = uxml.Q("f-material-index"); - var f_object = uxml.Q("f-object"); - f_object.RegisterValueChangeCallback(evt => { UpdateMaterialDropdown(); }); + var f_object = uxml.Q("f-object"); + f_object.objectType = typeof(Renderer); + f_object.allowSceneObjects = true; + + var f_target_object = uxml.Q("f-obj-target-object"); + var f_reference_path = uxml.Q("f-obj-ref-path"); + + f_object.RegisterValueChangedCallback(evt => + { + var gameObj = (evt.newValue as Renderer)?.gameObject; + + if (gameObj == null) + { + f_target_object.value = null; + f_reference_path.value = ""; + } + else + { + var path = RuntimeUtil.AvatarRootPath(gameObj); + + f_reference_path.value = path; + if (path == "") + { + f_target_object.value = null; + } + else + { + f_target_object.value = gameObj; + } + } + + EditorApplication.delayCall += UpdateMaterialDropdown; + }); UpdateMaterialDropdown(); + + f_target_object.RegisterValueChangedCallback(_ => UpdateVisualTarget()); + f_reference_path.RegisterValueChangedCallback(_ => UpdateVisualTarget()); // Link dropdown to material index field var f_material_index_int = uxml.Q("f-material-index-int"); @@ -49,6 +83,23 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger return uxml; + void UpdateVisualTarget() + { + var targetObject = AvatarObjectReference.Get(property.FindPropertyRelative("Object")); + Renderer targetRenderer; + + try + { + targetRenderer = targetObject?.GetComponent(); + } + catch (MissingComponentException e) + { + targetRenderer = null; + } + + f_object.SetValueWithoutNotify(targetRenderer); + } + void UpdateMaterialDropdown() { var toggledObject = AvatarObjectReference.Get(property.FindPropertyRelative("Object")); diff --git a/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.uxml b/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.uxml index 0a468f68..ca9afd40 100644 --- a/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.uxml +++ b/Editor/Inspector/MaterialSetter/MaterialSwitchObjectEditor.uxml @@ -1,10 +1,19 @@  - + + - + + + + + + + + + + - \ No newline at end of file diff --git a/Editor/Inspector/Menu/MenuPreviewGUI.cs b/Editor/Inspector/Menu/MenuPreviewGUI.cs index dc605814..9a2fe0ab 100644 --- a/Editor/Inspector/Menu/MenuPreviewGUI.cs +++ b/Editor/Inspector/Menu/MenuPreviewGUI.cs @@ -206,6 +206,7 @@ namespace nadena.dev.modular_avatar.core.editor if (source is MenuNodesUnder nodesUnder) { + GUILayout.BeginHorizontal(); if (GUILayout.Button(G("menuitem.misc.add_item"))) { var newChild = new GameObject(); @@ -214,6 +215,29 @@ namespace nadena.dev.modular_avatar.core.editor newChild.AddComponent(); Undo.RegisterCreatedObjectUndo(newChild, "Added menu item"); } + + if (GUILayout.Button(G("menuitem.misc.add_toggle"))) + { + var newChild = new GameObject(); + newChild.name = "New toggle"; + newChild.transform.SetParent(nodesUnder.root.transform, false); + + var mami = newChild.AddComponent(); + mami.Control = new VRCExpressionsMenu.Control() + { + type = VRCExpressionsMenu.Control.ControlType.Toggle, + value = 1, + }; + mami.isSaved = true; + mami.isSynced = true; + + newChild.AddComponent(); + + Selection.activeObject = newChild; + Undo.RegisterCreatedObjectUndo(newChild, "Added menu toggle"); + } + + GUILayout.EndHorizontal(); } } } diff --git a/Editor/Inspector/Menu/ToggleCreatorShortcut.cs b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs new file mode 100644 index 00000000..56105421 --- /dev/null +++ b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs @@ -0,0 +1,62 @@ +using nadena.dev.modular_avatar.ui; +using UnityEditor; +using UnityEngine; +using VRC.SDK3.Avatars.ScriptableObjects; + +namespace nadena.dev.modular_avatar.core.editor +{ + internal static class ToggleCreatorShortcut + { + [MenuItem(UnityMenuItems.GameObject_CreateToggle, false, UnityMenuItems.GameObject_CreateToggleOrder)] + private static void CreateToggle() + { + var selected = Selection.activeGameObject; + if (selected == null) return; + + var avatarRoot = RuntimeUtil.FindAvatarTransformInParents(selected.transform); + if (avatarRoot == null) return; + + bool createInstaller = true; + Transform parent = avatarRoot; + + try + { + var selectedMenuItem = selected.GetComponent(); + if (selectedMenuItem?.Control?.type == VRCExpressionsMenu.Control.ControlType.SubMenu + && selectedMenuItem.MenuSource == SubmenuSource.Children + ) + { + parent = selected.transform; + createInstaller = false; + } + } + catch (MissingComponentException e) + { + // ignore + } + + var toggle = new GameObject("New Toggle"); + + var objToggle = toggle.AddComponent(); + + toggle.transform.SetParent(parent, false); + toggle.AddComponent().Control = new VRCExpressionsMenu.Control + { + type = VRCExpressionsMenu.Control.ControlType.Toggle, + name = "New Toggle", + value = 1, + }; + + if (createInstaller) + { + toggle.AddComponent(); + } + + Selection.activeGameObject = toggle; + EditorGUIUtility.PingObject(objToggle); + + + Undo.RegisterCreatedObjectUndo(toggle, "Create Toggle"); + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/Menu/ToggleCreatorShortcut.cs.meta b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs.meta new file mode 100644 index 00000000..4b9775c0 --- /dev/null +++ b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7e15fef260544783af5ff1fd5f13acd3 +timeCreated: 1723341065 \ No newline at end of file diff --git a/Editor/Inspector/ObjectToggle/ObjectSwitcher.uxml b/Editor/Inspector/ObjectToggle/ObjectSwitcher.uxml index d5b38020..a1771d76 100644 --- a/Editor/Inspector/ObjectToggle/ObjectSwitcher.uxml +++ b/Editor/Inspector/ObjectToggle/ObjectSwitcher.uxml @@ -2,6 +2,8 @@ xmlns:ma="nadena.dev.modular_avatar.core.editor"> + + - - \ No newline at end of file diff --git a/Editor/Inspector/ShapeChanger/ShapeChanger.uxml b/Editor/Inspector/ShapeChanger/ShapeChanger.uxml index 8f3ad838..b3b5db99 100644 --- a/Editor/Inspector/ShapeChanger/ShapeChanger.uxml +++ b/Editor/Inspector/ShapeChanger/ShapeChanger.uxml @@ -2,8 +2,8 @@ xmlns:ma="nadena.dev.modular_avatar.core.editor"> - - + + - - \ No newline at end of file diff --git a/Editor/Localization/en-US.json b/Editor/Localization/en-US.json index d48d07fb..71c70a18 100644 --- a/Editor/Localization/en-US.json +++ b/Editor/Localization/en-US.json @@ -247,5 +247,8 @@ "ma_info.param_usage_ui.other_objects": "Other objects on this avatar", "ma_info.param_usage_ui.free_space": "Unused parameter space ({0} bits)", "ma_info.param_usage_ui.bits_template": "{0} ({1} bits)", - "ma_info.param_usage_ui.no_data": "[ NO DATA ]" + "ma_info.param_usage_ui.no_data": "[ NO DATA ]", + "reactive_object.inverse": "Inverse Condition", + "reactive_object.material-setter.set-to": "Set material to: ", + "reactive_object.shape-changer.target-renderer": "Target Renderer" } \ No newline at end of file diff --git a/Editor/Localization/ja-JP.json b/Editor/Localization/ja-JP.json index 0598fe0a..f56b9598 100644 --- a/Editor/Localization/ja-JP.json +++ b/Editor/Localization/ja-JP.json @@ -243,5 +243,8 @@ "ma_info.param_usage_ui.other_objects": "このアバター内の他のオブジェクト", "ma_info.param_usage_ui.free_space": "未使用領域 ({0} 個のビット)", "ma_info.param_usage_ui.bits_template": "{0} ({1} 個のビットを使用中)", - "ma_info.param_usage_ui.no_data": "[ NO DATA ]" + "ma_info.param_usage_ui.no_data": "[ NO DATA ]", + "reactive_object.inverse": "条件を反転", + "reactive_object.material-setter.set-to": "変更先のマテリアル", + "reactive_object.shape-changer.target-renderer": "操作するレンダラー" } \ No newline at end of file diff --git a/Runtime/ModularAvatarMenuItem.cs b/Runtime/ModularAvatarMenuItem.cs index 13fedb3c..cf8d8f6a 100644 --- a/Runtime/ModularAvatarMenuItem.cs +++ b/Runtime/ModularAvatarMenuItem.cs @@ -1,5 +1,6 @@ #if MA_VRCSDK3_AVATARS +using System; using System.Linq; using nadena.dev.modular_avatar.core.menu; using UnityEngine; @@ -42,6 +43,18 @@ namespace nadena.dev.modular_avatar.core /// public bool isDefault; + private void Reset() + { + Control = new VRCExpressionsMenu.Control(); + Control.type = VRCExpressionsMenu.Control.ControlType.Toggle; + Control.value = 1; + isSaved = true; + isSynced = true; + isDefault = false; + + MenuSource = SubmenuSource.Children; + } + protected override void OnValidate() { base.OnValidate(); diff --git a/Runtime/UI/UnityMenuItems.cs b/Runtime/UI/UnityMenuItems.cs index 0de512b7..a9a9c944 100644 --- a/Runtime/UI/UnityMenuItems.cs +++ b/Runtime/UI/UnityMenuItems.cs @@ -4,9 +4,12 @@ { internal const string GameObject_SetupOutfit = "GameObject/Modular Avatar/Setup Outfit"; internal const int GameObject_SetupOutfitOrder = -1000; + + internal const string GameObject_CreateToggle = "GameObject/Modular Avatar/Create Toggle"; + internal const int GameObject_CreateToggleOrder = GameObject_SetupOutfitOrder + 1; internal const string GameObject_ManualBake = "GameObject/Modular Avatar/Manual Bake Avatar"; - internal const int GameObject_ManualBakeOrder = GameObject_SetupOutfitOrder + 1; + internal const int GameObject_ManualBakeOrder = GameObject_CreateToggleOrder + 1; // @@ -14,7 +17,7 @@ internal const int GameObject_EnableInfoOrder = -799; internal const string GameObject_ExtractMenu = "GameObject/Modular Avatar/Extract Menu"; - internal const int GameObject_ExtractMenuOrder = GameObject_EnableInfoOrder + 1; + internal const int GameObject_ExtractMenuOrder = GameObject_EnableInfoOrder + 100;