Jelajahi Sumber

增加搜索栏输入中文的组件

Void_F 1 bulan lalu
induk
melakukan
ac45f2218a
47 mengubah file dengan 2463 tambahan dan 4 penghapusan
  1. 31 3
      Assets/Prefabs/UI/3D/GCZL.prefab
  2. 27 0
      Assets/Prefabs/UI/SWFZ/SPJK.prefab
  3. 29 0
      Assets/Prefabs/UI/SWFZ/ZMJK.prefab
  4. 29 0
      Assets/Prefabs/UI/XHYZT/GCJK.prefab
  5. 98 1
      Assets/Scene 1.unity
  6. 21 0
      Assets/Scripts/UI/UIView/3D/GCZLLayer.cs
  7. 8 0
      Assets/WebGLSupport.meta
  8. 8 0
      Assets/WebGLSupport/Editor.meta
  9. 59 0
      Assets/WebGLSupport/Editor/Postprocessor.cs
  10. 2 0
      Assets/WebGLSupport/Editor/Postprocessor.cs.meta
  11. 8 0
      Assets/WebGLSupport/WebGLInput.meta
  12. 8 0
      Assets/WebGLSupport/WebGLInput/Detail.meta
  13. 62 0
      Assets/WebGLSupport/WebGLInput/Detail/RebuildChecker.cs
  14. 11 0
      Assets/WebGLSupport/WebGLInput/Detail/RebuildChecker.cs.meta
  15. 45 0
      Assets/WebGLSupport/WebGLInput/Detail/Support.cs
  16. 2 0
      Assets/WebGLSupport/WebGLInput/Detail/Support.cs.meta
  17. 8 0
      Assets/WebGLSupport/WebGLInput/Events.meta
  18. 20 0
      Assets/WebGLSupport/WebGLInput/Events/KeyboardEvent.cs
  19. 2 0
      Assets/WebGLSupport/WebGLInput/Events/KeyboardEvent.cs.meta
  20. 8 0
      Assets/WebGLSupport/WebGLInput/Mobile.meta
  21. 87 0
      Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.cs
  22. 11 0
      Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.cs.meta
  23. 23 0
      Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.jslib
  24. 34 0
      Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.jslib.meta
  25. 8 0
      Assets/WebGLSupport/WebGLInput/UIToolKit.meta
  26. 67 0
      Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLInputManipulator.cs
  27. 2 0
      Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLInputManipulator.cs.meta
  28. 13 0
      Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLUIToolkitTextField.cs
  29. 2 0
      Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLUIToolkitTextField.cs.meta
  30. 480 0
      Assets/WebGLSupport/WebGLInput/WebGLInput.cs
  31. 11 0
      Assets/WebGLSupport/WebGLInput/WebGLInput.cs.meta
  32. 216 0
      Assets/WebGLSupport/WebGLInput/WebGLInput.jslib
  33. 34 0
      Assets/WebGLSupport/WebGLInput/WebGLInput.jslib.meta
  34. 8 0
      Assets/WebGLSupport/WebGLInput/Wrapper.meta
  35. 46 0
      Assets/WebGLSupport/WebGLInput/Wrapper/IInputField.cs
  36. 11 0
      Assets/WebGLSupport/WebGLInput/Wrapper/IInputField.cs.meta
  37. 119 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedInputField.cs
  38. 11 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedInputField.cs.meta
  39. 212 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedTMPInputField.cs
  40. 11 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedTMPInputField.cs.meta
  41. 162 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedUIToolkit.cs
  42. 11 0
      Assets/WebGLSupport/WebGLInput/Wrapper/WrappedUIToolkit.cs.meta
  43. 8 0
      Assets/WebGLSupport/WebGLWindow.meta
  44. 138 0
      Assets/WebGLSupport/WebGLWindow/WebGLWindow.cs
  45. 11 0
      Assets/WebGLSupport/WebGLWindow/WebGLWindow.cs.meta
  46. 204 0
      Assets/WebGLSupport/WebGLWindow/WebGLWindow.jslib
  47. 37 0
      Assets/WebGLSupport/WebGLWindow/WebGLWindow.jslib.meta

+ 31 - 3
Assets/Prefabs/UI/3D/GCZL.prefab

@@ -1435,9 +1435,9 @@ RectTransform:
   m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 1, y: 1}
+  m_AnchorMax: {x: 0, y: 0}
   m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: -4.2, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0, y: 1}
 --- !u!222 &4452380873706791393
 CanvasRenderer:
@@ -1524,7 +1524,7 @@ RectTransform:
   m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 1, y: 1}
+  m_AnchorMax: {x: 0, y: 0}
   m_AnchoredPosition: {x: 0, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0.5, y: 0.5}
@@ -2236,6 +2236,8 @@ GameObject:
   - component: {fileID: 4452380874866707936}
   - component: {fileID: 4452380874866707937}
   - component: {fileID: 4452380874866707938}
+  - component: {fileID: 3581937935413681299}
+  - component: {fileID: 4840942960938587786}
   m_Layer: 5
   m_Name: Search
   m_TagString: Untagged
@@ -2447,6 +2449,31 @@ MonoBehaviour:
   m_CaretWidth: 1
   m_ReadOnly: 0
   m_ShouldActivateOnSelect: 1
+--- !u!114 &3581937935413681299
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4452380874866707940}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: cc33a39070010f94fb1c2dd721c1286d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  showHtmlElement: 0
+--- !u!114 &4840942960938587786
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4452380874866707940}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 56393f797a0f7e94e95547f5052052a4, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
 --- !u!1 &4452380874907860041
 GameObject:
   m_ObjectHideFlags: 0
@@ -2503,6 +2530,7 @@ MonoBehaviour:
   informationPrefab: {fileID: 5528671914952809849, guid: 3fb39873723719c4bb5a97fd1feac903, type: 3}
   classContent: {fileID: 4452380874075618982}
   informationContent: {fileID: 4452380874144021549}
+  informationSearchInput: {fileID: 4452380874866707938}
   zTLayer: {fileID: 0}
   sprites:
   - {fileID: 21300000, guid: 9eb4cb859e3c36b44bf2a2da8fa61736, type: 3}

+ 27 - 0
Assets/Prefabs/UI/SWFZ/SPJK.prefab

@@ -248,6 +248,8 @@ GameObject:
   - component: {fileID: 3483517250615139101}
   - component: {fileID: 8650244154791646045}
   - component: {fileID: 6744885183358372171}
+  - component: {fileID: 8766051601274175724}
+  - component: {fileID: 5479903655754082656}
   m_Layer: 5
   m_Name: InputField
   m_TagString: Untagged
@@ -459,6 +461,31 @@ MonoBehaviour:
   m_CaretWidth: 1
   m_ReadOnly: 0
   m_ShouldActivateOnSelect: 1
+--- !u!114 &8766051601274175724
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1408830096335601113}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: cc33a39070010f94fb1c2dd721c1286d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  showHtmlElement: 0
+--- !u!114 &5479903655754082656
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1408830096335601113}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 56393f797a0f7e94e95547f5052052a4, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
 --- !u!1 &1664038665848668414
 GameObject:
   m_ObjectHideFlags: 0

+ 29 - 0
Assets/Prefabs/UI/SWFZ/ZMJK.prefab

@@ -5206,6 +5206,8 @@ GameObject:
   - component: {fileID: 3483517250615139101}
   - component: {fileID: 8650244154791646045}
   - component: {fileID: 6744885183358372171}
+  - component: {fileID: 6049527522117729415}
+  - component: {fileID: 3461837893376645281}
   m_Layer: 5
   m_Name: InputField
   m_TagString: Untagged
@@ -5417,6 +5419,31 @@ MonoBehaviour:
   m_CaretWidth: 1
   m_ReadOnly: 0
   m_ShouldActivateOnSelect: 1
+--- !u!114 &6049527522117729415
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1408830096335601113}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: cc33a39070010f94fb1c2dd721c1286d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  showHtmlElement: 0
+--- !u!114 &3461837893376645281
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1408830096335601113}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 56393f797a0f7e94e95547f5052052a4, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
 --- !u!1 &1499534797885794991
 GameObject:
   m_ObjectHideFlags: 0
@@ -11429,6 +11456,8 @@ MonoBehaviour:
   shuiweiChart: {fileID: 643139369441244097}
   _zmSearchInputField: {fileID: 6744885183358372171}
   currentZMDataList: []
+  targetObj: {fileID: 0}
+  showGongPanel: 0
 --- !u!1 &4463901847923660319
 GameObject:
   m_ObjectHideFlags: 0

+ 29 - 0
Assets/Prefabs/UI/XHYZT/GCJK.prefab

@@ -4501,6 +4501,8 @@ GameObject:
   - component: {fileID: 1316089967122820796}
   - component: {fileID: 3627714807224385373}
   - component: {fileID: 6150266110101675048}
+  - component: {fileID: 7053112126674288355}
+  - component: {fileID: 119133356736932620}
   m_Layer: 5
   m_Name: InputField
   m_TagString: Untagged
@@ -4712,6 +4714,31 @@ MonoBehaviour:
   m_CaretWidth: 1
   m_ReadOnly: 0
   m_ShouldActivateOnSelect: 1
+--- !u!114 &7053112126674288355
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2878528905417651338}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: cc33a39070010f94fb1c2dd721c1286d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  showHtmlElement: 0
+--- !u!114 &119133356736932620
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2878528905417651338}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 56393f797a0f7e94e95547f5052052a4, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
 --- !u!1 &2941663907386582818
 GameObject:
   m_ObjectHideFlags: 0
@@ -10644,6 +10671,8 @@ MonoBehaviour:
   weatherToggle: {fileID: 2536395915099292973}
   runtimePointObj: {fileID: 5029940434980741371, guid: f7351d99134429b4280ee00172298cf5, type: 3}
   loading: {fileID: 1483224817772276406}
