using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[SelectionBase]
public class LeafPhysics : MonoBehaviour {
private Rigidbody body;
public Rigidbody Body { get { return body; } }
private LeafHandler leafHandler;
private List<Material> mats = new List<Material>();
public IEnumerable<Material> Mats { get { return mats; } }
// Use this for initialization
void Start () {
body = GetComponentInChildren<Rigidbody>();
PlusX = new TweeningForce(0, 1, 0.5f, 2);
MinusX = new TweeningForce(0, 1, 0.5f, 2);
PlusZ = new TweeningForce(0, 1, 0.5f, 2);
MinusZ = new TweeningForce(0, 1, 0.5f, 2);
TorqueX = new TweeningForce(-1, 1, 0.5f, 2);
TorqueZ = new TweeningForce(-1, 1, 0.5f, 2);
leafHandler = GameObject.FindObjectOfType<LeafHandler>();
if (leafHandler != null)
{
leafHandler.AddLeaf(this);
}
deadLifeSpan = UnityEngine.Random.Range(20, 40.0f);
deadLife = deadLifeSpan;
foreach (MeshRenderer mr in GetComponentsInChildren<MeshRenderer>())
{
mats.Add(mr.material);
}
Color c = Color.white;
c.r = UnityEngine.Random.Range(0.6f, 1.0f);
c.g = UnityEngine.Random.Range(0.6f, 1.0f);
c.b = UnityEngine.Random.Range(0.6f, 1.0f);
foreach (Material m in mats)
{
m.color = c;
}
}
void OnDestroy()
{
if (leafHandler != null)
{
leafHandler.RemoveLeaf(this);
}
}
//public float TorqueForceUpScale = 0.3f;
public float TorqueScale = 1.0f;
public float TorqueBounds = 5.0f;
public float TorqueSideScale = 1.0f;
public float SideRestitution = 0.5f;
//public float MaxForceUp = 1.0f;
//
//public float VelDownForceScale = 0.5f;
//public float VelDownForceDivide = 3f;
//
//public float StartPushVelDown = 3.0f;
//public float PushUpCurrent = 0;
//public float PushUpForce = 10;
//public float PushUpDecayRate = 1;
public bool Debug = false;
private TweeningForce PlusX;
private TweeningForce MinusX;
private TweeningForce PlusZ;
private TweeningForce MinusZ;
private TweeningForce TorqueX;
private TweeningForce TorqueZ;
private class TweeningForce
{
private float min, max, minMoveSpeed, maxMoveSpeed, current, target, speed;
public float Current { get { return current; } }
public TweeningForce(float min, float max, float minMoveSpeed, float maxMoveSpeed)
{
this.min = min;
this.max = max;
this.minMoveSpeed = minMoveSpeed;
this.maxMoveSpeed = maxMoveSpeed;
this.current = UnityEngine.Random.Range(min, max);
UpdateTarget();
}
private void UpdateTarget()
{
this.target = UnityEngine.Random.Range(min, max);
this.speed = UnityEngine.Random.Range(minMoveSpeed, maxMoveSpeed);
}
public void Update(float timeElapsed)
{
float moveAmount = speed * timeElapsed;
if (moveAmount >= Math.Abs(current - target))
{
current = target;
UpdateTarget();
}
else
{
float move = Math.Max(-moveAmount, Math.Min(moveAmount, target - current));
current += move;
}
}
}
public float BaseWindForce = 10;
public float AnglePow = 2;
private float deadLife = 0;
private float deadLifeSpan = 1;
private bool isFading = false;
public bool Resting = false;
private void FixedUpdate()
{
Resting = false;
}
private void OnCollisionStay(Collision collision)
{
Resting = collision.contacts.Length > 0 && Mathf.Abs(collision.contacts[0].normal.y) > 0.7f;
}
// Update is called once per frame
void Update () {
if (!body.isKinematic && body.velocity.sqrMagnitude > 0.01f)
{
deadLife = deadLifeSpan;
float baseForceUp = Mathf.Max(BaseWindForce * Mathf.Pow(Mathf.Abs(transform.up.y), AnglePow) * -body.velocity.y) * Time.deltaTime * 60;
body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + PlusX.Current), transform.position + Vector3.right * 0.4f);
body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + MinusX.Current), transform.position - Vector3.right * 0.4f);
body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + PlusZ.Current), transform.position + Vector3.forward * 0.4f);
body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + MinusZ.Current), transform.position - Vector3.forward * 0.4f);
/*
if (body.velocity.y < -StartPushVelDown)
{
PushUpCurrent = PushUpForce;
}
body.AddForce(Vector3.up * PushUpCurrent);
PushUpCurrent = Mathf.Max(0, PushUpCurrent - PushUpDecayRate * Time.deltaTime);
*/
Vector3 up = transform.up;
float torqueX = -up.x;
float torqueZ = -up.z;
float velYScale = Math.Max(0, -body.velocity.y);
body.AddRelativeForce(new Vector3(torqueX * TorqueSideScale, 0, torqueZ * TorqueSideScale) * velYScale);
//body.AddForce(Vector3.up * Mathf.Pow(Mathf.Max(-body.velocity.y / VelDownForceDivide), 2) * VelDownForceScale);
body.AddRelativeTorque(new Vector3(Mathf.Max(-TorqueBounds, Mathf.Min(TorqueBounds, torqueX * TorqueScale * 1.2f)) + TorqueX.Current * 0.5f, 0, Mathf.Max(-TorqueBounds, Mathf.Min(TorqueBounds, torqueZ * TorqueScale)) + TorqueZ.Current * 0.5f) * velYScale);
body.AddForce(new Vector3(-body.velocity.x, 0, -body.velocity.z) * SideRestitution * Time.deltaTime * 60);
}
else
{
deadLife -= Time.deltaTime * (leafHandler.NumLeaves >= leafHandler.MaxLeaves ? 3 : 1);
if (deadLife <= 0 && !isFading)
{
isFading = true;
SimpleTween tweenOut = new SimpleTween();
tweenOut.Init(v =>
{
foreach (Material m in mats)
{
Color c = m.color;
c.a = v;
m.color = c;
}
}, SimpleTween.EaseLinear, 1, 0, 2);
GameObject t = this.gameObject;
tweenOut.OnFinish = () =>
{
Destroy(t);
};
Destroy(this);
}
}
if (transform.position.y < -5)
{
Destroy(gameObject);
}
}
}