Unity WebGL 实现中文IME输入
·
参考项目:https://github.com/unity3d-jp/WebGLNativeInputField (项目实现了采用 html native input 可以激活中文输入法)
提醒:UI控件不能显示中文是中文字体的原因(把中文字体包含进去,可以去下载这个字体DroidSansFallback,体较小),能使用中文输入法和UI显示中文是不同的问题。
需求实现:
我使用的UI插件是NGUI,点击UIInput或者UILabel时,将会调用native html input,并且我会传递 x y w h 4个参数给html (jslib),然后html根据坐标和宽高创建input并且覆盖在我的游戏UI,功能实现简单,xywh正确计算即可。
下方例子控件是NGUI的UILabel,添加点击事件,调用Native Input,用户输入完毕后,获得html input 数据,更新UILabel。
------------------------------------------ 分割线 --------------------------------------------
核心代码是这两个文件,我希望首先先运行github的项目,再看我修改的代码,这样会比较容易理解。
//WebNativeDialog.jslib
var WebNativeDialog = {
SetupOverlayDialogHtml:function(defaultValue,x,y,w,h){
try {
defaultValue = Pointer_stringify(defaultValue);
} catch (e) {
}
if(!document.getElementById("nativeInputDialog")) {
// setup html
var html = '<div id="nativeInputDialog" style="background:transparent; width:100%; height:100%; margin: 0; padding: 0; position: absolute; left: 0; top:0; z-index:888;">' +
'<input id="nativeInputDialogInput" type="text" style="border: none; background: none; color: white; outline: none; display: block; position: relative; font-size: 20px; ">' +
'</div>';
$(document.body).append(html);
$('#nativeInputDialogInput').keypress(function (event) {
if (event.keyCode == 13) {
$('#nativeInputDialog').hide();
}
});
$('#nativeInputDialogInput').click(function () {
return false;
});
$('#nativeInputDialog').click(function () {
$('#nativeInputDialog').hide();
});
}
$('#nativeInputDialogInput').val(defaultValue);
$('#nativeInputDialogInput').css({left: x + 'px', top: y + 'px', width: w, height: h});
$('#nativeInputDialog').show();
$('#nativeInputDialogInput').focus();
},
HideUnityScreenIfHtmlOverlayCant:function(){
if( navigator.userAgent.indexOf("Chrome/") < 0 ){
document.getElementById("canvas").style.display="none";
}
},
IsRunningOnEdgeBrowser:function(){
if( navigator.userAgent.indexOf("Edge/") < 0 ){
return false;
}
return true;
},
IsOverlayDialogHtmlActive:function(){
return $('#nativeInputDialog').is(':visible');
},
IsOverlayDialogHtmlCanceled:function(){
return ($('#nativeInputDialog').is(':visible'));
},
GetOverlayHtmlInputFieldValue:function(){
var returnStr = $('#nativeInputDialogInput').val();
var bufferSize = lengthBytesUTF8(returnStr) + 1;
var buffer = _malloc(bufferSize);
stringToUTF8(returnStr, buffer, bufferSize);
return buffer;
}
};
mergeInto( LibraryManager.library , WebNativeDialog );
//WebGLNativeInputField.cs
public class WebGLNativeInputField : MonoBehaviour {
UILabel mInput;
// Use this for initialization
void Start () {
mInput = GetComponentInChildren<UILabel>();
}
public void OnClickInput (){
var inputbounds = CalculateWidgetScreenBounds (gameObject.GetComponentInChildren<UILabel> ().gameObject.transform);
WebNativeDialog.SetUpOverlayDialog (mInput.text,(int)inputbounds.min.x, (int)inputbounds.min.y, (int)inputbounds.size.x, (int)inputbounds.size.y);
mInput.text = "";
StartCoroutine(this.OverlayHtmlCoroutine());
}
private IEnumerator OverlayHtmlCoroutine(){
yield return new WaitForEndOfFrame();
#if UNITY_WEBGL && !UNITY_EDITOR
WebGLInput.captureAllKeyboardInput = false;
while (WebNativeDialog.IsOverlayDialogActive())
{
yield return null;
}
WebGLInput.captureAllKeyboardInput = true;
if (!WebNativeDialog.IsOverlayDialogCanceled())
{
mInput.text = WebNativeDialog.GetOverlayDialogValue();
}
#endif
}
static public Bounds CalculateWidgetScreenBounds (Transform child){
UIWidget[] widgets = child.GetComponentsInChildren<UIWidget>(true) as UIWidget[];
Bounds b = new Bounds(Vector3.zero, Vector3.zero);
bool first = true;
for (int i = 0, imax = widgets.Length; i < imax; ++i)
{
UIWidget w = widgets[i];
Vector2 size = w.localSize;
Vector2 offset = w.pivotOffset;
Transform toWorld = w.cachedTransform;
float x = (offset.x + 0.5f) * size.x;
float y = (offset.y - 0.5f) * size.y;
size *= 0.5f;
// Start with the corner of the widget
Vector3 v = new Vector3(x - size.x, y - size.y, 0f);
// Transform the coordinate from relative-to-widget to world space
v = toWorld.TransformPoint(v);
v = UICamera.currentCamera.WorldToScreenPoint(v);
v.y = Screen.height - v.y;
if (first)
{
first = false;
b = new Bounds(v, Vector3.zero);
}
else
{
b.Encapsulate(v);
}
// Repeat for the other 3 corners
v = new Vector3(x - size.x, y + size.y, 0f);
v = toWorld.TransformPoint(v);
v = UICamera.currentCamera.WorldToScreenPoint(v);
v.y = Screen.height - v.y;
b.Encapsulate(v);
v = new Vector3(x + size.x, y - size.y, 0f);
v = toWorld.TransformPoint(v);
v = UICamera.currentCamera.WorldToScreenPoint(v);
v.y = Screen.height - v.y;
b.Encapsulate(v);
v = new Vector3(x + size.x, y + size.y, 0f);
v = toWorld.TransformPoint(v);
v = UICamera.currentCamera.WorldToScreenPoint(v);
v.y = Screen.height - v.y;
b.Encapsulate(v);
}
return b;
}
}
警告:2018-06-14:
现在遇到一个问题,WebGL 在全屏下,这个不能使用(无法显示出这个 native input),怀疑可能和全屏一些深度显示有关,没有解决这个问题。 临时方案是全屏下不开启native input,如果有解决这个问题的,希望可以告诉我。
更多推荐
已为社区贡献1条内容
所有评论(0)