private int GetParameterSize()
    {
        int size = 0;

        for (int i = 0; i < expressionParams.parameters.Length; i++)
        {
            size += VRCExpressionParameters.TypeCost(expressionParams.parameters[i].valueType);
        }
        return(size);
    }
        /// <summary>
        /// Creates a copy of the avatar descriptor's parameter asset or creates one if it doesn't exist, adds a provided parameter,
        /// assigns the new parameter asset, and stores it in the specified directory.
        /// </summary>
        /// <param name="descriptor">The avatar descriptor to add the parameter to.</param>
        /// <param name="parameter">The parameter to add.</param>
        /// <param name="directory">The unique directory to store the new parameter asset, ex. "Assets/MyCoolScript/GeneratedAssets/725638/".</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 AddParameter(VRCAvatarDescriptor descriptor, VRCExpressionParameters.Parameter parameter, string directory, bool overwrite = true)
        {
            if (descriptor == null)
            {
                Debug.LogError("Couldn't add the parameter, the avatar descriptor is null!");
                return;
            }
            else if ((parameter == null) || (parameter.name == null))
            {
                Debug.LogError("Couldn't add the parameter, it or its name is null!");
                return;
            }
            else if ((directory == null) || (directory == ""))
            {
                Debug.Log("Directory was not specified, storing new parameters asset in " + defaultDirectory);
                directory = defaultDirectory;
            }

            descriptor.customExpressions = true;
            VRCExpressionParameters parameters = ScriptableObject.CreateInstance <VRCExpressionParameters>();

            parameters.parameters = new VRCExpressionParameters.Parameter[0];

            if (descriptor.expressionParameters == null)
            {
                AssetDatabase.CreateAsset(parameters, directory + "Parameters.asset");
            }
            else
            {
                if ((descriptor.expressionParameters.CalcTotalCost() + VRCExpressionParameters.TypeCost(parameter.valueType)) > VRCExpressionParameters.MAX_PARAMETER_COST)
                {
                    Debug.LogError("Couldn't add parameter '" + parameter.name + "', not enough memory free in the avatar's parameter asset!");
                    return;
                }

                string path = (directory + descriptor.expressionParameters.name + ".asset");
                path = (overwrite) ? path : AssetDatabase.GenerateUniqueAssetPath(path);
                if (AssetDatabase.GetAssetPath(descriptor.expressionParameters) != path) // if we have not made a copy yet
                {                                                                        // CopyAsset with two identical strings yields exception
                    AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(descriptor.expressionParameters), path);
                }
                parameters = AssetDatabase.LoadAssetAtPath(path, typeof(VRCExpressionParameters)) as VRCExpressionParameters;
            }

            if (parameters.FindParameter(parameter.name) == null)
            {
                int count = parameters.parameters.Length;
                VRCExpressionParameters.Parameter[] parameterArray = new VRCExpressionParameters.Parameter[count + 1];
                for (int i = 0; i < count; i++)
                {
                    parameterArray[i] = parameters.GetParameter(i);
                }
                parameterArray[count] = parameter;
                parameters.parameters = parameterArray;
            }

            EditorUtility.SetDirty(parameters);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            descriptor.expressionParameters = parameters;
        }
예제 #3
0
    private void ShowMenuFoldout(VRCExpressionsMenu menu, string title)
    {
        if (menu == null)
        {
            return;
        }

        bool b = expandedMenus.Contains(menu);

        // Remove before we go any further, prevents infinite recursion on cyclic menus.
        expandedMenus.Remove(menu);


        if (!EditorGUILayout.Foldout(b, title, true))
        {
            return;
        }

        EditorGUILayout.BeginVertical();
        GUILayout.BeginHorizontal();
        GUILayout.Space(EditorGUI.indentLevel * 17);
        Debug.Log(expressionParams.parameters.Length + ":" + menu.controls.Count);

        int size = 0;

        for (int i = 0; i < expressionParams.parameters.Length; i++)
        {
            size += VRCExpressionParameters.TypeCost(expressionParams.parameters[i].valueType);
        }

        if (menu.controls.Count < expressionParams.parameters.Length)
        {
            if (GUILayout.Button("Add Marker Here", GUILayout.Width(130)))
            {
                InstallMarker(ref menu);
            }
        }
        else
        {
            if (size < VRCExpressionParameters.MAX_PARAMETER_COST)
            {
                if (GUILayout.Button("enlarge parameters", GUILayout.Width(130)))
                {
                    if (size < VRCExpressionParameters.MAX_PARAMETER_COST)
                    {
                        VRCExpressionParameters.Parameter[] newParams = new VRCExpressionParameters.Parameter[expressionParams.parameters.Length + 1];
                        for (int i = 0; i < expressionParams.parameters.Length; i++)
                        {
                            newParams[i] = expressionParams.parameters[i];
                        }
                        newParams[expressionParams.parameters.Length] = new VRCExpressionParameters.Parameter();
                        expressionParams.parameters = newParams;
                        EditorUtility.SetDirty(expressionParams);
                    }
                }
            }
            else
            {
                GUILayout.Label("No room.", GUILayout.Width(130));
            }
        }
        GUILayout.EndHorizontal();

        EditorGUI.indentLevel++;
        foreach (var child in menu.controls)
        {
            if (child.type == ControlType.SubMenu)
            {
                ShowMenuFoldout(child.subMenu, child.name);
            }
        }
        EditorGUI.indentLevel--;
        EditorGUILayout.EndVertical();

        // Okay, it's safe to add the menu back.
        expandedMenus.Add(menu);
    }
