Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 71 additions & 59 deletions Assets/WebGLCopyAndPaste/Plugins/WebGLCopyAndPaste.jslib
Original file line number Diff line number Diff line change
Expand Up @@ -28,69 +28,81 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
mergeInto(LibraryManager.library, {
initWebGLCopyAndPaste__postset: '_initWebGLCopyAndPaste();',
initWebGLCopyAndPaste: function() {
// for some reason only on Safari does Unity call
// preventDefault so let's prevent preventDefault
// so the browser will generate copy and paste events
window.addEventListener = function(origFn) {
function noop() {}
var WebGLCopyAndPaste = {
$WebGLCopyAndPaste: {},

// I hope c,x,v are universal
const keys = {'c': true, 'x': true, 'v': true};
initWebGLCopyAndPaste__postset: '_initWebGLCopyAndPaste();',

// Emscripten doesn't support the spread operator or at
// least the one used by Unity 2019.4.1
return function(name, fn) {
const args = Array.prototype.slice.call(arguments);
if (name !== 'keypress') {
return origFn.apply(this, args);
}
args[1] = function(event) {
const hArgs = Array.prototype.slice.call(arguments);
if (keys[event.key.toLowerCase()] &&
((event.metaKey ? 1 : 0) + (event.ctrlKey ? 1 : 0)) === 1) {
event.preventDefault = noop;
}
return fn.apply(this, hArgs);
};
return origFn.apply(this, args);
};
}(window.addEventListener);
_initWebGLCopyAndPaste = function(objectNamePtr, cutCopyFuncNamePtr, pasteFuncNamePtr) {
window.becauseUnityIsBadWithJavascript_webglCopyAndPaste =
window.becauseUnityIsBadWithJavascript_webglCopyAndPaste || {
initialized: false,
objectName: Pointer_stringify(objectNamePtr),
cutCopyFuncName: Pointer_stringify(cutCopyFuncNamePtr),
pasteFuncName: Pointer_stringify(pasteFuncNamePtr),
};
const g = window.becauseUnityIsBadWithJavascript_webglCopyAndPaste;
initWebGLCopyAndPaste: function () {
// for some reason only on Safari does Unity call
// preventDefault so let's prevent preventDefault
// so the browser will generate copy and paste events
window.addEventListener = function (origFn) {
function noop() {
}

// I hope c,x,v are universal
const keys = {'c': true, 'x': true, 'v': true};

if (!g.initialized) {
window.addEventListener('cut', function(e) {
e.preventDefault();
SendMessage(g.objectName, g.cutCopyFuncName, 'x');
event.clipboardData.setData('text/plain', g.clipboardStr);
});
window.addEventListener('copy', function(e) {
e.preventDefault();
SendMessage(g.objectName, g.cutCopyFuncName, 'c');
event.clipboardData.setData('text/plain', g.clipboardStr);
});
window.addEventListener('paste', function(e) {
const str = e.clipboardData.getData('text');
SendMessage(g.objectName, g.pasteFuncName, str);
});
// Emscripten doesn't support the spread operator or at
// least the one used by Unity 2019.4.1
return function (name, fn) {
const args = Array.prototype.slice.call(arguments);
if (name !== 'keypress') {
return origFn.apply(this, args);
}
args[1] = function (event) {
const hArgs = Array.prototype.slice.call(arguments);
if (keys[event.key.toLowerCase()] &&
((event.metaKey ? 1 : 0) + (event.ctrlKey ? 1 : 0)) === 1) {
event.preventDefault = noop;
}
return fn.apply(this, hArgs);
};
return origFn.apply(this, args);
};
},
passCopyToBrowser: function(stringPtr) {
const g = window.becauseUnityIsBadWithJavascript_webglCopyAndPaste;
const str = Pointer_stringify(stringPtr);
g.clipboardStr = str;
},
});
}(window.addEventListener);

_initWebGLCopyAndPaste = function (cutCopyFuncPtr, pasteFuncPtr) {

function sendStringCallback (callback, str) {
var bufferSize = lengthBytesUTF8(str) + 1;
var buffer = _malloc(bufferSize);
stringToUTF8(str, buffer, bufferSize);
Runtime.dynCall('vi', callback, [buffer]);
}

WebGLCopyAndPaste.data =
WebGLCopyAndPaste.data || {
initialized: false,
cutCopyFunc: cutCopyFuncPtr,
pasteFunc: pasteFuncPtr,
};
const g = WebGLCopyAndPaste.data;

if (!g.initialized) {
window.addEventListener('cut', function (e) {
e.preventDefault();
sendStringCallback(g.cutCopyFunc, 'x');
event.clipboardData.setData('text/plain', g.clipboardStr);
});
window.addEventListener('copy', function (e) {
e.preventDefault();
sendStringCallback(g.cutCopyFunc, 'c');
event.clipboardData.setData('text/plain', g.clipboardStr);
});
window.addEventListener('paste', function (e) {
const str = e.clipboardData.getData('text');
sendStringCallback(g.pasteFunc, str);
});
}
};
},

passCopyToBrowser: function (stringPtr) {
WebGLCopyAndPaste.data.clipboardStr = Pointer_stringify(stringPtr);
},
};

autoAddDeps(WebGLCopyAndPaste, '$WebGLCopyAndPaste');
mergeInto(LibraryManager.library, WebGLCopyAndPaste);
43 changes: 0 additions & 43 deletions Assets/WebGLCopyAndPaste/Scenes/WebGLCopyAnPasteSampleScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -1166,49 +1166,6 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 972896129}
m_CullTransparentMesh: 0
--- !u!1 &1267957137
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1267957138}
- component: {fileID: 1267957139}
m_Layer: 0
m_Name: WebGLCopyAndPasteHelper
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1267957138
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1267957137}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1267957139
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1267957137}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9e56c2066eff9f34c812865afcc473c9, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1404080528
GameObject:
m_ObjectHideFlags: 0
Expand Down
131 changes: 60 additions & 71 deletions Assets/WebGLCopyAndPaste/Scripts/WebGLCopyAndPaste.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,87 +34,76 @@

