StandaloneFileBrowserWindows.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. namespace TriLibCore.SFB
  6. {
  7. public class StandaloneFileBrowserWindows : IStandaloneFileBrowser<ItemWithStream>
  8. {
  9. private const int BufferSize = 2048;
  10. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  11. private static extern bool DialogOpenFilePanel(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)]string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, [MarshalAs(UnmanagedType.LPWStr)]string extension, bool multiselect);
  12. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  13. private static extern bool DialogOpenFilePanelAsync(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)]string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, [MarshalAs(UnmanagedType.LPWStr)]string extension, bool multiselect, AsyncCallback callback);
  14. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  15. private static extern bool DialogOpenFolderPanel(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)]string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, bool multiselect);
  16. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  17. private static extern void DialogOpenFolderPanelAsync(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)]string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, bool multiselect, AsyncCallback callback);
  18. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  19. private static extern bool DialogSaveFilePanel(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)]string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, [MarshalAs(UnmanagedType.LPWStr)]string defaultName, [MarshalAs(UnmanagedType.LPWStr)]string extension);
  20. [DllImport("StandaloneFileBrowser", CharSet = CharSet.Unicode)]
  21. private static extern void DialogSaveFilePanelAsync(IntPtr buffer, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)] string title, [MarshalAs(UnmanagedType.LPWStr)]string directory, [MarshalAs(UnmanagedType.LPWStr)] string defaultName, [MarshalAs(UnmanagedType.LPWStr)]string extension, AsyncCallback callback);
  22. public IList<ItemWithStream> OpenFilePanel(string title, string directory, ExtensionFilter[] extensions, bool multiselect)
  23. {
  24. var results = new List<ItemWithStream>();
  25. var buffer = new char[BufferSize];
  26. var bufferLock = GCHandle.Alloc(buffer, GCHandleType.Pinned);
  27. if (DialogOpenFilePanel(bufferLock.AddrOfPinnedObject(), BufferSize, title, directory, GetFilterFromFileExtensionList(extensions), multiselect))
  28. {
  29. ParseResults(buffer, results, multiselect);
  30. }
  31. bufferLock.Free();
  32. return results.ToArray();
  33. }
  34. public void OpenFilePanelAsync(string title, string directory, ExtensionFilter[] extensions, bool multiselect, Action<IList<ItemWithStream>> cb)
  35. {
  36. //todo: async
  37. cb(OpenFilePanel(title, directory, extensions, multiselect));
  38. }
  39. public IList<ItemWithStream> OpenFolderPanel(string title, string directory, bool multiselect)
  40. {
  41. var results = new List<ItemWithStream>();
  42. var buffer = new char[BufferSize];
  43. var bufferLock = GCHandle.Alloc(buffer, GCHandleType.Pinned);
  44. if (DialogOpenFolderPanel(bufferLock.AddrOfPinnedObject(), BufferSize, title, directory, multiselect))
  45. {
  46. ParseResults(buffer, results, multiselect);
  47. }
  48. bufferLock.Free();
  49. return results;
  50. }
  51. public void OpenFolderPanelAsync(string title, string directory, bool multiselect, Action<IList<ItemWithStream>> cb)
  52. {
  53. //todo: async
  54. cb(OpenFolderPanel(title, directory, multiselect));
  55. }
  56. public ItemWithStream SaveFilePanel(string title, string directory, string defaultName, ExtensionFilter[] extensions)
  57. {
  58. var results = new List<ItemWithStream>();
  59. var buffer = new char[BufferSize];
  60. var bufferLock = GCHandle.Alloc(buffer, GCHandleType.Pinned);
  61. if (DialogSaveFilePanel(bufferLock.AddrOfPinnedObject(), BufferSize, title, directory, defaultName, GetFilterFromFileExtensionList(extensions)))
  62. {
  63. ParseResults(buffer, results, false);
  64. }
  65. bufferLock.Free();
  66. return results.Count > 0 ? results[0] : null;
  67. }
  68. public void SaveFilePanelAsync(string title, string directory, string defaultName, ExtensionFilter[] extensions, Action<ItemWithStream> cb)
  69. {
  70. //todo: async
  71. cb(SaveFilePanel(title, directory, defaultName, extensions));
  72. }
  73. private static string GetFilterFromFileExtensionList(ExtensionFilter[] extensions)
  74. {
  75. var filterString = "";
  76. if (extensions != null)
  77. {
  78. foreach (var extension in extensions)
  79. {
  80. if (!string.IsNullOrWhiteSpace(extension.Name))
  81. {
  82. filterString += extension.Name;
  83. }
  84. else
  85. {
  86. var descriptionString = "";
  87. foreach (var format in extension.Extensions)
  88. {
  89. if (descriptionString != "")
  90. {
  91. descriptionString += ",";
  92. }
  93. descriptionString += "(*" + (format[0] == '.' ? format.Substring(1) : format) + ")";
  94. }
  95. filterString += descriptionString;
  96. }
  97. filterString += "\0";
  98. foreach (var format in extension.Extensions)
  99. {
  100. filterString += "*" + (format[0] == '.' ? format.Substring(1) : format) + ";";
  101. }
  102. filterString += "\0";
  103. }
  104. }
  105. filterString += "\0";
  106. return filterString;
  107. }
  108. private static void ParseResults(char[] buffer, List<ItemWithStream> results, bool multiselect)
  109. {
  110. var currentStringBytes = new List<char>();
  111. foreach (var c in buffer)
  112. {
  113. if (c == 0)
  114. {
  115. var currentString = new string(currentStringBytes.ToArray());
  116. if (!string.IsNullOrWhiteSpace(currentString) && currentString != "\0")
  117. {
  118. var filename = multiselect && results.Count > 0 ? $"{results[0].Name}\\{currentString}" : currentString;
  119. results.Add(new ItemWithStream
  120. {
  121. Name = filename
  122. });
  123. }
  124. currentStringBytes.Clear();
  125. continue;
  126. }
  127. currentStringBytes.Add(c);
  128. }
  129. if (multiselect && results.Count > 1)
  130. {
  131. results.RemoveAt(0);
  132. }
  133. }
  134. }
  135. }
  136. #endif