Skip to content

Commit 04efb17

Browse files
committed
Add clipboard and download methods to bridge and commands
1 parent f41f47d commit 04efb17

File tree

3 files changed

+251
-0
lines changed

3 files changed

+251
-0
lines changed

Assets/Plugins/WebGL/WebBridge/CommonCommands.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,5 +274,88 @@ public void LogShaderCompilation(int enabled)
274274
GraphicsSettings.logWhenShaderIsCompiled = enabled == 1;
275275
Debug.Log($"GraphicsSettings.logWhenShaderIsCompiled: {GraphicsSettings.logWhenShaderIsCompiled}");
276276
}
277+
278+
/// <summary>
279+
/// Copy text to clipboard using the browser's clipboard API
280+
/// </summary>
281+
/// <param name="text">Text to copy to clipboard</param>
282+
[WebCommand(Description = "Copy text to clipboard")]
283+
public void CopyToClipboard(string text)
284+
{
285+
bool success = WebToolPlugins.CopyToClipboard(text);
286+
Debug.Log($"Copy to clipboard {(success ? "successful" : "failed")}: {text}");
287+
}
288+
289+
/// <summary>
290+
/// Get current clipboard content using the browser's clipboard API
291+
/// Note: Requires clipboard-read permission in modern browsers
292+
/// </summary>
293+
[WebCommand(Description = "Get current clipboard content")]
294+
public void GetClipboardContent()
295+
{
296+
string content = WebToolPlugins.GetClipboardContent();
297+
Debug.Log($"Clipboard content: {content}");
298+
}
299+
300+
/// <summary>
301+
/// Check if the browser has an internet connection
302+
/// </summary>
303+
[WebCommand(Description = "Check if browser is online")]
304+
public void CheckOnlineStatus()
305+
{
306+
bool isOnline = WebToolPlugins.IsOnline();
307+
Debug.Log($"<color=#4D65A4>Online Status:</color> {(isOnline ? "<color=#3bb508>Connected</color>" : "<color=#b50808>Disconnected</color>")}");
308+
}
309+
310+
/// <summary>
311+
/// Captures the current screen and saves it as a PNG file.
312+
/// </summary>
313+
[WebCommand(Description = "Save current screen as PNG")]
314+
public void SaveScreenshot()
315+
{
316+
SaveScreenshot(1);
317+
}
318+
319+
/// <summary>
320+
/// Captures the current screen and saves it as a PNG file.
321+
/// </summary>
322+
/// <param name="superSize">1 for normal size, 2 for double size, 4 for quadruple size</param>
323+
[WebCommand(Description = "Save current screen as PNG with variable super size")]
324+
public void SaveScreenshot(int superSize)
325+
{
326+
string filename = "screenshot.png";
327+
try
328+
{
329+
// Capture the screen
330+
var screenshot = ScreenCapture.CaptureScreenshotAsTexture(superSize);
331+
332+
try
333+
{
334+
// Convert to PNG
335+
byte[] pngData = screenshot.EncodeToPNG();
336+
337+
// Download through browser
338+
WebToolPlugins.DownloadBinaryFile(filename, pngData, "image/png");
339+
340+
Debug.Log($"Screenshot saved as {filename}");
341+
}
342+
finally
343+
{
344+
// Clean up the texture
345+
if (Application.isPlaying)
346+
{
347+
Destroy(screenshot);
348+
}
349+
else
350+
{
351+
DestroyImmediate(screenshot);
352+
}
353+
}
354+
}
355+
catch (System.Exception e)
356+
{
357+
Debug.LogError($"Failed to save screenshot: {e.Message}");
358+
}
359+
}
277360
}
278361
}

Assets/Plugins/WebGL/WebTools/WebToolPlugins.cs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ public static class WebToolPlugins
3434
private static extern string _GetUserAgent();
3535
[DllImport("__Internal")]
3636
private static extern uint _GetTotalMemorySize();
37+
[DllImport("__Internal")]
38+
private static extern bool _CopyToClipboard(string text);
39+
[DllImport("__Internal")]
40+
private static extern string _GetClipboardContent();
41+
[DllImport("__Internal")]
42+
private static extern int _IsOnline();
43+
[DllImport("__Internal")]
44+
private static extern void _DownloadFile(string filename, string content);
45+
[DllImport("__Internal")]
46+
private static extern void _DownloadBlob(string filename, byte[] byteArray, int byteLength, string mimeType);
47+
3748
#endif
3849