// #define WEBGL_COPY_AND_PASTE_SUPPORT_TEXTMESH_PRO

public class WebGLCopyAndPasteAPI {
public class WebGLCopyAndPasteAPI
{

#if UNITY_WEBGL
#if UNITY_WEBGL

[DllImport("__Internal")]
private static extern void initWebGLCopyAndPaste(string objectName, string cutCopyCallbackFuncName, string pasteCallbackFuncName);
[DllImport("__Internal")]
private static extern void passCopyToBrowser(string str);
[DllImport("__Internal")]
private static extern void initWebGLCopyAndPaste(StringCallback cutCopyCallback, StringCallback pasteCallback);
[DllImport("__Internal")]
private static extern void passCopyToBrowser(string str);

#endif
delegate void StringCallback( string content );

static public void Init(string objectName, string cutCopyCallbackFuncName, string pasteCallbackFuncName)
{
#if UNITY_WEBGL

initWebGLCopyAndPaste(objectName, cutCopyCallbackFuncName, pasteCallbackFuncName);

#endif
}

static public void PassCopyToBrowser(string str)
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
private static void Init()
{
#if UNITY_WEBGL

passCopyToBrowser(str);

#endif
}
}

public class WebGLCopyAndPaste : MonoBehaviour {
void Start()
{
if (!Application.isEditor) {
WebGLCopyAndPasteAPI.Init(this.name, "GetClipboard", "ReceivePaste");
if ( !Application.isEditor )
{
initWebGLCopyAndPaste(GetClipboard, ReceivePaste );
}
}
}

private void SendKey(string baseKey)
{
string appleKey = "%" + baseKey;
string naturalKey = "^" + baseKey;
private static void SendKey(string baseKey)
{
string appleKey = "%" + baseKey;
string naturalKey = "^" + baseKey;

var currentObj = EventSystem.current.currentSelectedGameObject;
if (currentObj == null) {
return;
}
{
var input = currentObj.GetComponent<UnityEngine.UI.InputField>();
if (input != null) {
// I don't know what's going on here. The code in InputField
// is looking for ctrl-c but that fails on Mac Chrome/Firefox
input.ProcessEvent(Event.KeyboardEvent(naturalKey));
input.ProcessEvent(Event.KeyboardEvent(appleKey));
// so let's hope one of these is basically a noop
return;
}
}
#if WEBGL_COPY_AND_PASTE_SUPPORT_TEXTMESH_PRO
{
var input = currentObj.GetComponent<TMPro.TMP_InputField>();
if (input != null) {
// I don't know what's going on here. The code in InputField
// is looking for ctrl-c but that fails on Mac Chrome/Firefox
// so let's hope one of these is basically a noop
input.ProcessEvent(Event.KeyboardEvent(naturalKey));
input.ProcessEvent(Event.KeyboardEvent(appleKey));
return;
}
}
#endif
}

var currentObj = EventSystem.current.currentSelectedGameObject;
if (currentObj == null) {
return;
}
{
var input = currentObj.GetComponent<UnityEngine.UI.InputField>();
if (input != null) {
// I don't know what's going on here. The code in InputField
// is looking for ctrl-c but that fails on Mac Chrome/Firefox
input.ProcessEvent(Event.KeyboardEvent(naturalKey));
input.ProcessEvent(Event.KeyboardEvent(appleKey));
// so let's hope one of these is basically a noop
return;
[AOT.MonoPInvokeCallback( typeof(StringCallback) )]
private static void GetClipboard(string key)
{
SendKey(key);
passCopyToBrowser(GUIUtility.systemCopyBuffer);
}
}
#if WEBGL_COPY_AND_PASTE_SUPPORT_TEXTMESH_PRO
{
var input = currentObj.GetComponent<TMPro.TMP_InputField>();
if (input != null) {
// I don't know what's going on here. The code in InputField
// is looking for ctrl-c but that fails on Mac Chrome/Firefox
// so let's hope one of these is basically a noop
input.ProcessEvent(Event.KeyboardEvent(naturalKey));
input.ProcessEvent(Event.KeyboardEvent(appleKey));
return;

[AOT.MonoPInvokeCallback( typeof(StringCallback) )]
private static void ReceivePaste(string str)
{
GUIUtility.systemCopyBuffer = str;
}
}
#endif
}

public void GetClipboard(string key)
{
SendKey(key);
WebGLCopyAndPasteAPI.PassCopyToBrowser(GUIUtility.systemCopyBuffer);
}
#endif

public void ReceivePaste(string str)
{
GUIUtility.systemCopyBuffer = str;
}
}
}
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ Example: https://greggman.github.io/unity-webgl-copy-and-paste/

1. Download and add in [this unity package](https://github.com/greggman/unity-webgl-copy-and-paste/releases/latest) into your project.

2. Make a `GameObject` and add in the `WebGLCopyAndPaste` script.

3. If you are using [`TMPro.TMP_InputField`](https://docs.unity3d.com/Packages/com.unity.textmeshpro@2.1/api/TMPro.TMP_InputField.html) then edit `Assets/WebGLCopyAndPaste/Scripts/WebGLCopyAndPaste.cs`
2. If you are using [`TMPro.TMP_InputField`](https://docs.unity3d.com/Packages/com.unity.textmeshpro@2.1/api/TMPro.TMP_InputField.html) then edit `Assets/WebGLCopyAndPaste/Scripts/WebGLCopyAndPaste.cs`
and uncomment this line

```
Expand Down Expand Up @@ -48,6 +46,14 @@ https://github.com/kou-yeung/WebGLInput

## ChangeList

* 0.1.0

* Removed the need for MonoBehaviours

* Replaced messages with proper callbacks

* Fixed data storing in `window`

* 0.0.2

* Support cut
Expand Down