714 lines
27 KiB
C#
714 lines
27 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
using System.IO;
|
|||
|
|
using System;
|
|||
|
|
using SFB;
|
|||
|
|
using System.Collections;
|
|||
|
|
|
|||
|
|
public enum GeneralOptionPanelEvent
|
|||
|
|
{
|
|||
|
|
MouseGudies, BuildingModel, EditModel
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 用于持续检测用户的鼠标输入,并且做出对应UI的响应,这是一个测试中的脚本,之后需要重构
|
|||
|
|
/// </summary>
|
|||
|
|
public class MainMenuController : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
private Transform _Transform;
|
|||
|
|
private MainMenuView _MainMenuView;
|
|||
|
|
private MainMenuModel _MainMenuModel;
|
|||
|
|
|
|||
|
|
private GeneralOptionPanelController GeneralOptionPanel;
|
|||
|
|
private BuildingOptionPanelController BuildingOptionPanel;
|
|||
|
|
private SelectView _SelectView;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 用于指示当前选择的时间组序号,默认为0
|
|||
|
|
/// </summary>
|
|||
|
|
private int _SelectedBPMGroupIndex = 0;
|
|||
|
|
|
|||
|
|
[SerializeField] private bool isGuidesEnabled = true;//是否启用鼠标参考线
|
|||
|
|
[SerializeField] private bool isBuildingModelEnabled = false;//目前是否是创建模式,左键点击放置物件
|
|||
|
|
[SerializeField] private bool optionHasBeenCreated = false;//是否已经创建了一个会话选项,再次点击退出会话
|
|||
|
|
[SerializeField] private bool isAnyModelEnabled = false;//是否处于任何一种专注模式之下,这会关闭通常选项,使得用户右键会直接弹出该模式下的菜单
|
|||
|
|
[SerializeField] private bool isAnyCoroutineEnabled = false;//目前是否有创造新物件的协程正在运行,防止重复开启协程
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 用于在不同对象之间传递歌曲当前时间的全局容器,只负责传递,只在主控中赋值
|
|||
|
|
/// </summary>
|
|||
|
|
private SongInformationContainer _SongTimeContainer;
|
|||
|
|
private BaseNote _preGeneratedObject;
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 当歌曲时间发生变化事触发该事件,传入的时间为改变后的时间,更新之后的UI
|
|||
|
|
/// </summary>
|
|||
|
|
private event Action<float> OnTimeChange;
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region Unity生命周期函数
|
|||
|
|
void Start()
|
|||
|
|
{
|
|||
|
|
_MainMenuView = gameObject.GetComponent<MainMenuView>();
|
|||
|
|
_MainMenuModel = gameObject.GetComponent<MainMenuModel>();
|
|||
|
|
_Transform = gameObject.GetComponent<Transform>();
|
|||
|
|
//启用传递歌曲信息的容器
|
|||
|
|
_SongTimeContainer = new SongInformationContainer();
|
|||
|
|
_SongTimeContainer.UpdateSongInformation(0);
|
|||
|
|
|
|||
|
|
Application.targetFrameRate = 60;
|
|||
|
|
|
|||
|
|
//初始化各个界面
|
|||
|
|
InitTopPenal();
|
|||
|
|
InitProgressBar();
|
|||
|
|
InitAllOptionPanel();
|
|||
|
|
|
|||
|
|
_SelectView = _MainMenuView.NotePool.Get(_MainMenuView.MainMenuSelectView);
|
|||
|
|
_SelectView.Init(0, _SongTimeContainer, _MainMenuModel.MainBPMGroup);
|
|||
|
|
|
|||
|
|
//注册事件
|
|||
|
|
OnTimeChange += _MainMenuView.TopPanel.ChangeTimeText;
|
|||
|
|
OnTimeChange += ChangeProgressBar;
|
|||
|
|
}
|
|||
|
|
void Update()
|
|||
|
|
{
|
|||
|
|
//使用鼠标滚轮来控制当前时间
|
|||
|
|
ChangeTimeWhitMouseScroll(Input.mouseScrollDelta.y);
|
|||
|
|
//在数据层更新当前的歌曲时间
|
|||
|
|
_SongTimeContainer.UpdateSongInformation(_MainMenuModel.SongCurrentTime);
|
|||
|
|
|
|||
|
|
//检查当前输入
|
|||
|
|
CheckUserInput();
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
#region 时间变化事件相关函数
|
|||
|
|
/// <summary>
|
|||
|
|
/// 通过鼠标滚轮更改时间
|
|||
|
|
/// </summary>
|
|||
|
|
private void ChangeTimeWhitMouseScroll(float value)
|
|||
|
|
{
|
|||
|
|
_MainMenuModel.SongCurrentTime += value * _MainMenuModel.MainBPMGroup.Beat / 4;
|
|||
|
|
if (value == 0) return;
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 改变进度条
|
|||
|
|
/// </summary>
|
|||
|
|
private void ChangeProgressBar(float time)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.ProgressBar.progressSlider.value = _MainMenuModel.Song.time / _MainMenuModel.Song.clip.length;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
#region TopPenal相关代码
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化顶部的UI控件
|
|||
|
|
/// </summary>
|
|||
|
|
private void InitTopPenal()
|
|||
|
|
{
|
|||
|
|
//基准BPM输入窗口
|
|||
|
|
_MainMenuView.TopPanel.BaseBPMInputField.onEndEdit?.AddListener(OnBaseBPMInputFieldEndEdit);
|
|||
|
|
_MainMenuView.TopPanel.BaseBPMInputField.text = _MainMenuModel.PersistentChartData.globalConfig.baseBPM.ToString();
|
|||
|
|
//当前时间输入窗口
|
|||
|
|
_MainMenuView.TopPanel.SongCurrentTimeInputField?.onEndEdit.AddListener(OnCurrentTimeInputFieldEndEdit);
|
|||
|
|
_MainMenuView.TopPanel.SongCurrentTimeInputField.text = _MainMenuModel.SongCurrentTime.ToString();
|
|||
|
|
//
|
|||
|
|
_MainMenuView.TopPanel.PlaySongButton.onClick.AddListener(OnPlaySongButtonClick);
|
|||
|
|
_MainMenuView.TopPanel.StopSongButton.onClick.AddListener(OnStopSongButtonClick);
|
|||
|
|
}
|
|||
|
|
Coroutine _runningCoroutine;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 开始播放按钮绑定的方法
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnPlaySongButtonClick()
|
|||
|
|
{
|
|||
|
|
if (_MainMenuModel.Song.isPlaying) return;
|
|||
|
|
_MainMenuModel.Song.Play();
|
|||
|
|
_runningCoroutine = StartCoroutine(InPlaying());
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 暂停播放按钮绑定的方法
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnStopSongButtonClick()
|
|||
|
|
{
|
|||
|
|
_MainMenuModel.Song.Pause();
|
|||
|
|
StopCoroutine(_runningCoroutine);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 歌曲在播放时开启的额外进程,实时监测歌曲是否在播放
|
|||
|
|
/// </summary>
|
|||
|
|
private IEnumerator InPlaying()
|
|||
|
|
{
|
|||
|
|
/*
|
|||
|
|
* 协程只在按钮事件中开启或者停止
|
|||
|
|
*/
|
|||
|
|
while (_MainMenuModel.Song.isPlaying)
|
|||
|
|
{
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 当BaseBPM被编辑时触发的函数
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnBaseBPMInputFieldEndEdit(string str)
|
|||
|
|
{
|
|||
|
|
var temp = _MainMenuModel.PersistentChartData.globalConfig.baseBPM = float.Parse(str);
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "现在歌曲BaseBPM已经被更改为: " + temp.ToString() + " (ゝ∀・)";
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 当前时间被编辑时触发的函数
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnCurrentTimeInputFieldEndEdit(string str)
|
|||
|
|
{
|
|||
|
|
_MainMenuModel.SongCurrentTime = float.Parse(str);
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "已定位时间至: " + str + " (・ω・)";
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
#region 进度条相关函数
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化进度条
|
|||
|
|
/// </summary>
|
|||
|
|
private void InitProgressBar()
|
|||
|
|
{
|
|||
|
|
//替换进度条的贴图,并且设置为开启状态
|
|||
|
|
_MainMenuView.ProgressBar.waveFormImage.texture = AudioWaveFormVisualization.BakeAudioWaveform(_MainMenuModel.Song.clip);
|
|||
|
|
_MainMenuView.ProgressBar.waveFormImage.gameObject.SetActive(true);
|
|||
|
|
|
|||
|
|
_MainMenuView.ProgressBar.OnDrag += () =>
|
|||
|
|
{
|
|||
|
|
//拖到尾时退出
|
|||
|
|
if (_MainMenuView.ProgressBar.progressSlider.value == 1)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
//同步歌曲时间
|
|||
|
|
_MainMenuModel.SongCurrentTime = _MainMenuView.ProgressBar.progressSlider.value * _MainMenuModel.Song.clip.length;
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 预览谱面,按下空格开启,抬起空格时间回归原位
|
|||
|
|
/// </summary>
|
|||
|
|
private IEnumerator ChartPreview(float startTime)
|
|||
|
|
{
|
|||
|
|
IEnumerator Play()
|
|||
|
|
{
|
|||
|
|
while (!Input.GetKeyUp(KeyCode.Space))
|
|||
|
|
{
|
|||
|
|
if (!_MainMenuView.ProgressBar.isDrag)
|
|||
|
|
{
|
|||
|
|
//_MainMenuView.ProgressBar.progressSlider.value = _MainMenuModel.Song.time / _MainMenuModel.Song.clip.length;
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
}
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
_MainMenuModel.Song.Pause();
|
|||
|
|
}
|
|||
|
|
yield return Play();
|
|||
|
|
//回到开启的时间
|
|||
|
|
_MainMenuModel.SongCurrentTime = startTime;
|
|||
|
|
OnTimeChange?.Invoke(_MainMenuModel.SongCurrentTime);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
/// <summary>
|
|||
|
|
/// 监听用户的输入
|
|||
|
|
/// </summary>
|
|||
|
|
private void CheckUserInput()
|
|||
|
|
{
|
|||
|
|
//之后需要更改为事件系统
|
|||
|
|
if (Input.GetMouseButtonDown(0))//鼠标左键
|
|||
|
|
{
|
|||
|
|
OnLeftClickCreateNewNote(_preGeneratedObject);
|
|||
|
|
}
|
|||
|
|
if (Input.GetMouseButtonDown(1))//鼠标右键
|
|||
|
|
{
|
|||
|
|
OnRightClickBuildingOptionPanelBehavior();
|
|||
|
|
OnRightClickGeneralOptionPanelBehavior();
|
|||
|
|
}
|
|||
|
|
if (Input.GetMouseButtonDown(2))//鼠标中键
|
|||
|
|
{
|
|||
|
|
print("鼠标中键被按下!");
|
|||
|
|
}
|
|||
|
|
if (Input.GetMouseButtonDown(3))//鼠标侧键
|
|||
|
|
{
|
|||
|
|
print("鼠标侧键被按下!");
|
|||
|
|
}
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Space))//空格键
|
|||
|
|
{
|
|||
|
|
_MainMenuModel.Song.Play();
|
|||
|
|
StartCoroutine(ChartPreview(_MainMenuModel.SongCurrentTime));
|
|||
|
|
}
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Escape))//ESC键
|
|||
|
|
{
|
|||
|
|
if (isBuildingModelEnabled)
|
|||
|
|
{
|
|||
|
|
isBuildingModelEnabled = false;
|
|||
|
|
isAnyModelEnabled = false;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "创建模式已退出 (ノ>ω<)ノ";
|
|||
|
|
CloseBuildingOptionPanel();
|
|||
|
|
}//使用ESC退出建造模式
|
|||
|
|
}
|
|||
|
|
if (Input.GetKeyDown(KeyCode.F))
|
|||
|
|
{
|
|||
|
|
ReadFile();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region 文件读写
|
|||
|
|
/// <summary>
|
|||
|
|
/// 文件写入操作
|
|||
|
|
/// </summary>
|
|||
|
|
private void WriteFile(string fileName, string content)
|
|||
|
|
{
|
|||
|
|
// 构建完整路径(推荐使用持久化数据路径)
|
|||
|
|
|
|||
|
|
string filePath = StandaloneFileBrowser.SaveFilePanel("选择文件夹", Application.persistentDataPath, fileName, "");
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 创建目录(如果不存在)
|
|||
|
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
|||
|
|
// 写入文件
|
|||
|
|
File.WriteAllText(filePath, content);
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "文件写入成功: (σ′▽‵)′▽‵)σ " + filePath;
|
|||
|
|
}
|
|||
|
|
catch (System.Exception e)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "写入文件失败: (´;ω;`)" + e.Message;
|
|||
|
|
}
|
|||
|
|
CloseGeneralOptionPanel();
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 选择谱面文件,读取
|
|||
|
|
/// </summary>
|
|||
|
|
private void ReadFile()
|
|||
|
|
{
|
|||
|
|
string[] filePath = StandaloneFileBrowser.OpenFolderPanel("选择文件夹", Application.persistentDataPath, false);
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
_MainMenuModel.ReadChartByPath(filePath[0] + "\\Chart.json");
|
|||
|
|
}
|
|||
|
|
catch (System.NullReferenceException e)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "空引用异常!" + e.Message;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
catch (System.IndexOutOfRangeException e)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "读取已取消 " + e.Message;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
#region 创建实例
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建新的note实例的函数
|
|||
|
|
/// </summary>
|
|||
|
|
private void CreateNewNote(Vector3 mouseWorldPos, NoteController note, int timingGroup)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "已创建 " + note.gameObject.name;
|
|||
|
|
|
|||
|
|
var selfRef = _MainMenuModel.CreateNewNoteDataItem(_MainMenuModel.SongCurrentTime, mouseWorldPos.x, mouseWorldPos.y, timingGroup);
|
|||
|
|
var Go = _MainMenuView.NotePool.Get(note);
|
|||
|
|
|
|||
|
|
Go.Init(
|
|||
|
|
new Vector2(
|
|||
|
|
mouseWorldPos.x,
|
|||
|
|
mouseWorldPos.y),
|
|||
|
|
_MainMenuModel.SongCurrentTime,
|
|||
|
|
_SongTimeContainer,
|
|||
|
|
_MainMenuModel.MainBPMGroup);
|
|||
|
|
|
|||
|
|
Go.SelfRef = selfRef;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建新的drag实例的函数
|
|||
|
|
/// </summary>
|
|||
|
|
private void CreateNewDrag(Vector3 mouseWorldPos, DragController drag, int timingGroup)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "已创建 " + drag.gameObject.name;
|
|||
|
|
|
|||
|
|
var selfRef = _MainMenuModel.CreateNewDragDataItem(_MainMenuModel.SongCurrentTime, mouseWorldPos.x, mouseWorldPos.y, timingGroup);
|
|||
|
|
var Go = _MainMenuView.NotePool.Get(drag);
|
|||
|
|
|
|||
|
|
Go.Init(
|
|||
|
|
new Vector2(
|
|||
|
|
mouseWorldPos.x,
|
|||
|
|
mouseWorldPos.y),
|
|||
|
|
_MainMenuModel.SongCurrentTime,
|
|||
|
|
_SongTimeContainer,
|
|||
|
|
_MainMenuModel.MainBPMGroup);
|
|||
|
|
|
|||
|
|
Go.SelfRef = selfRef;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建新的Flick实例的函数
|
|||
|
|
/// </summary>
|
|||
|
|
private IEnumerator CreateNewFlick(Vector3 mouseWorldPos, FlickController flick, int timingGroup)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "当前位置信息已录入,请将鼠标移动至四周点击确定方向,原地点击不选择方向,右键取消创建";
|
|||
|
|
FlickDirection direction = FlickDirection.Any;
|
|||
|
|
Vector3 currentMousePos = new Vector3();
|
|||
|
|
|
|||
|
|
IEnumerator WaitSecondClick()
|
|||
|
|
{
|
|||
|
|
yield return null;//卡掉最开始true状态
|
|||
|
|
while (!Input.GetMouseButtonDown(0))
|
|||
|
|
{
|
|||
|
|
yield return null;//等待至左键再次按下
|
|||
|
|
}
|
|||
|
|
currentMousePos = Camera.main.ScreenToWorldPoint(
|
|||
|
|
new Vector3(Input.mousePosition.x, Input.mousePosition.y, 8));//这里获取鼠标目前的位置
|
|||
|
|
}
|
|||
|
|
yield return WaitSecondClick();
|
|||
|
|
isAnyCoroutineEnabled = false;
|
|||
|
|
//这里开始依据所得坐标获取向量以确定位置
|
|||
|
|
var tempVector = currentMousePos - mouseWorldPos;
|
|||
|
|
float sqrMagnitude = tempVector.sqrMagnitude;
|
|||
|
|
|
|||
|
|
// 模平方小于等于1视为任意方向
|
|||
|
|
if (sqrMagnitude <= 1f)
|
|||
|
|
{
|
|||
|
|
direction = FlickDirection.Any;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 计算向量角度(弧度转角度)
|
|||
|
|
float angle = Mathf.Atan2(tempVector.y, tempVector.x) * Mathf.Rad2Deg;
|
|||
|
|
|
|||
|
|
// 转换为0-360度范围
|
|||
|
|
if (angle < 0) angle += 360f;
|
|||
|
|
|
|||
|
|
// 划分8个45度区域并添加22.5度偏移使区域居中
|
|||
|
|
int sector = (int)((angle + 22.5f) / 45f) % 8;
|
|||
|
|
|
|||
|
|
// 映射到方向枚举
|
|||
|
|
direction = sector switch
|
|||
|
|
{
|
|||
|
|
0 => FlickDirection.Right,
|
|||
|
|
1 => FlickDirection.RightUp,
|
|||
|
|
2 => FlickDirection.Up,
|
|||
|
|
3 => FlickDirection.LeftUp,
|
|||
|
|
4 => FlickDirection.Left,
|
|||
|
|
5 => FlickDirection.LeftDown,
|
|||
|
|
6 => FlickDirection.Down,
|
|||
|
|
7 => FlickDirection.RightDown,
|
|||
|
|
_ => FlickDirection.Any // 安全后备
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "第一次点击位置:" + mouseWorldPos.ToString() + "第二次点击位置" + currentMousePos.ToString() + " 结果为:" + direction;
|
|||
|
|
|
|||
|
|
var selfRef = _MainMenuModel.CreateNewFlickDataItem(_MainMenuModel.SongCurrentTime, mouseWorldPos.x, mouseWorldPos.y, timingGroup, direction);
|
|||
|
|
var Go = _MainMenuView.NotePool.Get(flick);
|
|||
|
|
//初始化一个实例
|
|||
|
|
Go.Init(
|
|||
|
|
new Vector2(
|
|||
|
|
mouseWorldPos.x,
|
|||
|
|
mouseWorldPos.y),
|
|||
|
|
_MainMenuModel.SongCurrentTime,
|
|||
|
|
_SongTimeContainer,
|
|||
|
|
direction,
|
|||
|
|
_MainMenuView.FlickSpritePairs,
|
|||
|
|
_MainMenuModel.MainBPMGroup
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
Go.SelfRef = selfRef;
|
|||
|
|
}
|
|||
|
|
private IEnumerator CreateNewDataFlow(Vector3 mouseWorldPos, DataFlowController dataFlow, int timingGroup)
|
|||
|
|
{
|
|||
|
|
ReferencePointLocation reference = ReferencePointLocation.Near;
|
|||
|
|
float startTime = _MainMenuModel.SongCurrentTime;
|
|||
|
|
float endTime=0;
|
|||
|
|
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "当前位置时间信息已录入,请选择第二个位置,右键取消创建";
|
|||
|
|
|
|||
|
|
Vector3 currentMousePos = new Vector3();
|
|||
|
|
|
|||
|
|
//这里开始进行位置选择逻辑
|
|||
|
|
IEnumerator WaitSecondClick()
|
|||
|
|
{
|
|||
|
|
yield return null;//卡掉最开始true状态
|
|||
|
|
while (!Input.GetMouseButtonDown(0))
|
|||
|
|
{
|
|||
|
|
yield return null;//等待至左键再次按下
|
|||
|
|
}
|
|||
|
|
currentMousePos = Camera.main.ScreenToWorldPoint(
|
|||
|
|
new Vector3(
|
|||
|
|
Input.mousePosition.x,
|
|||
|
|
Input.mousePosition.y,
|
|||
|
|
8));//这里获取鼠标目前的位置
|
|||
|
|
endTime = _MainMenuModel.SongCurrentTime;
|
|||
|
|
}
|
|||
|
|
yield return WaitSecondClick();
|
|||
|
|
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "按[1-6]数字按键确定样式,[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom]";
|
|||
|
|
|
|||
|
|
//这里开始类型选择逻辑
|
|||
|
|
IEnumerator WaitNumKeyDown()
|
|||
|
|
{
|
|||
|
|
yield return null;
|
|||
|
|
bool isReferenceSelected = false;
|
|||
|
|
while (!(Input.GetMouseButtonDown(0) && isReferenceSelected))
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha1)|| Input.GetKeyDown(KeyCode.Keypad1))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.Near;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.Far;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.RightTop;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.RightBottom;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.LeftTop;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6))
|
|||
|
|
{
|
|||
|
|
reference = ReferencePointLocation.LeftBottom;
|
|||
|
|
isReferenceSelected = true;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = $"当前位置为{reference},[Near, Far, RightTop, RightBottom, LeftTop, LeftBottom],再次单击确定选择";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yield return null;//等待至左键再次按下
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yield return WaitNumKeyDown();
|
|||
|
|
isAnyCoroutineEnabled = false;
|
|||
|
|
|
|||
|
|
var selfRef = _MainMenuModel.CreateNewSnakeDataItem(
|
|||
|
|
startTime,
|
|||
|
|
mouseWorldPos.x,
|
|||
|
|
mouseWorldPos.y,
|
|||
|
|
currentMousePos.x,
|
|||
|
|
currentMousePos.y,
|
|||
|
|
endTime,
|
|||
|
|
timingGroup,
|
|||
|
|
reference);
|
|||
|
|
|
|||
|
|
var Go = _MainMenuView.NotePool.Get(dataFlow);
|
|||
|
|
Go.Init(
|
|||
|
|
mouseWorldPos,
|
|||
|
|
currentMousePos,
|
|||
|
|
startTime,
|
|||
|
|
endTime,
|
|||
|
|
0.4f,
|
|||
|
|
_SongTimeContainer,
|
|||
|
|
_MainMenuModel.MainBPMGroup,
|
|||
|
|
reference
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
Go.SelfRef = selfRef;
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "开始位置:"+ mouseWorldPos.ToString()+" 时间:"+startTime+" 结束位置:"+ currentMousePos.ToString()+" 时间:"+ endTime;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 点击左键时创建新的物件
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnLeftClickCreateNewNote(BaseNote preGeneratedObject)
|
|||
|
|
{
|
|||
|
|
if (!(isBuildingModelEnabled && !BuildingOptionPanel.gameObject.activeSelf)) return;
|
|||
|
|
Vector3 mousePos = Input.mousePosition;
|
|||
|
|
//处于创造模式下,单击左键将会创造预备创造的物件
|
|||
|
|
switch (preGeneratedObject)
|
|||
|
|
{
|
|||
|
|
case NoteController:
|
|||
|
|
{
|
|||
|
|
CreateNewNote(
|
|||
|
|
Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 8)),
|
|||
|
|
_MainMenuView.NotePrefab,
|
|||
|
|
_MainMenuModel.MainBPMGroup.GroupNum);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case DragController:
|
|||
|
|
{
|
|||
|
|
CreateNewDrag(
|
|||
|
|
Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 8)),
|
|||
|
|
_MainMenuView.DragPrefab,
|
|||
|
|
_MainMenuModel.MainBPMGroup.GroupNum);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case FlickController:
|
|||
|
|
{
|
|||
|
|
if (isAnyCoroutineEnabled) break;//防止首尾嵌套
|
|||
|
|
StartCoroutine(
|
|||
|
|
CreateNewFlick(
|
|||
|
|
Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 8)),
|
|||
|
|
_MainMenuView.FlickPrefab,
|
|||
|
|
_MainMenuModel.MainBPMGroup.GroupNum)
|
|||
|
|
);
|
|||
|
|
isAnyCoroutineEnabled = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case DataFlowController:
|
|||
|
|
{
|
|||
|
|
if (isAnyCoroutineEnabled) break;//防止首尾嵌套
|
|||
|
|
StartCoroutine(
|
|||
|
|
CreateNewDataFlow(Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 8)),
|
|||
|
|
_MainMenuView.DataFlowPrefab,
|
|||
|
|
_MainMenuModel.MainBPMGroup.GroupNum)
|
|||
|
|
);
|
|||
|
|
isAnyCoroutineEnabled = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case null:
|
|||
|
|
{
|
|||
|
|
UnityEngine.Debug.LogError("存在空引用异常,请检查预制体是否被正常加载");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
default: print("存在非法输入亦或是不存在该类型"); break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
#region 右键会话窗口
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化所有右键会话窗口
|
|||
|
|
/// </summary>
|
|||
|
|
private void InitAllOptionPanel()
|
|||
|
|
{
|
|||
|
|
GeneralOptionPanel = Instantiate(_MainMenuView.GeneralOptionPanel, _Transform);
|
|||
|
|
BuildingOptionPanel = Instantiate(_MainMenuView.BuildingOptionPanel, _Transform);
|
|||
|
|
|
|||
|
|
GeneralOptionPanel.gameObject.SetActive(false);
|
|||
|
|
BuildingOptionPanel.gameObject.SetActive(false);
|
|||
|
|
|
|||
|
|
//鼠标右键界面初始化业务逻辑
|
|||
|
|
InitGeneralOptionPanel();
|
|||
|
|
InitBuildingOptionPanel();
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化通常会话窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void InitGeneralOptionPanel()
|
|||
|
|
{
|
|||
|
|
GeneralOptionPanel.MouseGudies.onClick.AddListener(null);
|
|||
|
|
GeneralOptionPanel.BuildingModel.onClick.AddListener(OpenBuildOptionPanel);
|
|||
|
|
GeneralOptionPanel.EditModel.onClick.AddListener(null);
|
|||
|
|
GeneralOptionPanel.Output.onClick.AddListener(()=> WriteFile("Chart.json", _MainMenuModel.GetChartJson()));
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化建造窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void InitBuildingOptionPanel()
|
|||
|
|
{
|
|||
|
|
BuildingOptionPanel.NoteButton.onClick.AddListener(() => OnBuildingModelButtonClick(BuildingOptionPanel.NoteButton.gameObject, _MainMenuView.NotePrefab));
|
|||
|
|
BuildingOptionPanel.DragButton.onClick.AddListener(() => OnBuildingModelButtonClick(BuildingOptionPanel.DragButton.gameObject, _MainMenuView.DragPrefab));
|
|||
|
|
BuildingOptionPanel.FlickButton.onClick.AddListener(() => OnBuildingModelButtonClick(BuildingOptionPanel.FlickButton.gameObject, _MainMenuView.FlickPrefab));
|
|||
|
|
BuildingOptionPanel.DataFlowButton.onClick.AddListener(() => OnBuildingModelButtonClick(BuildingOptionPanel.DataFlowButton.gameObject, _MainMenuView.DataFlowPrefab));
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 任意创建模式下的note按钮被点击时,替换预备放置的物件,打印输出当前按钮的信息,关闭当前窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void OnBuildingModelButtonClick(GameObject buttonObject, BaseNote preGeneratedObject)
|
|||
|
|
{
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = buttonObject.name + "已经启用,按ESC可退出创建模式 (ゝ∀・)⌒☆";
|
|||
|
|
CloseBuildingOptionPanel();
|
|||
|
|
//替换预生成的物件
|
|||
|
|
_preGeneratedObject = preGeneratedObject;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 开启创建模式,该模式下玩家右键将直接打开建造模式面板,自由选择对应的物件进行放置
|
|||
|
|
/// </summary>
|
|||
|
|
void OpenBuildOptionPanel()
|
|||
|
|
{
|
|||
|
|
Vector3 mousePos = Input.mousePosition;
|
|||
|
|
//关闭通常会话选项的同时将开启创建模式
|
|||
|
|
CloseGeneralOptionPanel();
|
|||
|
|
isBuildingModelEnabled = true;
|
|||
|
|
isAnyModelEnabled = true;
|
|||
|
|
BuildingOptionPanel.gameObject.SetActive(true);
|
|||
|
|
BuildingOptionPanel.GetComponent<Transform>().position = new Vector3(mousePos.x, mousePos.y, 8);
|
|||
|
|
_MainMenuView.TopPanel.StatusBar.text = "已进入创建模式,按ESC可退出创建模式 (ゝ∀・)⌒☆";
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 通过鼠标来创建创建模式会话窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void OpenBuildOptionPanelWithMouse()
|
|||
|
|
{
|
|||
|
|
Vector3 mousePos = Input.mousePosition;
|
|||
|
|
isAnyModelEnabled = true;
|
|||
|
|
BuildingOptionPanel.gameObject.SetActive(true);
|
|||
|
|
BuildingOptionPanel.GetComponent<Transform>().position = new Vector3(mousePos.x, mousePos.y, 8);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 关闭创建模式会话窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void CloseBuildingOptionPanel()
|
|||
|
|
{
|
|||
|
|
BuildingOptionPanel.gameObject.SetActive(false);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 关闭通常会话窗口
|
|||
|
|
/// </summary>
|
|||
|
|
void CloseGeneralOptionPanel()
|
|||
|
|
{
|
|||
|
|
//如果再次点击右键这关闭窗口
|
|||
|
|
optionHasBeenCreated = false;
|
|||
|
|
GeneralOptionPanel.gameObject.SetActive(false);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 在右键点击时通常面板的响应
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnRightClickGeneralOptionPanelBehavior()
|
|||
|
|
{
|
|||
|
|
if (isAnyModelEnabled) return;
|
|||
|
|
Vector3 mousePos = Input.mousePosition;
|
|||
|
|
if (optionHasBeenCreated)
|
|||
|
|
{
|
|||
|
|
//当不处于任何模式之下,用户右键会直接生成通常选项
|
|||
|
|
CloseGeneralOptionPanel();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//激活右键窗口
|
|||
|
|
optionHasBeenCreated = true;
|
|||
|
|
GeneralOptionPanel.gameObject.SetActive(true);
|
|||
|
|
GeneralOptionPanel.GetComponent<Transform>().position = new Vector3(mousePos.x, mousePos.y, 8);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 在右键按下时建造面板的响应
|
|||
|
|
/// </summary>
|
|||
|
|
private void OnRightClickBuildingOptionPanelBehavior()
|
|||
|
|
{
|
|||
|
|
if (!isBuildingModelEnabled) return;
|
|||
|
|
if (BuildingOptionPanel.gameObject.activeSelf)
|
|||
|
|
{
|
|||
|
|
//假如,处于创建模式下,会话窗口存在,右键将关闭窗口
|
|||
|
|
CloseBuildingOptionPanel();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//但是如果窗口不存在,则直接创建一个
|
|||
|
|
OpenBuildOptionPanelWithMouse();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
}
|