using UnityEngine; using System.Collections.Generic; using Lean.Common; using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute; namespace Lean.Touch { /// This component shows you a basic implementation of a block in a match-3 style game. [ExecuteInEditMode] [HelpURL(LeanTouch.PlusHelpUrlPrefix + "LeanSelectableBlock")] [AddComponentMenu(LeanTouch.ComponentPathPrefix + "Selectable Block")] public class LeanSelectableBlock : LeanSelectableByFingerBehaviour { // This stores a list of all blocks public static List Instances = new List(); /// Current X grid coordinate of this block. public int X { set { x = value; } get { return x; } } [FSA("X")] [SerializeField] private int x; /// Current Y grid coordinate of this block. public int Y { set { y = value; } get { return y; } } [FSA("Y")] [SerializeField] private int y; /// The size of the block in world space. public float BlockSize { set { blockSize = value; } get { return blockSize; } } [FSA("BlockSize")] [SerializeField] private float blockSize = 2.5f; /// Auto deselect this block when swapping? public bool DeselectOnSwap { set { deselectOnSwap = value; } get { return deselectOnSwap; } } [FSA("DeselectOnSwap")] [SerializeField] private bool deselectOnSwap = true; /// If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value. /// -1 = Instantly change. /// 1 = Slowly change. /// 10 = Quickly change. public float Damping { set { damping = value; } get { return damping; } } [FSA("Damping")] [FSA("Dampening")] [SerializeField] private float damping = 10.0f; public static LeanSelectableBlock FindBlock(int x, int y) { for (var i = Instances.Count - 1; i >= 0; i--) { var block = Instances[i]; if (block.x == x && block.y == y) { return block; } } return null; } protected override void OnEnable() { base.OnEnable(); Instances.Add(this); } protected override void OnDisable() { base.OnDisable(); Instances.Remove(this); } public static void Swap(LeanSelectableBlock a, LeanSelectableBlock b) { var tempX = a.x; var tempY = a.y; a.x = b.x; a.y = b.y; b.x = tempX; b.y = tempY; } protected virtual void Update() { // Is this selected and has a selecting finger? if (Selectable != null && Selectable.IsSelected == true) { var finger = Selectable.SelectingFinger; if (finger != null) { // Camera exists? var camera = LeanHelper.GetCamera(null); if (camera != null) { // Find the screen point of the finger using the depth of this block var screenPoint = new Vector3(finger.ScreenPosition.x, finger.ScreenPosition.y, camera.WorldToScreenPoint(transform.position).z); // Find the world space point under the finger var worldPoint = camera.ScreenToWorldPoint(screenPoint); // Find the block coordinate at this point var dragX = Mathf.RoundToInt(worldPoint.x / blockSize); var dragY = Mathf.RoundToInt(worldPoint.y / blockSize); // Is this block right next to this one? var distX = Mathf.Abs(x - dragX); var distY = Mathf.Abs(y - dragY); if (distX + distY == 1) { // Swap blocks if one exists at this coordinate var block = FindBlock(dragX, dragY); if (block != null) { Swap(this, block); if (deselectOnSwap == true) { Selectable.Deselect(); } } } } } } // Smoothly move to new position var targetPosition = Vector3.zero; var factor = LeanHelper.GetDampenFactor(damping, Time.deltaTime); targetPosition.x = x * blockSize; targetPosition.y = y * blockSize; transform.localPosition = Vector3.Lerp(transform.localPosition, targetPosition, factor); } } } #if UNITY_EDITOR namespace Lean.Touch.Editor { using TARGET = LeanSelectableBlock; [UnityEditor.CanEditMultipleObjects] [UnityEditor.CustomEditor(typeof(TARGET), true)] public class LeanSelectableBlock_Editor : LeanEditor { protected override void OnInspector() { TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts); Draw("x", "Current X grid coordinate of this block."); Draw("y", "Current Y grid coordinate of this block."); Draw("blockSize", "The size of the block in world space."); Draw("deselectOnSwap", "Auto deselect this block when swapping?"); Draw("damping", "If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value.\n\n-1 = Instantly change.\n\n1 = Slowly change.\n\n10 = Quickly change."); } } } #endif