using asap.core; using cfg; using DG.Tweening; using System.Collections.Generic; using System.Collections; using UnityEngine; using UnityEngine.Assertions; public class Block : MonoBehaviour { private Rigidbody2D _rb; private BoxCollider2D _bc; public BlockState State; private bool _freezable = false; private Tables _tables; private InfiniteBuildingConf _cfg; public int Idx; public IEventAggregator EventAggregator; public bool Freezable => _freezable; //private Transform _focus; public Rigidbody2D Rb => _rb; private List _furnitureList; private class Furniture { public readonly GameObject Go; public readonly Vector3 TargetScale; public Furniture(GameObject go, Vector3 targetScale) { Go = go; TargetScale = targetScale; } } public float Height { get { if (_tables.TbConstructionUnits.DataMap.ContainsKey(Idx)) return _tables.TbConstructionUnits[Idx].Height; Debug.LogError($"Block index {Idx} is not in the table."); return 0; } } public float Width => _bc.size.x; public float WorldHeight => transform.position.y + _bc.offset.y + _bc.size.y / 2; public bool IsCurrentBlockStill => Rb.velocity.magnitude <= _cfg.blockFreezeVelocity && Mathf.Abs(Rb.angularVelocity) <= _cfg.blockFreezeAngularVelocity && _acc.magnitude <= _cfg.blockFreezeAcc && Mathf.Abs(_angularAcc) <= _cfg.blockFreezeAngularAcc; public int FallPoint { get { Assert.IsTrue(_tables.TbConstructionUnits.DataMap.ContainsKey(Idx), $"Block index {Idx} is not in the table."); return _tables.TbConstructionUnits[Idx].FallPoint; } } public int StackPoint { get { Assert.IsTrue(_tables.TbConstructionUnits.DataMap.ContainsKey(Idx), $"Block index {Idx} is not in the table."); return _tables.TbConstructionUnits[Idx].StackPoint; } } private void Awake() { _rb = GetComponent(); _bc = GetComponent(); _tables = GContext.container.Resolve(); } private Vector2 previousVelocity, _acc; private float previousAngularVelocity, _angularAcc; public Vector2 Acc => _acc; public float AngularAcc => _angularAcc; private void Start() { previousAngularVelocity = _rb.angularVelocity; previousVelocity = _rb.velocity; } private void FixedUpdate() { _acc = (_rb.velocity - previousVelocity) / Time.fixedDeltaTime; _angularAcc = (_rb.angularVelocity - previousAngularVelocity) / Time.fixedDeltaTime; previousVelocity = _rb.velocity; previousAngularVelocity = _rb.angularVelocity; } public void InitHangingBlock(BlockState s, int idx, IEventAggregator ea, InfiniteBuildingConf config) { State = BlockState.Hanging; _furnitureList = new List(); GetFurnitures(transform, 0, _furnitureList); State = s; Idx = idx; EventAggregator = ea; _cfg = config; foreach (var fur in _furnitureList) SetFurnitureScale(fur, 0); } public void InitRecordBlock(InfiniteBuildingConf config) { _cfg = config; _furnitureList = new List(); GetFurnitures(transform, 0, _furnitureList); } private void OnCollisionEnter2D(Collision2D collision) { //Debug.Log($"Play audio from {gameObject.name} to {collision.gameObject.name}"); int a = gameObject.GetHashCode(); int b = collision.gameObject.GetHashCode(); if (a > b) (a, b) = (b, a); string hash = string.Format("{0}{1}", a, b); EventAggregator.Publish(new EventInfiniteBuildingCollisionSound(hash)); if (_freezable == false && State == BlockState.Free) EventAggregator.Publish(new EventInfiniteBuildingFirstCollision(this)); _freezable = true; } private void OnCollisionExit2D(Collision2D collision) { //Debug.Log($"Detach audio from {gameObject.name} to {collision.gameObject.name}"); } private int targetDepth = 2; private void GetFurnitures(Transform parent, int currentDepth, List result) { if (currentDepth == targetDepth) { result.Add(new Furniture(parent.gameObject, parent.gameObject.transform.localScale)); return; } foreach (Transform child in parent) { GetFurnitures(child, currentDepth + 1, result); } } private void SetFurnitureScale(Furniture f, float scale) { if (!f.Go.name.StartsWith("B999_glass")) f.Go.transform.localScale = f.TargetScale * scale; } public void PlayFurnitureAnimation() { foreach (var fur in _furnitureList) { if (fur.Go.name.StartsWith("B999_glass")) StartCoroutine(GlassTransfer(fur)); else fur.Go.transform.DOScale(fur.TargetScale, Random.Range(_cfg.animationDurationRange.x, _cfg.animationDurationRange.y)); } } private IEnumerator GlassTransfer(Furniture f) { yield return new WaitForSeconds(_cfg.animationDurationRange.y); Material mat = f.Go.GetComponent().material; float t = 0; while (t <= _cfg.animationDurationRange.z) { t += Time.deltaTime; mat.SetColor("_EmissionColor", Color.Lerp(Color.black, _cfg.glassColor, t / _cfg.animationDurationRange.z)); yield return null; } } public void LitBlock() { foreach (var fur in _furnitureList) { if (fur.Go.name.StartsWith("B999_glass")) fur.Go.GetComponent().material .SetColor("_EmissionColor", _cfg.glassColor); } } public void Drop() { //_djl.breakForce = 0; //_djr.breakForce = 0; State = BlockState.Free; Rb.drag = 0; //DestroyCountDown(); } public void Rest() { //_cts.Cancel(); //_cts.Dispose(); State = BlockState.Resting; //_rb.velocity = Vector3.zero; //_rb.isKinematic = true; //Debug.Log(_focus.position); //Debug.Log(Height); //_rb.MovePosition(new Vector2(_rb.position.x, _focus.position.y)); //OnRest?.Invoke(delta); } //public void DestroySelf() //{ // Debug.Log($"awsl {gameObject}"); // try // { // _cts?.Cancel(); // _cts?.Dispose(); // } // catch(ObjectDisposedException e) // { // Debug.Log($"source disposed: {e}"); // } // if (_state == BlockState.Free) // OnDestroy?.Invoke(); // Destroy(gameObject); //} } public enum BlockState { Hanging, Free, Resting, Locked }