+  buyuanBtn: {fileID: 0}
+  taokouBtn: {fileID: 0}
 --- !u!1 &6205949641887129071
 GameObject:
   m_ObjectHideFlags: 0

File diff ditekan karena terlalu besar
+ 98 - 1
Assets/Scene 1.unity


+ 21 - 0
Assets/Scripts/UI/UIView/3D/GCZLLayer.cs

@@ -15,6 +15,7 @@ public class GCZLLayer : MonoBehaviour
 
     public RectTransform classContent;
     public RectTransform informationContent;
+    public InputField informationSearchInput;
     public YZTLayer zTLayer;
 
     public Sprite[] sprites;
@@ -191,6 +192,8 @@ public class GCZLLayer : MonoBehaviour
         CameraManager.SwitchCamera(0);
         InitButton();
         InitInformation(0);
+        
+        informationSearchInput.onValueChanged.AddListener(SearchInformationItem);
     }
 
     void InitButton()
@@ -316,6 +319,24 @@ public class GCZLLayer : MonoBehaviour
             }
         }
     }
+    
+    public void SearchInformationItem(string s_name)
+    {
+        if (s_name.Equals(""))
+        {
+            for (int i = 0; i < informations.Count; i++)
+            {
+                informations[i].gameObject.SetActive(true);
+            }
+        }
+        else
+        {
+            for (int i = 0; i < informations.Count; i++)
+            {
+                informations[i].gameObject.SetActive(informations[i].transform.Find("Name").GetComponentInChildren<Text>().text.Contains(s_name));
+            }
+        }
+    }
 
 
     async Task InitData()

+ 8 - 0
Assets/WebGLSupport.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 19b231dc2e1ab5e47bb801e8853f659a
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/WebGLSupport/Editor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 59d15a398f7a6ef4ca057f6d2471425f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 59 - 0
Assets/WebGLSupport/Editor/Postprocessor.cs

@@ -0,0 +1,59 @@
+using System.IO;
+using UnityEditor;
+using UnityEditor.Callbacks;
+using UnityEngine;
+
+namespace WebGLSupport
+{
+    public class Postprocessor
+    {
+        const string MenuPath = "Assets/WebGLSupport/OverwriteFullscreenButton";
+
+#if UNITY_2021_1_OR_NEWER
+        static readonly bool supportedPostprocessor = true;
+        static readonly string defaultFullscreenFunc = "unityInstance.SetFullscreen(1);";
+        static readonly string fullscreenNode = "unity-container";
+#else
+        static readonly bool supportedPostprocessor = false;
+        static readonly string defaultFullscreenFunc = "";
+        static readonly string fullscreenNode = "";
+#endif
+
+        private static bool IsEnable => PlayerPrefs.GetInt(MenuPath, 1) == 1;
+
+        [PostProcessBuild(1)]
+        public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
+        {
+            if (target != BuildTarget.WebGL) return;
+            if (!supportedPostprocessor) return;
+            if (!IsEnable) return;
+
+            var path = Path.Combine(pathToBuiltProject, "index.html");
+            if (!File.Exists(path)) return;
+
+            var html = File.ReadAllText(path);
+
+            // check node is exist
+            if (html.Contains(fullscreenNode))
+            {
+                html = html.Replace(defaultFullscreenFunc, $"document.makeFullscreen('{fullscreenNode}');");
+                File.WriteAllText(path, html);
+            }
+        }
+
+        [MenuItem(MenuPath)]
+        public static void OverwriteDefaultFullscreenButton()
+        {
+            var flag = !Menu.GetChecked(MenuPath);
+            Menu.SetChecked(MenuPath, flag);
+            PlayerPrefs.SetInt(MenuPath, flag ? 1 : 0);
+        }
+
+        [MenuItem(MenuPath, validate = true)]
+        private static bool OverwriteDefaultFullscreenButtonValidator()
+        {
+            Menu.SetChecked(MenuPath, IsEnable);
+            return true;
+        }
+    }
+}

+ 2 - 0
Assets/WebGLSupport/Editor/Postprocessor.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: a264ac0d7a7e8a746aa37a17a495e24f

+ 8 - 0
Assets/WebGLSupport/WebGLInput.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 23d83eab8f753b04fb7f1384ac6676a0
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/WebGLSupport/WebGLInput/Detail.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dd840bb14379149498902237a63bb794
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 62 - 0
Assets/WebGLSupport/WebGLInput/Detail/RebuildChecker.cs

@@ -0,0 +1,62 @@
+using UnityEngine;
+
+namespace WebGLSupport.Detail
+{
+    public class RebuildChecker
+    {
+        IInputField input;
+
+        string beforeString;
+        int beforeCaretPosition;
+        int beforeSelectionFocusPosition;
+        int beforeSelectionAnchorPosition;
+        //Vector2 anchoredPosition;
+
+        public RebuildChecker(IInputField input)
+        {
+            this.input = input;
+        }
+
+        public bool NeedRebuild(bool debug = false)
+        {
+            var res = false;
+
+            // any not same
+            if (beforeString != input.text)
+            {
+                if(debug) Debug.Log(string.Format("beforeString : {0} != {1}", beforeString, input.text));
+                beforeString = input.text;
+                res = true;
+            }
+
+            if (beforeCaretPosition != input.caretPosition)
+            {
+                if (debug) Debug.Log(string.Format("beforeCaretPosition : {0} != {1}", beforeCaretPosition, input.caretPosition));
+                beforeCaretPosition = input.caretPosition;
+                res = true;
+            }
+
+            if (beforeSelectionFocusPosition != input.selectionFocusPosition)
+            {
+                if (debug) Debug.Log(string.Format("beforeSelectionFocusPosition : {0} != {1}", beforeSelectionFocusPosition, input.selectionFocusPosition));
+                beforeSelectionFocusPosition = input.selectionFocusPosition;
+                res = true;
+            }
+
+            if (beforeSelectionAnchorPosition != input.selectionAnchorPosition)
+            {
+                if (debug) Debug.Log(string.Format("beforeSelectionAnchorPosition : {0} != {1}", beforeSelectionAnchorPosition, input.selectionAnchorPosition));
+                beforeSelectionAnchorPosition = input.selectionAnchorPosition;
+                res = true;
+            }
+
+            //if (anchoredPosition != input.TextComponentRectTransform().anchoredPosition)
+            //{
+            //    if (debug) Debug.Log(string.Format("anchoredPosition : {0} != {1}", anchoredPosition, input.TextComponentRectTransform().anchoredPosition));
+            //    anchoredPosition = input.TextComponentRectTransform().anchoredPosition;
+            //    res = true;
+            //}
+            return res;
+        }
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Detail/RebuildChecker.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3cb8b49a6bee2384b888ba951eb2bdbd
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 45 - 0
Assets/WebGLSupport/WebGLInput/Detail/Support.cs

@@ -0,0 +1,45 @@
+using UnityEngine;
+
+namespace WebGLSupport.Detail
+{
+    public static class Support
+    {
+        /// <summary>
+        /// 画面内の描画範囲を取得する
+        /// </summary>
+        /// <param name="uiElement"></param>
+        /// <returns></returns>
+        public static Rect GetScreenCoordinates(RectTransform uiElement)
+        {
+            var worldCorners = new Vector3[4];
+            uiElement.GetWorldCorners(worldCorners);
+
+            // try to support RenderMode:WorldSpace
+            var canvas = uiElement.GetComponentInParent<Canvas>();
+            var useCamera = (canvas.renderMode != RenderMode.ScreenSpaceOverlay);
+            if (canvas && useCamera)
+            {
+                var camera = canvas.worldCamera;
+                if (!camera) camera = Camera.main;
+
+                for (var i = 0; i < worldCorners.Length; i++)
+                {
+                    worldCorners[i] = camera.WorldToScreenPoint(worldCorners[i]);
+                }
+            }
+
+            var min = new Vector3(float.MaxValue, float.MaxValue);
+            var max = new Vector3(float.MinValue, float.MinValue);
+            for (var i = 0; i < worldCorners.Length; i++)
+            {
+                min.x = Mathf.Min(min.x, worldCorners[i].x);
+                min.y = Mathf.Min(min.y, worldCorners[i].y);
+                max.x = Mathf.Max(max.x, worldCorners[i].x);
+                max.y = Mathf.Max(max.y, worldCorners[i].y);
+            }
+
+            return new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
+        }
+
+    }
+}

+ 2 - 0
Assets/WebGLSupport/WebGLInput/Detail/Support.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 12cf2979a42548647b4a59fab831a36b

+ 8 - 0
Assets/WebGLSupport/WebGLInput/Events.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 863f75c59ad9cf44b89143346c17e55b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 20 - 0
Assets/WebGLSupport/WebGLInput/Events/KeyboardEvent.cs

@@ -0,0 +1,20 @@
+namespace WebGLSupport
+{
+    public delegate void KeyboardEventHandler(WebGLInput input, KeyboardEvent keyboardEvent);
+    public sealed class KeyboardEvent
+    {
+        public string Key { get; }
+        public int Code { get; }
+        public bool ShiftKey { get; }
+        public bool CtrlKey { get; }
+        public bool AltKey { get; }
+        public KeyboardEvent(string key, int code, bool shiftKey, bool ctrlKey, bool altKey)
+        {
+            Key = key;
+            Code = code;
+            ShiftKey = shiftKey;
+            CtrlKey = ctrlKey;
+            AltKey = altKey;
+        }
+    }
+}

+ 2 - 0
Assets/WebGLSupport/WebGLInput/Events/KeyboardEvent.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 81551fe61b23b9d41b0a261e062d1ba0

+ 8 - 0
Assets/WebGLSupport/WebGLInput/Mobile.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8fcb4aaeec72ef54486eff0172891c0b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 87 - 0
Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.cs

@@ -0,0 +1,87 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System.Runtime.InteropServices; // for DllImport
+using AOT;
+using System;
+
+namespace WebGLSupport
+{
+    class WebGLInputMobilePlugin
+    {
+#if UNITY_WEBGL && !UNITY_EDITOR
+        [DllImport("__Internal")]
+        public static extern int WebGLInputMobileRegister(Action<int> OnTouchEnd);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputMobileOnFocusOut(int id, Action<int> OnFocusOut);
+#else
+        /// <summary>
+        /// ID を割り振り
+        /// </summary>
+        /// <returns></returns>
+        public static int WebGLInputMobileRegister(Action<int> OnTouchEnd) { return 0; }
+
+        public static void WebGLInputMobileOnFocusOut(int id, Action<int> OnFocusOut) { }
+#endif
+    }
+
+    public class WebGLInputMobile : MonoBehaviour, IPointerDownHandler
+    {
+        static Dictionary<int, WebGLInputMobile> instances = new Dictionary<int, WebGLInputMobile>();
+
+        int id = -1;
+
+        private void Awake()
+        {
+#if !(UNITY_WEBGL && !UNITY_EDITOR)
+            // WebGL 以外、更新メソッドは動作しないようにします
+            enabled = false;
+#endif
+        }
+
+        /// <summary>
+        /// 押されたら、touchend イベントを登録する
+        /// </summary>
+        /// <param name="eventData"></param>
+        public void OnPointerDown(PointerEventData eventData)
+        {
+            if (id != -1) return;
+            id = WebGLInputMobilePlugin.WebGLInputMobileRegister(OnTouchEnd);
+            instances[id] = this;
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int>))]
+        static void OnTouchEnd(int id)
+        {
+            var @this = instances[id];
+            @this.GetComponent<WebGLInput>().OnSelect();
+            @this.StartCoroutine(RegisterOnFocusOut(id));
+        }
+
+        static IEnumerator RegisterOnFocusOut(int id)
+        {
+            yield return null;  // wait one frame.
+            WebGLInputMobilePlugin.WebGLInputMobileOnFocusOut(id, OnFocusOut);
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int>))]
+        static void OnFocusOut(int id)
+        {
+            var @this = instances[id];
+            @this.StartCoroutine(ExecFocusOut(id));
+        }
+
+        static IEnumerator ExecFocusOut(int id)
+        {
+            yield return null;  // wait one frame.
+            var @this = instances[id];
+            @this.GetComponent<WebGLInput>().DeactivateInputField();
+            // release
+            @this.id = -1;
+            instances.Remove(id);
+        }
+    }
+}
+

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 56393f797a0f7e94e95547f5052052a4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 23 - 0
Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.jslib

