MediaPlayerEditor_Player.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. using UnityEngine;
  2. using UnityEditor;
  3. //-----------------------------------------------------------------------------
  4. // Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6. namespace RenderHeads.Media.AVProVideo.Editor
  7. {
  8. /// <summary>
  9. /// Editor for the MediaPlayer component
  10. /// </summary>
  11. public partial class MediaPlayerEditor : UnityEditor.Editor
  12. {
  13. private static GUIContent FilePathSplitEllipses = new GUIContent("-");
  14. private static GUIContent _iconPlayButton;
  15. private static GUIContent _iconPauseButton;
  16. private static GUIContent _iconSceneViewAudio;
  17. private static GUIContent _iconProject;
  18. private static GUIContent _iconRotateTool;
  19. private static bool _showAlpha = false;
  20. private static bool _showPreview = false;
  21. private static Material _materialResolve;
  22. private static Material _materialIMGUI;
  23. private static RenderTexture _previewTexture;
  24. private static float _lastTextureRatio = -1f;
  25. private static int _previewTextureFrameCount = -1;
  26. private MediaReference _queuedLoadMediaRef = null;
  27. private bool _queuedToggleShowPreview = false;
  28. private void OnInspectorGUI_MediaInfo()
  29. {
  30. MediaPlayer media = (this.target) as MediaPlayer;
  31. IMediaInfo info = media.Info;
  32. IMediaControl control = media.Control;
  33. ITextTracks textTracks = media.TextTracks;
  34. IAudioTracks audioTracks = media.AudioTracks;
  35. IVideoTracks videoTracks = media.VideoTracks;
  36. if (info != null)
  37. {
  38. if (!info.HasVideo() && !info.HasAudio())// && !info.HasText())
  39. {
  40. GUILayout.Label("No media loaded");
  41. }
  42. else
  43. {
  44. if (info.HasVideo())
  45. {
  46. GUILayout.BeginHorizontal();
  47. {
  48. string dimensionText = string.Format("{0}x{1}@{2:0.##}", info.GetVideoWidth(), info.GetVideoHeight(), info.GetVideoFrameRate());
  49. GUILayout.Label(dimensionText);
  50. GUILayout.FlexibleSpace();
  51. string rateText = "0.00";
  52. if (media.Info != null)
  53. {
  54. rateText = media.Info.GetVideoDisplayRate().ToString("F2");
  55. }
  56. GUILayout.Label(rateText + "FPS");
  57. }
  58. GUILayout.EndHorizontal();
  59. EditorGUILayout.Space();
  60. }
  61. if (info.HasVideo())
  62. {
  63. VideoTracks tracks = videoTracks.GetVideoTracks();
  64. if (tracks.Count > 0)
  65. {
  66. GUILayout.Label("Video Tracks: " + tracks.Count);
  67. foreach (VideoTrack track in tracks)
  68. {
  69. bool isActiveTrack = (track == videoTracks.GetActiveVideoTrack());
  70. GUI.color = isActiveTrack?Color.green:Color.white;
  71. {
  72. if (GUILayout.Button(track.DisplayName))
  73. {
  74. if (isActiveTrack)
  75. {
  76. videoTracks.SetActiveVideoTrack(null);
  77. }
  78. else
  79. {
  80. videoTracks.SetActiveVideoTrack(track);
  81. }
  82. }
  83. }
  84. }
  85. GUI.color = Color.white;
  86. EditorGUILayout.Space();
  87. }
  88. }
  89. if (info.HasAudio())
  90. {
  91. AudioTracks tracks = audioTracks.GetAudioTracks();
  92. if (tracks.Count > 0)
  93. {
  94. GUILayout.Label("Audio Tracks: " + tracks.Count);
  95. foreach (AudioTrack track in tracks)
  96. {
  97. bool isActiveTrack = (track == audioTracks.GetActiveAudioTrack());
  98. GUI.color = isActiveTrack?Color.green:Color.white;
  99. {
  100. if (GUILayout.Button(track.DisplayName))
  101. {
  102. if (isActiveTrack)
  103. {
  104. audioTracks.SetActiveAudioTrack(null);
  105. }
  106. else
  107. {
  108. audioTracks.SetActiveAudioTrack(track);
  109. }
  110. }
  111. }
  112. }
  113. GUI.color = Color.white;
  114. /*int channelCount = control.GetAudioChannelCount();
  115. if (channelCount > 0)
  116. {
  117. GUILayout.Label("Audio Channels: " + channelCount);
  118. AudioChannelMaskFlags audioChannels = control.GetAudioChannelMask();
  119. GUILayout.Label("(" + audioChannels + ")", EditorHelper.IMGUI.GetWordWrappedTextAreaStyle());
  120. }*/
  121. EditorGUILayout.Space();
  122. }
  123. }
  124. {
  125. TextTracks tracks = textTracks.GetTextTracks();
  126. if (tracks.Count > 0)
  127. {
  128. GUILayout.Label("Text Tracks: " + tracks.Count);
  129. foreach (TextTrack track in tracks)
  130. {
  131. bool isActiveTrack = (track == textTracks.GetActiveTextTrack());
  132. GUI.color = isActiveTrack?Color.green:Color.white;
  133. {
  134. if (GUILayout.Button(track.DisplayName))
  135. {
  136. if (isActiveTrack)
  137. {
  138. textTracks.SetActiveTextTrack(null);
  139. }
  140. else
  141. {
  142. textTracks.SetActiveTextTrack(track);
  143. }
  144. }
  145. }
  146. }
  147. GUI.color = Color.white;
  148. if (textTracks.GetActiveTextTrack() != null)
  149. {
  150. string text = string.Empty;
  151. if (textTracks.GetCurrentTextCue() != null)
  152. {
  153. text = textTracks.GetCurrentTextCue().Text;
  154. // Clip the text if it is too long
  155. if (text.Length >= 96)
  156. {
  157. text = string.Format("{0}...({1} chars)", text.Substring(0, 96), text.Length);
  158. }
  159. }
  160. GUILayout.Label(text, EditorHelper.IMGUI.GetWordWrappedTextAreaStyle(), GUILayout.Height(48f));
  161. }
  162. EditorGUILayout.Space();
  163. }
  164. }
  165. }
  166. }
  167. else
  168. {
  169. GUILayout.Label("No media loaded");
  170. }
  171. }
  172. private void ClosePreview()
  173. {
  174. if (_materialResolve)
  175. {
  176. DestroyImmediate(_materialResolve); _materialResolve = null;
  177. }
  178. if (_materialIMGUI)
  179. {
  180. DestroyImmediate(_materialIMGUI); _materialIMGUI = null;
  181. }
  182. if (_previewTexture)
  183. {
  184. RenderTexture.ReleaseTemporary(_previewTexture); _previewTexture = null;
  185. }
  186. }
  187. private void RenderPreview(MediaPlayer media)
  188. {
  189. int textureFrameCount = media.TextureProducer.GetTextureFrameCount();
  190. if (textureFrameCount != _previewTextureFrameCount)
  191. {
  192. _previewTextureFrameCount = textureFrameCount;
  193. if (!_materialResolve)
  194. {
  195. _materialResolve = VideoRender.CreateResolveMaterial( false );
  196. VideoRender.SetupResolveMaterial(_materialResolve, VideoResolveOptions.Create());
  197. }
  198. if (!_materialIMGUI)
  199. {
  200. _materialIMGUI = VideoRender.CreateIMGUIMaterial();
  201. }
  202. VideoRender.SetupMaterialForMedia(_materialResolve, media, -1);
  203. VideoRender.ResolveFlags resolveFlags = (VideoRender.ResolveFlags.ColorspaceSRGB | VideoRender.ResolveFlags.Mipmaps | VideoRender.ResolveFlags.PackedAlpha | VideoRender.ResolveFlags.StereoLeft);
  204. _previewTexture = VideoRender.ResolveVideoToRenderTexture(_materialResolve, _previewTexture, media.TextureProducer, resolveFlags);
  205. }
  206. }
  207. private void DrawCenterCroppedLabel(Rect rect, string text)
  208. {
  209. if (Event.current.type != EventType.Repaint) return;
  210. GUIContent textContent = new GUIContent(text);
  211. Vector2 textSize = GUI.skin.label.CalcSize(textContent);
  212. if (textSize.x > rect.width)
  213. {
  214. float ellipseWidth = GUI.skin.label.CalcSize(FilePathSplitEllipses).x;
  215. // Left
  216. Rect rleft = rect;
  217. rleft.xMax -= (rleft.width / 2f);
  218. rleft.xMax -= (ellipseWidth / 2f);
  219. GUI.Label(rleft, textContent);
  220. // Right
  221. Rect rRight = rect;
  222. rRight.xMin += (rRight.width / 2f);
  223. rRight.xMin += (ellipseWidth / 2f);
  224. GUI.Label(rRight, textContent, EditorHelper.IMGUI.GetRightAlignedLabelStyle());
  225. // Center
  226. Rect rCenter = rect;
  227. rCenter.xMin += (rect.width / 2f) - (ellipseWidth / 2f);
  228. rCenter.xMax -= (rect.width / 2f) - (ellipseWidth / 2f);
  229. GUI.Label(rCenter, FilePathSplitEllipses, EditorHelper.IMGUI.GetCenterAlignedLabelStyle());
  230. }
  231. else
  232. {
  233. GUI.Label(rect, textContent, EditorHelper.IMGUI.GetCenterAlignedLabelStyle());
  234. }
  235. }
  236. private void OnInspectorGUI_Player(MediaPlayer mediaPlayer, ITextureProducer textureSource)
  237. {
  238. EditorGUILayout.BeginVertical(GUI.skin.box);
  239. Rect titleRect = Rect.zero;
  240. // Display filename as title of preview
  241. {
  242. string mediaFileName = string.Empty;
  243. if ((MediaSource)_propMediaSource.enumValueIndex == MediaSource.Path)
  244. {
  245. mediaFileName = mediaPlayer.MediaPath.Path;
  246. }
  247. else if ((MediaSource)_propMediaSource.enumValueIndex == MediaSource.Reference)
  248. {
  249. if (_propMediaReference.objectReferenceValue != null)
  250. {
  251. mediaFileName = ((MediaReference)_propMediaReference.objectReferenceValue).GetCurrentPlatformMediaReference().MediaPath.Path;
  252. }
  253. }
  254. // Display the file name, cropping if necessary
  255. if (!string.IsNullOrEmpty(mediaFileName) &&
  256. (0 > mediaFileName.IndexOfAny(System.IO.Path.GetInvalidPathChars())))
  257. {
  258. string text = System.IO.Path.GetFileName(mediaFileName);
  259. titleRect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.label);
  260. // Draw background
  261. GUI.Box(titleRect, GUIContent.none, EditorStyles.toolbarButton);
  262. DrawCenterCroppedLabel(titleRect, text);
  263. }
  264. }
  265. // Toggle preview
  266. if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.isMouse)
  267. {
  268. if (titleRect.Contains(Event.current.mousePosition))
  269. {
  270. _queuedToggleShowPreview = true;
  271. }
  272. }
  273. if (_showPreview)
  274. {
  275. Texture texture = EditorGUIUtility.whiteTexture;
  276. float textureRatio = 16f / 9f;
  277. if (_lastTextureRatio > 0f)
  278. {
  279. textureRatio = _lastTextureRatio;
  280. }
  281. if (textureSource != null && textureSource.GetTexture() != null)
  282. {
  283. texture = textureSource.GetTexture();
  284. if (_previewTexture)
  285. {
  286. texture = _previewTexture;
  287. }
  288. _lastTextureRatio = textureRatio = (((float)texture.width / (float)texture.height) * textureSource.GetTexturePixelAspectRatio());
  289. }
  290. // Reserve rectangle for texture
  291. //GUILayout.BeginHorizontal(GUILayout.MaxHeight(Screen.height / 2f), GUILayout.ExpandHeight(true));
  292. //GUILayout.FlexibleSpace();
  293. Rect textureRect;
  294. //textureRect = GUILayoutUtility.GetRect(256f, 256f);
  295. if (texture != EditorGUIUtility.whiteTexture)
  296. {
  297. if (_showAlpha)
  298. {
  299. float rectRatio = textureRatio * 2f;
  300. rectRatio = Mathf.Max(1f, rectRatio);
  301. textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true));
  302. }
  303. else
  304. {
  305. //textureRatio *= 2f;
  306. float rectRatio = Mathf.Max(1f, textureRatio);
  307. textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true), GUILayout.Height(256f));
  308. /*GUIStyle style = new GUIStyle(GUI.skin.box);
  309. style.stretchHeight = true;
  310. style.stretchWidth = true;
  311. style.fixedWidth = 0;
  312. style.fixedHeight = 0;
  313. textureRect = GUILayoutUtility.GetRect(Screen.width, Screen.width, 128f, Screen.height / 1.2f, style);*/
  314. }
  315. }
  316. else
  317. {
  318. float rectRatio = Mathf.Max(1f, textureRatio);
  319. textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true), GUILayout.Height(256f));
  320. }
  321. if (textureRect.height > (Screen.height / 2f))
  322. {
  323. //textureRect.height = Screen.height / 2f;
  324. }
  325. //Debug.Log(textureRect.height + " " + Screen.height);
  326. //GUILayout.FlexibleSpace();
  327. //GUILayout.EndHorizontal();
  328. // Pause / Play toggle on mouse click
  329. if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.isMouse)
  330. {
  331. if (textureRect.Contains(Event.current.mousePosition))
  332. {
  333. if (mediaPlayer.Control != null)
  334. {
  335. if (mediaPlayer.Control.IsPaused())
  336. {
  337. mediaPlayer.Play();
  338. }
  339. else
  340. {
  341. mediaPlayer.Pause();
  342. }
  343. }
  344. }
  345. }
  346. if (Event.current.type == EventType.Repaint)
  347. {
  348. GUI.color = Color.gray;
  349. EditorGUI.DrawTextureTransparent(textureRect, Texture2D.blackTexture, ScaleMode.StretchToFill);
  350. GUI.color = Color.white;
  351. //EditorGUI.DrawTextureAlpha(textureRect, Texture2D.whiteTexture, ScaleMode.ScaleToFit);
  352. //GUI.color = Color.black;
  353. //GUI.DrawTexture(textureRect, texture, ScaleMode.StretchToFill, false);
  354. //GUI.color = Color.white;
  355. // Draw the texture
  356. if (textureSource != null && textureSource.RequiresVerticalFlip())
  357. {
  358. // GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, textureRect.y + (textureRect.height / 2f)));
  359. }
  360. if (!GUI.enabled)
  361. {
  362. //GUI.color = Color.black;
  363. //GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
  364. //GUI.color = Color.white;
  365. }
  366. else
  367. {
  368. if (_showPreview && texture != EditorGUIUtility.whiteTexture)
  369. {
  370. RenderPreview(mediaPlayer);
  371. }
  372. if (!_showAlpha)
  373. {
  374. if (texture != EditorGUIUtility.whiteTexture)
  375. {
  376. // TODO: In Linear mode, this displays the texture too bright, but GUI.DrawTexture displays it correctly
  377. //GL.sRGBWrite = true;
  378. //GUI.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, false);
  379. if (_previewTexture)
  380. {
  381. EditorGUI.DrawPreviewTexture(textureRect, _previewTexture, _materialIMGUI, ScaleMode.ScaleToFit, textureRatio);
  382. }
  383. //EditorGUI.DrawTextureTransparent(textureRect, rt, ScaleMode.ScaleToFit);
  384. //VideoRender.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, AlphaPacking.None, _materialPreview);
  385. //GL.sRGBWrite = false;
  386. }
  387. else
  388. {
  389. // Fill with black
  390. //GUI.color = Color.black;
  391. //GUI.DrawTexture(textureRect, texture, ScaleMode.StretchToFill, false);
  392. //GUI.color = Color.white;
  393. }
  394. }
  395. else
  396. {
  397. textureRect.width /= 2f;
  398. //GUI.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, false);
  399. //GL.sRGBWrite = true;
  400. //VideoRender.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, AlphaPacking.None, _materialIMGUI);
  401. //GL.sRGBWrite = false;
  402. textureRect.x += textureRect.width;
  403. //EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit);
  404. }
  405. }
  406. }
  407. }
  408. IMediaInfo info = mediaPlayer.Info;
  409. IMediaControl control = mediaPlayer.Control;
  410. bool showBrowseMenu = false;
  411. if (true)
  412. {
  413. bool isPlaying = false;
  414. if (control != null)
  415. {
  416. isPlaying = control.IsPlaying();
  417. }
  418. // Slider layout
  419. EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight/2f));
  420. Rect sliderRect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.horizontalSlider, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
  421. EditorGUILayout.EndHorizontal();
  422. float currentTime = 0f;
  423. float durationTime = 0.001f;
  424. if (control != null)
  425. {
  426. currentTime = (float)control.GetCurrentTime();
  427. durationTime = (float)info.GetDuration();
  428. if (float.IsNaN(durationTime))
  429. {
  430. durationTime = 0f;
  431. }
  432. // RJT NOTE: Sometimes current time can exceed duration temporarily before a finished event occurs so clamp for display purposes
  433. if (currentTime > durationTime)
  434. {
  435. currentTime = durationTime;
  436. }
  437. }
  438. TimeRange timelineRange = new TimeRange(0.0, 0.001); // A tiny default duration to prevent divide by zero's
  439. if (info != null)
  440. {
  441. timelineRange = Helper.GetTimelineRange(info.GetDuration(), control.GetSeekableTimes());
  442. }
  443. // Slider
  444. {
  445. // Draw buffering
  446. if (control != null && timelineRange.Duration > 0.0 && Event.current.type == EventType.Repaint)
  447. {
  448. GUI.color = new Color(0f, 1f, 0f, 0.25f);
  449. TimeRanges times = control.GetBufferedTimes();
  450. if (timelineRange.Duration > 0.0)
  451. {
  452. for (int i = 0; i < times.Count; i++)
  453. {
  454. Rect bufferedRect = sliderRect;
  455. float startT = Mathf.Clamp01((float)((times[i].StartTime - timelineRange.StartTime) / timelineRange.Duration));
  456. float endT = Mathf.Clamp01((float)((times[i].EndTime - timelineRange.StartTime) / timelineRange.Duration));
  457. bufferedRect.xMin = sliderRect.xMin + sliderRect.width * startT;
  458. bufferedRect.xMax = sliderRect.xMin + sliderRect.width * endT;
  459. bufferedRect.yMin += sliderRect.height * 0.5f;
  460. GUI.DrawTexture(bufferedRect, Texture2D.whiteTexture);
  461. }
  462. }
  463. GUI.color = Color.white;
  464. }
  465. // Timeline slider
  466. {
  467. float newTime = GUI.HorizontalSlider(sliderRect, currentTime, (float)timelineRange.StartTime, (float)timelineRange.EndTime);
  468. if (newTime != currentTime)
  469. {
  470. if (control != null)
  471. {
  472. // NOTE: For unknown reasons the seeks here behave differently to the MediaPlayerUI demo
  473. // When scrubbing (especially with NotchLC) while the video is playing, the frames will not update and a Stalled state will be shown,
  474. // but using the MediaPlayerUI the same scrubbing will updates the frames. Perhaps it's just an execution order issue
  475. control.Seek(newTime);
  476. }
  477. }
  478. }
  479. }
  480. EditorGUILayout.BeginHorizontal();
  481. string timeTotal = "∞";
  482. if (!float.IsInfinity(durationTime))
  483. {
  484. timeTotal = Helper.GetTimeString(durationTime, false);
  485. }
  486. string timeUsed = Helper.GetTimeString(currentTime - (float)timelineRange.StartTime, false);
  487. GUILayout.Label(timeUsed, GUILayout.ExpandWidth(false));
  488. //GUILayout.Label("/", GUILayout.ExpandWidth(false));
  489. GUILayout.FlexibleSpace();
  490. GUILayout.Label(timeTotal, GUILayout.ExpandWidth(false));
  491. EditorGUILayout.EndHorizontal();
  492. // In non-pro we need to make these 3 icon content black as the buttons are light
  493. // and the icons are white by default
  494. if (!EditorGUIUtility.isProSkin)
  495. {
  496. GUI.contentColor = Color.black;
  497. }
  498. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  499. // Play/Pause
  500. {
  501. float maxHeight = GUI.skin.button.CalcHeight(_iconSceneViewAudio, 0f);
  502. if (!isPlaying)
  503. {
  504. GUI.color = Color.green;
  505. if (GUILayout.Button(_iconPlayButton, GUILayout.ExpandWidth(false), GUILayout.Height(maxHeight)))
  506. {
  507. if (control != null)
  508. {
  509. control.Play();
  510. }
  511. else
  512. {
  513. if (mediaPlayer.MediaSource == MediaSource.Path)
  514. {
  515. mediaPlayer.OpenMedia(mediaPlayer.MediaPath.PathType, mediaPlayer.MediaPath.Path, true);
  516. }
  517. else if (mediaPlayer.MediaSource == MediaSource.Reference)
  518. {
  519. mediaPlayer.OpenMedia(mediaPlayer.MediaReference, true);
  520. }
  521. }
  522. }
  523. }
  524. else
  525. {
  526. GUI.color = Color.yellow;
  527. if (GUILayout.Button(_iconPauseButton, GUILayout.ExpandWidth(false), GUILayout.Height(maxHeight)))
  528. {
  529. if (control != null)
  530. {
  531. control.Pause();
  532. }
  533. }
  534. }
  535. GUI.color = Color.white;
  536. }
  537. // Looping
  538. {
  539. if (!_propLoop.boolValue)
  540. {
  541. GUI.color = Color.grey;
  542. }
  543. float maxHeight = GUI.skin.button.CalcHeight(_iconSceneViewAudio, 0f);
  544. //GUIContent icon = new GUIContent("∞");
  545. if (GUILayout.Button(_iconRotateTool, GUILayout.Height(maxHeight)))
  546. {
  547. if (control != null)
  548. {
  549. control.SetLooping(!_propLoop.boolValue);
  550. }
  551. _propLoop.boolValue = !_propLoop.boolValue;
  552. }
  553. GUI.color = Color.white;
  554. }
  555. // Mute & Volume
  556. EditorGUI.BeginDisabledGroup(UnityEditor.EditorUtility.audioMasterMute);
  557. {
  558. if (_propMuted.boolValue)
  559. {
  560. GUI.color = Color.gray;
  561. }
  562. float maxWidth = _iconPlayButton.image.width;
  563. //if (GUILayout.Button("Muted", GUILayout.ExpandWidth(false), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
  564. //string iconName = "d_AudioListener Icon"; // Unity 2019+
  565. if (GUILayout.Button(_iconSceneViewAudio))//, GUILayout.Width(maxWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight), GUILayout.ExpandHeight(false)))
  566. {
  567. if (control != null)
  568. {
  569. control.MuteAudio(!_propMuted.boolValue);
  570. }
  571. _propMuted.boolValue = !_propMuted.boolValue;
  572. }
  573. GUI.color = Color.white;
  574. }
  575. if (!_propMuted.boolValue)
  576. {
  577. EditorGUI.BeginChangeCheck();
  578. float newVolume = GUILayout.HorizontalSlider(_propVolume.floatValue, 0f, 1f, GUILayout.ExpandWidth(true), GUILayout.MinWidth(64f));
  579. if (EditorGUI.EndChangeCheck())
  580. {
  581. if (control != null)
  582. {
  583. control.SetVolume(newVolume);
  584. }
  585. _propVolume.floatValue = newVolume;
  586. }
  587. }
  588. EditorGUI.EndDisabledGroup();
  589. GUI.contentColor = Color.white;
  590. GUILayout.FlexibleSpace();
  591. if (Event.current.commandName == "ObjectSelectorClosed" &&
  592. EditorGUIUtility.GetObjectPickerControlID() == 200)
  593. {
  594. _queuedLoadMediaRef = (MediaReference)EditorGUIUtility.GetObjectPickerObject();
  595. }
  596. if (GUILayout.Button(_iconProject, GUILayout.ExpandWidth(false)))
  597. {
  598. showBrowseMenu = true;
  599. }
  600. EditorGUILayout.EndHorizontal();
  601. }
  602. EditorGUILayout.EndVertical();
  603. if (showBrowseMenu)
  604. {
  605. RecentMenu.Create(_propMediaPath, _propMediaSource, MediaFileExtensions, true, 200);
  606. }
  607. if (_queuedLoadMediaRef && Event.current.type == EventType.Repaint)
  608. {
  609. //MediaPlayer mediaPlayer = (MediaPlayer)_propMediaPath.serializedObject.targetObject;
  610. if (mediaPlayer)
  611. {
  612. mediaPlayer.OpenMedia(_queuedLoadMediaRef, true);
  613. _queuedLoadMediaRef = null;
  614. }
  615. }
  616. if (_queuedToggleShowPreview)
  617. {
  618. _showPreview = !_showPreview;
  619. _queuedToggleShowPreview = false;
  620. this.Repaint();
  621. }
  622. }
  623. private void OnInspectorGUI_VideoPreview(MediaPlayer media, ITextureProducer textureSource)
  624. {
  625. EditorGUILayout.LabelField("* Inspector preview affects playback performance");
  626. Texture texture = null;
  627. if (textureSource != null)
  628. {
  629. texture = textureSource.GetTexture();
  630. }
  631. if (texture == null)
  632. {
  633. texture = EditorGUIUtility.whiteTexture;
  634. }
  635. float ratio = (float)texture.width / (float)texture.height;
  636. // Reserve rectangle for texture
  637. GUILayout.BeginHorizontal();
  638. GUILayout.FlexibleSpace();
  639. Rect textureRect;
  640. if (texture != EditorGUIUtility.whiteTexture)
  641. {
  642. if (_showAlpha)
  643. {
  644. ratio *= 2f;
  645. textureRect = GUILayoutUtility.GetRect(Screen.width / 2, Screen.width / 2, (Screen.width / 2) / ratio, (Screen.width / 2) / ratio);
  646. }
  647. else
  648. {
  649. textureRect = GUILayoutUtility.GetRect(Screen.width / 2, Screen.width / 2, (Screen.width / 2) / ratio, (Screen.width / 2) / ratio);
  650. }
  651. }
  652. else
  653. {
  654. textureRect = GUILayoutUtility.GetRect(1920f / 40f, 1080f / 40f, GUILayout.ExpandWidth(true));
  655. }
  656. GUILayout.FlexibleSpace();
  657. GUILayout.EndHorizontal();
  658. // Dimensions
  659. string dimensionText = string.Format("{0}x{1}@{2:0.##}", 0, 0, 0.0f);
  660. if (texture != EditorGUIUtility.whiteTexture && media.Info != null)
  661. {
  662. dimensionText = string.Format("{0}x{1}@{2:0.##}", texture.width, texture.height, media.Info.GetVideoFrameRate());
  663. }
  664. EditorHelper.IMGUI.CentreLabel(dimensionText);
  665. string rateText = "0";
  666. string playerText = string.Empty;
  667. if (media.Info != null)
  668. {
  669. rateText = media.Info.GetVideoDisplayRate().ToString("F2");
  670. playerText = media.Info.GetPlayerDescription();
  671. }
  672. EditorGUILayout.LabelField("Display Rate", rateText);
  673. EditorGUILayout.LabelField("Using", playerText);
  674. _showAlpha = EditorGUILayout.Toggle("Show Alpha", _showAlpha);
  675. // Draw the texture
  676. Matrix4x4 prevMatrix = GUI.matrix;
  677. if (textureSource != null && textureSource.RequiresVerticalFlip())
  678. {
  679. GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0, textureRect.y + (textureRect.height / 2)));
  680. }
  681. if (!GUI.enabled)
  682. {
  683. GUI.color = Color.grey;
  684. GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
  685. GUI.color = Color.white;
  686. }
  687. else
  688. {
  689. if (!_showAlpha)
  690. {
  691. // TODO: In Linear mode, this displays the texture too bright, but GUI.DrawTexture displays it correctly
  692. EditorGUI.DrawTextureTransparent(textureRect, texture, ScaleMode.ScaleToFit);
  693. }
  694. else
  695. {
  696. textureRect.width /= 2f;
  697. GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
  698. textureRect.x += textureRect.width;
  699. EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit);
  700. }
  701. }
  702. GUI.matrix = prevMatrix;
  703. // Select texture button
  704. /*if (texture != null && texture != EditorGUIUtility.whiteTexture)
  705. {
  706. GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  707. GUILayout.FlexibleSpace();
  708. for (int i = 0; i < textureSource.GetTextureCount(); i++)
  709. {
  710. Texture textures = textureSource.GetTexture(i);
  711. if (GUILayout.Button("Select Texture", GUILayout.ExpandWidth(false)))
  712. {
  713. Selection.activeObject = textures;
  714. }
  715. }
  716. if (GUILayout.Button("Save PNG", GUILayout.ExpandWidth(true)))
  717. {
  718. media.SaveFrameToPng();
  719. }
  720. GUILayout.FlexibleSpace();
  721. GUILayout.EndHorizontal();
  722. }*/
  723. }
  724. private void OnInspectorGUI_PlayControls(IMediaControl control, IMediaInfo info)
  725. {
  726. GUILayout.Space(8.0f);
  727. // Slider
  728. EditorGUILayout.BeginHorizontal();
  729. bool isPlaying = false;
  730. if (control != null)
  731. {
  732. isPlaying = control.IsPlaying();
  733. }
  734. float currentTime = 0f;
  735. if (control != null)
  736. {
  737. currentTime = (float)control.GetCurrentTime();
  738. }
  739. float durationTime = 0f;
  740. if (info != null)
  741. {
  742. durationTime = (float)info.GetDuration();
  743. if (float.IsNaN(durationTime))
  744. {
  745. durationTime = 0f;
  746. }
  747. }
  748. string timeUsed = Helper.GetTimeString(currentTime, true);
  749. GUILayout.Label(timeUsed, GUILayout.ExpandWidth(false));
  750. float newTime = GUILayout.HorizontalSlider(currentTime, 0f, durationTime, GUILayout.ExpandWidth(true));
  751. if (newTime != currentTime)
  752. {
  753. control.Seek(newTime);
  754. }
  755. string timeTotal = "Infinity";
  756. if (!float.IsInfinity(durationTime))
  757. {
  758. timeTotal = Helper.GetTimeString(durationTime, true);
  759. }
  760. GUILayout.Label(timeTotal, GUILayout.ExpandWidth(false));
  761. EditorGUILayout.EndHorizontal();
  762. // Buttons
  763. EditorGUILayout.BeginHorizontal();
  764. if (GUILayout.Button("Rewind", GUILayout.ExpandWidth(false)))
  765. {
  766. control.Rewind();
  767. }
  768. if (!isPlaying)
  769. {
  770. GUI.color = Color.green;
  771. if (GUILayout.Button("Play", GUILayout.ExpandWidth(true)))
  772. {
  773. control.Play();
  774. }
  775. }
  776. else
  777. {
  778. GUI.color = Color.yellow;
  779. if (GUILayout.Button("Pause", GUILayout.ExpandWidth(true)))
  780. {
  781. control.Pause();
  782. }
  783. }
  784. GUI.color = Color.white;
  785. EditorGUILayout.EndHorizontal();
  786. }
  787. void OnInspectorGUI_Preview()
  788. {
  789. MediaPlayer media = (this.target) as MediaPlayer;
  790. EditorGUI.BeginDisabledGroup(!(media.TextureProducer != null && media.Info.HasVideo()));
  791. OnInspectorGUI_VideoPreview(media, media.TextureProducer);
  792. EditorGUI.EndDisabledGroup();
  793. EditorGUI.BeginDisabledGroup(!(media.Control != null && media.Control.CanPlay() && media.isActiveAndEnabled && !EditorApplication.isPaused));
  794. OnInspectorGUI_PlayControls(media.Control, media.Info);
  795. EditorGUI.EndDisabledGroup();
  796. }
  797. }
  798. }