/* Crowd Simulator Engine
** Copyright (C) 2018 - Inria Rennes - Rainbow - Julien Pettre
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
** Authors: Julien Bruneau
**
** Contact: crowd_group@inria.fr
*/
using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
///
/// Main manager: Load the scene, create all the agents and manage users input
///
public class LoadEnv : MonoBehaviour
{
#region attributes
List avatars; // List of agents
public GameObject cam; // Scene camera
private CamRecorder cam_Rec; // Control scene recording
private CamMvt cam_Movement; // Control camera movement behavior
private MenuManager menuM; // Control the starting menu
//private float rotSpeed = 5;
// --------------------------
// CAMERA MOVEMENT PARAMETERS
const float camTranslationSpeed = 25.0f; // Camera translation speed
const float camShiftPower = 250.0f; // Shift effect on camera speed
const float camMaxShiftPower = 1000.0f; // Maximun shift effect on camera speed
const float camRotationSpeed = 0.25f; // Rotation speed
Vector3 lastMouse = new Vector3(255, 255, 255); // Last mouse position to check its movement
float camShiftHold = 1.0f; // Control the effect of shift with holding time
#endregion
///
/// Scene and agents initialization
///
void Start()
{
avatars = new List();
cam_Rec = cam.GetComponent();
cam_Movement = cam.GetComponent();
cam_Rec.enabled = false;
cam_Movement.enabled = false;
menuM = gameObject.GetComponent();
}
///
/// Load a scenario: create stage and spawn agents
///
/// The path to the scenario file
public void loadScenario(string trajDir)
{
// --------------------------------------------------
// SET RANDOM SEED TO HAVE SAME RESULTS AT EVERY RUNS
Random.InitState(75482);
// ---------------------------------
// INITIALIZE SCENE FROM CONFIG FILE
// -------------
// CAMERA CONFIG
cam_Rec.enabled = true;
cam_Movement.enabled = true;
cam.transform.position = ConfigReader.camPosition;
cam.transform.rotation = Quaternion.Euler(ConfigReader.camRotation);
cam_Movement.lookAt_Id = ConfigReader.camLookAtTarget;
cam_Movement.follow_Id = ConfigReader.camFollowTarget;
cam_Movement.follow_LockX = !ConfigReader.camFollowOnX;
cam_Movement.follow_LockZ = !ConfigReader.camFollowOnY;
// -------------
// RECORD CONFIG
cam_Rec.record = ConfigReader.recording;
cam_Rec.timeToStart = ConfigReader.recordingStart;
cam_Rec.timeToStop = ConfigReader.recordingEnd;
cam_Rec.framerate = ConfigReader.recordingFramerate;
//FB don't know why there this check
if (ConfigReader.recordingSaveDir[1] != ':')
cam_Rec.saveDir = Directory.GetCurrentDirectory().Replace("\\", "/") + "/" + ConfigReader.recordingSaveDir;
else
cam_Rec.saveDir = ConfigReader.recordingSaveDir;
Camera.main.GetComponent().Init();
InitDeepRecorders();
// ---------------------
// CLEAR PREVIOUS AGENTS
foreach (GameObject a in avatars)
{
Destroy(a);
}
avatars.Clear();
// -------------
// CREATE AGENTS
DirectoryInfo dir = new DirectoryInfo(trajDir);
FileInfo[] info = dir.GetFiles("*.csv");
if (info.Length == 0)
info = dir.GetFiles("*.txt");
var crowdParentObject = new GameObject("Crowd");
FollowTrajectory tmpFollower;
int i = 0;
object testRocketMan = Resources.Load("rocketboxtxtvar/Prefabs/f001");
foreach (FileInfo f in info)
{
// ------------------------------------------------------------
// IF NO ROCKETMAN (PROPRIETARY ASSETS), USE PLASTICMAN INSTEAD
GameObject character = (testRocketMan!=null) ? CreateAgent_RocketBox(i) : CreateAgent_PlasticMan(i);
character.transform.parent = crowdParentObject.transform;
avatars.Add(character);
// ---------------------
// SET NAME, TAG, AND ID
character.name += i.ToString("D4");
character.tag = "Player";
character.GetComponent().ID = i;
// ----------------------------------
// FOLLOWTRAJECTORY SCRIPT MANAGEMENT
// Setup of the CSV filename and disable the start synchro
tmpFollower = character.GetComponent();
tmpFollower.SetCsvFilename(f.FullName);
tmpFollower._SyncLaunchWithTrajectory = true; // start the character at the csv time
// -------------------------------
// Load animation controller from ressources
string PathAnimeController = "PlasticMan/Animation/LocomotionFinal";
character.GetComponent().runtimeAnimatorController = Resources.Load(PathAnimeController) as RuntimeAnimatorController;
// make sure that object on the floor (height 0)
character.transform.position = new Vector3(character.transform.position.x, 0.0f, character.transform.position.z);
i++;
}
cam_Movement.updateTargetedObject();
}
///
/// Manage which deep recorder is used and initialize it
///
private void InitDeepRecorders()
{
GameObject DeepRecorders = GameObject.FindGameObjectWithTag("DeepRecorders");
if (ConfigReader.recordingBodyBoundingBoxes)
DeepRecorders.GetComponent().Init(ConfigReader.recordingSaveDir);
else
DeepRecorders.GetComponent().enabled = false;
if (ConfigReader.recordingHeadBoundingBoxes)
DeepRecorders.GetComponent().Init(ConfigReader.recordingSaveDir);
else
DeepRecorders.GetComponent().enabled = false;
}
Color? GetColorForAgentId(int id)
{
if (ConfigReader.agentsColor != null && ConfigReader.agentsColor.Count > 0)
{
foreach (ConfigAgentColor c in ConfigReader.agentsColor)
{
if (id > c.firstAgent - 1 && id < c.lastAgent + 1 && (id - c.firstAgent) % c.step == 0)
return new Color(c.red, c.green, c.blue, 1);
}
}
return null;
}
Material CreateMaterialWithColor(Color color)
{
var tmpMaterial = new Material(Shader.Find("Legacy Shaders/Diffuse"));
tmpMaterial.color = color;
return tmpMaterial;
}
string GetModelName_RocketBox(int id)
{
string path;
int modelId;
if (id % 2 == 0)
{
path = "Prefabs/m";
modelId = id / 2;
}
else
{
path = "Prefabs/f";
modelId = (id - 1) / 2;
}
modelId = (modelId % 20) + 1;
return "rocketboxtxtvar/" + path + modelId.ToString("D3");
}
GameObject CreateAgent_RocketBox(int id)
{
// -------------------
// LOAD AGENT IN UNITY
GameObject gameObject = Instantiate(Resources.Load(GetModelName_RocketBox(id)));
// -------------------
// SET BOUNDING BOXES ITEM
gameObject.AddComponent();
gameObject.AddComponent();
GameObject headBoundingBox = Instantiate(Resources.Load("HeadBoundingBoxes/Hbb_RocketBox"));
Transform Head = gameObject.transform.Find("Bip01/Bip01 Pelvis/Bip01 Spine/Bip01 Spine1/Bip01 Spine2/Bip01 Neck/Bip01 Head");
headBoundingBox.transform.parent = Head;
// ---------------------------------------------
// SET AGENT'S COLOR WHEN SPECIFY IN CONFIG FILE
var tmpColor = GetColorForAgentId(id);
if (tmpColor.HasValue)
{
var tmpMaterial = CreateMaterialWithColor(tmpColor.Value);
Material[] mats = new Material[] { tmpMaterial, tmpMaterial, tmpMaterial };
SkinnedMeshRenderer[] rendererList = gameObject.GetComponentsInChildren();
foreach (SkinnedMeshRenderer renderer in rendererList)
renderer.materials = mats;
}
return gameObject;
}
GameObject CreateAgent_PlasticMan(int id)
{
// -------------------
// LOAD AGENT IN UNITY
GameObject gameObject = Instantiate(Resources.Load("PlasticMan/plasticman"));
// -------------------
// SET BOUNDING BOXES ITEM
gameObject.AddComponent();
GameObject headBoundingBox = Instantiate(Resources.Load("HeadBoundingBoxes/Hbb_PlasticMan"));
Transform Head = gameObject.transform.Find("Plasticman:Reference/Plasticman:Hips/Plasticman:Spine/Plasticman:Spine1/Plasticman:Spine2/Plasticman:Spine3/Plasticman:Neck/Plasticman:Head");
headBoundingBox.transform.parent = Head;
// -----------------
// SET AGENT'S COLOR
var tmpColor = GetColorForAgentId(id);
if (!tmpColor.HasValue)
tmpColor = new Color(Random.value, Random.value, Random.value, 1);
var tmpRenderer = gameObject.GetComponentInChildren();
tmpRenderer.material = CreateMaterialWithColor(tmpColor.Value);
return gameObject;
}
///
/// Update camera state
///
private void Update()
{
ConfigReader.camPosition = cam.transform.position;
ConfigReader.camRotation = cam.transform.rotation.eulerAngles;
}
///
/// Manage users Input
///
void LateUpdate()
{
// -------------------
// ESCAPE => EXIT APPS
if (Input.GetKeyDown(KeyCode.Escape) == true)
{
menuM.toogleMenu();
}
// -------------------------------
// MOUSE + RCLICK => ROTATE CAMERA
if (Input.GetMouseButton(1))
{
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camRotationSpeed, lastMouse.x * camRotationSpeed, 0);
lastMouse = new Vector3(cam.transform.eulerAngles.x + lastMouse.x, cam.transform.eulerAngles.y + lastMouse.y, 0);
// Block all the way up or down to prevent glitches
if (lastMouse.x > 180 && lastMouse.x < 270)
lastMouse.x = 270;
else if (lastMouse.x > 90 && lastMouse.x < 180)
lastMouse.x = 90;
cam.transform.eulerAngles = lastMouse;
}
lastMouse = Input.mousePosition;
// -----------------------------------------
// ARROWS, SHIFT, CTRL => CAMERA TRANSLATION
Vector3 p = new Vector3();
if (Input.GetKey(KeyCode.UpArrow))
{
p += new Vector3(0, 0, 1);
}
if (Input.GetKey(KeyCode.DownArrow))
{
p += new Vector3(0, 0, -1);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
p += new Vector3(-1, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow))
{
p += new Vector3(1, 0, 0);
}
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
camShiftHold += Time.fixedUnscaledDeltaTime;
p = p * Mathf.Max(camShiftHold * camShiftPower, camMaxShiftPower);
}
else
{
camShiftHold = Mathf.Clamp(camShiftHold * 0.5f, 1f, 1000f);
p = p * camTranslationSpeed;
}
p = p * Time.fixedUnscaledDeltaTime;
Vector3 newPosition = cam.transform.position;
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
{ //If player wants to move on X and Z axis only
cam.transform.Translate(p);
newPosition.x = cam.transform.position.x;
newPosition.z = cam.transform.position.z;
cam.transform.position = newPosition;
}
else
{
cam.transform.Translate(p);
}
// --------------------------
// F5 => SAVE CAMERA POSITION
if (Input.GetKeyDown(KeyCode.F5))
{
menuM.saveConfig();
}
// ----------------------
// SPACE => PAUSE UNPAUSE
if (Input.GetKeyDown(KeyCode.Space))
{
if (Time.timeScale == 0)
Time.timeScale = 1;
else
Time.timeScale = 0;
}
}
}