@@ -0,0 +1,23 @@
+var WebGLInputMobile = {
+    $instances: [],
+
+    WebGLInputMobileRegister: function (touchend) {
+        var id = instances.push(null) - 1;
+
+        document.body.addEventListener("touchend", function () {
+            document.body.removeEventListener("touchend", arguments.callee);
+            Runtime.dynCall("vi", touchend, [id]);
+        });
+
+        return id;
+    },
+    WebGLInputMobileOnFocusOut: function (id, focusout) {
+        document.body.addEventListener("focusout", function () {
+            document.body.removeEventListener("focusout", arguments.callee);
+            Runtime.dynCall("vi", focusout, [id]);
+        });
+    },
+}
+
+autoAddDeps(WebGLInputMobile, '$instances');
+mergeInto(LibraryManager.library, WebGLInputMobile);

+ 34 - 0
Assets/WebGLSupport/WebGLInput/Mobile/WebGLInputMobile.jslib.meta

@@ -0,0 +1,34 @@
+fileFormatVersion: 2
+guid: 4df3633103619754fb77d82a1d683868
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  isPreloaded: 0
+  isOverridable: 0
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  - first:
+      Facebook: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      WebGL: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/WebGLSupport/WebGLInput/UIToolKit.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1b7dfc1c4073fb3428679dbe79406c59
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 67 - 0
Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLInputManipulator.cs

@@ -0,0 +1,67 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace WebGLSupport
+{
+    public class WebGLInputManipulator : Manipulator
+    {
+        private GameObject go;
+        private bool showHtmlElement;
+
+        public WebGLInputManipulator(bool showHtmlElement = false)
+        {
+            this.showHtmlElement = showHtmlElement;
+        }
+        protected override void RegisterCallbacksOnTarget()
+        {
+            // uitoolkit is already support mobile.
+            if (!Application.isMobilePlatform)
+            {
+                var textInput = target.Q("unity-text-input");
+                textInput.RegisterCallback<FocusInEvent>(OnFocusInEvent);
+                textInput.RegisterCallback<FocusOutEvent>(OnFocusOutEvent);
+            }
+        }
+        protected override void UnregisterCallbacksFromTarget()
+        {
+            // uitoolkit is already support mobile.
+            if (!Application.isMobilePlatform)
+            {
+                var textInput = target.Q("unity-text-input");
+                textInput.UnregisterCallback<FocusInEvent>(OnFocusInEvent);
+                textInput.UnregisterCallback<FocusOutEvent>(OnFocusOutEvent);
+            }
+        }
+
+        private void OnFocusInEvent(FocusInEvent evt)
+        {
+            if (go != null)
+            {
+                GameObject.Destroy(go);
+                go = null;
+            }
+
+            go = new GameObject("WebGLInputManipulator");
+
+            // add WebGLUIToolkitMonoBehaviour for hold TextField!
+            var uitoolkit = go.AddComponent<WebGLUIToolkitTextField>();
+            uitoolkit.TextField = target as TextField;
+
+            // add WebGLInput to handle the event!
+            var webglInput = go.AddComponent<WebGLInput>();
+            webglInput.showHtmlElement = showHtmlElement;
+
+            // select it!!
+            webglInput.OnSelect();
+        }
+
+        private void OnFocusOutEvent(FocusOutEvent evt)
+        {
+            if (go != null)
+            {
+                GameObject.Destroy(go);
+                go = null;
+            }
+        }
+    }
+}

+ 2 - 0
Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLInputManipulator.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 0235a2af8956c404c88f16d375fad74b

+ 13 - 0
Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLUIToolkitTextField.cs

@@ -0,0 +1,13 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace WebGLSupport
+{
+    /// <summary>
+    /// UIToolkit TextField
+    /// </summary>
+    public class WebGLUIToolkitTextField : MonoBehaviour
+    {
+        public TextField TextField { get; set; }
+    }
+}

+ 2 - 0
Assets/WebGLSupport/WebGLInput/UIToolKit/WebGLUIToolkitTextField.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 78226379c6d667741815566e6261c706

+ 480 - 0
Assets/WebGLSupport/WebGLInput/WebGLInput.cs

