using System.Collections.Generic;
using MoreMountains.Tools;
using MoreMountains.Feedbacks;
using UnityEngine;
using UnityEngine.SceneManagement;
using Random = UnityEngine.Random;
namespace MoreMountains.Feel
{
///
/// A class used in Feel's Brass demo to generate a ground that reacts to the music made of many cubes
///
public class FeelBrassGroundGenerator : MonoBehaviour
{
[Header("Dimensions")]
/// the amount of rows of cubes we want to draw
public int NumberOfRows = 10;
/// the amount of columns of cubes we want to draw
public int NumberOfColumns = 10;
/// the offset to apply to all cubes
public Vector3 Offset;
/// the offset to apply to the dancer's position
public Vector3 DancerOffset;
/// the curve on which to remap cube's amplitude
public AnimationCurve Amplitude;
/// the width of a cube
public float Width = 0.5f;
/// the depth of a cube
public float Depth = 0.5f;
/// the minimum amount by which to multiply the amplitude level
public float MinRandom = 1f;
/// the maximum amount by which to multiply the amplitude level
public float MaxRandom = 2f;
/// the fixed multiplier to apply to the amplitude level
public float AmplitudeMultiplier = 2f;
/// the amount of floating cubes we want
public int FloatingCubesAmount = 20;
[Header("Air Cubes")]
/// the chance (in percent) of a floating block spawning for every grid cell
public int FloatingBlockChance = 3;
/// the minimum height at which floating cubes can be found
public float MinHeight = 1f;
/// the maximum height at which floating cubes can be found
public float MaxHeight = 5f;
/// the radius around the dancer within which no floating cube should be spawned
public float MinDistanceToDancer = 2f;
/// the minimum scale for floating cubes
public float MinScale = 0.5f;
/// the maximum scale for floating cubes
public float MaxScale = 2f;
[Header("Materials")]
/// the main ground material
public Material GroundMaterial;
/// an alt material for the ground, used only for some cubes
public Material GroundMaterialAlt1;
/// another alt material for the ground, used only for some cubes
public Material GroundMaterialAlt2;
[Header("Bindings")]
/// the prefab to use for the ground cubes
public MMRadioReceiver GroundPrefabToInstantiate;
/// the node under which to nest all cubes
public Transform ParentContainer;
/// the dancer in the scene
public Transform Dancer;
[Header("Behaviour")]
/// whether or not to generate the ground on Awake
public bool GenerateOnAwake = false;
[Header("Debug")]
/// a test button to generate the ground
[MMInspectorButton("GenerateGround")]
public bool GenerateGroundBtn;
protected MMRadioReceiver _receiver;
protected Vector3 _wipPosition;
protected string _wipName;
protected int _counter;
///
/// On Awake we generate our ground if needed
///
protected virtual void Awake()
{
if (GenerateOnAwake)
{
GenerateGround();
}
}
///
/// Instantiates cubes to form a ground and randomizes their settings
///
protected virtual void GenerateGround()
{
int counter = 0;
List list = new List();
for (int i = 0; i< ParentContainer.transform.childCount; i++)
{
list.Add(ParentContainer.transform.GetChild(i).gameObject);
}
foreach(GameObject child in list)
{
counter++;
if (Application.isPlaying)
{
Destroy(child.gameObject);
}
else
{
DestroyImmediate(child.gameObject);
}
}
_counter = 0;
// we instantiate our ground grid
for (int i = 0; i < NumberOfRows; i++)
{
for (int j = 0; j < NumberOfColumns; j++)
{
_wipPosition.x = i * Width;
_wipPosition.y = 0;
_wipPosition.z = j * Depth;
_wipPosition += Offset;
_wipName = "GroundBlock_" + _counter;
InstantiateBlock(_wipPosition, _wipName);
_counter++;
}
}
// we generate some floating cubes too
for (int i = 0; i < NumberOfRows; i++)
{
for (int j = 0; j < NumberOfColumns; j++)
{
_wipPosition.x = i * Width;
_wipPosition.y = Random.Range(MinHeight,MaxHeight);
_wipPosition.z = j * Depth;
_wipPosition += Offset;
if ((MMMaths.Chance(FloatingBlockChance)) && (Vector3.Distance(_wipPosition, Dancer.transform.position) > MinDistanceToDancer))
{
_wipName = "AirBlock_" + _counter;
_receiver = InstantiateBlock(_wipPosition, _wipName);
_receiver.transform.localScale = _receiver.transform.localScale * Random.Range(MinScale, MaxScale);
_receiver.MinRandomLevelMultiplier *= 3f;
_receiver.MaxRandomLevelMultiplier *= 3f;
MMAutoRotate autoRotate = _receiver.gameObject.AddComponent();
autoRotate.RotationSpeed = new Vector3(0f, 100f, 0f);
_counter++;
}
}
}
}
protected virtual MMRadioReceiver InstantiateBlock(Vector3 newPosition, string newName)
{
// instantiating the block and setting its name
_receiver = Instantiate(GroundPrefabToInstantiate, newPosition, Quaternion.identity, ParentContainer);
if (ParentContainer == null)
{
SceneManager.MoveGameObjectToScene(_receiver.gameObject, this.gameObject.scene);
}
_receiver.name = newName;
// setting its receiver settings
float distanceToDancer = Vector3.Distance(Dancer.transform.position + DancerOffset, newPosition);
float maxDistance = Mathf.Max(NumberOfColumns * Depth, NumberOfRows * Width) / 2f;
float remappedDistance = MMMaths.Remap(distanceToDancer, 0f, maxDistance, 0f, 1f);
float newAmplitude = Amplitude.Evaluate(remappedDistance);
float random = Random.Range(MinRandom, MaxRandom);
newAmplitude *= random;
newAmplitude *= AmplitudeMultiplier;
int channel = Random.Range(0, 2);
_receiver.MinRandomLevelMultiplier = newAmplitude;
_receiver.MaxRandomLevelMultiplier = newAmplitude;
_receiver.GenerateRandomLevelMultiplier();
_receiver.Channel = channel;
// setting its material
float randomMaterial = Random.Range(0f, 100f);
if (randomMaterial < 80f)
{
_receiver.GetComponent().material = GroundMaterial;
}
else
{
if (randomMaterial < 90f)
{
_receiver.GetComponent().material = GroundMaterialAlt1;
}
else
{
_receiver.GetComponent().material = GroundMaterialAlt2;
}
}
// setting its position
_receiver.transform.position = newPosition;
return _receiver;
}
}
}