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