예제 #4
0
        void OnGUI()
        {
            EditorGUILayout.BeginHorizontal();
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
            if (Stage.Instruction == stage)
            {
                EditorGUILayout.HelpBox("Welcome to Avatar 8Track. This tool let's you automagically turn a folder of songs into a music player in your avatars radial menu.\n"
                                        + "Song Library Setup\n"
                                        + "   - Create a folder somewhere under Assets\n"
                                        + "   - Put all of your songs into that folder\n"
                                        + "        The folder name does not matter.\n"
                                        + "        All songs from the folder will be added\n"
                                        , MessageType.None, true);
                EditorGUILayout.HelpBox("Do not store anything but your songs in the Song Library, it may be deleted", MessageType.Warning, true);
                EditorGUILayout.HelpBox("One song library per avatar!", MessageType.Warning, true);
                EditorGUILayout.HelpBox("If you update the library with new songs just run the tool again", MessageType.Info, true);
                EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

                // --- Avatar stuff ---
                EditorGUI.BeginChangeCheck();
                avatarIndex = EditorGUILayout.Popup("Avatar", avatarIndex, avatarKeys, EditorStyles.popup);
                if (EditorGUI.EndChangeCheck())
                {
                    expressionParameters = avatars[avatarKeys[avatarIndex]].expressionParameters;
                    expressionsMenu      = avatars[avatarKeys[avatarIndex]].expressionsMenu;
                    _8TrackEditor.SetFromAvatar(avatars[avatarKeys[avatarIndex]]);
                }
                //--- 8Track object
                EditorGUILayout.HelpBox("The 8Track object will hold all of your AudioClip Components."
                                        + "\nIt must be a first child of your avatar."
                                        + "\nThe name of the 8Track object will determine names for various assets."
                                        + "\nI highly recommend you use the default object.", MessageType.Info, true);
                EditorGUILayout.LabelField("The 8Track Object");
                _8TrackEditor._8TrackObject = (GameObject)EditorGUILayout.ObjectField(_8TrackEditor._8TrackObject, typeof(GameObject), true);
                if (null == _8TrackEditor._8TrackObject)
                {
                    _8trackValid = false;
                    if (GUILayout.Button("Create _8Track Object", GUILayout.Height(30)))
                    {
                        _8TrackEditor._8TrackObject = new GameObject("8Track");
                        _8TrackEditor._8TrackObject.transform.parent = _8TrackEditor.Avatar.transform;
                        Debug.Log($"Created new object for tracks [{_8TrackEditor._8TrackObject.name}]");
                    }
                    else
                    {
                        _8TrackEditor.SetFromAvatar(avatars[avatarKeys[avatarIndex]]);
                    }
                }
                else if (_8TrackEditor._8TrackObject.transform.parent != _8TrackEditor.Avatar.transform)
                {
                    EditorGUILayout.HelpBox("The 8Track object must be a child of the avatar selected", MessageType.Error, true);
                    _8trackValid = false;
                }
                else
                {
                    _8trackValid = true;
                }

                //set var
                if (null != _8TrackEditor._8TrackObject)
                {
                    _8TrackEditor.VolumeEPName = Avatar8Track.GetVarName(_8TrackEditor._8TrackObject, Avatar8Track.volumeEPNameSuffix);
                    _8TrackEditor.TrackEPName  = Avatar8Track.GetVarName(_8TrackEditor._8TrackObject, Avatar8Track.trackEPNameSuffix);
                }

                EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

                //--- Parameters
                if (expressionValid)
                {
                    EditorGUILayout.HelpBox("A Integer and Float parameter will be added", MessageType.Info, true);
                }
                else if (null != expressionParameters)
                {
                    EditorGUILayout.HelpBox("The ExpressionParameters does not have space for a float and an int" + "\nYou can delete empty parameters to make room", MessageType.Error, true);
                    if (GUILayout.Button("Delete Empty Parameters", GUILayout.Height(30)))
                    {
                        for (int i = 0; i < expressionParameters.parameters.Length; i++)
                        {
                            if (string.IsNullOrEmpty(expressionParameters.parameters[i].name))
                            {
                                ArrayUtility.RemoveAt <VRCExpressionParameters.Parameter>(ref expressionParameters.parameters, i);
                                i--;
                            }
                        }
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("An ExpressionParameters object is required", MessageType.Error, true);
                }

                EditorGUILayout.LabelField("VRC ExpressionParameters File");
                expressionParameters = (VRCExpressionParameters)EditorGUILayout.ObjectField(expressionParameters, typeof(VRCExpressionParameters), true);

                if (null != expressionParameters && null != _8TrackEditor._8TrackObject)
                {
                    int cost = VRCExpressionParameters.TypeCost(VRCExpressionParameters.ValueType.Int) + VRCExpressionParameters.TypeCost(VRCExpressionParameters.ValueType.Float);
                    VRCExpressionParameters.Parameter[] parameters = expressionParameters.parameters;
                    foreach (VRCExpressionParameters.Parameter parameter in parameters)
                    {
                        if (parameter.name == _8TrackEditor.VolumeEPName)
                        {
                            cost -= VRCExpressionParameters.TypeCost(VRCExpressionParameters.ValueType.Float);
                        }
                        else if (parameter.name == _8TrackEditor.TrackEPName)
                        {
                            cost -= VRCExpressionParameters.TypeCost(VRCExpressionParameters.ValueType.Int);
                        }
                    }
                    expressionValid = expressionParameters.CalcTotalCost() + cost <= VRCExpressionParameters.MAX_PARAMETER_COST;
                }
                else
                {
                    expressionValid = null != expressionParameters;
                }
                EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

                //--- Menu
                if (menuValid)
                {
                    EditorGUILayout.HelpBox("Which VRCExpressionsMenu do you want the SubMenu added to", MessageType.Info, true);
                }
                else if (null != expressionsMenu)
                {
                    EditorGUILayout.HelpBox("The VRCExpressionsMenu is full", MessageType.Error, true);
                }

                if (null == expressionsMenu)
                {
                    EditorGUILayout.HelpBox("ExpressionsMenu is not set", MessageType.Warning, true);
                }

                EditorGUILayout.LabelField("VRC Expressions Menu File");
                expressionsMenu = (VRCExpressionsMenu)EditorGUILayout.ObjectField(expressionsMenu, typeof(VRCExpressionsMenu), true);

                if (null != expressionsMenu && null != _8TrackEditor._8TrackObject)
                {
                    menuValid = expressionsMenu.controls.Count < VRCExpressionsMenu.MAX_CONTROLS;
                    foreach (VRCExpressionsMenu.Control control in expressionsMenu.controls)
                    {
                        if (control.name == _8TrackEditor._8TrackObject.name)
                        {
                            menuValid = true;
                        }
                    }
                }
                else
                {
                    menuValid = true;
                }


                if (null != expressionParameters && menuValid && expressionValid && _8trackValid)
                {
                    Button(Stage._8Track, "Setup");
                }
            }
            else if (Stage._8Track == stage)
            {
                _8TrackEditor.OnGUI();
                Button(Stage.Instruction, "Back <-");
                if (_8TrackEditor.IsValid())
                {
                    Button(Stage.Burn, "Continue ->");
                }
            }

            if (Stage.Burn == stage)
            {
                EditorGUILayout.HelpBox("Read Carefully!!!!!!", MessageType.Error);
                EditorGUILayout.HelpBox("This will break the 8Track functionality for any other avatar this song library has been added to previously."
                                        + "\nDuplicate the song library if you want to add it to a separate avatar.", MessageType.Warning);
                EditorGUILayout.HelpBox("Avatar 8Tracks lets you update your song library by re-running it on the same avatar."
                                        + "\nfor convenience it auto-detects and deletes assets it has created previously and replaces them."
                                        + "\nDouble check the following items below were not manually edited by you."
                                        , MessageType.Warning);
                EditorGUILayout.LabelField("FX Controller Layers, Expression Parameters, and Expression Menu Controls with the following names", EditorStyles.wordWrappedLabel);
                EditorGUILayout.LabelField($"     [{_8TrackEditor.TrackEPName}]", EditorStyles.boldLabel);
                EditorGUILayout.LabelField($"     [{_8TrackEditor.VolumeEPName}]", EditorStyles.boldLabel);
                EditorGUILayout.LabelField($"     [{_8TrackEditor._8TrackObject.name}]", EditorStyles.boldLabel);
                EditorGUILayout.HelpBox($"All AnimationClips, and ExpressionsMenus will be deleted in [{GetAssetDirectory(_8TrackEditor.AudioClip, true)}]", MessageType.Warning);
                Button(Stage._8Track, "Back <-");
                if (GUILayout.Button("Accept And Burn Tracks", GUILayout.Height(30)))
                {
                    try {
                        string songLibrary = GetAssetDirectory(_8TrackEditor.AudioClip, false);
                        CleanSongLibrary(songLibrary);
                        List <AudioClip> libAssets = GetSongList(songLibrary);
                        _8TrackEditor.BurnTracks(libAssets);
                        VRC_Actions(songLibrary, libAssets, _8TrackEditor);
                        AssetDatabase.SaveAssets();
                        EditorUtility.DisplayDialog("Avatar 8Tracks", "You're ready to rock", "great");
                        this.Close();
                    } catch (System.Exception e) {
                        EditorUtility.DisplayDialog("so... this happened", e.Message, "sorry");
                        Debug.LogException(e);
                        this.Close();
                    }
                }
                DrawEnd();
            }
            else
            {
                DrawEnd();
            }
        }