@@ -0,0 +1,480 @@
+#if UNITY_2018_2_OR_NEWER
+#define TMP_WEBGL_SUPPORT
+#endif
+
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+using AOT;
+using System.Runtime.InteropServices; // for DllImport
+using System.Collections;
+using UnityEngine.EventSystems;
+
+namespace WebGLSupport
+{
+    internal class WebGLInputPlugin
+    {
+#if UNITY_WEBGL && !UNITY_EDITOR
+        [DllImport("__Internal")]
+        public static extern void WebGLInputInit();
+        [DllImport("__Internal")]
+        public static extern int WebGLInputCreate(string canvasId, int x, int y, int width, int height, int fontsize, string text, string placeholder, bool isMultiLine, bool isPassword, bool isHidden, bool isMobile);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputEnterSubmit(int id, bool flag);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputTab(int id, Action<int, int> cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputFocus(int id);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputOnFocus(int id, Action<int> cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputOnBlur(int id, Action<int> cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputOnValueChange(int id, Action<int, string> cb);
+        
+        [DllImport("__Internal")]
+        public static extern void WebGLInputOnEditEnd(int id, Action<int, string> cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputOnKeyboardEvent(int id, Action<int, int, string, int, int, int, int> cb);
+
+        [DllImport("__Internal")]
+        public static extern int WebGLInputSelectionStart(int id);
+
+        [DllImport("__Internal")]
+        public static extern int WebGLInputSelectionEnd(int id);
+
+        [DllImport("__Internal")]
+        public static extern int WebGLInputSelectionDirection(int id);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputSetSelectionRange(int id, int start, int end);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputMaxLength(int id, int maxlength);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputText(int id, string text);
+
+        [DllImport("__Internal")]
+        public static extern bool WebGLInputIsFocus(int id);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputDelete(int id);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLInputForceBlur(int id);
+
+#if WEBGLINPUT_TAB
+        [DllImport("__Internal")]
+        public static extern void WebGLInputEnableTabText(int id, bool enable);
+#endif
+#else
+        public static void WebGLInputInit() { }
+        public static int WebGLInputCreate(string canvasId, int x, int y, int width, int height, int fontsize, string text, string placeholder, bool isMultiLine, bool isPassword, bool isHidden, bool isMobile) { return 0; }
+        public static void WebGLInputEnterSubmit(int id, bool flag) { }
+        public static void WebGLInputTab(int id, Action<int, int> cb) { }
+        public static void WebGLInputFocus(int id) { }
+        public static void WebGLInputOnFocus(int id, Action<int> cb) { }
+        public static void WebGLInputOnBlur(int id, Action<int> cb) { }
+        public static void WebGLInputOnValueChange(int id, Action<int, string> cb) { }
+        public static void WebGLInputOnEditEnd(int id, Action<int, string> cb) { }
+        public static void WebGLInputOnKeyboardEvent(int id, Action<int, int, string, int, int, int, int> cb) { }
+        public static int WebGLInputSelectionStart(int id) { return 0; }
+        public static int WebGLInputSelectionEnd(int id) { return 0; }
+        public static int WebGLInputSelectionDirection(int id) { return 0; }
+        public static void WebGLInputSetSelectionRange(int id, int start, int end) { }
+        public static void WebGLInputMaxLength(int id, int maxlength) { }
+        public static void WebGLInputText(int id, string text) { }
+        public static bool WebGLInputIsFocus(int id) { return false; }
+        public static void WebGLInputDelete(int id) { }
+        public static void WebGLInputForceBlur(int id) { }
+
+#if WEBGLINPUT_TAB
+        public static void WebGLInputEnableTabText(int id, bool enable) { }
+#endif
+
+#endif
+    }
+
+    public class WebGLInput : MonoBehaviour, IComparable<WebGLInput>
+    {
+        public static event KeyboardEventHandler OnKeyboardDown;
+        public static event KeyboardEventHandler OnKeyboardUp;
+
+        static Dictionary<int, WebGLInput> instances = new Dictionary<int, WebGLInput>();
+        public static string CanvasId { get; set; }
+
+#if WEBGLINPUT_TAB
+        public bool enableTabText = false;
+#endif
+
+        static WebGLInput()
+        {
+            CanvasId = WebGLWindow.GetCanvasName();
+            WebGLInputPlugin.WebGLInputInit();
+        }
+        public int Id { get { return id; } }
+        internal int id = -1;
+        public IInputField input { get; private set; }
+        bool blurBlock = false;
+
+        [TooltipAttribute("show input element on canvas. this will make you select text by drag.")]
+        public bool showHtmlElement = false;
+
+        private IInputField Setup()
+        {
+            if (GetComponent<InputField>()) return new WrappedInputField(GetComponent<InputField>());
+
+            if (GetComponent<WebGLUIToolkitTextField>()) return new WrappedUIToolkit(GetComponent<WebGLUIToolkitTextField>());
+#if TMP_WEBGL_SUPPORT
+            if (GetComponent<TMPro.TMP_InputField>()) return new WrappedTMPInputField(GetComponent<TMPro.TMP_InputField>());
+#endif // TMP_WEBGL_SUPPORT
+
+            throw new Exception("Can not Setup WebGLInput!!");
+        }
+
+        private void Awake()
+        {
+            input = Setup();
+#if !(UNITY_WEBGL && !UNITY_EDITOR)
+            // WebGL 以外、更新メソッドは動作しないようにします
+            enabled = false;
+#endif
+            // for mobile platform
+            if (Application.isMobilePlatform)
+            {
+                if (input.EnableMobileSupport)
+                {
+                    gameObject.AddComponent<WebGLInputMobile>();
+                }
+                else
+                {
+                    // when disable mobile input. disable self!
+                    enabled = false;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Get the element rect of input
+        /// </summary>
+        /// <returns></returns>
+        RectInt GetElemetRect()
+        {
+            var rect = input.GetScreenCoordinates();
+            // モバイルの場合、強制表示する
+            if (showHtmlElement || Application.isMobilePlatform)
+            {
+                var x = (int)(rect.x);
+                var y = (int)(Screen.height - (rect.y + rect.height));
+                return new RectInt(x, y, (int)rect.width, (int)rect.height);
+            }
+            else
+            {
+                var x = (int)(rect.x);
+                var y = (int)(Screen.height - (rect.y));
+                return new RectInt(x, y, (int)rect.width, (int)1);
+            }
+        }
+        /// <summary>
+        /// 対象が選択されたとき
+        /// </summary>
+        /// <param name="eventData"></param>
+        public void OnSelect()
+        {
+            if (id != -1) throw new Exception("OnSelect : id != -1");
+
+            var rect = GetElemetRect();
+            bool isPassword = input.contentType == ContentType.Password;
+
+            var fontSize = Mathf.Max(14, input.fontSize); // limit font size : 14 !!
+
+            // モバイルの場合、強制表示する
+            var isHidden = !(showHtmlElement || Application.isMobilePlatform);
+            id = WebGLInputPlugin.WebGLInputCreate(WebGLInput.CanvasId, rect.x, rect.y, rect.width, rect.height, fontSize, input.text, input.placeholder, input.lineType != LineType.SingleLine, isPassword, isHidden, Application.isMobilePlatform);
+
+            instances[id] = this;
+            WebGLInputPlugin.WebGLInputEnterSubmit(id, input.lineType != LineType.MultiLineNewline);
+            WebGLInputPlugin.WebGLInputOnFocus(id, OnFocus);
+            WebGLInputPlugin.WebGLInputOnBlur(id, OnBlur);
+            WebGLInputPlugin.WebGLInputOnValueChange(id, OnValueChange);
+            WebGLInputPlugin.WebGLInputOnEditEnd(id, OnEditEnd);
+            WebGLInputPlugin.WebGLInputOnKeyboardEvent(id, OnKeyboardEvent);
+            WebGLInputPlugin.WebGLInputTab(id, OnTab);
+
+            // default value : https://www.w3schools.com/tags/att_input_maxlength.asp
+            WebGLInputPlugin.WebGLInputMaxLength(id, (input.characterLimit > 0) ? input.characterLimit : 524288);
+            WebGLInputPlugin.WebGLInputFocus(id);
+#if WEBGLINPUT_TAB
+            WebGLInputPlugin.WebGLInputEnableTabText(id, enableTabText);
+#endif
+            if (input.OnFocusSelectAll)
+            {
+                WebGLInputPlugin.WebGLInputSetSelectionRange(id, 0, input.text.Length);
+            }
+            else
+            {
+                WebGLInputPlugin.WebGLInputSetSelectionRange(id, input.caretPosition, input.caretPosition);
+            }
+
+            WebGLWindow.OnBlurEvent += OnWindowBlur;
+        }
+
+        /// <summary>
+        /// sync text from inputfield
+        /// </summary>
+        /// <param name="cursorIndex"></param>
+        public void SyncText(int? cursorIndex = null)
+        {
+            if (!instances.ContainsKey(id)) return;
+
+            var instance = instances[id];
+
+            WebGLInputPlugin.WebGLInputText(id, instance.input.text);
+
+            if (cursorIndex.HasValue)
+            {
+                WebGLInputPlugin.WebGLInputSetSelectionRange(id, cursorIndex.Value, cursorIndex.Value);
+            }
+        }
+
+        private void OnWindowBlur()
+        {
+            blurBlock = true;
+        }
+
+        internal void DeactivateInputField()
+        {
+            if (!instances.ContainsKey(id)) return;
+
+            WebGLInputPlugin.WebGLInputDelete(id);
+            input.DeactivateInputField();
+            instances.Remove(id);
+            id = -1;    // reset id to -1;
+            WebGLWindow.OnBlurEvent -= OnWindowBlur;
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int>))]
+        static void OnFocus(int id)
+        {
+#if UNITY_WEBGL && !UNITY_EDITOR
+            Input.ResetInputAxes(); // Inputの状態リセット
+            UnityEngine.WebGLInput.captureAllKeyboardInput = false;
+#endif
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int>))]
+        static void OnBlur(int id)
+        {
+#if UNITY_WEBGL && !UNITY_EDITOR
+            UnityEngine.WebGLInput.captureAllKeyboardInput = true;
+            Input.ResetInputAxes(); // Inputの状態リセット
+#endif
+            instances[id].StartCoroutine(Blur(id));
+        }
+
+        static IEnumerator Blur(int id)
+        {
+            yield return null;
+            if (!instances.ContainsKey(id)) yield break;
+
+            var block = instances[id].blurBlock;    // get blur block state
+            instances[id].blurBlock = false;        // reset instalce block state
+            if (block) yield break;                 // if block. break it!!
+            instances[id].DeactivateInputField();
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int, string>))]
+        static void OnValueChange(int id, string value)
+        {
+            if (!instances.ContainsKey(id)) return;
+
+            var instance = instances[id];
+            if (!instance.input.ReadOnly)
+            {
+                instance.input.text = value;
+            }
+
+            // InputField.ContentType.Name が Name の場合、先頭文字が強制的大文字になるため小文字にして比べる
+            if (instance.input.contentType == ContentType.Name)
+            {
+                if (string.Compare(instance.input.text, value, true) == 0)
+                {
+                    value = instance.input.text;
+                }
+            }
+
+            // InputField の ContentType による整形したテキストを HTML の input に再設定します
+            if (value != instance.input.text)
+            {
+                var start = WebGLInputPlugin.WebGLInputSelectionStart(id);
+                var end = WebGLInputPlugin.WebGLInputSelectionEnd(id);
+                // take the offset.when char remove from input.
+                var offset = instance.input.text.Length - value.Length;
+
+                WebGLInputPlugin.WebGLInputText(id, instance.input.text);
+                // reset the input element selection range!!
+                WebGLInputPlugin.WebGLInputSetSelectionRange(id, start + offset, end + offset);
+            }
+        }
+        [MonoPInvokeCallback(typeof(Action<int, string>))]
+        static void OnEditEnd(int id, string value)
+        {
+            if (!instances[id].input.ReadOnly)
+            {
+                instances[id].input.text = value;
+            }
+        }
+        [MonoPInvokeCallback(typeof(Action<int, int>))]
+        static void OnTab(int id, int value)
+        {
+            WebGLInputTabFocus.OnTab(instances[id], value);
+        }
+
+        [MonoPInvokeCallback(typeof(Action<int, int, string, int, int, int, int>))]
+        static void OnKeyboardEvent(int id, int mode, string key, int code, int shiftKey, int ctrlKey, int altKey)
+        {
+            if (!instances.ContainsKey(id)) return;
+            var instance = instances[id];
+
+            // mode : keydown(1) keyup(3)
+            var cb = mode switch
+            {
+                1 => OnKeyboardDown,
+                2 => OnKeyboardUp,
+                _ => default
+            };
+
+            if (cb != null)
+            {
+                cb(instance, new KeyboardEvent(key, code, shiftKey != 0, ctrlKey != 0, altKey != 0));
+            }
+        }
+
+        void Update()
+        {
+            if (input == null || !input.isFocused)
+            {
+                CheckOutFocus();
+                return;
+            }
+
+            // 未登録の場合、選択する
+            if (!instances.ContainsKey(id))
+            {
+                if (Application.isMobilePlatform)
+                {
+                    return;
+                }
+                else
+                {
+                    OnSelect();
+                }
+            }
+            else if (!WebGLInputPlugin.WebGLInputIsFocus(id))
+            {
+                if (Application.isMobilePlatform)
+                {
+                    //input.DeactivateInputField();
+                    return;
+                }
+                else
+                {
+                    // focus this id
+                    WebGLInputPlugin.WebGLInputFocus(id);
+                }
+            }
+
+            var start = WebGLInputPlugin.WebGLInputSelectionStart(id);
+            var end = WebGLInputPlugin.WebGLInputSelectionEnd(id);
+            // 選択方向によって設定します
+            if (WebGLInputPlugin.WebGLInputSelectionDirection(id) == -1)
+            {
+                input.selectionFocusPosition = start;
+                input.selectionAnchorPosition = end;
+            }
+            else
+            {
+                input.selectionFocusPosition = end;
+                input.selectionAnchorPosition = start;
+            }
+
+            input.Rebuild();
+        }
+
+        private void OnDestroy()
+        {
+            if (!instances.ContainsKey(id)) return;
+
+#if UNITY_WEBGL && !UNITY_EDITOR
+            UnityEngine.WebGLInput.captureAllKeyboardInput = true;
+            Input.ResetInputAxes(); // Inputの状態リセット
+#endif
+            DeactivateInputField();
+        }
+
+        private void OnEnable()
+        {
+            WebGLInputTabFocus.Add(this);
+        }
+        private void OnDisable()
+        {
+            WebGLInputTabFocus.Remove(this);
+        }
+        public int CompareTo(WebGLInput other)
+        {
+            var a = input.GetScreenCoordinates();
+            var b = other.input.GetScreenCoordinates();
+            var res = b.y.CompareTo(a.y);
+            if (res == 0) res = a.x.CompareTo(b.x);
+            return res;
+        }
+
+        private void CheckOutFocus()
+        {
+            if (!Application.isMobilePlatform) return;
+            if (!instances.ContainsKey(id)) return;
+            var current = EventSystem.current.currentSelectedGameObject;
+            if (current != null) return;
+            WebGLInputPlugin.WebGLInputForceBlur(id);   // Input ではないし、キーボードを閉じる
+        }
+
+        /// <summary>
+        /// to manage tab focus
+        /// base on scene position
+        /// </summary>
+        static class WebGLInputTabFocus
+        {
+            static List<WebGLInput> inputs = new List<WebGLInput>();
+
+            public static void Add(WebGLInput input)
+            {
+                inputs.Add(input);
+                inputs.Sort();
+            }
+
+            public static void Remove(WebGLInput input)
+            {
+                inputs.Remove(input);
+            }
+
+            public static void OnTab(WebGLInput input, int value)
+            {
+                if (inputs.Count <= 1) return;
+                var index = inputs.IndexOf(input);
+                index += value;
+                if (index < 0) index = inputs.Count - 1;
+                else if (index >= inputs.Count) index = 0;
+                inputs[index].input.ActivateInputField();
+            }
+        }
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLInput/WebGLInput.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cc33a39070010f94fb1c2dd721c1286d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 216 - 0
Assets/WebGLSupport/WebGLInput/WebGLInput.jslib

@@ -0,0 +1,216 @@
+var WebGLInput = {
+    $instances: [],
+    WebGLInputInit : function() {
+        // use WebAssembly.Table : makeDynCall
+        // when enable. dynCall is undefined
+        if(typeof dynCall === "undefined")
+        {
+            // make Runtime.dynCall to undefined
+            Runtime = { dynCall : undefined }
+        }
+        else
+        {
+            // Remove the `Runtime` object from "v1.37.27: 12/24/2017"
+            // if Runtime not defined. create and add functon!!
+            if(typeof Runtime === "undefined") Runtime = { dynCall : dynCall }
+        }
+    },
+    WebGLInputCreate: function (canvasId, x, y, width, height, fontsize, text, placeholder, isMultiLine, isPassword, isHidden, isMobile) {
+
+        var container = document.getElementById(UTF8ToString(canvasId));
+        var canvas = container.getElementsByTagName('canvas')[0];
+
+        // if container is null and have canvas
+        if (!container && canvas)
+        {
+            // set the container to canvas.parentNode
+            container = canvas.parentNode;
+        }
+
+        if(canvas)
+        {
+            var scaleX = container.offsetWidth / canvas.width;
+            var scaleY = container.offsetHeight / canvas.height;
+
+            if(scaleX && scaleY)
+            {
+                x *= scaleX;
+                width *= scaleX;
+                y *= scaleY;
+                height *= scaleY;
+            }
+        }
+
+        var input = document.createElement(isMultiLine?"textarea":"input");
+        input.style.position = "absolute";
+
+        if(isMobile) {
+            input.style.bottom = 1 + "vh";
+            input.style.left = 5 + "vw";
+            input.style.width = 90 + "vw";
+            input.style.height = (isMultiLine? 18 : 10) + "vh";
+            input.style.fontSize = 5 + "vh";
+            input.style.borderWidth = 5 + "px";
+            input.style.borderColor = "#000000";
+        } else {
+            input.style.top = y + "px";
+            input.style.left = x + "px";
+            input.style.width = width + "px";
+            input.style.height = height + "px";
+            input.style.fontSize = fontsize + "px";
+        }
+
+        input.style.outlineWidth = 1 + 'px';
+        input.style.opacity = isHidden?0:1;
+        input.style.resize = 'none'; // for textarea
+        input.style.padding = '0px 1px';
+        input.style.cursor = "default";
+        input.style.touchAction = 'none';
+
+        input.spellcheck = false;
+        input.value = UTF8ToString(text);
+        input.placeholder = UTF8ToString(placeholder);
+        input.style.outlineColor = 'black';
+        
+        if(isPassword){
+            input.type = 'password';
+        }
+
+        if(isMobile) {
+            document.body.appendChild(input);
+        } else {
+            container.appendChild(input);
+        }
+        return instances.push(input) - 1;
+    },
+    WebGLInputEnterSubmit: function(id, falg){
+        var input = instances[id];
+        // for enter key
+        input.addEventListener('keydown', function(e) {
+            if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
+                if(falg)
+                {
+                    e.preventDefault();
+                    input.blur();
+                }
+            }
+        });
+    },
+    WebGLInputTab:function(id, cb) {
+        var input = instances[id];
+        // for tab key
+        input.addEventListener('keydown', function (e) {
+            if ((e.which && e.which === 9) || (e.keyCode && e.keyCode === 9)) {
+                e.preventDefault();
+
+                // if enable tab text
+                if(input.enableTabText){
+                    var val = input.value;
+                    var start = input.selectionStart;
+                    var end = input.selectionEnd;
+                    input.value = val.substr(0, start) + '\t' + val.substr(end, val.length);
+                    input.setSelectionRange(start + 1, start + 1);
+                    input.oninput();	// call oninput to exe ValueChange function!!
+                } else {
+                    (!!Runtime.dynCall) ? Runtime.dynCall("vii", cb, [id, e.shiftKey ? -1 : 1]) : {{{ makeDynCall("vii", "cb") }}}(id, e.shiftKey ? -1 : 1);
+                }
+            }
+        });
+    },
+    WebGLInputFocus: function(id){
+        var input = instances[id];
+        input.focus();
+    },
+    WebGLInputOnFocus: function (id, cb) {
+        var input = instances[id];
+        input.onfocus = function () {
+            (!!Runtime.dynCall) ? Runtime.dynCall("vi", cb, [id]) : {{{ makeDynCall("vi", "cb") }}}(id);
+        };
+    },
+    WebGLInputOnBlur: function (id, cb) {
+        var input = instances[id];
+        input.onblur = function () {
+            (!!Runtime.dynCall) ? Runtime.dynCall("vi", cb, [id]) : {{{ makeDynCall("vi", "cb") }}}(id);
+        };
+    },
+    WebGLInputIsFocus: function (id) {
+        return instances[id] === document.activeElement;
+    },
+    WebGLInputOnValueChange:function(id, cb){
+        var input = instances[id];
+        input.oninput = function () {
+            var returnStr = input.value;
+            var bufferSize = lengthBytesUTF8(returnStr) + 1;
+            var buffer = _malloc(bufferSize);
+            stringToUTF8(returnStr, buffer, bufferSize);
+            (!!Runtime.dynCall) ? Runtime.dynCall("vii", cb, [id, buffer]) : {{{ makeDynCall("vii", "cb") }}}(id, buffer);
+        };
+    },
+    WebGLInputOnEditEnd:function(id, cb){
+        var input = instances[id];
+        input.onchange = function () {
+            var returnStr = input.value;
+            var bufferSize = lengthBytesUTF8(returnStr) + 1;
+            var buffer = _malloc(bufferSize);
+            stringToUTF8(returnStr, buffer, bufferSize);
+            (!!Runtime.dynCall) ? Runtime.dynCall("vii", cb, [id, buffer]) : {{{ makeDynCall("vii", "cb") }}}(id, buffer);
+        };
+    },
+    WebGLInputOnKeyboardEvent:function(id, cb){
+        var input = instances[id];
+        var func = function(mode, e) {
+            if (e instanceof KeyboardEvent){
+                var bufferSize = lengthBytesUTF8(e.key) + 1;
+                var key = _malloc(bufferSize);
+                stringToUTF8(e.key, key, bufferSize);
+                var code = e.code;
+                var shift = e.shiftKey ? 1 : 0;
+                var ctrl = e.ctrlKey ? 1 : 0;
+                var alt = e.altKey ? 1 : 0;
+                (!!Runtime.dynCall) ? Runtime.dynCall("viiiiiii", cb, [id, mode, key, code, shift, ctrl, alt]) : {{{ makeDynCall("viiiiiii", "cb") }}}(id, mode, key, code, shift, ctrl, alt);
+            }
+        }
+        input.addEventListener('keydown', function(e) { func(1, e); });
+        input.addEventListener('keyup', function(e) { func(2, e); });
+    },
+    WebGLInputSelectionStart:function(id){
+        var input = instances[id];
+        return input.selectionStart;
+    },
+    WebGLInputSelectionEnd:function(id){
+        var input = instances[id];
+        return input.selectionEnd;
+    },
+    WebGLInputSelectionDirection:function(id){
+        var input = instances[id];
+        return (input.selectionDirection == "backward")?-1:1;
+    },
+    WebGLInputSetSelectionRange:function(id, start, end){
+        var input = instances[id];
+        input.setSelectionRange(start, end);
+    },
+    WebGLInputMaxLength:function(id, maxlength){
+        var input = instances[id];
+        input.maxLength = maxlength;
+    },
+    WebGLInputText:function(id, text){
+        var input = instances[id];
+        input.value = UTF8ToString(text);
+    },
+    WebGLInputDelete:function(id){
+        var input = instances[id];
+        input.parentNode.removeChild(input);
+        instances[id] = null;
+    },
+    WebGLInputEnableTabText:function(id, enable) {
+        var input = instances[id];
+        input.enableTabText = enable;
+    },
+    WebGLInputForceBlur:function(id) {
+        var input = instances[id];
+        input.blur();
+    },
+}
+
+autoAddDeps(WebGLInput, '$instances');
+mergeInto(LibraryManager.library, WebGLInput);

+ 34 - 0
Assets/WebGLSupport/WebGLInput/WebGLInput.jslib.meta

@@ -0,0 +1,34 @@
+fileFormatVersion: 2
+guid: 7df541bf7b903fb45b24fab892876393
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  isPreloaded: 0
+  isOverridable: 0
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  - first:
+      Facebook: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      WebGL: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/WebGLSupport/WebGLInput/Wrapper.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dfaa1fbdc36ec0d45b321b02a2089b55
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 46 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/IInputField.cs

@@ -0,0 +1,46 @@
+using UnityEngine;
+
+namespace WebGLSupport
+{
+    public enum ContentType
+    {
+        Standard = 0,
+        Autocorrected = 1,
+        IntegerNumber = 2,
+        DecimalNumber = 3,
+        Alphanumeric = 4,
+        Name = 5,
+        EmailAddress = 6,
+        Password = 7,
+        Pin = 8,
+        Custom = 9
+    }
+    public enum LineType
+    {
+        SingleLine = 0,
+        MultiLineSubmit = 1,
+        MultiLineNewline = 2
+    }
+    public interface IInputField
+    {
+        ContentType contentType { get; }
+        LineType lineType { get; }
+        int fontSize { get; }
+        string text { get; set; }
+        string placeholder { get; }
+        int characterLimit { get; }
+        int caretPosition { get; }
+        bool isFocused { get; }
+        int selectionFocusPosition { get; set; }
+        int selectionAnchorPosition { get; set; }
+        bool ReadOnly { get; }
+        bool OnFocusSelectAll { get; }
+        bool EnableMobileSupport { get; }
+
+        Rect GetScreenCoordinates();
+
+        void ActivateInputField();
+        void DeactivateInputField();
+        void Rebuild();
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/IInputField.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8be52c4f26f76e04fbae3cb86e539bdb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 119 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedInputField.cs

@@ -0,0 +1,119 @@
+using UnityEngine;
+using UnityEngine.UI;
+using WebGLSupport.Detail;
+
+namespace WebGLSupport
+{
+    /// <summary>
+    /// Wrapper for UnityEngine.UI.InputField
+    /// </summary>
+    class WrappedInputField : IInputField
+    {
+        InputField input;
+        RebuildChecker checker;
+
+        public bool ReadOnly { get { return input.readOnly; } }
+
+        public string text
+        {
+            get { return input.text; }
+            set { input.text = value; }
+        }
+
+        public string placeholder
+        {
+            get
+            {
+                if (!input.placeholder) return "";
+                var text = input.placeholder.GetComponent<Text>();
+                return text ? text.text : "";
+            }
+        }
+
+        public int fontSize
+        {
+            get { return input.textComponent.fontSize; }
+        }
+
+        public ContentType contentType
+        {
+            get { return (ContentType)input.contentType; }
+        }
+
+        public LineType lineType
+        {
+            get { return (LineType)input.lineType; }
+        }
+
+        public int characterLimit
+        {
+            get { return input.characterLimit; }
+        }
+
+        public int caretPosition
+        {
+            get { return input.caretPosition; }
+        }
+
+        public bool isFocused
+        {
+            get { return input.isFocused; }
+        }
+
+        public int selectionFocusPosition
+        {
+            get { return input.selectionFocusPosition; }
+            set { input.selectionFocusPosition = value; }
+        }
+
+        public int selectionAnchorPosition
+        {
+            get { return input.selectionAnchorPosition; }
+            set { input.selectionAnchorPosition = value; }
+        }
+
+        public bool OnFocusSelectAll
+        {
+            get { return true; }
+        }
+
+        public bool EnableMobileSupport
+        {
+            get
+            {
+                // return false to use unity mobile keyboard support
+                return false;
+            }
+        }
+
+        public WrappedInputField(InputField input)
+        {
+            this.input = input;
+            checker = new RebuildChecker(this);
+        }
+
+        public void ActivateInputField()
+        {
+            input.ActivateInputField();
+        }
+
+        public void DeactivateInputField()
+        {
+            input.DeactivateInputField();
+        }
+
+        public void Rebuild()
+        {
+            if (checker.NeedRebuild())
+            {
+                input.textComponent.SetAllDirty();
+                input.Rebuild(CanvasUpdate.LatePreRender);
+            }
+        }
+
+        public Rect GetScreenCoordinates()
+        {
+            return Support.GetScreenCoordinates(input.GetComponent<RectTransform>());
+        }
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedInputField.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0c8464791034e144ca224c37c1816e37
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 212 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedTMPInputField.cs

@@ -0,0 +1,212 @@
+#if UNITY_2018_2_OR_NEWER
+#define TMP_WEBGL_SUPPORT
+#endif
+
+#if TMP_WEBGL_SUPPORT
+using UnityEngine;
+using TMPro;
+using WebGLSupport.Detail;
+using UnityEngine.UI;
+using System;
+
+namespace WebGLSupport
+{
+    /// <summary>
+    /// Wrapper for TMPro.TMP_InputField
+    /// </summary>
+    class WrappedTMPInputField : IInputField
+    {
+        TMP_InputField input;
+        RebuildChecker checker;
+        Coroutine delayedGraphicRebuild;
+
+        public bool ReadOnly { get { return input.readOnly; } }
+
+        public string text
+        {
+            get { return input.text; }
+            set { input.text = FixContentTypeByInputField(value); }
+        }
+
+        /// <summary>
+        /// workaround!!
+        /// when use TMP_InputField.text = "xxx"; is will set the text directly.
+        /// so, use InputField for match the ContentType!
+        /// </summary>
+        /// <param name="inText"></param>
+        /// <returns></returns>
+        private string FixContentTypeByInputField(string inText)
+        {
+            var go = new GameObject("FixContentTypeByInputField for WebGLInput");
+            go.SetActive(false);
+            var i = go.AddComponent<InputField>();
+            i.contentType = (InputField.ContentType)Enum.Parse(typeof(InputField.ContentType), input.contentType.ToString());
+            i.lineType = (InputField.LineType)Enum.Parse(typeof(InputField.LineType), input.lineType.ToString());
+            i.inputType = (InputField.InputType)Enum.Parse(typeof(InputField.InputType), input.inputType.ToString());
+            i.keyboardType = input.keyboardType;
+            i.characterValidation = (InputField.CharacterValidation)Enum.Parse(typeof(InputField.CharacterValidation), input.characterValidation.ToString());
+            i.characterLimit = input.characterLimit;
+            i.text = inText;
+            var res = i.text;
+            GameObject.Destroy(go);
+            return res;
+        }
+
+        public string placeholder
+        {
+            get
+            {
+                if (!input.placeholder) return "";
+                var text = input.placeholder.GetComponent<TMP_Text>();
+                return text ? text.text : "";
+            }
+        }
+
+        public int fontSize
+        {
+            get { return (int)input.textComponent.fontSize; }
+        }
+
+        public ContentType contentType
+        {
+            get { return (ContentType)input.contentType; }
+        }
+
+        public LineType lineType
+        {
+            get { return (LineType)input.lineType; }
+        }
+
+        public int characterLimit
+        {
+            get { return input.characterLimit; }
+        }
+
+        public int caretPosition
+        {
+            get { return input.caretPosition; }
+        }
+
+        public bool isFocused
+        {
+            get { return input.isFocused; }
+        }
+
+        public int selectionFocusPosition
+        {
+            get { return input.selectionStringFocusPosition; }
+            set { input.selectionStringFocusPosition = value; }
+        }
+
+        public int selectionAnchorPosition
+        {
+            get { return input.selectionStringAnchorPosition; }
+            set { input.selectionStringAnchorPosition = value; }
+        }
+
+        public bool OnFocusSelectAll
+        {
+            get { return input.onFocusSelectAll; }
+        }
+
+        public bool EnableMobileSupport
+        {
+            get
+            {
+                // [2023.2] Latest Development on TextMesh Pro
+                // https://forum.unity.com/threads/2023-2-latest-development-on-textmesh-pro.1434757/
+                // As of 2023.2, the TextMesh Pro package (com.unity.textmeshpro) has been merged into the uGUI package (com.unity.ugui) and the TextMesh Pro package has been deprecated.
+                // In this version, TextMeshPro is default support mobile input. so disable WebGLInput mobile support
+#if UNITY_2023_2_OR_NEWER
+                // return false to use unity mobile keyboard support
+                return false;
+#else
+                return true;
+#endif
+            }
+        }
+
+        public WrappedTMPInputField(TMP_InputField input)
+        {
+            this.input = input;
+            checker = new RebuildChecker(this);
+        }
+
+        public Rect GetScreenCoordinates()
+        {
+            // 表示範囲
+            // MEMO :
+            //  TMP では textComponent を移動させてクリッピングするため、
+            //  表示範囲外になる場合があるので、自分の範囲を返す
+            return Support.GetScreenCoordinates(input.GetComponent<RectTransform>());
+        }
+
+
+
+        public void ActivateInputField()
+        {
+            input.ActivateInputField();
+        }
+
+        public void DeactivateInputField()
+        {
+            input.DeactivateInputField();
+        }
+
+        public void Rebuild()
+        {
+#if UNITY_2020_1_OR_NEWER
+            if (checker.NeedRebuild())
+            {
+                input.textComponent.SetVerticesDirty();
+                input.textComponent.SetLayoutDirty();
+                input.Rebuild(CanvasUpdate.LatePreRender);
+            }
+#else
+            if (input.textComponent.enabled && checker.NeedRebuild())
+            {
+                //================================
+                // fix bug for tmp
+                // TMPの不具合で、正しく座標を設定されてなかったため、試しに対応する
+                var rt = input.textComponent.GetComponent<RectTransform>();
+                var size = input.textComponent.GetPreferredValues();
+                if (size.x < rt.rect.xMax)
+                {
+                    // textComponent の座標を更新
+                    var pos = rt.anchoredPosition;
+                    pos.x = 0;
+                    rt.anchoredPosition = pos;
+
+                    // caret の座標更新
+                    var caret = input.GetComponentInChildren<TMP_SelectionCaret>();
+                    var caretRect = caret.GetComponent<RectTransform>();
+                    caretRect.anchoredPosition = rt.anchoredPosition;
+                }
+                //==============================
+
+                // HACK : 1フレーム無効にする
+                // MEMO : 他にいい方法Rebuildがあれば対応する
+                // LayoutRebuilder.ForceRebuildLayoutImmediate(); で試してダメでした
+                input.textComponent.enabled = rectOverlaps(input.textComponent.rectTransform, input.textViewport);
+                input.textComponent.SetAllDirty();
+                input.Rebuild(CanvasUpdate.LatePreRender);
+                //Debug.Log(input.textComponent.enabled);
+            }
+            else
+            {
+                input.textComponent.enabled = true;
+            }
+#endif
+        }
+
+        bool rectOverlaps(RectTransform rectTrans1, RectTransform rectTrans2)
+        {
+            Rect rect1 = new Rect(rectTrans1.localPosition.x, rectTrans1.localPosition.y, rectTrans1.rect.width, rectTrans1.rect.height);
+            Rect rect2 = new Rect(rectTrans2.localPosition.x, rectTrans2.localPosition.y, rectTrans2.rect.width, rectTrans2.rect.height);
+
+            return rect1.Overlaps(rect2);
+        }
+    }
+}
+
+#endif // TMP_WEBGL_SUPPORT

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedTMPInputField.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e1629c3a135d89a45aca880fa8052f5d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 162 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedUIToolkit.cs

@@ -0,0 +1,162 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace WebGLSupport
+{
+    /// <summary>
+    /// Wrapper for UnityEngine.UIElements.TextField
+    /// </summary>
+    class WrappedUIToolkit : IInputField
+    {
+        TextField input;
+
+        public bool ReadOnly { get { return input.isReadOnly; } }
+
+        public string text
+        {
+            get { return input.value; }
+            set { input.value = value; }
+        }
+
+        public string placeholder
+        {
+            get
+            {
+#if UNITY_2023_1_OR_NEWER
+                return input.textEdition.placeholder;
+#else
+                return "";
+#endif
+            }
+        }
+
+        public int fontSize
+        {
+            /// MEMO : how to get the fontsize?
+            get { return 20; }
+        }
+
+        public ContentType contentType
+        {
+            get
+            {
+                if (input.isPasswordField)
+                {
+                    return ContentType.Password;
+                }
+
+#if UNITY_2022_1_OR_NEWER
+                var keyboardType = input.keyboardType;
+#else
+                var keyboardType = TouchScreenKeyboardType.Default;
+#endif
+                return keyboardType switch
+                {
+                    TouchScreenKeyboardType.Default => ContentType.Standard,
+                    TouchScreenKeyboardType.ASCIICapable => ContentType.Alphanumeric,
+                    TouchScreenKeyboardType.NumbersAndPunctuation => ContentType.Standard,
+                    TouchScreenKeyboardType.URL => ContentType.Standard,
+                    TouchScreenKeyboardType.NumberPad => ContentType.IntegerNumber,
+                    TouchScreenKeyboardType.PhonePad => ContentType.Standard,
+                    TouchScreenKeyboardType.NamePhonePad => ContentType.Standard,
+                    TouchScreenKeyboardType.EmailAddress => ContentType.EmailAddress,
+                    //TouchScreenKeyboardType.NintendoNetworkAccount => throw new System.NotImplementedException(),
+                    TouchScreenKeyboardType.Social => ContentType.Standard,
+                    TouchScreenKeyboardType.Search => ContentType.Standard,
+                    TouchScreenKeyboardType.DecimalPad => ContentType.DecimalNumber,
+                    TouchScreenKeyboardType.OneTimeCode => ContentType.Standard,
+                    _ => ContentType.Standard,
+                };
+            }
+        }
+
+        public LineType lineType
+        {
+            get
+            {
+                return input.multiline ? LineType.MultiLineNewline : LineType.SingleLine;
+            }
+        }
+
+        public int characterLimit
+        {
+            get { return input.maxLength; }
+        }
+
+        public int caretPosition
+        {
+            get { return input.cursorIndex; }
+        }
+
+        public bool isFocused
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        public int selectionFocusPosition
+        {
+            get { return input.cursorIndex; }
+#if UNITY_2022_1_OR_NEWER
+            set { input.cursorIndex = value; }
+#else
+            set { input.SelectRange(value, input.selectIndex); }
+#endif
+        }
+
+        public int selectionAnchorPosition
+        {
+            get { return input.selectIndex; }
+#if UNITY_2022_1_OR_NEWER
+            set { input.selectIndex = value; }
+#else
+            set { input.SelectRange(input.cursorIndex, value); }
+#endif
+        }
+
+        public bool OnFocusSelectAll
+        {
+#if UNITY_2022_1_OR_NEWER
+            get { return input.selectAllOnFocus || input.selectAllOnMouseUp; }
+#else
+            get { return true; }
+#endif
+        }
+
+        public bool EnableMobileSupport
+        {
+            get
+            {
+                // return false to use unity mobile keyboard support
+                return false;
+            }
+        }
+
+        public WrappedUIToolkit(WebGLUIToolkitTextField input)
+        {
+            this.input = input.TextField;
+        }
+
+        public Rect GetScreenCoordinates()
+        {
+            var textInput = input.Q("unity-text-input");
+            var rect = textInput.worldBound;
+            return new Rect(rect.x, Screen.height - (rect.y + rect.height), rect.width, rect.height);
+        }
+
+        public void ActivateInputField()
+        {
+        }
+
+        public void DeactivateInputField()
+        {
+            input.Blur();
+        }
+
+        public void Rebuild()
+        {
+        }
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLInput/Wrapper/WrappedUIToolkit.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a84ff74590e7172468127b13d7c934da
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/WebGLSupport/WebGLWindow.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ef582d6b11c3602438e4a301923e45dc
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 138 - 0
Assets/WebGLSupport/WebGLWindow/WebGLWindow.cs

@@ -0,0 +1,138 @@
+using System;
+using AOT;
+using System.Runtime.InteropServices; // for DllImport
+using UnityEngine;
+
+namespace WebGLSupport
+{
+    static class WebGLWindowPlugin
+    {
+#if UNITY_WEBGL && !UNITY_EDITOR
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowInit();
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowUninit();
+
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowOnFocus(Action cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowOnBlur(Action cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowOnResize(Action cb);
+
+        [DllImport("__Internal")]
+        public static extern void WebGLWindowInjectFullscreen();
+
+        [DllImport("__Internal")]
+        public static extern string WebGLWindowGetCanvasName();
+
+        [DllImport("__Internal")]
+        public static extern void MakeFullscreen(string str);
+
+        [DllImport("__Internal")]
+        public static extern void ExitFullscreen();
+
+        [DllImport("__Internal")]
+        public static extern bool IsFullscreen();
+#else
+        public static void WebGLWindowInit() { }
+        public static void WebGLWindowUninit() { }
+        public static void WebGLWindowOnFocus(Action cb) { }
+        public static void WebGLWindowOnBlur(Action cb) { }
+        public static void WebGLWindowOnResize(Action cb) { }
+        public static void WebGLWindowInjectFullscreen() { }
+        public static string WebGLWindowGetCanvasName() { return ""; }
+        public static void MakeFullscreen(string str) { }
+        public static void ExitFullscreen() { }
+        public static bool IsFullscreen() { return false; }
+#endif
+
+    }
+
+    public static class WebGLWindow
+    {
+        static WebGLWindow()
+        {
+            WebGLWindowPlugin.WebGLWindowInit();
+        }
+        public static bool Focus { get; private set; }
+        public static event Action OnFocusEvent = () => { };
+        public static event Action OnBlurEvent = () => { };
+        public static event Action OnResizeEvent = () => { };
+
+        static string ViewportContent;
+        static void Init()
+        {
+            Focus = true;
+            WebGLWindowPlugin.WebGLWindowOnFocus(OnWindowFocus);
+            WebGLWindowPlugin.WebGLWindowOnBlur(OnWindowBlur);
+            WebGLWindowPlugin.WebGLWindowOnResize(OnWindowResize);
+            WebGLWindowPlugin.WebGLWindowInjectFullscreen();
+
+            Application.quitting += Uninit;
+        }
+        static void Uninit()
+        {
+            WebGLWindowPlugin.WebGLWindowUninit();
+            Application.quitting -= Uninit;
+        }
+
+        [MonoPInvokeCallback(typeof(Action))]
+        static void OnWindowFocus()
+        {
+            Focus = true;
+            OnFocusEvent();
+        }
+
+        [MonoPInvokeCallback(typeof(Action))]
+        static void OnWindowBlur()
+        {
+            Focus = false;
+            OnBlurEvent();
+        }
+
+        [MonoPInvokeCallback(typeof(Action))]
+        static void OnWindowResize()
+        {
+            OnResizeEvent();
+        }
+
+        [RuntimeInitializeOnLoadMethod]
+        static void RuntimeInitializeOnLoadMethod()
+        {
+            Init();
+        }
+
+        public static string GetCanvasName()
+        {
+            return WebGLWindowPlugin.WebGLWindowGetCanvasName();
+        }
+
+        public static void MakeFullscreen(string fullscreenElementName = null)
+        {
+            WebGLWindowPlugin.MakeFullscreen(fullscreenElementName ?? GetCanvasName());
+        }
+
+        public static void ExitFullscreen()
+        {
+            WebGLWindowPlugin.ExitFullscreen();
+        }
+        public static bool IsFullscreen()
+        {
+            return WebGLWindowPlugin.IsFullscreen();
+        }
+        public static void SwitchFullscreen()
+        {
+            if (IsFullscreen())
+            {
+                ExitFullscreen();
+            }
+            else
+            {
+                MakeFullscreen();
+            }
+        }
+    }
+}

+ 11 - 0
Assets/WebGLSupport/WebGLWindow/WebGLWindow.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5fcbb4f34ed8e894896251ff74a4633d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 204 - 0
Assets/WebGLSupport/WebGLWindow/WebGLWindow.jslib

@@ -0,0 +1,204 @@
+var WebGLWindow = {
+    focusListener: null,
+    blurListener: null,
+    resizeListener: null,
+    
+    WebGLWindowInit : function() {
+        // use WebAssembly.Table : makeDynCall
+        // when enable. dynCall is undefined
+        if(typeof dynCall === "undefined")
+        {
+            // make Runtime.dynCall to undefined
+            Runtime = { dynCall : undefined }
+        }
+        else
+        {
+            // Remove the `Runtime` object from "v1.37.27: 12/24/2017"
+            // if Runtime not defined. create and add functon!!
+            if(typeof Runtime === "undefined") Runtime = { dynCall : dynCall }
+        }
+    },
+    WebGLWindowUninit : function() {
+        if(focusListener) {
+            window.removeEventListener('focus', this.focusListener);
+            this.focusListener = null;
+        }
+        if(blurListener) {
+            window.removeEventListener('blur', this.blurListener);
+            this.blurListener = null;
+        }
+        if(resizeListener) {
+            window.removeEventListener('resize', this.resizeListener);
+            this.resizeListener = null;
+        }
+    },
+
+    WebGLWindowGetCanvasName: function() {
+        var elements = document.getElementsByTagName('canvas');
+        var returnStr = "";
+        if(elements.length >= 1)
+        {
+            returnStr = elements[0].parentNode.id;
+            // workaround : for WebGLTemplate:Minimal temp! body element not have id!
+            if(returnStr == '')
+            {
+                returnStr = elements[0].parentNode.id = 'WebGLWindow:Canvas:ParentNode';
+            }
+        }
+        var bufferSize = lengthBytesUTF8(returnStr) + 1;
+        var buffer = _malloc(bufferSize);
+        stringToUTF8(returnStr, buffer, bufferSize);
+        return buffer;
+    },
+    WebGLWindowOnFocus: function (cb) {
+        this.focusListener = function () { 
+            (!!Runtime.dynCall) ? Runtime.dynCall("v", cb, []) : {{{ makeDynCall("v", "cb") }}}(); 
+        };
+        window.addEventListener('focus', this.focusListener);
+    },
+    WebGLWindowOnBlur: function (cb) {
+        this.blurListener = function () { 
+            (!!Runtime.dynCall) ? Runtime.dynCall("v", cb, []) : {{{ makeDynCall("v", "cb") }}}(); 
+        };
+        window.addEventListener('blur', this.blurListener);
+    },
+    WebGLWindowOnResize: function(cb) {
+        this.resizeListener = function () { 
+            (!!Runtime.dynCall) ? Runtime.dynCall("v", cb, []) : {{{ makeDynCall("v", "cb") }}}(); 
+        };
+        window.addEventListener('resize', this.resizeListener);
+    },
+    WebGLWindowInjectFullscreen : function () {
+        document.makeFullscreen = function (id, keepAspectRatio) {
+            // get fullscreen object
+            var getFullScreenObject = function () {
+                var doc = window.document;
+                var objFullScreen = doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement;
+                return (objFullScreen);
+            }
+
+            // handle fullscreen event
+            var eventFullScreen = function (callback) {
+                document.addEventListener("fullscreenchange", callback, false);
+                document.addEventListener("webkitfullscreenchange", callback, false);
+                document.addEventListener("mozfullscreenchange", callback, false);
+                document.addEventListener("MSFullscreenChange", callback, false);
+            }
+
+            var removeEventFullScreen = function (callback) {
+                document.removeEventListener("fullscreenchange", callback, false);
+                document.removeEventListener("webkitfullscreenchange", callback, false);
+                document.removeEventListener("mozfullscreenchange", callback, false);
+                document.removeEventListener("MSFullscreenChange", callback, false);
+            }
+
+            var div = document.createElement("div");
+            document.body.appendChild(div);
+
+            // save canvas size to originSize
+            var canvas = document.getElementsByTagName('canvas')[0];
+            var originSize = 
+            {
+                width : canvas.style.width,
+                height : canvas.style.height,
+            };
+
+            var fullscreenRoot = document.getElementById(id);
+
+            // when build with minimal default template
+            // the fullscreenRoot is <body>
+            var isBody = fullscreenRoot.tagName.toLowerCase() == "body";
+            if(isBody)
+            {
+                // swip the id to div
+                div.id = fullscreenRoot.id;
+                fullscreenRoot.id = "";
+                // overwrite the fullscreen root
+                fullscreenRoot = canvas;
+            }
+
+            var beforeParent = fullscreenRoot.parentNode;
+            var beforeStyle = window.getComputedStyle(fullscreenRoot);
+            var beforeWidth = parseInt(beforeStyle.width);
+            var beforeHeight = parseInt(beforeStyle.height);
+
+            // to keep element index after fullscreen
+            var index = Array.from(beforeParent.children).findIndex(function (v) { return v == fullscreenRoot; });
+            div.appendChild(fullscreenRoot);
+
+            // recv fullscreen function
+            var fullscreenFunc = function () {
+                if (getFullScreenObject()) {
+                    if (keepAspectRatio) {
+                        var ratio = Math.min(window.screen.width / beforeWidth, window.screen.height / beforeHeight);
+                        var width = Math.floor(beforeWidth * ratio);
+                        var height = Math.floor(beforeHeight * ratio);
+
+                        fullscreenRoot.style.width = width + 'px';
+                        fullscreenRoot.style.height = height + 'px';
+                    } else {
+                        fullscreenRoot.style.width = window.screen.width + 'px';
+                        fullscreenRoot.style.height = window.screen.height + 'px';
+                    }
+
+                    // make canvas size 100% to fix screen size
+                    canvas.style.width = "100%";
+                    canvas.style.height = "100%";
+
+                } else {
+                    fullscreenRoot.style.width = beforeWidth + 'px';
+                    fullscreenRoot.style.height = beforeHeight + 'px';
+                    beforeParent.insertBefore(fullscreenRoot, Array.from(beforeParent.children)[index]);
+
+                    if(isBody)
+                    {
+                        beforeParent.id = div.id;
+                    }
+
+                    div.parentNode.removeChild(div);
+
+                    // set canvas size to origin size
+                    canvas.style.width = originSize.width;
+                    canvas.style.height = originSize.height;
+
+                    // remove this function
+                    removeEventFullScreen(fullscreenFunc);
+                }
+            }
+
+            // listener fullscreen event
+            eventFullScreen(fullscreenFunc);
+
+            if (div.mozRequestFullScreen) div.mozRequestFullScreen();
+            else if (div.webkitRequestFullScreen) div.webkitRequestFullScreen();
+            else if (div.msRequestFullscreen) div.msRequestFullscreen();
+            else if (div.requestFullscreen) div.requestFullscreen();
+        }
+    },
+    MakeFullscreen : function (str) {
+        document.makeFullscreen(UTF8ToString(str));
+    },
+    ExitFullscreen : function() {
+        // get fullscreen object
+        var doc = window.document;
+        var objFullScreen = doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement;
+
+        if (objFullScreen)
+        {
+            if (document.exitFullscreen) document.exitFullscreen();
+            else if (document.msExitFullscreen) document.msExitFullscreen();
+            else if (document.mozCancelFullScreen) document.mozCancelFullScreen();
+            else if (document.webkitExitFullscreen) document.webkitExitFullscreen();
+        }
+    },
+    IsFullscreen : function() {
+        // get fullscreen object
+        var doc = window.document;
+        var objFullScreen = doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement;
+
+        // check full screen elemenet is not null!
+        return objFullScreen != null;
+    },
+}
+
+mergeInto(LibraryManager.library, WebGLWindow);

+ 37 - 0
Assets/WebGLSupport/WebGLWindow/WebGLWindow.jslib.meta

@@ -0,0 +1,37 @@
+fileFormatVersion: 2
+guid: 5edef37b75c044e41a013a62fec2e1ff
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  - first:
+      Facebook: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      WebGL: WebGL
+    second:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini