Gameplay Ingredients是一组用于 Unity 游戏的运行时和编辑器工具:一组脚本的集合,可在制作游戏和原型时简化简单的任务。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

251 行
8.2 KiB

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Cinemachine;
namespace GameplayIngredients.Editor
{
public static class LinkGameView
{
static readonly string kPreferenceName = "GameplayIngredients.LinkGameView";
static readonly string kCinemachinePreferenceName = "GameplayIngredients.LinkGameViewCinemachine";
static readonly string kLinkCameraName = "___LINK__SCENE__VIEW__CAMERA___";
public static bool Active
{
get
{
// Get preference only when not playing
if (!Application.isPlaying)
m_Active = EditorPrefs.GetBool(kPreferenceName, false);
return m_Active;
}
set
{
// Update preference only when not playing
if(!Application.isPlaying)
EditorPrefs.SetBool(kPreferenceName, value);
m_Active = value;
if(s_GameObject != null)
s_GameObject.SetActive(value);
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
}
}
public static bool CinemachineActive
{
get
{
// Get preference only when not playing
if (!Application.isPlaying)
m_CinemachineActive = EditorPrefs.GetBool(kCinemachinePreferenceName, false);
return m_CinemachineActive;
}
set
{
// Update preference only when not playing
if (!Application.isPlaying)
EditorPrefs.SetBool(kCinemachinePreferenceName, value);
UpdateCinemachinePreview(value);
m_CinemachineActive = value;
}
}
static bool m_Active = false;
static bool m_CinemachineActive = false;
public static SceneView LockedSceneView
{
get
{
return s_LockedSceneView;
}
set
{
s_LockedSceneView = value;
}
}
static SceneView s_LockedSceneView;
[InitializeOnLoadMethod]
static void Initialize()
{
SceneView.duringSceneGui += Update;
EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
static void OnPlayModeChanged(PlayModeStateChange state)
{
// Reset State when entering editmode or play mode
if(state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode)
{
if (Active)
Active = true;
else
Active = false;
if (CinemachineActive)
CinemachineActive = true;
else
CinemachineActive = false;
}
else // Cleanup before switching state
{
if (s_GameObject != null)
Object.DestroyImmediate(s_GameObject);
}
}
const string kMenuPath = "Edit/Link SceneView and GameView %,";
public const int kMenuPriority = 230;
[MenuItem(kMenuPath, priority = kMenuPriority, validate = false)]
static void Toggle()
{
if (Active)
Active = false;
else
Active = true;
}
[MenuItem(kMenuPath, priority = kMenuPriority, validate = true)]
static bool ToggleCheck()
{
Menu.SetChecked(kMenuPath, Active);
return SceneView.sceneViews.Count > 0;
}
public static GameObject Camera { get {return s_GameObject;} }
static GameObject s_GameObject;
static void Update(SceneView sceneView)
{
// Check if camera Exists
if (s_GameObject == null)
{
// If disconnected (should not happen, but hey...)
var result = GameObject.Find(kLinkCameraName);
if (result != null) // reconnect
s_GameObject = result;
else // Create the camera if it does not exist
s_GameObject = CreateLinkedCamera();
if (Application.isPlaying)
Active = false;
}
// If we have a VirtualCameraManager, manage its state here
if(Application.isPlaying && Manager.Has<VirtualCameraManager>())
{
var camera = Manager.Get<VirtualCameraManager>().gameObject;
if(camera.activeInHierarchy && Active) // We need to disable the VirtualCameraManager
{
camera.SetActive(false);
}
else if (!camera.activeInHierarchy && !Active) // We need to re-enable the VirtualCameraManager
{
camera.SetActive(true);
}
}
if (Active && !CinemachineActive)
{
var sv = s_LockedSceneView == null ? SceneView.lastActiveSceneView : s_LockedSceneView;
var sceneCamera = sv.camera;
var camera = s_GameObject.GetComponent<Camera>();
bool needRepaint = sceneCamera.transform.position != camera.transform.position
|| sceneCamera.transform.rotation != camera.transform.rotation
|| sceneCamera.fieldOfView != camera.fieldOfView;
if(needRepaint)
{
s_GameObject.transform.position = sceneCamera.transform.position;
s_GameObject.transform.rotation = sceneCamera.transform.rotation;
camera.orthographic = sceneCamera.orthographic;
camera.fieldOfView = sceneCamera.fieldOfView;
camera.orthographicSize = sceneCamera.orthographicSize;
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
needRepaint = false;
}
}
}
const string kDefaultLinkPrefabName = "LinkGameViewCamera";
static GameObject CreateLinkedCamera()
{
// Try to find an Asset named as the default name
string[] assets = AssetDatabase.FindAssets(kDefaultLinkPrefabName);
if(assets.Length > 0)
{
string path = AssetDatabase.GUIDToAssetPath(assets[0]);
GameObject obj = (GameObject)AssetDatabase.LoadAssetAtPath(path, typeof(GameObject));
if (obj != null)
{
var instance = GameObject.Instantiate(obj);
if(instance.GetComponent<Camera>() != null)
{
instance.hideFlags = HideFlags.HideAndDontSave;
instance.tag = "MainCamera";
instance.name = kLinkCameraName;
instance.SetActive(Active);
instance.GetComponent<Camera>().depth = int.MaxValue;
return instance;
}
else
{
Debug.LogWarning("LinkGameView Found default prefab but has no camera!");
}
}
else
Debug.LogWarning("LinkGameView Found default prefab but is not gameobject!");
}
// Otherwise ... Create default from code
var go = new GameObject(kLinkCameraName);
go.hideFlags = HideFlags.HideAndDontSave;
go.tag = "MainCamera";
var camera = go.AddComponent<Camera>();
camera.depth = int.MaxValue;
go.SetActive(Active);
return go;
}
static void UpdateCinemachinePreview(bool value)
{
if (s_GameObject == null)
return;
CinemachineBrain brain;
if (!s_GameObject.TryGetComponent<CinemachineBrain>(out brain))
{
brain = s_GameObject.AddComponent<CinemachineBrain>();
}
brain.enabled = value;
}
}
}