using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
///
///
public class RecentMenu
{
public static void Create(SerializedProperty propPath, SerializedProperty propMediaSource, string fileExtensions, bool autoLoadMedia, int mediaReferencePickerId = -1)
{
RecentItems.Load();
RecentMenu menu = new RecentMenu();
menu.FileBrowseButton(propPath, propMediaSource, fileExtensions, autoLoadMedia, mediaReferencePickerId);
}
private void FileBrowseButton(SerializedProperty propPath, SerializedProperty propMediaSource, string fileExtensions, bool autoLoadMedia, int mediaReferencePickerId = -1)
{
GenericMenu toolsMenu = new GenericMenu();
if (mediaReferencePickerId >= 0)
{
toolsMenu.AddItem(new GUIContent("Media References..."), false, Callback_BrowseMediaReferences, (object)mediaReferencePickerId);
}
toolsMenu.AddItem(new GUIContent("Browse..."), false, Callback_Browse, new BrowseData(propPath, propMediaSource, fileExtensions, autoLoadMedia));
CreateMenu_StreamingAssets(toolsMenu, "StreamingAssets/", propPath, propMediaSource, autoLoadMedia);
CreateMenu_RecentFiles(toolsMenu, RecentItems.Files, "Recent Files/" , propPath, propMediaSource, autoLoadMedia);
CreateMenu_RecentUrls(toolsMenu, RecentItems.Urls, "Recent URLs/", propPath, propMediaSource, autoLoadMedia);
toolsMenu.ShowAsContext();
}
private struct RecentMenuItemData
{
public RecentMenuItemData(string path, SerializedProperty propPath, SerializedProperty propMediaSource, bool autoLoadMedia)
{
this.path = path;
this.propPath = propPath;
this.propMediaSource = propMediaSource;
this.autoLoadMedia = autoLoadMedia;
}
public string path;
public bool autoLoadMedia;
public SerializedProperty propPath;
public SerializedProperty propMediaSource;
}
private void Callback_Select(object obj)
{
RecentMenuItemData data = (RecentMenuItemData)obj;
// Move it to the top of the list
RecentItems.Add(data.path);
// Resolve to relative path
MediaPath mediaPath = EditorHelper.GetMediaPathFromFullPath(data.path);
SerializedProperty propMediaPath = data.propPath.FindPropertyRelative("_path");
SerializedProperty propMediaPathType = data.propPath.FindPropertyRelative("_pathType");
// Assign to properties
propMediaPath.stringValue = mediaPath.Path.Replace("\\", "/");
propMediaPathType.enumValueIndex = (int)mediaPath.PathType;
if (data.propMediaSource != null) data.propMediaSource.enumValueIndex = (int)MediaSource.Path;
// Mark as modified
data.propPath.serializedObject.ApplyModifiedProperties();
foreach (Object o in data.propPath.serializedObject.targetObjects)
{
EditorUtility.SetDirty(o);
}
if (data.autoLoadMedia)
{
MediaPlayer mediaPlayer = (MediaPlayer)data.propPath.serializedObject.targetObject;
if (mediaPlayer != null)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaPath, autoPlay:true);
}
}
}
private void Callback_ClearList(object obj)
{
((List)obj).Clear();
RecentItems.Save();
}
private void Callback_ClearMissingFiles()
{
RecentItems.ClearMissingFiles();
RecentItems.Save();
}
private struct BrowseData
{
public BrowseData(SerializedProperty propPath, SerializedProperty propMediaSource, string extensions, bool autoLoadMedia)
{
this.extensions = extensions;
this.propPath = propPath;
this.propMediaSource = propMediaSource;
this.autoLoadMedia = autoLoadMedia;
}
public bool autoLoadMedia;
public string extensions;
public SerializedProperty propPath;
public SerializedProperty propMediaSource;
}
private void Callback_BrowseMediaReferences(object obj)
{
int controlID = (int)obj;
EditorGUIUtility.ShowObjectPicker(null, false, "", controlID);
}
private void Callback_Browse(object obj)
{
BrowseData data = (BrowseData)obj;
SerializedProperty propFilePath = data.propPath.FindPropertyRelative("_path");
SerializedProperty propFilePathType = data.propPath.FindPropertyRelative("_pathType");
string startFolder = EditorHelper.GetBrowsableFolder(propFilePath.stringValue, (MediaPathType)propFilePathType.enumValueIndex);
string videoPath = propFilePath.stringValue;
string fullPath = string.Empty;
MediaPath mediaPath = new MediaPath();
if (EditorHelper.OpenMediaFileDialog(startFolder, ref mediaPath, ref fullPath, data.extensions))
{
// Assign to properties
propFilePath.stringValue = mediaPath.Path.Replace("\\", "/");
propFilePathType.enumValueIndex = (int)mediaPath.PathType;
if (data.propMediaSource != null) data.propMediaSource.enumValueIndex = (int)MediaSource.Path;
// Mark as modified
data.propPath.serializedObject.ApplyModifiedProperties();
foreach (Object o in data.propPath.serializedObject.targetObjects)
{
EditorUtility.SetDirty(o);
}
if (data.autoLoadMedia)
{
MediaPlayer mediaPlayer = (MediaPlayer)data.propPath.serializedObject.targetObject;
if (mediaPlayer != null)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaPath, autoPlay:true);
}
}
RecentItems.Add(fullPath);
}
}
private void CreateMenu_RecentFiles(GenericMenu menu, List items, string prefix, SerializedProperty propPath, SerializedProperty propMediaSource, bool autoLoadMedia)
{
int missingCount = 0;
for (int i = 0; i < items.Count; i++)
{
string path = items[i];
// Slashes in path must be replaced as they cause the menu to create submenuts
string itemName = ReplaceSlashes(path);
// TODO: shorten if itemName too long
if (System.IO.File.Exists(path))
{
menu.AddItem(new GUIContent(prefix + itemName), false, Callback_Select, new RecentMenuItemData(path, propPath, propMediaSource, autoLoadMedia));
}
else
{
menu.AddDisabledItem(new GUIContent(prefix + itemName));
missingCount++;
}
}
if (items.Count > 0)
{
menu.AddSeparator(prefix + "");
menu.AddItem(new GUIContent(prefix + "Clear"), false, Callback_ClearList, items);
if (missingCount > 0)
{
menu.AddItem(new GUIContent(prefix + "Clear Missing (" + missingCount + ")"), false, Callback_ClearMissingFiles);
}
}
else
{
menu.AddDisabledItem(new GUIContent(prefix + "No recent files yet"));
}
}
private void CreateMenu_RecentUrls(GenericMenu menu, List items, string prefix, SerializedProperty propPath, SerializedProperty propMediaSource, bool autoLoadMedia)
{
for (int i = 0; i < items.Count; i++)
{
string path = items[i];
// Slashes in path must be replaced as they cause the menu to create submenuts
string itemName = ReplaceSlashes(path);
// TODO: shorten if itemName too long
menu.AddItem(new GUIContent(prefix + itemName), false, Callback_Select, new RecentMenuItemData(path, propPath, propMediaSource, autoLoadMedia));
}
if (items.Count > 0)
{
menu.AddSeparator(prefix + "");
menu.AddItem(new GUIContent(prefix + "Clear"), false, Callback_ClearList, items);
}
else
{
menu.AddDisabledItem(new GUIContent(prefix + "No recent URLs yet"));
}
}
private static string ReplaceSlashes(string text)
{
string slashReplacement = "\u2215";
#if UNITY_EDITOR_WIN
// Special replacement for "//" in URLS so they aren't spaced too far apart
text = text.Replace("//", " \u2215 \u2215 ");
// On Windows we have to add extra spaces so it doesn't look squashed together
slashReplacement = " \u2215 ";
#endif
text = text.Replace("/", slashReplacement).Replace("\\", slashReplacement);
// Unity will place text after " _" on the right of the menu, so we replace it so this doesn't happen
text = text.Replace(" _", "_");
return text;
}
private static List FindMediaFilesInStreamingAssetsFolder()
{
List files = new List();
if (System.IO.Directory.Exists(Application.streamingAssetsPath))
{
string[] allFiles = System.IO.Directory.GetFiles(Application.streamingAssetsPath, "*", System.IO.SearchOption.AllDirectories);
if (allFiles != null && allFiles.Length > 0)
{
// Filter by type
for (int i = 0; i < allFiles.Length; i++)
{
bool remove = false;
if (allFiles[i].EndsWith(".meta", System.StringComparison.InvariantCultureIgnoreCase))
{
remove = true;
}
#if UNITY_EDITOR_OSX
remove = remove || allFiles[i].EndsWith(".DS_Store");
#endif
if (!remove)
{
files.Add(allFiles[i]);
}
}
}
}
return files;
}
private void CreateMenu_StreamingAssets(GenericMenu menu, string prefix, SerializedProperty propPath, SerializedProperty propMediaSource, bool autoLoadMedia)
{
List files = FindMediaFilesInStreamingAssetsFolder();
if (files.Count > 0)
{
for (int i = 0; i < files.Count; i++)
{
string path = files[i];
if (System.IO.File.Exists(path))
{
string itemName = path.Replace(Application.streamingAssetsPath, "");
if (itemName.StartsWith("/") || itemName.StartsWith("\\"))
{
itemName = itemName.Remove(0, 1);
}
itemName = itemName.Replace("\\", "/");
menu.AddItem(new GUIContent(prefix + itemName), false, Callback_Select, new RecentMenuItemData(path, propPath, propMediaSource, autoLoadMedia));
}
}
}
else
{
menu.AddDisabledItem(new GUIContent(prefix + "StreamingAssets folder missing or contains no files"));
}
}
}
}