CinemachineSettings.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System;
  4. namespace Cinemachine.Editor
  5. {
  6. [InitializeOnLoad]
  7. internal sealed class CinemachineSettings
  8. {
  9. public static class CinemachineCoreSettings
  10. {
  11. private static readonly string hShowInGameGuidesKey = "CNMCN_Core_ShowInGameGuides";
  12. public static bool ShowInGameGuides
  13. {
  14. get { return EditorPrefs.GetBool(hShowInGameGuidesKey, true); }
  15. set
  16. {
  17. if (ShowInGameGuides != value)
  18. {
  19. EditorPrefs.SetBool(hShowInGameGuidesKey, value);
  20. UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
  21. }
  22. }
  23. }
  24. static string kUseTimelneScrubbingCache = "CNMCN_Timeeline_UseTimelineScrubbingCache";
  25. public static bool UseTimelneScrubbingCache
  26. {
  27. get { return EditorPrefs.GetBool(kUseTimelneScrubbingCache, true); }
  28. set
  29. {
  30. if (UseTimelneScrubbingCache != value)
  31. EditorPrefs.SetBool(kUseTimelneScrubbingCache, value);
  32. }
  33. }
  34. private static readonly string kCoreActiveGizmoColourKey = "CNMCN_Core_Active_Gizmo_Colour";
  35. public static readonly Color kDefaultActiveColour = new Color32(255, 0, 0, 100);
  36. public static Color ActiveGizmoColour
  37. {
  38. get
  39. {
  40. string packedColour = EditorPrefs.GetString(kCoreActiveGizmoColourKey, PackColor(kDefaultActiveColour));
  41. return UnpackColour(packedColour);
  42. }
  43. set
  44. {
  45. if (ActiveGizmoColour != value)
  46. {
  47. string packedColour = PackColor(value);
  48. EditorPrefs.SetString(kCoreActiveGizmoColourKey, packedColour);
  49. }
  50. }
  51. }
  52. private static readonly string kCoreInactiveGizmoColourKey = "CNMCN_Core_Inactive_Gizmo_Colour";
  53. public static readonly Color kDefaultInactiveColour = new Color32(9, 54, 87, 100);
  54. public static Color InactiveGizmoColour
  55. {
  56. get
  57. {
  58. string packedColour = EditorPrefs.GetString(kCoreInactiveGizmoColourKey, PackColor(kDefaultInactiveColour));
  59. return UnpackColour(packedColour);
  60. }
  61. set
  62. {
  63. if (InactiveGizmoColour != value)
  64. {
  65. string packedColour = PackColor(value);
  66. EditorPrefs.SetString(kCoreInactiveGizmoColourKey, packedColour);
  67. }
  68. }
  69. }
  70. }
  71. public static class ComposerSettings
  72. {
  73. private static readonly string kOverlayOpacityKey = "CNMCN_Overlay_Opacity";
  74. private static readonly string kComposerHardBoundsColourKey = "CNMCN_Composer_HardBounds_Colour";
  75. private static readonly string kComposerSoftBoundsColourKey = "CNMCN_Composer_SoftBounds_Colour";
  76. private static readonly string kComposerTargetColourKey = "CNMCN_Composer_Target_Colour";
  77. private static readonly string kComposerTargetSizeKey = "CNMCN_Composer_Target_Size";
  78. public const float kDefaultOverlayOpacity = 0.15f;
  79. public static readonly Color kDefaultHardBoundsColour = new Color32(255, 0, 72, 255);
  80. public static readonly Color kDefaultSoftBoundsColour = new Color32(0, 194, 255, 255);
  81. public static readonly Color kDefaultTargetColour = new Color32(255, 254, 25, 255);
  82. public static float OverlayOpacity
  83. {
  84. get { return EditorPrefs.GetFloat(kOverlayOpacityKey, kDefaultOverlayOpacity); }
  85. set
  86. {
  87. if (value != OverlayOpacity)
  88. {
  89. EditorPrefs.SetFloat(kOverlayOpacityKey, value);
  90. }
  91. }
  92. }
  93. public static Color HardBoundsOverlayColour
  94. {
  95. get
  96. {
  97. string packedColour = EditorPrefs.GetString(kComposerHardBoundsColourKey, PackColor(kDefaultHardBoundsColour));
  98. return UnpackColour(packedColour);
  99. }
  100. set
  101. {
  102. if (HardBoundsOverlayColour != value)
  103. {
  104. string packedColour = PackColor(value);
  105. EditorPrefs.SetString(kComposerHardBoundsColourKey, packedColour);
  106. }
  107. }
  108. }
  109. public static Color SoftBoundsOverlayColour
  110. {
  111. get
  112. {
  113. string packedColour = EditorPrefs.GetString(kComposerSoftBoundsColourKey, PackColor(kDefaultSoftBoundsColour));
  114. return UnpackColour(packedColour);
  115. }
  116. set
  117. {
  118. if (SoftBoundsOverlayColour != value)
  119. {
  120. string packedColour = PackColor(value);
  121. EditorPrefs.SetString(kComposerSoftBoundsColourKey, packedColour);
  122. }
  123. }
  124. }
  125. public static Color TargetColour
  126. {
  127. get
  128. {
  129. string packedColour = EditorPrefs.GetString(kComposerTargetColourKey, PackColor(kDefaultTargetColour));
  130. return UnpackColour(packedColour);
  131. }
  132. set
  133. {
  134. if (TargetColour != value)
  135. {
  136. string packedColour = PackColor(value);
  137. EditorPrefs.SetString(kComposerTargetColourKey, packedColour);
  138. }
  139. }
  140. }
  141. public static float TargetSize
  142. {
  143. get
  144. {
  145. return EditorPrefs.GetFloat(kComposerTargetSizeKey, 5f);
  146. }
  147. set
  148. {
  149. if (TargetSize != value)
  150. {
  151. EditorPrefs.SetFloat(kComposerTargetSizeKey, value);
  152. }
  153. }
  154. }
  155. }
  156. private static bool ShowCoreSettings
  157. {
  158. get { return EditorPrefs.GetBool(kCoreSettingsFoldKey, false); }
  159. set
  160. {
  161. if (value != ShowCoreSettings)
  162. {
  163. EditorPrefs.SetBool(kCoreSettingsFoldKey, value);
  164. }
  165. }
  166. }
  167. private static bool ShowComposerSettings
  168. {
  169. get { return EditorPrefs.GetBool(kComposerSettingsFoldKey, false); }
  170. set
  171. {
  172. if (value != ShowComposerSettings)
  173. {
  174. EditorPrefs.SetBool(kComposerSettingsFoldKey, value);
  175. }
  176. }
  177. }
  178. private static Texture2D sCinemachineLogoTexture = null;
  179. internal static Texture2D CinemachineLogoTexture
  180. {
  181. get
  182. {
  183. if (sCinemachineLogoTexture == null)
  184. sCinemachineLogoTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(
  185. ScriptableObjectUtility.CinemachineRealativeInstallPath
  186. + "/Editor/EditorResources/cm_logo_sm.png");
  187. if (sCinemachineLogoTexture != null)
  188. sCinemachineLogoTexture.hideFlags = HideFlags.DontSaveInEditor;
  189. return sCinemachineLogoTexture;
  190. }
  191. }
  192. private static Texture2D sCinemachineHeader = null;
  193. internal static Texture2D CinemachineHeader
  194. {
  195. get
  196. {
  197. if (sCinemachineHeader == null)
  198. sCinemachineHeader = AssetDatabase.LoadAssetAtPath<Texture2D>(
  199. ScriptableObjectUtility.CinemachineRealativeInstallPath
  200. + "/Editor/EditorResources/cinemachine_header.tif");
  201. ;
  202. if (sCinemachineHeader != null)
  203. sCinemachineHeader.hideFlags = HideFlags.DontSaveInEditor;
  204. return sCinemachineHeader;
  205. }
  206. }
  207. private static readonly string kCoreSettingsFoldKey = "CNMCN_Core_Folded";
  208. private static readonly string kComposerSettingsFoldKey = "CNMCN_Composer_Folded";
  209. internal static event Action AdditionalCategories = null;
  210. static CinemachineSettings()
  211. {
  212. if (CinemachineLogoTexture != null)
  213. {
  214. EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
  215. }
  216. }
  217. class Styles {
  218. //private static readonly GUIContent sCoreShowHiddenObjectsToggle = new GUIContent("Show Hidden Objects", "If checked, Cinemachine hidden objects will be shown in the inspector. This might be necessary to repair broken script mappings when upgrading from a pre-release version");
  219. public static readonly GUIContent sCoreActiveGizmosColour = new GUIContent("Active Virtual Camera", "The colour for the active virtual camera's gizmos");
  220. public static readonly GUIContent sCoreInactiveGizmosColour = new GUIContent("Inactive Virtual Camera", "The colour for all inactive virtual camera gizmos");
  221. public static readonly GUIContent sComposerOverlayOpacity = new GUIContent("Overlay Opacity", "The alpha of the composer's overlay when a virtual camera is selected with composer module enabled");
  222. public static readonly GUIContent sComposerHardBoundsOverlay = new GUIContent("Hard Bounds Overlay", "The colour of the composer overlay's hard bounds region");
  223. public static readonly GUIContent sComposerSoftBoundsOverlay = new GUIContent("Soft Bounds Overlay", "The colour of the composer overlay's soft bounds region");
  224. public static readonly GUIContent sComposerTargetOverlay = new GUIContent("Composer Target", "The colour of the composer overlay's target");
  225. public static readonly GUIContent sComposerTargetOverlayPixels = new GUIContent("Target Size (px)", "The size of the composer overlay's target box in pixels");
  226. }
  227. private const string kCinemachineHeaderPath = "cinemachine_header.tif";
  228. private const string kCinemachineDocURL = @"http://www.cinemachineimagery.com/documentation/";
  229. private static Vector2 sScrollPosition = Vector2.zero;
  230. #if UNITY_2019_1_OR_NEWER
  231. [SettingsProvider]
  232. static SettingsProvider CreateProjectSettingsProvider()
  233. {
  234. var provider = new SettingsProvider("Preferences/Cinemachine", SettingsScope.User, SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>());
  235. provider.guiHandler = (sarchContext) => OnGUI();
  236. return provider;
  237. }
  238. #else
  239. [PreferenceItem("Cinemachine")]
  240. #endif
  241. private static void OnGUI()
  242. {
  243. if (CinemachineHeader != null)
  244. {
  245. const float kWidth = 350f;
  246. float aspectRatio = (float)CinemachineHeader.height / (float)CinemachineHeader.width;
  247. GUILayout.BeginScrollView(Vector2.zero, false, false, GUILayout.Width(kWidth), GUILayout.Height(kWidth * aspectRatio));
  248. Rect texRect = new Rect(0f, 0f, kWidth, kWidth * aspectRatio);
  249. GUILayout.BeginArea(texRect);
  250. GUI.DrawTexture(texRect, CinemachineHeader, ScaleMode.ScaleToFit);
  251. GUILayout.EndArea();
  252. GUILayout.EndScrollView();
  253. }
  254. sScrollPosition = GUILayout.BeginScrollView(sScrollPosition);
  255. //CinemachineCore.sShowHiddenObjects
  256. // = EditorGUILayout.Toggle("Show Hidden Objects", CinemachineCore.sShowHiddenObjects);
  257. ShowCoreSettings = EditorGUILayout.Foldout(ShowCoreSettings, "Runtime Settings", true);
  258. if (ShowCoreSettings)
  259. {
  260. EditorGUI.indentLevel++;
  261. EditorGUI.BeginChangeCheck();
  262. EditorGUILayout.BeginHorizontal();
  263. EditorGUI.BeginChangeCheck();
  264. Color newActiveGizmoColour = EditorGUILayout.ColorField(Styles.sCoreActiveGizmosColour, CinemachineCoreSettings.ActiveGizmoColour);
  265. if (EditorGUI.EndChangeCheck())
  266. {
  267. CinemachineCoreSettings.ActiveGizmoColour = newActiveGizmoColour;
  268. UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
  269. }
  270. if (GUILayout.Button("Reset"))
  271. {
  272. CinemachineCoreSettings.ActiveGizmoColour = CinemachineCoreSettings.kDefaultActiveColour;
  273. }
  274. EditorGUILayout.EndHorizontal();
  275. EditorGUILayout.BeginHorizontal();
  276. EditorGUI.BeginChangeCheck();
  277. Color newInactiveGizmoColour = EditorGUILayout.ColorField(Styles.sCoreInactiveGizmosColour, CinemachineCoreSettings.InactiveGizmoColour);
  278. if (EditorGUI.EndChangeCheck())
  279. {
  280. CinemachineCoreSettings.InactiveGizmoColour = newInactiveGizmoColour;
  281. UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
  282. }
  283. if (GUILayout.Button("Reset"))
  284. {
  285. CinemachineCoreSettings.InactiveGizmoColour = CinemachineCoreSettings.kDefaultInactiveColour;
  286. }
  287. EditorGUILayout.EndHorizontal();
  288. EditorGUI.indentLevel--;
  289. }
  290. ShowComposerSettings = EditorGUILayout.Foldout(ShowComposerSettings, "Composer Settings", true);
  291. if (ShowComposerSettings)
  292. {
  293. EditorGUI.indentLevel++;
  294. EditorGUILayout.BeginHorizontal();
  295. EditorGUI.BeginChangeCheck();
  296. float overlayOpacity = EditorGUILayout.Slider(Styles.sComposerOverlayOpacity, ComposerSettings.OverlayOpacity, 0f, 1f);
  297. if (EditorGUI.EndChangeCheck())
  298. {
  299. ComposerSettings.OverlayOpacity = overlayOpacity;
  300. }
  301. if (GUILayout.Button("Reset"))
  302. {
  303. ComposerSettings.OverlayOpacity = ComposerSettings.kDefaultOverlayOpacity;
  304. }
  305. EditorGUILayout.EndHorizontal();
  306. EditorGUILayout.BeginHorizontal();
  307. EditorGUI.BeginChangeCheck();
  308. Color newHardEdgeColor = EditorGUILayout.ColorField(Styles.sComposerHardBoundsOverlay, ComposerSettings.HardBoundsOverlayColour);
  309. if (EditorGUI.EndChangeCheck())
  310. {
  311. ComposerSettings.HardBoundsOverlayColour = newHardEdgeColor;
  312. }
  313. if (GUILayout.Button("Reset"))
  314. {
  315. ComposerSettings.HardBoundsOverlayColour = ComposerSettings.kDefaultHardBoundsColour;
  316. }
  317. EditorGUILayout.EndHorizontal();
  318. EditorGUILayout.BeginHorizontal();
  319. EditorGUI.BeginChangeCheck();
  320. Color newSoftEdgeColor = EditorGUILayout.ColorField(Styles.sComposerSoftBoundsOverlay, ComposerSettings.SoftBoundsOverlayColour);
  321. if (EditorGUI.EndChangeCheck())
  322. {
  323. ComposerSettings.SoftBoundsOverlayColour = newSoftEdgeColor;
  324. }
  325. if (GUILayout.Button("Reset"))
  326. {
  327. ComposerSettings.SoftBoundsOverlayColour = ComposerSettings.kDefaultSoftBoundsColour;
  328. }
  329. EditorGUILayout.EndHorizontal();
  330. EditorGUILayout.BeginHorizontal();
  331. EditorGUI.BeginChangeCheck();
  332. Color newTargetColour = EditorGUILayout.ColorField(Styles.sComposerTargetOverlay, ComposerSettings.TargetColour);
  333. if (EditorGUI.EndChangeCheck())
  334. {
  335. ComposerSettings.TargetColour = newTargetColour;
  336. }
  337. if (GUILayout.Button("Reset"))
  338. {
  339. ComposerSettings.TargetColour = ComposerSettings.kDefaultTargetColour;
  340. }
  341. EditorGUILayout.EndHorizontal();
  342. EditorGUI.BeginChangeCheck();
  343. float targetSide = EditorGUILayout.FloatField(Styles.sComposerTargetOverlayPixels, ComposerSettings.TargetSize);
  344. if (EditorGUI.EndChangeCheck())
  345. {
  346. ComposerSettings.TargetSize = targetSide;
  347. }
  348. EditorGUI.indentLevel--;
  349. }
  350. if (AdditionalCategories != null)
  351. {
  352. AdditionalCategories();
  353. }
  354. GUILayout.EndScrollView();
  355. //if (GUILayout.Button("Open Documentation"))
  356. //{
  357. // Application.OpenURL(kCinemachineDocURL);
  358. //}
  359. }
  360. private static void OnHierarchyGUI(int instanceID, Rect selectionRect)
  361. {
  362. GameObject instance = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
  363. if (instance == null)
  364. {
  365. // Object in process of being deleted?
  366. return;
  367. }
  368. if (instance.GetComponent<CinemachineBrain>() != null)
  369. {
  370. Rect texRect = new Rect(selectionRect.xMax - selectionRect.height, selectionRect.yMin, selectionRect.height, selectionRect.height);
  371. GUI.DrawTexture(texRect, CinemachineLogoTexture, ScaleMode.ScaleAndCrop);
  372. }
  373. }
  374. internal static Color UnpackColour(string str)
  375. {
  376. if (!string.IsNullOrEmpty(str))
  377. {
  378. byte[] bytes = Base64Decode(str);
  379. if ((bytes != null) && bytes.Length == 16)
  380. {
  381. float r = BitConverter.ToSingle(bytes, 0);
  382. float g = BitConverter.ToSingle(bytes, 4);
  383. float b = BitConverter.ToSingle(bytes, 8);
  384. float a = BitConverter.ToSingle(bytes, 12);
  385. return new Color(r, g, b, a);
  386. }
  387. }
  388. return Color.white;
  389. }
  390. internal static string PackColor(Color col)
  391. {
  392. byte[] bytes = new byte[16];
  393. byte[] rBytes = BitConverter.GetBytes(col.r);
  394. byte[] gBytes = BitConverter.GetBytes(col.g);
  395. byte[] bBytes = BitConverter.GetBytes(col.b);
  396. byte[] aBytes = BitConverter.GetBytes(col.a);
  397. Buffer.BlockCopy(rBytes, 0, bytes, 0, 4);
  398. Buffer.BlockCopy(gBytes, 0, bytes, 4, 4);
  399. Buffer.BlockCopy(bBytes, 0, bytes, 8, 4);
  400. Buffer.BlockCopy(aBytes, 0, bytes, 12, 4);
  401. return Base64Encode(bytes);
  402. }
  403. private static string Base64Encode(byte[] data)
  404. {
  405. return Convert.ToBase64String(data);
  406. }
  407. private static byte[] Base64Decode(string base64EncodedData)
  408. {
  409. return Convert.FromBase64String(base64EncodedData);
  410. }
  411. }
  412. }