305 lines
9.8 KiB
C#
305 lines
9.8 KiB
C#
/**
|
|
* 全屏示例的 UI 控制器
|
|
*
|
|
* Author: Kirurobo http://twitter.com/kirurobo
|
|
* License: MIT
|
|
*/
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Kirurobo
|
|
{
|
|
/// <summary>
|
|
/// 使用 Toggle 开关 WindowController 设置的示例
|
|
/// </summary>
|
|
public class FullscreenSample : MonoBehaviour
|
|
{
|
|
private UniWindowController uniwinc;
|
|
private RectTransform canvasRect;
|
|
|
|
private float mouseMoveSS = 0f; // 鼠标轨迹平方和。[px^2]
|
|
private float mouseMoveSSThreshold = 36f; // 点击(非拖拽)阈值。[px^2]
|
|
private Vector3 lastMousePosition; // 右键点击位置。
|
|
private float touchDuration = 0f;
|
|
private float touchDurationThreshold = 0.5f; // 长按时间阈值。[s]
|
|
|
|
public Toggle transparentToggle;
|
|
public Toggle topmostToggle;
|
|
public Toggle bottommostToggle;
|
|
public Dropdown fitWindowDropdown;
|
|
public Button quitButton;
|
|
public Button menuCloseButton;
|
|
public RectTransform menuPanel;
|
|
|
|
/// <summary>
|
|
/// 设置
|
|
/// </summary>
|
|
void Start()
|
|
{
|
|
// 查找 UniWindowController
|
|
uniwinc = GameObject.FindAnyObjectByType<UniWindowController>();
|
|
|
|
// 获取 Canvas 的 RectTransform
|
|
if (menuPanel) canvasRect = menuPanel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
|
|
|
// 根据有效显示器数量创建选项
|
|
UpdateMonitorDropdown();
|
|
|
|
// 将 Toggle 的选中状态与当前状态同步
|
|
UpdateUI();
|
|
|
|
// 初始状态下关闭菜单
|
|
CloseMenu();
|
|
|
|
if (uniwinc)
|
|
{
|
|
// 操作 UI 时将其反映到窗口
|
|
transparentToggle?.onValueChanged.AddListener(val => uniwinc.isTransparent = val);
|
|
topmostToggle?.onValueChanged.AddListener(val => uniwinc.isTopmost = val);
|
|
bottommostToggle?.onValueChanged.AddListener(val => uniwinc.isBottommost = val);
|
|
fitWindowDropdown?.onValueChanged.AddListener(val => SetFitToMonitor(val));
|
|
quitButton?.onClick.AddListener(Quit);
|
|
menuCloseButton?.onClick.AddListener(CloseMenu);
|
|
|
|
// Add events
|
|
uniwinc.OnStateChanged += (type) =>
|
|
{
|
|
UpdateUI();
|
|
//ShowEventMessage("Window state changed: " + type);
|
|
};
|
|
uniwinc.OnMonitorChanged += () => {
|
|
UpdateMonitorDropdown();
|
|
UpdateUI();
|
|
//ShowEventMessage("Resolution changed!");
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 每帧执行
|
|
/// </summary>
|
|
private void Update()
|
|
{
|
|
// 鼠标右键点击时显示上下文菜单。
|
|
// 如果鼠标移动距离在阈值以下,则视为点击
|
|
if (InputProxy.GetMouseButtonDown(1))
|
|
{
|
|
lastMousePosition = InputProxy.mousePosition;
|
|
touchDuration = 0f;
|
|
}
|
|
if (InputProxy.GetMouseButton(1))
|
|
{
|
|
mouseMoveSS += (InputProxy.mousePosition - lastMousePosition).sqrMagnitude;
|
|
}
|
|
if (InputProxy.GetMouseButtonUp(1))
|
|
{
|
|
if (mouseMoveSS < mouseMoveSSThreshold)
|
|
{
|
|
ShowMenu(lastMousePosition);
|
|
}
|
|
mouseMoveSS = 0f;
|
|
touchDuration = 0f;
|
|
}
|
|
|
|
// 暂时仅在 Legacy Input Manager 中处理触摸
|
|
#if ENABLE_LEGACY_INPUT_MANAGER
|
|
// 长按也可显示菜单
|
|
if (Input.touchSupported && (Input.touchCount > 0))
|
|
{
|
|
Touch touch = Input.GetTouch(0);
|
|
if (touch.phase == TouchPhase.Began)
|
|
{
|
|
lastMousePosition = Input.mousePosition;
|
|
touchDuration = 0f;
|
|
}
|
|
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
|
|
{
|
|
mouseMoveSS += touch.deltaPosition.sqrMagnitude;
|
|
touchDuration += touch.deltaTime;
|
|
}
|
|
if (touch.phase == TouchPhase.Ended)
|
|
{
|
|
if ((mouseMoveSS < mouseMoveSSThreshold) && (touchDuration >= touchDurationThreshold))
|
|
{
|
|
ShowMenu(lastMousePosition);
|
|
}
|
|
mouseMoveSS = 0f;
|
|
touchDuration = 0f;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// 按下 [Space] 键也可显示菜单
|
|
if (InputProxy.GetKeyUp("space"))
|
|
{
|
|
if (menuPanel)
|
|
{
|
|
if (menuPanel.gameObject.activeSelf) {
|
|
CloseMenu();
|
|
} else {
|
|
Vector2 pos = new Vector2(Screen.width / 2, Screen.height / 2);
|
|
ShowMenu(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 按下 [ESC] 时退出或停止播放
|
|
if (InputProxy.GetKeyUp("escape"))
|
|
{
|
|
Quit();
|
|
}
|
|
}
|
|
|
|
void Quit()
|
|
{
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 适配显示器下拉列表更改时的处理
|
|
/// </summary>
|
|
/// <param name="val"></param>
|
|
void SetFitToMonitor(int val)
|
|
{
|
|
if (!uniwinc) return;
|
|
|
|
if (val < 1)
|
|
{
|
|
// 下拉列表第一项为不适配
|
|
uniwinc.shouldFitMonitor = false;
|
|
}
|
|
else
|
|
{
|
|
// 由于从第二项开始,显示器编号减1
|
|
uniwinc.monitorToFit = val - 1;
|
|
uniwinc.shouldFitMonitor = true; // 从false变为true时才会移动窗口,因此先指定显示器编号再更改
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 在指定坐标显示上下文菜单
|
|
/// </summary>
|
|
/// <param name="position">指定中心坐标</param>
|
|
private void ShowMenu(Vector2 position)
|
|
{
|
|
if (menuPanel)
|
|
{
|
|
Vector2 pos = position * (canvasRect.sizeDelta.x / Screen.width);
|
|
float w = menuPanel.rect.width;
|
|
float h = menuPanel.rect.height;
|
|
|
|
// 以指定坐标为中心进行位置调整
|
|
pos.y = Mathf.Max(Mathf.Min(pos.y, Screen.height - h / 2f), h / 2f); // 如果超出则向上移动
|
|
pos.x = Mathf.Max(Mathf.Min(pos.x, Screen.width - w / 2f), w / 2f); // 如果超出右侧则向左移动
|
|
|
|
menuPanel.pivot = Vector2.one * 0.5f; // 设置为中心
|
|
menuPanel.anchorMin = Vector2.zero;
|
|
menuPanel.anchorMax = Vector2.zero;
|
|
menuPanel.anchoredPosition = pos;
|
|
|
|
menuPanel.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 关闭上下文菜单
|
|
/// </summary>
|
|
private void CloseMenu()
|
|
{
|
|
if (menuPanel)
|
|
{
|
|
menuPanel.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将实际状态反映到 UI 显示
|
|
/// </summary>
|
|
private void UpdateUI()
|
|
{
|
|
if (uniwinc)
|
|
{
|
|
if (transparentToggle)
|
|
{
|
|
transparentToggle.isOn = uniwinc.isTransparent;
|
|
}
|
|
|
|
if (topmostToggle)
|
|
{
|
|
topmostToggle.isOn = uniwinc.isTopmost;
|
|
}
|
|
|
|
if (bottommostToggle)
|
|
{
|
|
bottommostToggle.isOn = uniwinc.isBottommost;
|
|
}
|
|
|
|
if (fitWindowDropdown)
|
|
{
|
|
if (uniwinc.shouldFitMonitor)
|
|
{
|
|
fitWindowDropdown.value = uniwinc.monitorToFit + 1;
|
|
}
|
|
else
|
|
{
|
|
fitWindowDropdown.value = 0;
|
|
}
|
|
fitWindowDropdown.RefreshShownValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新显示器选择下拉列表的选项
|
|
/// 之后需要调用 UpdateUI()
|
|
/// </summary>
|
|
void UpdateMonitorDropdown()
|
|
{
|
|
if (!fitWindowDropdown) return;
|
|
|
|
// 删除除第一项以外的选项
|
|
fitWindowDropdown.options.RemoveRange(1, fitWindowDropdown.options.Count - 1);
|
|
|
|
if (!uniwinc)
|
|
{
|
|
fitWindowDropdown.value = 0;
|
|
}
|
|
else
|
|
{
|
|
int count = UniWindowController.GetMonitorCount();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
fitWindowDropdown.options.Add(new Dropdown.OptionData("适配显示器 " + i));
|
|
}
|
|
if (uniwinc.monitorToFit >= count)
|
|
{
|
|
uniwinc.monitorToFit = count - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 显示带超时功能的消息
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
private void ShowEventMessage(string message)
|
|
{
|
|
Debug.Log(message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 如果 UI 中有文本框,则显示消息。否则输出到控制台
|
|
/// </summary>
|
|
/// <param name="text"></param>
|
|
public void OutputMessage(string text)
|
|
{
|
|
Debug.Log(text);
|
|
}
|
|
}
|
|
}
|