/// <summary>
        /// Scene has to be fully loaded for all characters and objects to exist in the game
        /// </summary>
        private void SceneLoaded(Scene s, LoadSceneMode lsm)
        {
            if (s.name == "StudioNotification" && LoadClicked)
            {
                LoadClicked = false;

                try
                {
                    IKObjectInfoList.Clear();
                    PluginData ExtendedData = ExtendedSave.GetSceneExtendedDataById(PluginName);

                    if (ExtendedData != null && ExtendedData.data.ContainsKey("AnimationInfo"))
                    {
                        List <AnimationControllerInfo> AnimationControllerInfoList;

                        AnimationControllerInfoList = ((object[])ExtendedData.data["AnimationInfo"]).Select(x => AnimationControllerInfo.Unserialize((byte[])x)).ToList();

                        foreach (var AnimInfo in AnimationControllerInfoList)
                        {
                            IKObjectInfo LoadedAnimInfo = new IKObjectInfo();

                            var Character = Singleton <Studio.Studio> .Instance.dicObjectCtrl.Where(x => x.Key == AnimInfo.CharDicKey).Select(x => x.Value as OCIChar).First();

                            LoadedAnimInfo.CharacterKey    = AnimInfo.CharDicKey;
                            LoadedAnimInfo.CharacterObject = GameObject.Find(Character.charInfo.name);
                            LoadedAnimInfo.IKPart          = AnimInfo.IKPart;
                            LoadedAnimInfo.IKTarget        = Character.listIKTarget.Where(x => x.boneObject.name == AnimInfo.IKPart).First();

                            var LinkedItem = Singleton <Studio.Studio> .Instance.dicObjectCtrl.Where(x => x.Key == AnimInfo.ItemDicKey).Select(x => x.Value).First();

                            switch (LinkedItem)
                            {
                            case OCIItem Item:
                                LoadedAnimInfo.ObjectKey      = Item.objectInfo.dicKey;
                                LoadedAnimInfo.SelectedObject = Item.childRoot.gameObject;
                                break;

                            case OCIFolder Folder:
                                LoadedAnimInfo.ObjectKey      = Folder.objectInfo.dicKey;
                                LoadedAnimInfo.SelectedObject = Folder.childRoot.gameObject;
                                break;

                            case OCIRoute Route:
                                LoadedAnimInfo.ObjectKey      = Route.objectInfo.dicKey;
                                LoadedAnimInfo.SelectedObject = Route.childRoot.gameObject;
                                break;
                            }

                            IKObjectInfoList.Add(LoadedAnimInfo);
                        }
                    }
                    Logger.Log(LogLevel.Debug, "Loaded KK_AnimationController animations");
                }
                catch (Exception ex)
                {
                    Logger.Log(LogLevel.Error | LogLevel.Message, "Could not load KK_AnimationController animations.");
                    Logger.Log(LogLevel.Error, ex.ToString());
                }
            }
        }
        private void Update()
        {
            //Control + key to remove the link between body part and object
            if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(AnimationControllerHotkey.Value.MainKey))
            {
                TreeNodeObject[] selectNodes = Singleton <Studio.Studio> .Instance.treeNodeCtrl.selectNodes;
                for (int i = 0; i < selectNodes.Length; i++)
                {
                    if (Singleton <Studio.Studio> .Instance.dicInfo.TryGetValue(selectNodes[i], out ObjectCtrlInfo objectCtrlInfo))
                    {
                        if (objectCtrlInfo is OCIChar ociChar)
                        {
                            IKObjectInfoList.RemoveAll(x => x.CharacterObject == GameObject.Find(ociChar.charInfo.name) &&
                                                       x.IKTarget.boneObject.name == IKPart);
                        }
                    }
                }
            }
            //Shift + key to change the IK Node
            else if ((Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) && Input.GetKeyDown(AnimationControllerHotkey.Value.MainKey))
            {
                if (IKPart == "")
                {
                    IKPart = IKParts.ElementAt(0).Key;
                }
                else
                {
                    int index = Array.IndexOf(IKParts.Keys.ToArray(), IKPart);
                    if (index == IKParts.Count - 1)
                    {
                        IKPart = IKParts.ElementAt(0).Key;
                    }
                    else
                    {
                        IKPart = IKParts.ElementAt(index + 1).Key;
                    }
                }
                Logger.Log(LogLevel.Info | LogLevel.Message, $"Selected IK Node:{IKParts[IKPart]}");
            }
            //Press key to link the selected character with the selected object (select both in workspace first)
            else if (AnimationControllerHotkey.IsDown())
            {
                if (IKPart == "")
                {
                    Logger.Log(LogLevel.Info | LogLevel.Message, "Set an IK part first (shift+hotkey)");
                }

                IKObjectInfo     IKObject    = new IKObjectInfo();
                TreeNodeObject[] selectNodes = Singleton <Studio.Studio> .Instance.treeNodeCtrl.selectNodes;

                for (int i = 0; i < selectNodes.Length; i++)
                {
                    if (Singleton <Studio.Studio> .Instance.dicInfo.TryGetValue(selectNodes[i], out ObjectCtrlInfo objectCtrlInfo))
                    {
                        switch (objectCtrlInfo)
                        {
                        case OCIItem Item:
                            IKObject.ObjectKey      = objectCtrlInfo.objectInfo.dicKey;
                            IKObject.SelectedObject = Item.childRoot.gameObject;
                            break;

                        case OCIFolder Folder:
                            IKObject.ObjectKey      = objectCtrlInfo.objectInfo.dicKey;
                            IKObject.SelectedObject = Folder.childRoot.gameObject;
                            break;

                        case OCIChar Character:
                            IKObject.CharacterKey    = objectCtrlInfo.objectInfo.dicKey;
                            IKObject.CharacterObject = GameObject.Find(Character.charInfo.name);
                            IKObject.IKTarget        = Character.listIKTarget.Where(x => x.boneObject.name == IKPart).First();
                            IKObject.IKPart          = IKPart;
                            break;

                        case OCIRoute Route:
                            IKObject.ObjectKey      = objectCtrlInfo.objectInfo.dicKey;
                            IKObject.SelectedObject = Route.childRoot.gameObject;
                            break;
                        }
                    }
                }

                if (IKObject.SelectedObject != null && IKObject.CharacterObject != null && IKObject.IKTarget != null)
                {
                    IKObjectInfoList.RemoveAll(x => x.CharacterObject == IKObject.CharacterObject &&
                                               x.IKTarget == IKObject.IKTarget);
                    IKObjectInfoList.Add(IKObject);
                }
            }

            //Every update, match the part to the object
            for (int i = 0; i < IKObjectInfoList.Count;)
            {
                if (IKObjectInfoList[i].CheckNull())
                {
                    //The character or the object it was attached to was deleted, remove it from the list
                    IKObjectInfoList.RemoveAt(i);
                }
                else
                {
                    IKObjectInfoList[i].IKTarget.guideObject.SetWorldPos(IKObjectInfoList[i].SelectedObject.transform.position);
                    IKObjectInfoList[i].IKTarget.targetInfo.changeAmount.rot = IKObjectInfoList[i].SelectedObject.transform.localRotation.eulerAngles;
                    i++;
                }
            }
        }