// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using UnityEngine; namespace Microsoft.MixedReality.Toolkit.UI { /// /// Use a Unity primitive cube or cylinder as a border segment relative to the scale of the AnchorTransform /// Use with ButtonSize on the component and the Anchor for consistent results /// Works best when using with ButtonSize, but not required - See ButtonSize for more info. /// [ExecuteInEditMode] [AddComponentMenu("Scripts/MRTK/SDK/ButtonBorder")] public class ButtonBorder : MonoBehaviour { /// /// A scale factor for button layouts, default is based on 2048 pixels to 1 meter. /// Similar to values used in designer and 2D art programs and helps create consistency across teams. /// /// Use Case: /// A designer created a basic button background using a Cube and ButtonSize /// Add some more borders, using more cubes or cylinders, that will scale to the edges of the background size /// [Tooltip("A pixel to Unity unit conversion, Default: 2048x2048 pixels covers a 1x1 Unity Unit or default primitive size")] [SerializeField] private float BasePixelScale = 2048; /// /// The transform to offset from. /// [Tooltip("The transform this object should be linked and aligned to")] [SerializeField] private Transform AnchorTransform = null; /// /// Width of the border /// [Tooltip("Size of the border using pixel values from our design program.")] [SerializeField] private float Weight = 10; /// /// The depth of the border /// [Tooltip("Depth of the border using pixel values from our design program.")] [SerializeField] private float Depth = 20; /// /// A vector that sets the border position to the edge of the Anchor and /// scales it to match the edge it is assigned to. /// Ex: Vector3.right would place the border on the Anchor's right side. /// [Tooltip("Where to set this object's center point in relation to the Anchor's center point")] [SerializeField] private Vector3 Alignment = Vector3.zero; /// /// An absolute value to offset the border from the Anchor's edge /// [Tooltip("That absolute amount to offset the position")] [SerializeField] private Vector3 PositionOffset = Vector3.zero; /// /// Overlap the edge it is assigned to so there are not gaps in the corners /// [Tooltip("Will extend the height or width of the border to create corners.")] [SerializeField] private bool AddCorner = true; /// /// These scales and positions are applied in Unity Editor only while doing layout. /// Turn off for responsive UI type results when editing ItemSize during runtime. /// Scales will be applied each frame. /// [Tooltip("should this only run in Edit mode, to avoid updating as items move?")] [SerializeField] private bool OnlyInEditMode = true; private Vector3 scale; private Vector3 startPosition; private Vector3 weighDirection; private Vector3 localPosition; private Vector3 anchorTransformLocalPosition; private Vector3 anchorTransformLocalScale; /// /// Set the size and position /// private void UpdateSize() { // Vector3 weighDireciton = new Vector3(Mathf.Abs(Alignment.x), Mathf.Abs(Alignment.y), Mathf.Abs(Alignment.z)); // Vector3 scale = weighDireciton * (Weight / BasePixelScale);// Vector3.Scale(Alignment, Scale) + Offset / BasePixelScale; weighDirection.x = Mathf.Abs(Alignment.x); weighDirection.y = Mathf.Abs(Alignment.y); weighDirection.z = Mathf.Abs(Alignment.z); scale.x = weighDirection.x * (Weight / BasePixelScale); scale.y = weighDirection.y * (Weight / BasePixelScale); scale.z = weighDirection.z * (Weight / BasePixelScale); float size = ((Weight * 2) / BasePixelScale); if (scale.x > scale.y) { scale.y = AddCorner ? AnchorTransform.localScale.y + size : AnchorTransform.localScale.y; } else { scale.x = AddCorner ? AnchorTransform.localScale.x + size : AnchorTransform.localScale.x; } scale.z = Depth / BasePixelScale; transform.localScale = scale; anchorTransformLocalPosition = AnchorTransform.localPosition; anchorTransformLocalScale = AnchorTransform.localScale; startPosition = anchorTransformLocalPosition; if (AnchorTransform != this.transform) { // startPosition = AnchorTransform.localPosition + (Vector3.Scale(AnchorTransform.localScale * 0.5f, Alignment)); startPosition.x = anchorTransformLocalPosition.x + ((anchorTransformLocalScale.x * 0.5f) * Alignment.x); startPosition.y = anchorTransformLocalPosition.y + ((anchorTransformLocalScale.y * 0.5f) * Alignment.y); startPosition.z = anchorTransformLocalPosition.z + ((anchorTransformLocalScale.z * 0.5f) * Alignment.z); } // transform.localPosition = startPosition + (Alignment * Weight * 0.5f / BasePixelScale) + (PositionOffset / BasePixelScale); localPosition.x = startPosition.x + (Alignment.x * Weight * 0.5f / BasePixelScale) + (PositionOffset.x / BasePixelScale); localPosition.y = startPosition.y + (Alignment.y * Weight * 0.5f / BasePixelScale) + (PositionOffset.y / BasePixelScale); localPosition.z = startPosition.z + (Alignment.z * Weight * 0.5f / BasePixelScale) + (PositionOffset.z / BasePixelScale); transform.localPosition = localPosition; } // Update is called once per frame void Update() { if ((Application.isPlaying && !OnlyInEditMode) || (!Application.isPlaying)) { UpdateSize(); } } } }