using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class ClosetGenerator : SerializedMonoBehaviour
{
[Title("tube properties")]
public float radius = 10;
public int boxesPerLevel = 36;
public int numberOfLevels = 20;
public float boxHeight = 2f;
public Material tubeMaterial;
public ParticleSystem _poofParticle;
[Title("drawer properties")]
public float drawerDepth = 1f;
public float drawerBackThickness = 0.3f;
public float drawerSidesThickness = 0.3f;
public float drawerUpDownThickness = 0.3f;
public float colliderSideScale = 1.3f;
[Title("drawer spacing")]
public float drawerSideSpacing = 0.1f;
public float drawerVerticalSpacing = 0.1f;
[Title("assets")]
public float spawnProbability = 0.6f;
public float assetsScale = 1f;
public float assetsSpacing = 1f;
public List<AssetsParams> _assetsToSpawn;
public List<GameObject> _spawnedAssets;
public struct AssetsParams
{
public GameObject asset;
public Vector3 rotation;
public float offset;
}
[Title("fall animation")]
[SerializeField]
public float animTime = 1f;
public AnimationCurve _animCurve;
public float blinktime = 1;
public float destroyTime = 1;
[Title("objects list")]
public List<List<ClosetCell>> drawerList = new List<List<ClosetCell>>();
private void Update()
{
}
[Button]
private void GenerateTube()
{
ClearTube();
GameObject tubeParent = new GameObject();
tubeParent.transform.parent = this.transform;
float anglePerBox = 360f / boxesPerLevel;
//generating tube
for (int y = 0; y < numberOfLevels; y++)
{
float height = (boxHeight * (y + 1)) - (boxHeight * 0.5f);
List<ClosetCell> horizontalDrawers = new List<ClosetCell>();
for (int x = 0; x < boxesPerLevel; x++)
{
GameObject myBox = new GameObject();
myBox.transform.position = new Vector3(0f, height, 0f);
myBox.transform.parent = tubeParent.transform;
myBox.transform.eulerAngles = new Vector3(0, anglePerBox * x, 0);
myBox.transform.Translate(Vector3.forward * radius);
myBox.transform.localScale = new Vector3(1, 1 - (drawerVerticalSpacing / 2), 1);
DestroyImmediate(myBox.GetComponent<MeshRenderer>());
myBox.layer = LayerMask.NameToLayer("Tube");
myBox.name = x.ToString() + "," + y.ToString();
var closetCell = myBox.AddComponent<ClosetCell>();
closetCell.index = new Vector2Int(x, y);
horizontalDrawers.Add(closetCell);
GenerateChildDrawer(myBox);
}
drawerList.Add(horizontalDrawers);
}
//spawning assets in tube
}
[Button]
private void spawnAssets()
{
for (int y = 0; y < numberOfLevels; y++)
{
for (int x = 0; x < boxesPerLevel; x++)
{
for (int i = 0; i < 3; i++)
{
if (Random.Range(0f, 1f)<spawnProbability)
{
int random = Random.Range(0, _assetsToSpawn.Count);
var go = _assetsToSpawn[random].asset;
var rotation = _assetsToSpawn[random].rotation;
var offset = _assetsToSpawn[random].offset;
Vector3 position = new Vector3((i - 1) * assetsSpacing, 0, -drawerDepth / 2);
drawerList[y][x].AddObject(go, position, rotation, assetsScale, offset, boxHeight * 0.85f, i, colliderSideScale);
}
else
{
Vector3 position = new Vector3((i - 1) * assetsSpacing, 0, -drawerDepth / 2);
drawerList[y][x].AddObject(null, position, Vector3.zero, 1, 0, boxHeight * 0.85f, i, colliderSideScale);
}
}
}
}
}
[Button]
public void DestroyCell(Vector2Int cell)
{
List<GameObject> objectsToAnimate = new List<GameObject>();
List<float> startPositions = new List<float>();
List<float> endpositions = new List<float>();
for (int y = 0; y < numberOfLevels; y++)
{
for (int x = 0; x < boxesPerLevel; x++)
{
if (x == cell.x && y > cell.y)
{
if (drawerList[y][x] != null)
{
objectsToAnimate.Add(drawerList[y][x].gameObject);
Debug.Log(drawerList[y][x].gameObject.name);
startPositions.Add(drawerList[y][x].transform.position.y);
endpositions.Add(drawerList[y][x].transform.position.y - boxHeight);
}
}
}
}
Destroy(drawerList[cell.y][cell.x].gameObject);
drawerList[cell.y][cell.x] = null;
StartCoroutine(Animate(objectsToAnimate.ToArray(), startPositions.ToArray(), endpositions.ToArray()));
}
public void CheckCell(Vector2Int cell)
{
if(drawerList[cell.y][cell.x]._slots[0].item.name == drawerList[cell.y][cell.x]._slots[1].item.name && drawerList[cell.y][cell.x]._slots[2].item.name == drawerList[cell.y][cell.x]._slots[1].item.name)
{
StartCoroutine(DestroyCoroutine(cell));
}
}
private IEnumerator DestroyCoroutine(Vector2Int cell)
{
drawerList[cell.y][cell.x]._slots[0].item.GetComponent<Item>().Blink(blinktime);
drawerList[cell.y][cell.x]._slots[1].item.GetComponent<Item>().Blink(blinktime);
drawerList[cell.y][cell.x]._slots[2].item.GetComponent<Item>().Blink(blinktime);
yield return new WaitForSeconds(destroyTime);
_poofParticle.transform.position = drawerList[cell.y][cell.x].transform.position;
_poofParticle.transform.eulerAngles = drawerList[cell.y][cell.x].transform.eulerAngles;
_poofParticle.Play();
DestroyCell(cell);
}
private IEnumerator Animate(GameObject[] objectsToAnimate, float[] startPositions, float[] endpositions)
{
if (objectsToAnimate == null || objectsToAnimate.Length == 0)
{
Debug.LogWarning("No objects to animate.");
yield break;
}
float elapsedTime = 0f;
while (elapsedTime < animTime)
{
Debug.Log("animating");
float t = elapsedTime / animTime;
float curveValue = _animCurve.Evaluate(t);
for (int i = 0; i < objectsToAnimate.Length; i++)
{
Vector3 newPosition = Vector3.Lerp(
new Vector3(objectsToAnimate[i].transform.position.x, startPositions[i], objectsToAnimate[i].transform.position.z),
new Vector3(objectsToAnimate[i].transform.position.x, endpositions[i], objectsToAnimate[i].transform.position.z),
1 - curveValue);
objectsToAnimate[i].transform.position = newPosition;
}
elapsedTime += Time.deltaTime;
yield return null;
}
for (int i = 0; i < objectsToAnimate.Length; i++)
{
objectsToAnimate[i].transform.position = new Vector3(objectsToAnimate[i].transform.position.x, endpositions[i], objectsToAnimate[i].transform.position.z);
}
}
private void GenerateChildDrawer(GameObject cell)
{
GameObject drawerBack = GameObject.CreatePrimitive(PrimitiveType.Cube);
drawerBack.name = "drawerBack";
drawerBack.transform.parent = cell.transform;
drawerBack.transform.localPosition = Vector3.zero - new Vector3(0, 0, drawerDepth);
drawerBack.transform.localEulerAngles = Vector3.zero;
drawerBack.transform.localScale = new Vector3(((2 * Mathf.PI * (radius - drawerDepth)) / boxesPerLevel), boxHeight, drawerBackThickness);
drawerBack.layer = LayerMask.NameToLayer("Tube");
if (tubeMaterial != null) drawerBack.GetComponent<Renderer>().material = tubeMaterial;
float sidePosition = (((2 * Mathf.PI * (radius - (drawerDepth * 0.5f))) / boxesPerLevel) / 2) * 1 - drawerSideSpacing;
GameObject drawerLeft = GameObject.CreatePrimitive(PrimitiveType.Cube);
drawerLeft.name = "drawerLeft";
drawerLeft.transform.parent = cell.transform;
drawerLeft.transform.localPosition = new Vector3(sidePosition, 0, -drawerDepth / 2);
drawerLeft.transform.LookAt(new Vector3(0, drawerLeft.transform.position.y, 0));
drawerLeft.transform.localScale = new Vector3(drawerSidesThickness, boxHeight, drawerDepth);
drawerLeft.layer = LayerMask.NameToLayer("Tube");
if (tubeMaterial != null) drawerLeft.GetComponent<Renderer>().material = tubeMaterial;
GameObject drawerRight = GameObject.CreatePrimitive(PrimitiveType.Cube);
drawerRight.name = "drawerRight";
drawerRight.transform.parent = cell.transform;
drawerRight.transform.localPosition = new Vector3(-sidePosition, 0, -drawerDepth / 2);
drawerRight.transform.LookAt(new Vector3(0, drawerRight.transform.position.y, 0));
drawerRight.transform.localScale = new Vector3(drawerSidesThickness, boxHeight, drawerDepth);
drawerRight.layer = LayerMask.NameToLayer("Tube");
if (tubeMaterial != null) drawerRight.GetComponent<Renderer>().material = tubeMaterial;
int subparts = 5;
for (int i = 0; i < subparts; i++)
{
GameObject drawerUp = GameObject.CreatePrimitive(PrimitiveType.Cube);
drawerUp.name = "drawerUp";
drawerUp.transform.parent = cell.transform;
drawerUp.transform.localPosition = new Vector3(0, (boxHeight / 2) - (drawerUpDownThickness / 2), (-drawerDepth * (i + 0.5f)) / subparts);
drawerUp.transform.LookAt(new Vector3(0, drawerUp.transform.position.y, 0));
float myRadius = (2 * Mathf.PI * (Vector3.Distance(drawerUp.transform.position, new Vector3(0, drawerUp.transform.position.y, 0))) / boxesPerLevel);
drawerUp.transform.localScale = new Vector3(myRadius - drawerSidesThickness, drawerUpDownThickness, drawerDepth / subparts);
if (tubeMaterial != null) drawerUp.GetComponent<Renderer>().material = tubeMaterial;
drawerUp.layer = LayerMask.NameToLayer("Tube");
GameObject drawerDown = Instantiate(drawerUp, drawerUp.transform.parent, false);
drawerDown.name = "drawerDown";
//drawerDown.transform.parent = drawerUp.transform.parent;
drawerDown.transform.localPosition = new Vector3(drawerDown.transform.localPosition.x, -drawerDown.transform.localPosition.y, drawerDown.transform.localPosition.z);
}
}
[Button]
private void ClearTube()
{
drawerList.Clear();
_spawnedAssets.Clear();
Transform[] meshRenderers = this.transform.GetComponentsInChildren<Transform>();
for (int i = 0; i < meshRenderers.Length; i++)
{
if (meshRenderers[i] != this.transform)
{
DestroyImmediate(meshRenderers[i].gameObject);
}
}
}
}