using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
///
/// Handles detecting whether or not a real-world location is valid for placing a Bunny object
/// in the ZED plane detection samples. To be valid, it must find a plane at the given location
/// and that plane must face upward. Turns a placeholder object blue when valid, and red when not.
/// Also works with VR controllers if the SteamVR or Oculus Integration plugins are installed.
///
public class BunnyPlacement : MonoBehaviour
{
///
/// Textures assigned to the placeholder object when placement is valid.
/// Index of each texture corresponds to the index of the material on the placeholder object.
///
[Tooltip("Textures assigned to the placeholder object when placement is valid. " +
"Index of each texture corresponds to the index of the material on the placeholder object.")]
public Texture[] goodPlacementTex;
///
/// Textures assigned to the placeholder object when placement is not valid.
/// Index of each texture corresponds to the index of the material on the placeholder object.
///
[Tooltip("Textures assigned to the placeholder object when placement is not valid. " +
"Index of each texture corresponds to the index of the material on the placeholder object.")]
public Texture[] badPlacementTex;
///
/// Light object in the placeholder object. We change its color based on placement validity.
///
private Light pointlight;
///
/// The ZEDControllerTracker object in the VR controller used to place the object, if applicable.
///
private ZEDControllerTracker_DemoInputs tracker;
///
/// The scene's ZED Plane Detection Manager.
///
private ZEDPlaneDetectionManager zedPlane;
///
/// The BunnySpawner object, normally on the same object as this component.
///
private BunnySpawner bunnySpawner;
///
/// The placeholder object's transform.
///
private Transform placeholder;
///
/// Whether or not we are able to spawn a bunny here.
///
private bool canspawnbunny;
///
/// Possible states of the button used for input, whether the spacebar, a VR controller trigger, etc.
///
public enum state
{
Idle,
Down,
Press,
Up
};
///
/// The current state of the button used for input.
///
public state button { get; private set; }
///
/// Awake is used to initialize any variables or game state before the game starts.
///
void Awake()
{
canspawnbunny = false;
tracker = GetComponent();
zedPlane = FindObjectOfType();
bunnySpawner = GetComponent();
}
///
/// Sets a reference to the placeholder object. Set from BunnySpawner.cs.
///
/// The placeholder object.
public void SetPlaceholder(Transform pointer)
{
placeholder = pointer;
pointlight = pointer.GetChild(0).GetComponentInChildren();
}
///
/// Update is called every frame.
/// Here we receive the input from the Controller.
/// Then we decide what to do in each case.
///
private void Update()
{
if (tracker == null)
{
if (Input.GetKeyDown(KeyCode.Space))
button = state.Down;
else if (Input.GetKey(KeyCode.Space))
button = state.Press;
else if (Input.GetKeyUp(KeyCode.Space))
button = state.Up;
else
button = state.Idle;
}
else
{
if (tracker.CheckClickButton(ControllerButtonState.Down))
button = state.Down;
else if (tracker.CheckClickButton(ControllerButtonState.Held))
button = state.Press;
else if (tracker.CheckClickButton(ControllerButtonState.Up))
button = state.Up;
else button = state.Idle;
}
//If the Trigger Button is being used.
if (button != state.Idle)
{
//It just got pressed.
if (button == state.Down)
{
//Enable the bunnySpawner to display the placeholder.
bunnySpawner.canDisplayPlaceholder = true;
//If we were holding the baseball bat but the user wants to re-place the bunny, hide the baseball bat.
if (bunnySpawner.baseballBat != null)
bunnySpawner.baseballBat.SetActive(false);
//Clean up the list of detected planes.
if (zedPlane.hitPlaneList.Count > 0)
{
for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
{
Destroy(zedPlane.hitPlaneList[i].gameObject);
zedPlane.hitPlaneList.RemoveAt(i);
}
}
//Destroy the current Bunny, if any, on the scene.
if (!bunnySpawner.canSpawnMultipleBunnies && bunnySpawner.currentBunny != null)
{
Destroy(bunnySpawner.currentBunny);
bunnySpawner.currentBunny = null;
}
}
//From the first input to the next ones as it keeps being hold down.
if (button == state.Press || button == state.Down)
{
if (zedPlane.hitPlaneList.Count == 0)
{
//Start detecting planes through the ZED Plane Detection Manager.
foreach (ZEDManager manager in ZEDManager.GetInstances()) //Check all active ZED cameras for planes.
{
if (zedPlane.DetectPlaneAtHit(manager, manager.GetMainCamera().WorldToScreenPoint(placeholder.position)))
{
//Get the normal of the plane.
ZEDPlaneGameObject currentPlane = zedPlane.hitPlaneList[zedPlane.hitPlaneList.Count - 1];
Vector3 planeNormal = currentPlane.worldNormal;
//Check if the plane has a normal close enough to Y (horizontal surface) to be stable for the Bunny to spawn into.
if (Vector3.Dot(planeNormal, Vector3.up) > 0.85f)
{
//Allow spawning the Bunny, and set the placeholder to a positive color.
if (canspawnbunny == false)
{
canspawnbunny = true;
bunnySpawner.placeHolderMat[0].mainTexture = goodPlacementTex[0];
bunnySpawner.placeHolderMat[1].mainTexture = goodPlacementTex[1];
pointlight.color = Color.blue;
}
else //Clear the list of planes.
{
for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
{
if (i == 0)
{
Destroy(zedPlane.hitPlaneList[i].gameObject);
zedPlane.hitPlaneList.RemoveAt(i);
}
}
}
}
else //Surface wasn't horizontal enough
{
//Don't allow the Bunny to spawn, and set the placeholder to a negative color.
canspawnbunny = false;
bunnySpawner.placeHolderMat[0].mainTexture = badPlacementTex[0];
bunnySpawner.placeHolderMat[1].mainTexture = badPlacementTex[1];
pointlight.color = Color.red;
//Clear the list of planes.
for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
{
Destroy(zedPlane.hitPlaneList[i].gameObject);
zedPlane.hitPlaneList.RemoveAt(i);
}
}
break; //If we detected a plane in one view, no need to go through the rest of the cameras.
}
}
}
else if (zedPlane.hitPlaneList.Count > 0)
{
if (!Physics.Raycast(transform.position, placeholder.position - transform.position))
{
//Don't allow for the Bunny to spawn, and set the placeholder to a negative color.
canspawnbunny = false;
bunnySpawner.placeHolderMat[0].mainTexture = badPlacementTex[0];
bunnySpawner.placeHolderMat[1].mainTexture = badPlacementTex[1];
pointlight.color = Color.red;
//Clear the list of planes.
for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
{
Destroy(zedPlane.hitPlaneList[i].gameObject);
zedPlane.hitPlaneList.RemoveAt(i);
}
}
}
}
//Button is released.
if (button == state.Up)
{
//If at that moment the bunny was allowed to spawn, proceed ot make the call.
if (canspawnbunny)
{
bunnySpawner.SpawnBunny(placeholder.position);
}
else //Clear the list of planes.
{
for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
{
Destroy(zedPlane.hitPlaneList[i].gameObject);
zedPlane.hitPlaneList.RemoveAt(i);
}
}
//Reset the booleans.
canspawnbunny = false;
bunnySpawner.canDisplayPlaceholder = false;
}
}
}
}