Last active
November 15, 2024 20:02
-
-
Save pbhogan/2094a033c094ddd1b0b8f37a5dffd005 to your computer and use it in GitHub Desktop.
Unity UI-Toolkit Aspect Ratio Preserving Panel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This is free and unencumbered software released into the public | |
domain. | |
Anyone is free to copy, modify, publish, use, compile, sell, or | |
distribute this software, either in source code form or as a compiled | |
binary, for any purpose, commercial or non-commercial, and by any | |
means. | |
In jurisdictions that recognize copyright laws, the author or authors | |
of this software dedicate any and all copyright interest in the | |
software to the public domain. We make this dedication for the | |
benefit of the public at large and to the detriment of our heirs and | |
successors. We intend this dedication to be an overt act of | |
relinquishment in perpetuity of all present and future rights to this | |
software under copyright law. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
namespace GallantGames.UI | |
{ | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UIElements; | |
[UnityEngine.Scripting.Preserve] | |
public class AspectRatioPanel : VisualElement | |
{ | |
[UnityEngine.Scripting.Preserve] | |
public new class UxmlFactory : UxmlFactory<AspectRatioPanel, UxmlTraits> {} | |
[UnityEngine.Scripting.Preserve] | |
public new class UxmlTraits : VisualElement.UxmlTraits | |
{ | |
readonly UxmlIntAttributeDescription aspectRatioX = new() { name = "aspect-ratio-x", defaultValue = 16, restriction = new UxmlValueBounds { min = "1" } }; | |
readonly UxmlIntAttributeDescription aspectRatioY = new() { name = "aspect-ratio-y", defaultValue = 9, restriction = new UxmlValueBounds { min = "1" } }; | |
readonly UxmlIntAttributeDescription balanceX = new() { name = "balance-x", defaultValue = 50, restriction = new UxmlValueBounds { min = "0", max = "100" } }; | |
readonly UxmlIntAttributeDescription balanceY = new() { name = "balance-y", defaultValue = 50, restriction = new UxmlValueBounds { min = "0", max = "100" } }; | |
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription | |
{ | |
get { yield break; } | |
} | |
public override void Init( VisualElement visualElement, IUxmlAttributes attributes, CreationContext creationContext ) | |
{ | |
base.Init( visualElement, attributes, creationContext ); | |
var element = visualElement as AspectRatioPanel; | |
if (element != null) | |
{ | |
element.AspectRatioX = Mathf.Max( 1, aspectRatioX.GetValueFromBag( attributes, creationContext ) ); | |
element.AspectRatioY = Mathf.Max( 1, aspectRatioY.GetValueFromBag( attributes, creationContext ) ); | |
element.BalanceX = Mathf.Clamp( balanceX.GetValueFromBag( attributes, creationContext ), 0, 100 ); | |
element.BalanceY = Mathf.Clamp( balanceY.GetValueFromBag( attributes, creationContext ), 0, 100 ); | |
element.FitToParent(); | |
} | |
} | |
} | |
public int AspectRatioX { get; private set; } = 16; | |
public int AspectRatioY { get; private set; } = 9; | |
public int BalanceX { get; private set; } = 50; | |
public int BalanceY { get; private set; } = 50; | |
public AspectRatioPanel() | |
{ | |
style.position = Position.Absolute; | |
style.left = 0; | |
style.top = 0; | |
style.right = StyleKeyword.Undefined; | |
style.bottom = StyleKeyword.Undefined; | |
RegisterCallback<AttachToPanelEvent>( OnAttachToPanelEvent ); | |
} | |
void OnAttachToPanelEvent( AttachToPanelEvent e ) | |
{ | |
parent?.RegisterCallback<GeometryChangedEvent>( OnGeometryChangedEvent ); | |
FitToParent(); | |
} | |
void OnGeometryChangedEvent( GeometryChangedEvent e ) | |
{ | |
FitToParent(); | |
} | |
void FitToParent() | |
{ | |
if (parent == null) return; | |
var parentW = parent.resolvedStyle.width; | |
var parentH = parent.resolvedStyle.height; | |
if (float.IsNaN( parentW ) || float.IsNaN( parentH )) return; | |
style.position = Position.Absolute; | |
style.left = 0; | |
style.top = 0; | |
style.right = StyleKeyword.Undefined; | |
style.bottom = StyleKeyword.Undefined; | |
if (AspectRatioX <= 0.0f || AspectRatioY <= 0.0f) | |
{ | |
style.width = parentW; | |
style.height = parentH; | |
return; | |
} | |
var ratio = Mathf.Min( parentW / AspectRatioX, parentH / AspectRatioY ); | |
var targetW = Mathf.Floor( AspectRatioX * ratio ); | |
var targetH = Mathf.Floor( AspectRatioY * ratio ); | |
style.width = targetW; | |
style.height = targetH; | |
var marginX = parentW - targetW; | |
var marginY = parentH - targetH; | |
style.left = Mathf.Floor( marginX * BalanceX / 100.0f ); | |
style.top = Mathf.Floor( marginY * BalanceY / 100.0f ); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ui:VisualElement name="FlexBox" style="flex-direction: row; position: absolute; left: 0; top: 0; right: 0; bottom: 0;"> | |
<ui:VisualElement name="Side-L" style="background-color: rgb(0, 166, 255); flex-grow: 1; margin-left: 20px; margin-right: 10px; margin-top: 20px; margin-bottom: 20px; width: 50%;"> | |
<GallantGames.UI.AspectRatioPanel aspect-ratio-x="16" aspect-ratio-y="9" style="background-color: yellow;" /> | |
</ui:VisualElement> | |
<ui:VisualElement name="Side-R" style="background-color: rgb(255, 64, 0); flex-grow: 1; margin-left: 10px; margin-right: 20px; margin-top: 20px; margin-bottom: 20px; width: 50%;"> | |
<GallantGames.UI.AspectRatioPanel aspect-ratio-x="9" aspect-ratio-y="16" style="background-color: yellow;" /> | |
</ui:VisualElement> | |
</ui:VisualElement> |
chakibchemso
commented
Aug 13, 2024
- you can use current aspect ratio of the camera to always match the viewport
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment