//tips
//unity/webview連動
昨日の続きで、前回の情報をもとに新たにTexture2Dで色付けしたものを生成することもできる。
Texture2Dは引数を取ることができ、第一引数はテクスチャの幅、第二引数はテクスチャの高さ、第三引数はテクスチャフォーマット、第四引数はミップマップを作成するか否かになる。
下記で1ピクセルごとの色指定がなされている。
Color col = new Color(1.0f, 0.0f, 0.0f, 1.0f); // Red/Green/Blue/Alphaの順に色指定.
for (int y = 0; y < m_texture.height; y++) {
for (int x = 0; x < m_texture.width; x++) {
m_texture.SetPixel(x, y, col);
}
}
m_texture.Apply();
SetPixel()で色指定、Apply()で確定する。
TextureFormat.ARGB32は色数が多くやピクセル単位が重要で、透過情報も必要なときに使用されるフォーマットでunityの画像にはこのようなテクスチャ形式が割り当てられている。
private static Texture2D _debugTexture = null;
private void OnGUI()
{
if (_debugTexture == null)
{
_debugTexture = new Texture2D(4, 4, TextureFormat.ARGB32, false);
for (int y = 0; y < _debugTexture.height; y++)
{
for (int x = 0; x < _debugTexture.width; x++)
{
Color color = new Color(1.0f, 0.0f, 0.0f, 0.5f);
_debugTexture.SetPixel(x, y, color);
}
}
_debugTexture.Apply();
}
var rect = _screenRect;
rect.yMax = Screen.height - _screenRect.yMin;
rect.yMin = rect.yMax - _screenRect.height;
GUI.DrawTexture(rect, _debugTexture);
}
}
ここから本題に入っていく。screenRectの情報を取得できているのでこれをwebviewの表示領域に適応させる。
まずは単純にWebViewSample2スクリプトのvar margins = WebViewUtils.ToMarginsの引数として[SerializeField] RectTransform _rectTrans;をimage画像のアタッチによって差し込んでみたが表示は全範囲でなされてしまっていた。
一旦初期の下記の形で考えていく。TestRectTransformToScreenSpaceRect スクリプトのCalcurateScreenSpaceRectとWebViewSample2のint[] CalcMargins(GameObject target)のどこに違いがあり後者でWorldCornersToScreenCornersを使用するとエラーが発生するのかを認識していく。
margins = CalcMargins(targetObject);
webViewObject.SetMargins(margins[0], margins[1], margins[2], margins[3]);
下記のようにwebviewsamplesを編集してみたが、なぜかgoogleの画面がimageの中に表示されない。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WebViewSample2 : MonoBehaviour
{
[SerializeField]
RectTransform targetObject;
WebViewObject webViewObject;
[SerializeField]
TestRectTransformToScreenSpaceRect TestRectTransformToScreenSpaceRect;
[SerializeField] RectTransform _rectTrans;
//WebViewUtils WebViewUtils;
int[] margins = { 0, 0, 0, 0 };
[SerializeField]
Camera mycamera;
void Start()
{
webViewObject = (new GameObject("WebViewObject")).AddComponent<WebViewObject>();
webViewObject.Init(
ld: (msg) => Debug.Log(string.Format("CallOnLoaded[{0}]", msg)),
enableWKWebView: true);
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
webViewObject.bitmapRefreshCycle = 1;
#endif
// お好きなMarginにしてください
margins = CalcMargins(targetObject);
webViewObject.SetMargins(margins[0], margins[1], margins[2], margins[3]);
webViewObject.SetVisibility(true);
// お好きなURLにしてください
webViewObject.LoadURL("https://www.google.co.jp");
}
int[] CalcMargins(RectTransform target)
{
var canvas = target.GetComponentInParent<Canvas>();
Vector3[] targetWorldCorners = new Vector3[4];
target.GetWorldCorners(targetWorldCorners);//targetworldcornersに格納
Vector2[] targetScreenCorners = new Vector2[4];
targetScreenCorners[0] = RectTransformUtility.WorldToScreenPoint(mycamera, targetWorldCorners[0]);
targetScreenCorners[1] = RectTransformUtility.WorldToScreenPoint(mycamera, targetWorldCorners[1]);
targetScreenCorners[2] = RectTransformUtility.WorldToScreenPoint(mycamera, targetWorldCorners[2]);
targetScreenCorners[3] = RectTransformUtility.WorldToScreenPoint(mycamera, targetWorldCorners[3]);
margins[0] = Math.Abs((int)targetScreenCorners[0].x);
margins[1] = Math.Abs(Screen.height - (int)targetScreenCorners[2].y);
margins[2] = Math.Abs(Screen.width - (int)targetScreenCorners[2].x);
margins[3] = Math.Abs((int)targetScreenCorners[0].y);
return margins;
}
}
Marginsがうまく計算されておらず、初期設定の0になっていないかをデバッグで確認。
そうすると下記の数値が取得できた。
Debug.Log(margins[0]);//128
Debug.Log(margins[1]);//762
Debug.Log(margins[2]);//1604
Debug.Log(margins[3]);//2
marginsは0:左、1:上、2:右、3:下なのでこの数値は少しおかしいことがわかる。
一旦スクリーンのサイズを確認し、現在のimageのスクリーン位置を算出し確かめてみることにする。
まずは簡単に値を変えて実行。webViewObject.SetMargins(100, 100, 100, 500);にすると下がかなり削られることがわかる。width1726,height760での表示であることがcanvasからもわかるので上記のmarginsは数値の取得元がおかしいことになる。
webViewObject.SetMargins(100, 200, 1000, 200);とするとおおよその感覚がわかる。まずページは伸縮せずに一部削れた形で表示されるが、中央部分はきちんと反映対象に含まれている。そして、スクロールも機能する。
このようなmarginsの値にならない原因を探す。
まずはDebug.Log(targetScreenCorners[0]);などを表示させ確認する。
Debug.Log(targetScreenCorners[0]);//(128.3, -2.8)
Debug.Log(targetScreenCorners[1]);//(301.7, -2.1)
Debug.Log(targetScreenCorners[2]);//(122.3, -2.1)
Debug.Log(targetScreenCorners[3]);//(-106.5, -2.8)
となり描かれている点が、正方形のimageの各頂点と一致しない。平面に直す前のDebug.Log(targetWorldCorners[0]);の方も確認する。
Debug.Log(targetWorldCorners[0]);//(313.0, 330.0, 0.0)
Debug.Log(targetWorldCorners[1]);//(313.0, 430.0, 0.0)
Debug.Log(targetWorldCorners[2]);//(413.0, 430.0, 0.0)
Debug.Log(targetWorldCorners[3]);//(413.0, 330.0, 0.0)
こちらでは正常な値を取れている。RectTransformUtility.WorldToScreenPointの内容がうまくいっていないことが問題であることがわかった。
今回は平面であるためtargetWorldCorners[0]を計算に適用するだけで良いので、一旦そちらで反映を行えないか試してみる。
marginsの反映部分をtargetWorldCornersに変更する。
margins[0] = Math.Abs((int)targetWorldCorners[0].x);
margins[1] = Math.Abs(Screen.height - (int)targetWorldCorners[2].y);
margins[2] = Math.Abs(Screen.width - (int)targetWorldCorners[2].x);
margins[3] = Math.Abs((int)targetWorldCorners[0].y);
検索スペースの少しの部分しか表示することができなかったが無事にgoogleのページを移すことができた。
ここからはなぜRectTransformUtility.WorldToScreenPointが機能しなかったのかを探っていく。