private void SubControl(VRCExpressionsMenu.Control control, int controlIndex, LyumaAv3Menu menu, string labelType) { var parameterName = control.parameter.name; var intValue = (int)control.value; var isActive = menu.IsVisualActive(parameterName, intValue); EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(menu.HasActiveControl() && !menu.IsActiveControl(controlIndex)); if (GreenBackground(isActive || menu.IsActiveControl(controlIndex), () => ParameterizedButton(control, parameterName, intValue))) { if (!menu.IsActiveControl(controlIndex)) { if (IsValidParameterName(parameterName)) { menu.UserControlEnter(controlIndex, parameterName, intValue); } else { menu.UserControlEnter(controlIndex); } } else { menu.UserControlExit(); } } EditorGUI.EndDisabledGroup(); LabelType(labelType); EditorGUILayout.EndHorizontal(); }
internal void ExpressionParameterReset(VRCExpressionsMenu.Control control) { if (!string.IsNullOrEmpty(control.parameter.name)) { SetExpressionParameter(control.parameter.name, 0); } }
public RadialButton CreateButton(VRCExpressionsMenu.Control control, float xpos, float ypos) { RadialButton newButton = Instantiate(RadialMenuController.current.ButtonPrefab) as RadialButton; Button selectable = newButton.GetComponent <Button>(); if (null == control) { if (null == Parent) { selectable.interactable = false; control = new VRCExpressionsMenu.Control() { icon = RadialMenuController.current.HomeIcon, name = "home" }; } else { selectable.onClick.AddListener(delegate { RadialMenuController.current.SwapMenu(this, Parent); }); control = new VRCExpressionsMenu.Control() { icon = RadialMenuController.current.BackIcon, name = "back" }; } } newButton.Initialize(this, control, xpos, ypos); newButton.gameObject.name = control.name; return(newButton); }
private static Emh.EmhType TypeOf(VRCExpressionsMenu.Control control) { switch (control.type) { case VRCExpressionsMenu.Control.ControlType.Button: return(Emh.EmhType.Button); case VRCExpressionsMenu.Control.ControlType.Toggle: return(Emh.EmhType.Toggle); case VRCExpressionsMenu.Control.ControlType.SubMenu: return(Emh.EmhType.SubMenu); case VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet: return(Emh.EmhType.TwoAxisPuppet); case VRCExpressionsMenu.Control.ControlType.FourAxisPuppet: return(Emh.EmhType.FourAxisPuppet); case VRCExpressionsMenu.Control.ControlType.RadialPuppet: return(Emh.EmhType.RadialPuppet); default: throw new ArgumentOutOfRangeException(); } }
public RadialMenuControl(RadialMenu menu, VRCExpressionsMenu.Control control) : base(control.name, control.icon, control.type, control.value) { _menu = menu; _subMenu = control.subMenu; _subLabels = control.labels; _parameter = menu.GetParam(control.parameter.name); _subParameters = control.subParameters.Select(parameter => menu.GetParam(parameter.name)).ToArray(); }
public static VRCExpressionsMenu.Control AddVRCExpressionsMenuControl(VRCExpressionsMenu menu, ControlType controlType, string parameterName, List <Object> dirtyAssets) { var control = new VRCExpressionsMenu.Control { name = ObjectNames.NicifyVariableName(parameterName), type = controlType, subParameters = new Parameter[1], parameter = new Parameter(), }; switch (controlType) { case ControlType.Button: case ControlType.Toggle: control.parameter = new Parameter { name = parameterName }; break; case ControlType.RadialPuppet: control.subParameters[0] = new Parameter { name = parameterName }; break; default: throw new ArgumentException(nameof(controlType), $"{controlType}", null); } void FixAv3Emulator() { try { // Hacky hack to avoid a bug in Lyuma.Av3Emulator control.icon = Texture2D.blackTexture; var m = new SerializedObject(menu); m.Update(); var c = m.FindProperty("controls"); var element = c.GetArrayElementAtIndex(Mathf.Min(0, c.arraySize - 1)); var icon = element.FindPropertyRelative("icon"); icon.objectReferenceInstanceIDValue = 0; m.ApplyModifiedProperties(); } catch (Exception) { // ignored } } if (menu != null) { menu.controls.Add(control); dirtyAssets.Add(menu); FixAv3Emulator(); } return(control); }
private void FromFourAxis(VRCExpressionsMenu.Control control, int controlIndex) { var menu = (LyumaAv3Menu)target; SubControl(control, controlIndex, menu, "FourAxis"); if (menu.IsActiveControl(controlIndex)) { var sanitySubParamLength = control.subParameters.Length; if (sanitySubParamLength > 0) { SliderFloat(menu, control.subParameters[0], "Up", 0f, 1f); } if (sanitySubParamLength > 1) { SliderFloat(menu, control.subParameters[1], "Right", 0f, 1f); } if (sanitySubParamLength > 2) { SliderFloat(menu, control.subParameters[2], "Down", 0f, 1f); } if (sanitySubParamLength > 3) { SliderFloat(menu, control.subParameters[3], "Left", 0f, 1f); } var oldColor = Color.HSVToRGB( 0, (sanitySubParamLength > 0 ? menu.FindFloat(control.subParameters[0].name) : 0) * 0.5f + 0.5f - (sanitySubParamLength > 2 ? menu.FindFloat(control.subParameters[2].name) : 0) * 0.5f + 0.5f, (sanitySubParamLength > 1 ? menu.FindFloat(control.subParameters[1].name) : 0) * 0.5f + 0.5f - (sanitySubParamLength > 3 ? menu.FindFloat(control.subParameters[3].name) : 0) * 0.5f + 0.5f); var newColor = EditorGUILayout.ColorField(oldColor); if (oldColor.r != newColor.r || oldColor.g != newColor.g || oldColor.b != newColor.b) { Color.RGBToHSV(newColor, out _, out var s, out var v); if (sanitySubParamLength > 0) { menu.UserFloat(control.subParameters[0].name, Mathf.Clamp(v * 2 - 1, 0f, 1f)); } if (sanitySubParamLength > 1) { menu.UserFloat(control.subParameters[1].name, Mathf.Clamp(s * 2 - 1, 0f, 1f)); } if (sanitySubParamLength > 2) { menu.UserFloat(control.subParameters[2].name, -Mathf.Clamp(v * 2 - 1, -1f, 0f)); } if (sanitySubParamLength > 3) { menu.UserFloat(control.subParameters[3].name, -Mathf.Clamp(s * 2 - 1, -1f, 0f)); } } } }
public RadialMenu CreateMenu(RadialMenu parent, VRCExpressionsMenu.Control control) { RadialMenu rMenu = Instantiate(RadialMenuPrefab) as RadialMenu; rMenu.gameObject.name = control.subMenu.name; rMenu.Initialize(parent, control.subMenu, parameters); rMenu.transform.SetParent(transform, false); rMenu.gameObject.SetActive(false); subMenus.Add(rMenu.gameObject); return(rMenu); }
private void AddMarkerToMenu(ref VRCExpressionsMenu menu) { var control = new VRCExpressionsMenu.Control(); control.type = ControlType.Toggle; control.name = "Toggle Marker"; control.parameter = new VRCExpressionsMenu.Control.Parameter(); control.parameter.name = "ToggleMarker"; control.value = 1; // control.icon // TODO menu.controls.Add(control); //avatarDescriptor.expressionsMenu EditorUtility.SetDirty(avatarDescriptor.expressionsMenu); }
private void FromRadial(VRCExpressionsMenu.Control control, int controlIndex) { var menu = (LyumaAv3Menu)target; SubControl(control, controlIndex, menu, "Radial"); if (menu.IsActiveControl(controlIndex)) { if (control.subParameters.Length > 0) { SliderFloat(menu, control.subParameters[0], "Rotation", 0f, 1f); } } }
internal void ExpressionParameterSet(VRCExpressionsMenu.Control control, params float[] values) { //Debug.Log($"setting [{control.name}]: {control.type}, sub params {values.Length}"); if (!string.IsNullOrEmpty(control.parameter.name)) { SetExpressionParameter(control.parameter.name, control.value); } for (int i = 0; i < control.subParameters.Length; i++) { if (i < values.Length && !string.IsNullOrEmpty(control.subParameters[i].name)) { SetExpressionParameter(control.subParameters[i].name, values[i]); } } }
//Default Constructor public PageItem() { Type = ItemType.Toggle; InitialState = false; ObjectReference = ""; UseAnimations = false; TransitionType = true; TransitionDuration = 0f; TransitionOffset = false; EnableClip = null; DisableClip = null; Sync = SyncMode.Auto; Saved = true; EnableGroup = new GroupItem[0]; DisableGroup = new GroupItem[0]; ButtonGroup = new GroupItem[0]; Control = new VRCExpressionsMenu.Control(); }
public MenuControlDefinition(IAnimationDefinition parent, VRCExpressionsMenu.Control control) { Name = control.name; Parent = parent; Control = control; Type = control.type; if (Type == VRCExpressionsMenu.Control.ControlType.SubMenu) { AddMenu(control.subMenu); return; } MainParameter = AddParameter(control.parameter); foreach (var controlSubParameter in control.subParameters) { SubParameters.Add(AddParameter(controlSubParameter)); } }
private void FromToggle(VRCExpressionsMenu.Control control, string labelType) { var menu = (LyumaAv3Menu)target; var parameterName = control.parameter.name; var controlValue = control.value; var isActive = menu.IsVisualActive(parameterName, controlValue); EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(menu.HasActiveControl()); if (GreenBackground(isActive, () => ParameterizedButton(control, parameterName, controlValue))) { menu.UserToggle(parameterName, controlValue); } EditorGUI.EndDisabledGroup(); LabelType(labelType); EditorGUILayout.EndHorizontal(); }
private void FromTwoAxis(VRCExpressionsMenu.Control control, int controlIndex) { var menu = (LyumaAv3Menu)target; SubControl(control, controlIndex, menu, "TwoAxis"); if (menu.IsActiveControl(controlIndex)) { var sanitySubParamLength = control.subParameters.Length; if (sanitySubParamLength > 0) { SliderFloat(menu, control.subParameters[0], "Horizontal", -1f, 1f); } if (sanitySubParamLength > 1) { SliderFloat(menu, control.subParameters[1], "Vertical", -1f, 1f); } var oldColor = Color.HSVToRGB( 0, sanitySubParamLength > 0 ? menu.FindFloat(control.subParameters[0].name) * 0.5f + 0.5f : 0, sanitySubParamLength > 1 ? menu.FindFloat(control.subParameters[1].name) * 0.5f + 0.5f : 0); var newColor = EditorGUILayout.ColorField(oldColor); if (oldColor.r != newColor.r || oldColor.g != newColor.g || oldColor.b != newColor.b) { Color.RGBToHSV(newColor, out _, out var s, out var v); if (sanitySubParamLength > 0) { menu.UserFloat(control.subParameters[0].name, s * 2 - 1); } if (sanitySubParamLength > 1) { menu.UserFloat(control.subParameters[1].name, v * 2 - 1); } } } }
private void FromSubMenu(VRCExpressionsMenu.Control control) { var menu = (LyumaAv3Menu)target; var parameterName = control.parameter.name; var wantedValue = control.value; EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(menu.HasActiveControl()); if (ParameterizedButton(control, parameterName, wantedValue)) { if (IsValidParameterName(parameterName)) { menu.UserSubMenu(control.subMenu, parameterName, wantedValue); } else { menu.UserSubMenu(control.subMenu); } } EditorGUI.EndDisabledGroup(); LabelType("SubMenu"); EditorGUILayout.EndHorizontal(); }
private bool ParameterizedButton(VRCExpressionsMenu.Control control, string parameterName, float wantedValue) { var hasParameter = IsValidParameterName(parameterName); return(GUILayout.Button(new GUIContent(control.name + (hasParameter ? " (" + parameterName + " = " + wantedValue + ")" : ""), ResizedIcon(control.icon)))); }
public void Initialize(RadialMenu parent, VRCExpressionsMenu.Control control, float xpos, float ypos) { this.RadialMenu = parent; this.Control = control; this.xpos = xpos; this.ypos = ypos; Texture2D tex = Control.icon ?? null; this.Selectable = GetComponent <Button>(); RadialMenuController.current.MenuActivationEvent += MenuActivationEvent; string error = ""; if (VRCExpressionsMenu.Control.ControlType.SubMenu == Control.type) { if (null == tex) { tex = RadialMenuController.current.SubMenuIcon; } if (null == Control.subMenu) { Error = true; error = $"Sub Menu [{control.name}] is not set"; TEA_Manager.SDKError(error); } else { SubMenu = RadialMenuController.current.CreateMenu(parent, Control); } } if (VRCExpressionsMenu.Control.ControlType.RadialPuppet == Control.type) { if (null == tex) { tex = RadialMenuController.current.RadialPuppetIcon; } if (null == Control.subParameters[0] || string.IsNullOrEmpty(Control.subParameters[0].name)) { error = $"Radial Puppet [{control.name}] does not have a Rotation Parameter"; TEA_Manager.SDKError(error); Error = true; } } if (VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet == Control.type) { if (null == tex) { tex = RadialMenuController.current.TwoAxisIcon; } if ((null == Control.subParameters[0] || string.IsNullOrEmpty(Control.subParameters[0].name)) && (null == Control.subParameters[1] || string.IsNullOrEmpty(Control.subParameters[1].name))) { Error = true; error = $"Two Axis Radial Puppet [{control.name}] does not have a either Horizontal or Vertical Parameters"; TEA_Manager.SDKError(error); } } if (VRCExpressionsMenu.Control.ControlType.Toggle == Control.type) { if (null == tex) { tex = RadialMenuController.current.ToggleIcon; } } if (VRCExpressionsMenu.Control.ControlType.FourAxisPuppet == Control.type) { if (null == tex) { tex = RadialMenuController.current.FourAxisIcon; } if ((null == Control.subParameters[0] || string.IsNullOrEmpty(Control.subParameters[0].name)) && (null == Control.subParameters[1] || string.IsNullOrEmpty(Control.subParameters[1].name)) && (null == Control.subParameters[2] || string.IsNullOrEmpty(Control.subParameters[2].name)) && (null == Control.subParameters[3] || string.IsNullOrEmpty(Control.subParameters[3].name))) { Error = true; error = $"Four Axis Radial Puppet [{control.name}] is missing a parameter"; TEA_Manager.SDKError(error); } } if (VRCExpressionsMenu.Control.ControlType.Button == Control.type) { if (null == tex) { tex = RadialMenuController.current.ButtonIcon; } } if (!Error) { transform.Find("Text").GetComponent <Text>().text = Control.name; if (null != tex) { sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f)); SetImageSprite(image, sprite); } } else { sprite = RadialMenuController.current.ErrorSprite; SetImageSprite(image, sprite); transform.Find("Text").GetComponent <Text>().text = error; } transform.SetParent(RadialMenu.transform); SetScale(); SetOnClick(); }
private bool ParameterizedButton(VRCExpressionsMenu.Control control, string parameterName, float wantedValue) { var hasParameter = IsValidParameterName(parameterName); return(GUILayout.Button(new GUIContent(control.name + (hasParameter ? " (" + parameterName + " = " + wantedValue + ")" : ""), control.icon), GUILayout.MinHeight(36), GUILayout.MinWidth(40), GUILayout.ExpandHeight(true))); }
/// <summary> /// Creates a copy of the avatar descriptor's topmost menu asset or creates one if it doesn't exist, adds the provided menu as a submenu, /// assigns the new topmost menu asset, and stores it in the specified directory. /// </summary> /// <param name="descriptor">The avatar descriptor to add the submenu to.</param> /// <param name="menuToAdd">The menu to add, which will become a submenu of the topmost menu.</param> /// <param name="controlName">The name of the submenu control for the menu to add.</param> /// <param name="directory">The unique directory to store the new topmost menu asset, ex. "Assets/MyCoolScript/GeneratedAssets/725638/".</param> /// <param name="controlParameter">Optionally, the parameter to trigger when the submenu is opened.</param> /// <param name="icon"> Optionally, the icon to display on this submenu. </param> /// <param name="overwrite">Optionally, choose to not overwrite an asset of the same name in directory. See class for more info.</param> public static void AddSubMenu(VRCAvatarDescriptor descriptor, VRCExpressionsMenu menuToAdd, string controlName, string directory, VRCExpressionsMenu.Control.Parameter controlParameter = null, Texture2D icon = null, bool overwrite = true) { if (descriptor == null) { Debug.LogError("Couldn't add the menu, the avatar descriptor is null!"); return; } else if ((menuToAdd == null) || (controlName == null) || (controlName == "")) { Debug.LogError("Couldn't add the menu, it or the name of its control is null!"); return; } else if ((directory == null) || (directory == "")) { Debug.Log("Directory was not specified, storing new topmost menu in " + defaultDirectory); directory = defaultDirectory; } descriptor.customExpressions = true; VRCExpressionsMenu topMenu = ScriptableObject.CreateInstance <VRCExpressionsMenu>(); if (descriptor.expressionsMenu == null) { AssetDatabase.CreateAsset(topMenu, directory + "Menu Topmost.asset"); } else { if (descriptor.expressionsMenu.controls.Count == 8) { Debug.LogWarning("Couldn't add menu. Please have an available slot in your avatar's topmost Expression Menu."); return; } string path = (directory + descriptor.expressionsMenu.name + ".asset"); path = (overwrite) ? path : AssetDatabase.GenerateUniqueAssetPath(path); if (AssetDatabase.GetAssetPath(descriptor.expressionsMenu) != path) // if we have not made a copy yet { // CopyAsset with two identical strings yields exception AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(descriptor.expressionsMenu), path); } topMenu = AssetDatabase.LoadAssetAtPath(path, typeof(VRCExpressionsMenu)) as VRCExpressionsMenu; } List <VRCExpressionsMenu.Control> controlList = topMenu.controls; for (int i = 0; i < controlList.Count; i++) { if (controlList[i].name.Equals(controlName) && controlList[i].type.Equals(VRCExpressionsMenu.Control.ControlType.SubMenu)) { // if a control for a submenu exists with the same name, replace the submenu controlList[i].subMenu = menuToAdd; controlList[i].parameter = controlParameter; controlList[i].icon = icon; EditorUtility.SetDirty(topMenu); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); descriptor.expressionsMenu = topMenu; return; } } VRCExpressionsMenu.Control control = new VRCExpressionsMenu.Control { name = controlName, type = VRCExpressionsMenu.Control.ControlType.SubMenu, subMenu = menuToAdd, parameter = controlParameter, icon = icon }; controlList.Add(control); topMenu.controls = controlList; EditorUtility.SetDirty(topMenu); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); descriptor.expressionsMenu = topMenu; }
public RadialButton(RadialMenu radialMenu, VRCExpressionsMenu.Control control) { this.RadialMenu = radialMenu; this.Control = control; this.Selectable = GetComponent <Button>(); }
public MenuControlDefinition AddControl(VRCExpressionsMenu.Control control) { return(Children.AddChild(new MenuControlDefinition(this, control))); }
private bool VRC_Actions(string songLibrary, List <AudioClip> libAssets, Avatar8TrackEditor _8Track) { //--- --- VRC Expression Parameters --- --- if (null != expressionParameters) { VRCExpressionParameters.Parameter volumeParam = new VRCExpressionParameters.Parameter() { name = _8Track.VolumeEPName, valueType = VRCExpressionParameters.ValueType.Float }; VRCExpressionParameters.Parameter trackParam = new VRCExpressionParameters.Parameter() { name = _8Track.TrackEPName, valueType = VRCExpressionParameters.ValueType.Int }; VRCExpressionParameters.Parameter[] parameters = expressionParameters.parameters; bool hasTrack = false; bool hasVolume = false; foreach (VRCExpressionParameters.Parameter parameter in parameters) { if (parameter.name == _8TrackEditor.VolumeEPName) { hasVolume = true; } else if (parameter.name == _8TrackEditor.TrackEPName) { hasTrack = true; } } if (!hasVolume) { ArrayUtility.Add <VRCExpressionParameters.Parameter>(ref expressionParameters.parameters, volumeParam); } if (!hasTrack) { ArrayUtility.Add <VRCExpressionParameters.Parameter>(ref expressionParameters.parameters, trackParam); } UnityEditor.EditorUtility.SetDirty(expressionParameters); } //--- --- VRC Expression Menu --- --- VRCExpressionsMenu mainMenu = new VRCExpressionsMenu() { name = _8Track._8TrackObject.name + " Menu" }; mainMenu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.StopIcon, name = "Stop", parameter = new VRCExpressionsMenu.Control.Parameter() { name = _8Track.TrackEPName }, type = VRCExpressionsMenu.Control.ControlType.Toggle, value = 0 }); mainMenu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.VolumeIcon, name = "Volume", subParameters = new VRCExpressionsMenu.Control.Parameter[] { new VRCExpressionsMenu.Control.Parameter() { name = _8Track.VolumeEPName } }, type = VRCExpressionsMenu.Control.ControlType.RadialPuppet }); VRCExpressionsMenu disk = new VRCExpressionsMenu() { name = "Disk " + 1 }; mainMenu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.DiskIcon, name = disk.name, type = VRCExpressionsMenu.Control.ControlType.SubMenu, subMenu = disk }); int menuCount = 3; VRCExpressionsMenu menu = mainMenu; List <VRCExpressionsMenu> menus = new List <VRCExpressionsMenu>(); int diskCount = 0; List <VRCExpressionsMenu> disks = new List <VRCExpressionsMenu> { disk }; int trackNumber = 0; do { if (libAssets.Count <= trackNumber) { break; } string trackName = libAssets[trackNumber].name; trackNumber++; if (diskCount == 8) { VRCExpressionsMenu newDisk = new VRCExpressionsMenu() { name = "Disk " + (disks.Count + 1) }; if (7 == menuCount && 0 < libAssets.Count - (trackNumber)) { VRCExpressionsMenu newMenu = new VRCExpressionsMenu() { name = "More..." }; menu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.FolderIcon, name = newMenu.name, type = VRCExpressionsMenu.Control.ControlType.SubMenu, subMenu = newMenu }); menus.Add(newMenu); menu = newMenu; menuCount = 0; } menu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.DiskIcon, name = newDisk.name, type = VRCExpressionsMenu.Control.ControlType.SubMenu, subMenu = newDisk }); menuCount++; disks.Add(newDisk); disk = newDisk; diskCount = 0; } disk.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.TrackIcon, name = trackName, parameter = new VRCExpressionsMenu.Control.Parameter() { name = _8Track.TrackEPName }, type = VRCExpressionsMenu.Control.ControlType.Toggle, value = trackNumber }); diskCount++; } while(true); foreach (VRCExpressionsMenu d in disks) { CreateAsset(_8Track.AudioClip, d, d.name + ".asset"); EditorUtility.SetDirty(d); } CreateAsset(_8Track.AudioClip, mainMenu, mainMenu.name + ".asset"); EditorUtility.SetDirty(mainMenu); for (int i = 0; i < menus.Count; i++) { CreateAsset(_8TrackEditor.AudioClip, menus[i], _8Track._8TrackObject.name + " Menu " + i + ".asset"); } if (null != expressionsMenu) { VRCExpressionsMenu.Control toggle = GetMenuControl(); expressionsMenu.controls.Remove(toggle); expressionsMenu.controls.Add(new VRCExpressionsMenu.Control() { icon = _8Track.FolderIcon, name = _8TrackEditor._8TrackObject.name, type = VRCExpressionsMenu.Control.ControlType.SubMenu, subMenu = mainMenu }); EditorUtility.SetDirty(expressionsMenu); } EditorUtility.SetDirty(expressionParameters); AssetDatabase.SaveAssets(); return(true); }