3950
private static bool _infoPanelVisible = false;
@@ -200,5 +211,95 @@ private static float GetMegaBytes(uint bytes)
200211
{
201212
return (float)bytes / (1024 * 1024);
202213
}
214+
215+
/// <summary>
216+
/// Copies the specified text to the system clipboard using the browser's clipboard API.
217+
/// Only works in WebGL builds and requires clipboard-write permission in modern browsers.
218+
/// </summary>
219+
/// <param name="text">The text to copy to the clipboard</param>
220+
/// <returns>True if the copy operation was successful, false otherwise</returns>
221+
public static bool CopyToClipboard(string text)
222+
{
223+
#if UNITY_WEBGL && !UNITY_EDITOR
224+
return _CopyToClipboard(text);
225+
#elif UNITY_EDITOR && WEBTOOLS_LOG_CALLS
226+
Debug.Log($"{nameof(WebToolPlugins)}.{nameof(CopyToClipboard)} called with: {text}");
227+
return false;
228+
#else
229+
return false;
230+
#endif
231+
}
232+
233+
/// <summary>
234+
/// Retrieves the current content from the system clipboard using the browser's clipboard API.
235+
/// Only works in WebGL builds and requires clipboard-read permission in modern browsers.
236+
/// </summary>
237+
/// <returns>The clipboard content as string, or empty string if clipboard is empty or access was denied</returns>
238+
public static string GetClipboardContent()
239+
{
240+
#if UNITY_WEBGL && !UNITY_EDITOR
241+
return _GetClipboardContent();
242+
#elif UNITY_EDITOR && WEBTOOLS_LOG_CALLS
243+
Debug.Log($"{nameof(WebToolPlugins)}.{nameof(GetClipboardContent)} called");
244+
return string.Empty;
245+
#else
246+
return string.Empty;
247+
#endif
248+
}
249+
250+
/// <summary>
251+
/// Checks if the browser currently has an internet connection using the navigator.onLine property.
252+
/// </summary>
253+
/// <returns>True if the browser is online, false if it's offline</returns>
254+
public static bool IsOnline()
255+
{
256+
#if UNITY_WEBGL && !UNITY_EDITOR
257+
return _IsOnline() == 1;
258+
#elif UNITY_EDITOR && WEBTOOLS_LOG_CALLS
259+
Debug.Log($"{nameof(WebToolPlugins)}.{nameof(IsOnline)} called");
260+
return true;
261+
#else
262+
return true;
263+
#endif
264+
}
265+
266+
/// <summary>
267+
/// Downloads a text file through the browser with the specified filename and content.
268+
/// Creates a temporary anchor element to trigger the download.
269+
/// </summary>
270+
/// <param name="filename">The name of the file to be downloaded</param>
271+
/// <param name="content">The text content to be saved in the file</param>
272+
public static void DownloadTextFile(string filename, string content)
273+
{
274+
#if UNITY_WEBGL && !UNITY_EDITOR
275+
_DownloadFile(filename, content);
276+
#elif UNITY_EDITOR && WEBTOOLS_LOG_CALLS
277+
Debug.Log($"{nameof(WebToolPlugins)}.{nameof(DownloadTextFile)} called with filename: {filename}");
278+
#endif
279+
}
280+
281+
/// <summary>
282+
/// Downloads a binary file through the browser with the specified filename and data.
283+
/// Creates a Blob with the specified MIME type and triggers the download.
284+
/// </summary>
285+
/// <param name="filename">The name of the file to be downloaded</param>
286+
/// <param name="data">The binary data to be saved in the file</param>
287+
/// <param name="mimeType">The MIME type of the file (defaults to "application/octet-stream")</param>
288+
/// <example>
289+
/// <code>
290+
/// // Example: Save a Texture2D as PNG
291+
/// Texture2D texture;
292+
/// byte[] pngData = texture.EncodeToPNG();
293+
/// WebToolPlugins.DownloadBinaryFile("texture.png", pngData, "image/png");
294+
/// </code>
295+
/// </example>
296+
public static void DownloadBinaryFile(string filename, byte[] data, string mimeType = "application/octet-stream")
297+
{
298+
#if UNITY_WEBGL && !UNITY_EDITOR
299+
_DownloadBlob(filename, data, data.Length, mimeType);
300+
#elif UNITY_EDITOR && WEBTOOLS_LOG_CALLS
301+
Debug.Log($"{nameof(WebToolPlugins)}.{nameof(DownloadBinaryFile)} called with filename: {filename}");
302+
#endif
303+
}
203304
}
204305
}

Assets/Plugins/WebGL/WebTools/WebToolPlugins.jslib

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,73 @@ var WebGlPlugins =
9797

9898
console.warn("Problem with retrieving total memory size");
9999
return -1;
100+
},
101+
102+
_CopyToClipboard: function(text) {
103+
var str = UTF8ToString(text);
104+
navigator.clipboard.writeText(str)
105+
.then(function() {
106+
console.log('Text copied to clipboard');
107+
return true;
108+
})
109+
.catch(function(err) {
110+
console.error('Failed to copy text: ', err);
111+
return false;
112+
});
113+
},
114+
115+
_GetClipboardContent: function() {
116+
// Note: This requires clipboard-read permission
117+
navigator.clipboard.readText()
118+
.then(function(text) {
119+
var bufferSize = lengthBytesUTF8(text) + 1;
120+
var buffer = _malloc(bufferSize);
121+
stringToUTF8(text, buffer, bufferSize);
122+
return buffer;
123+
})
124+
.catch(function(err) {
125+
console.error('Failed to read clipboard: ', err);
126+
return null;
127+
});
128+
},
129+
130+
_IsOnline: function() {
131+
return navigator.onLine ? 1 : 0;
132+
},
133+
134+
_DownloadFile: function(filename, content) {
135+
var filenameStr = UTF8ToString(filename);
136+
var contentStr = UTF8ToString(content);
137+
138+
var element = document.createElement('a');
139+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contentStr));
140+
element.setAttribute('download', filenameStr);
141+
element.style.display = 'none';
142+
document.body.appendChild(element);
143+
element.click();
144+
document.body.removeChild(element);
145+
},
146+
147+
_DownloadBlob: function(filename, byteArray, byteLength, mimeType) {
148+
var filenameStr = UTF8ToString(filename);
149+
var mimeTypeStr = UTF8ToString(mimeType);
150+
151+
var data = new Uint8Array(byteLength);
152+
for (var i = 0; i < byteLength; i++) {
153+
data[i] = HEAPU8[byteArray + i];
154+
}
155+
156+
var blob = new Blob([data], { type: mimeTypeStr });
157+
var url = URL.createObjectURL(blob);
158+
159+
var element = document.createElement('a');
160+
element.setAttribute('href', url);
161+
element.setAttribute('download', filenameStr);
162+
element.style.display = 'none';
163+
document.body.appendChild(element);
164+
element.click();
165+
document.body.removeChild(element);
166+
URL.revokeObjectURL(url);
100167
}
101168
};
102169

0 commit comments

Comments
 (0)