久しぶりにUMG触ったらアイコンがズレている事に気づく……
そして、これを解決させるのに結構時間がかかったのでメモ。
そもそもUMGのオブジェクトの座標を取るには?
下記ページを参考にすると座標の取り方が分かります。
https://qiita.com/sango/items/e9e89acb67120ccf4516
大変感謝して参考にしましょう。
C++でやる場合は USlateBlueprintLibrary::LocalToViewport がそれに当たります。
でも、一部例外があった
どうやら USlateBlueprintLibrary::LocalToViewport はレターボックスを考慮してない模様。
レターボックスが無い時は正常に座標が取れて、ある時は座標がズレるといった感じでした。
レターボックスの出現条件
メインで描画しているカメラの ConstrainAspectRatio フラグが立っており
ウィンドウサイズが想定したアスペクト比とあってない場合に発生します。
レターボックスのサイズを求めなければいけない
というわけでレターボックスのサイズを求めないと正確な座標が出ません。
レターボックスのサイズを求める関数どっかにあるんかな……と思って調べましたが
見つからなかったので結局自力で作りました。
FVector2D GetLetterBoxSize(const FVector2D& ViewportSize , UCameraComponent* pCameraComponent) { FVector2D LetterBoxSize = FVector2D::ZeroVector; float viewRate = ViewportSize.X / ViewportSize.Y; float diff = viewRate - pCameraComponent->AspectRatio; // 同じと判断する(比較している値は割と適当) if (FMath::Abs(diff) < 0.0001f) { } // 左右にレターボックスが出来ている else if (diff > 0) { float ratio = pCameraComponent->AspectRatio; LetterBoxSize.X = ViewportSize.X - (ViewportSize.Y * ratio); } // 上下にレターボックスが出来ている else { float ratio = 1.0f / pCameraComponent->AspectRatio; LetterBoxSize.Y = ViewportSize.Y - (ViewportSize.X * ratio); } return LetterBoxSize; }
レターボックスが両端にある。という事は?
ズレているサイズは半分でいい……という事で
USlateBlueprintLibrary::LocalToViewport で求まった座標から
LetterBoxSize x 0.5 の値を引いてやれば座標が取れると思います。
余談
今回の解説で正確な座標自体は取れますが
「となると、こんな事もできるよね!」と思って拡張すると
また新しいハマりポイントができるわけで……というか出てきたのです。
それに関してはまた今後で紹介します。