StartMenu!

This commit is contained in:
SoulliesOfficial
2025-03-08 14:21:10 -05:00
parent 28e0a6e4b0
commit e0ae43c25c
193 changed files with 43412 additions and 7940 deletions

View File

@@ -0,0 +1,200 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using DG.Tweening;
using Ichni.RhythmGame.Beatmap;
using TMPro;
using UniRx;
using UnityEditor;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Ichni.StartMenu
{
public partial class CreateEmptyProjectPage : MonoBehaviour
{
public CanvasGroup canvasGroup;
public Tweener fadeIn, fadeOut;
public TMP_InputField projectNameInputField, creatorNameInputField, bpmInputField, songLocationInputField, delayInputField;
public Button selectSongButton, autoFillSongPathButton;
public Button createEmptyProjectButton;
private OpenFileName songFile;
public string songName;
public ThemeBundleSelector themeBundleSelector;
private void Awake()
{
InitializeAnimations();
InitializeInfoUI();
}
private void Update()
{
if (Keyboard.current.escapeKey.wasPressedThisFrame)
{
fadeOut.Restart();
}
}
private void CreateEmptyProject()
{
string projectPath = Application.streamingAssetsPath + "/Projects/" + projectNameInputField.text;
//Create project folder
if (!Directory.Exists(projectPath))
{
Directory.CreateDirectory(projectPath);
}
InformationTransistor.instance.projectInfo_BM = new ProjectInformation_BM(
projectNameInputField.text,
creatorNameInputField.text,
PlayerSettings.bundleVersion,
DateTime.Now.ToString(CultureInfo.CurrentCulture),
DateTime.Now.ToString(CultureInfo.CurrentCulture),
themeBundleSelector.GetSelectedThemeBundleList());
File.Copy(songLocationInputField.text,
Application.streamingAssetsPath + "/Projects/" +
projectNameInputField.text + "/" + songName, true);
InformationTransistor.instance.songInfo_BM = new SongInformation_BM(
songName, float.Parse(bpmInputField.text),
float.Parse(delayInputField.text));
InformationTransistor.instance.isLoadedProject = false;
//Load ThemeBundles, then go to EditorScene
ThemeBundleManager.instance.LoadThemeBundles(InformationTransistor.instance.projectInfo_BM.selectedThemeBundleList);
ThemeBundleManager.instance.waitingBundleAmount
.Where(amount => amount == 0) // 当 waitingAmount 变为 0 时触发
.First()
.Subscribe(_ =>
{
Debug.Log("All AssetBundles are loaded. Switching scene.");
SceneManager.LoadScene("EditorScene");
}).AddTo(this);
}
}
public partial class CreateEmptyProjectPage
{
private void InitializeAnimations()
{
fadeIn = canvasGroup.DOFade(1f, 0.5f)
.SetEase(Ease.InOutQuad)
.SetAutoKill(false)
.OnComplete(() =>
{
canvasGroup.interactable = true;
canvasGroup.blocksRaycasts = true;
}).Pause();
fadeOut = canvasGroup.DOFade(0f, 0.5f)
.SetEase(Ease.InOutQuad)
.SetAutoKill(false)
.OnPlay(() =>
{
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
})
.OnComplete(() =>
{
StartMenuManager.instance.startPage.fadeIn.Restart();
})
.Pause();
}
private void InitializeInfoUI()
{
songLocationInputField.onEndEdit.AddListener((str) =>
{
string forward = Application.streamingAssetsPath + "/Songs/";
songName = str.Replace(forward, "");
});
selectSongButton.onClick.AddListener(SelectSong);
autoFillSongPathButton.onClick.AddListener(AutoFillSongPath);
createEmptyProjectButton.onClick.AddListener(CreateEmptyProject);
}
public void AutoFillSongPath()
{
string path = Application.streamingAssetsPath + "/Songs/";
songLocationInputField.text = path;
}
public void SelectSong()
{
songFile = new OpenFileName();
songFile.structSize = Marshal.SizeOf(songFile);
songFile.filter = "Music Files(*音频文件)\0*.wav;\0";
songFile.file = new string(new char[256]);
songFile.maxFile = songFile.file.Length;
songFile.fileTitle = new string(new char[64]);
songFile.maxFileTitle = songFile.fileTitle.Length;
songFile.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
songFile.title = "Select A Song";
songFile.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
if (LocalDialog.GetOpenFileName(songFile) && songFile.file != "")
{
songName = Path.GetFileName(songFile.file);
songLocationInputField.text = Path.GetFullPath(songFile.file);
}
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
public int structSize = 0;
public IntPtr dlgOwner = IntPtr.Zero;
public IntPtr instance = IntPtr.Zero;
public string filter = null;
public string customFilter = null;
public int maxCustFilter = 0;
public int filterIndex = 0;
public string file = null;
public int maxFile = 0;
public string fileTitle = null;
public int maxFileTitle = 0;
public string initialDir = null;
public string title = null;
public int flags = 0;
public short fileOffset = 0;
public short fileExtension = 0;
public string defExt = null;
public IntPtr custData = IntPtr.Zero;
public IntPtr hook = IntPtr.Zero;
public string templateName = null;
public IntPtr reservedPtr = IntPtr.Zero;
public int reservedInt = 0;
public int flagsEx = 0;
}
public static class LocalDialog
{
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
public static bool GetOFN([In, Out] OpenFileName ofn)
{
return GetOpenFileName(ofn);
}
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
public static bool GetSFN([In, Out] OpenFileName ofn)
{
return GetSaveFileName(ofn);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3aa727ae213742148372dfe4f74aa62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Ichni
{
public class InformationTransistor : SerializedMonoBehaviour
{
public static InformationTransistor instance;
public bool isLoadedProject;
public ProjectInformation_BM projectInfo_BM;
public SongInformation_BM songInfo_BM;
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbeb2962c1e154154a56486889cc5843
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UnityEngine;
namespace Ichni.StartMenu
{
public class LoadProjectModule : MonoBehaviour
{
public GameObject LoadProjectTab;
public RectTransform loadTabList;
public List<string> projectFileList;
public List<ProjectInformation_BM> projectInformationList;
public List<SongInformation_BM> songInformationList;
private void Start()
{
projectInformationList = new List<ProjectInformation_BM>();
songInformationList = new List<SongInformation_BM>();
GetAllProjects();
}
public void GetAllProjects()
{
string path = Path.Combine(Application.streamingAssetsPath, "Projects");
projectFileList = ES3.GetDirectories(path).ToList();
foreach (string project in projectFileList)
{
string projectInformationPath = path + "/" + project + "/ProjectInfo.json";
string songInformationPath = path + "/" + project + "/SongInfo.json";
if (!File.Exists(projectInformationPath) || !File.Exists(songInformationPath)) continue;
projectInformationList.Add(ES3.Load<ProjectInformation_BM>("ProjectInformation", projectInformationPath));
songInformationList.Add(ES3.Load<SongInformation_BM>("SongInformation", songInformationPath));
}
for (int i = 0; i < projectInformationList.Count; i++)
{
var currentProject = projectInformationList[i];
var song = songInformationList[i];
string projectName = currentProject.projectName;
string lastSavedTime = currentProject.lastSaveTime;
string songName = song.songName;
LoadProjectTab tab = LeanPool.Spawn(LoadProjectTab, loadTabList).GetComponent<LoadProjectTab>();
tab.SetUpTab(projectName, lastSavedTime, songName);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e40dd0d51c6a0462dbb1a6a406064156
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Ichni.StartMenu
{
public class LoadProjectTab : MonoBehaviour
{
public string projectName;
public TMP_Text projectNameText, lastSavedTimeText, songNameText;
public Button loadButton;
public void SetUpTab(string projectName, string lastSavedTime, string songName)
{
this.projectName = projectName;
projectNameText.text = projectName;
lastSavedTimeText.text = lastSavedTime;
songNameText.text = songName;
loadButton.onClick.AddListener(LoadProject);
}
public void LoadProject()
{
// var b = IchniApp.instance.GetModel<InformationTransistor>();
// if (b == null) Debug.LogError("XXX");
// b.isLoadedProject = true;
// IchniApp.instance.GetModel<InformationTransistor>().loadingFolder = projectName;
// StartPageManager.startPageManager.GoToEditScene();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aaf1c7bed195b4399aa6d3b5b4265930
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni.StartMenu
{
public class StartMenuManager : MonoBehaviour
{
public static StartMenuManager instance;
public StartPage startPage;
public CreateEmptyProjectPage createEmptyProjectPage;
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ee1f97eeecda414cbd7e21a9d0589a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Michsky.MUIP;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.StartMenu
{
public partial class StartPage : MonoBehaviour
{
public RectTransform background;
public CanvasGroup canvasGroup;
public ButtonManager createEmptyProjectButton;
public Sequence fadeIn, fadeOut;
private void Awake()
{
InitializeAnimations();
createEmptyProjectButton.onClick.AddListener(GoToNewProjectPage);
}
public void GoToNewProjectPage()
{
fadeOut.Restart();
}
}
public partial class StartPage
{
private void InitializeAnimations()
{
fadeIn = DOTween.Sequence();
fadeOut = DOTween.Sequence();
fadeIn.Join(canvasGroup.DOFade(1f, 0.5f))
.Join(background.DOScale(Vector3.one, 0.5f))
.SetEase(Ease.InOutQuad)
.SetAutoKill(false)
.OnComplete(() =>
{
canvasGroup.interactable = true;
canvasGroup.blocksRaycasts = true;
}).Pause();
fadeOut.Join(canvasGroup.DOFade(0f, 0.5f))
.Join(background.DOScale(Vector3.one * 2f, 0.5f))
.SetEase(Ease.InOutQuad)
.SetAutoKill(false)
.OnPlay(() =>
{
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
})
.OnComplete(() =>
{
StartMenuManager.instance.createEmptyProjectPage.fadeIn.Restart();
})
.Pause();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f4b9216445764528a39790ae30bcde1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.StartMenu
{
public class ThemeBundleSelector : MonoBehaviour
{
public GameObject themeBundleTab;
public RectTransform listTransform;
public List<ThemeBundleTab> themeBundleTabs;
private void Start()
{
SetUpList();
}
private void SetUpList()
{
themeBundleTabs = new List<ThemeBundleTab>();
foreach (var bundle in ThemeBundleManager.instance.themeBundleAbstractList)
{
ThemeBundleTab tab = Instantiate(themeBundleTab, listTransform).GetComponent<ThemeBundleTab>();
tab.SetUpTab(bundle);
themeBundleTabs.Add(tab);
}
}
public List<string> GetSelectedThemeBundleList()
{
return (from tab in themeBundleTabs where tab.toggle.isOn select tab.connectedThemeBundle.fileName).ToList();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2af4f91bacbc744c188532d3a8f1bea8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Ichni.StartMenu
{
public class ThemeBundleTab : MonoBehaviour
{
public ThemeBundleAbstract connectedThemeBundle;
public TMP_Text titleText;
public Toggle toggle;
public void SetUpTab(ThemeBundleAbstract themeBundleAbstract)
{
this.connectedThemeBundle = themeBundleAbstract;
this.titleText.text = themeBundleAbstract.displayName;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f408eaf8e6644d58a38d215032f4e52
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: