Work in progress refactor of InputManager, added UI structure

more-targets
Daniel Lovell 2024-09-16 09:15:45 -07:00
parent cfd5653620
commit 16f663ec78
26 changed files with 1282 additions and 177 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9411e01e9e0fecb45ac53c53b65fa917
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,234 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class InputManager : MonoBehaviour
{
public static InputManager Instance { get; private set; }
public bool mouseActive = true;
[System.Serializable]
public struct CameraPreset
{
public Vector3 position;
public Quaternion rotation;
}
public float autoplayCamSpeed = 2f;
public float xAutoRotateTime = 5f;
public float yAutoRotateTime = 5f;
private Coroutine autoplayRoutine;
public bool lockUserInput = false;
private float _yaw = 0.0f;
private float _pitch = 0.0f;
private float reloadModifier;
private void Awake()
{
if (Instance == null) {
Instance = this;
DontDestroyOnLoad(gameObject);
} else {
Destroy(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
HandleInput();
}
private void HandleMouseInput()
{
if (Input.GetMouseButton(0))
{
CameraController.Instance.OrbitCamera(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
}
else if (Input.GetMouseButton(1))
{
CameraController.Instance.RotateCamera(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
}
}
private void HandleInput()
{
if (!lockUserInput)
{
HandleLockableInput();
}
HandleNonLockableInput();
}
void HandleScrollWheelInput()
{
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
CameraController.Instance.ZoomCamera(Input.GetAxis("Mouse ScrollWheel") * 500);
}
}
void HandleLockableInput()
{
HandleMouseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
reloadModifier = -.1f;
_cameraSpeed = _cameraSpeedMax;
}
else
{
reloadModifier = .1f;
_cameraSpeed = _cameraSpeedNormal;
}
// TRANSLATIONAL MOVEMENT
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Forward);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Left);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Back);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Right);
}
if (Input.GetKey(KeyCode.Q))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Up);
}
if (Input.GetKey(KeyCode.E))
{
CameraController.Instance.TranslateCamera(CameraController.TranslationInput.Down);
}
}
void HandleNonLockableInput()
{
HandleScrollWheelInput();
if (Input.GetKeyDown(KeyCode.I))
if (Input.GetKeyDown(KeyCode.C))
{
}
if (Input.GetKeyDown(KeyCode.Space))
{
// Pause the time
if (SimManager.Instance.IsSimulationRunning()) {
SimManager.Instance.PauseSimulation();
} else {
SimManager.Instance.ResumeSimulation();
}
}
if (Input.GetKeyDown(KeyCode.P))
{
autoRotate = !autoRotate;
if (autoRotate)
{
autoplayRoutine = StartCoroutine(AutoPlayRoutine());
}
else
{
StopCoroutine( autoplayRoutine );
}
}
if (Input.GetKeyDown(KeyCode.Alpha1))
{
// ORIGIN
transform.position = new Vector3(0, 20, -20);
SetCameraRotation(Quaternion.Euler(24f, -0.5f, 0));
Camera.main.fieldOfView = 45f;
ResetCameraTarget();
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
transform.position = new Vector3(0, 30, -20);
SetCameraRotation(Quaternion.Euler(36.6f, -0.5f, 0));
Camera.main.fieldOfView = 60f;
ResetCameraTarget();
}
if (Input.GetKeyDown(KeyCode.Alpha4))
{
if (Input.GetKey(KeyCode.LeftShift))
{
fourPos.position = transform.position;
fourPos.rotation = transform.rotation;
}
else
{
transform.position = fourPos.position;
SetCameraRotation(fourPos.rotation);
ResetCameraTarget();
}
}
if (Input.GetKeyDown(KeyCode.Alpha5))
{
if (Input.GetKey(KeyCode.LeftShift))
{
fivePos.position = transform.position;
fivePos.rotation = transform.rotation;
}
else
{
transform.position = fivePos.position;
SetCameraRotation(fivePos.rotation);
ResetCameraTarget();
}
}
if (Input.GetKeyDown(KeyCode.Alpha6))
{
if (Input.GetKey(KeyCode.LeftShift))
{
sixPos.position = transform.position;
sixPos.rotation = transform.rotation;
}
else
{
transform.position = sixPos.position;
SetCameraRotation(sixPos.rotation);
ResetCameraTarget();
}
}
}
}

8
Assets/Scripts/UI.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c17270294c7dd6d45b8731a468423a83
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +1,179 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System.Linq;
public class InputManager : MonoBehaviour public class CameraController : MonoBehaviour
{ {
#region Singleton
public static InputManager Instance { get; private set; } /// <summary>
/// Singleton instance of the CameraController.
/// </summary>
public static CameraController Instance { get; private set; }
#endregion
#region Camera Settings
/// <summary>
/// Determines if mouse input is active for camera control.
/// </summary>
public bool mouseActive = true; public bool mouseActive = true;
/// <summary>
/// Locks user input for camera control.
/// </summary>
public bool lockUserInput = false;
/// <summary>
/// Normal speed of camera movement.
/// </summary>
[SerializeField] private float _cameraSpeedNormal = 100.0f;
/// <summary>
/// Maximum speed of camera movement.
/// </summary>
[SerializeField] private float _cameraSpeedMax = 1000.0f;
/// <summary>
/// Current speed of camera movement.
/// </summary>
private float _cameraSpeed;
/// <summary>
/// Horizontal rotation speed.
/// </summary>
public float _speedH = 2.0f;
/// <summary>
/// Vertical rotation speed.
/// </summary>
public float _speedV = 2.0f;
/// <summary>
/// Current yaw angle of the camera.
/// </summary>
private float _yaw = 0.0f;
/// <summary>
/// Current pitch angle of the camera.
/// </summary>
private float _pitch = 0.0f;
#endregion
#region Orbit Settings
/// <summary>
/// Determines if the camera should auto-rotate.
/// </summary>
public bool autoRotate = false;
/// <summary>
/// Target transform for orbit rotation.
/// </summary>
public Transform target;
/// <summary>
/// Distance from the camera to the orbit target.
/// </summary>
[SerializeField] private float _orbitDistance = 5.0f;
/// <summary>
/// Horizontal orbit rotation speed.
/// </summary>
[SerializeField] private float _orbitXSpeed = 120.0f;
/// <summary>
/// Vertical orbit rotation speed.
/// </summary>
[SerializeField] private float _orbitYSpeed = 120.0f;
/// <summary>
/// Speed of camera zoom.
/// </summary>
[SerializeField] private float _zoomSpeed = 500.0f;
/// <summary>
/// Minimum vertical angle limit for orbit.
/// </summary>
public float orbitYMinLimit = -20f;
/// <summary>
/// Maximum vertical angle limit for orbit.
/// </summary>
public float orbitYMaxLimit = 80f;
/// <summary>
/// Minimum distance for orbit.
/// </summary>
private float _orbitDistanceMin = 10f;
/// <summary>
/// Maximum distance for orbit.
/// </summary>
private float _orbitDistanceMax = 10000f;
/// <summary>
/// Current horizontal orbit angle.
/// </summary>
private float _orbitX = 0.0f;
/// <summary>
/// Current vertical orbit angle.
/// </summary>
private float _orbitY = 0.0f;
#endregion
#region Rendering
/// <summary>
/// Renderer for the orbit target.
/// </summary>
public Renderer targetRenderer;
/// <summary>
/// Renderer for the floor.
/// </summary>
public Renderer floorRenderer;
/// <summary>
/// Alpha value for material transparency.
/// </summary>
public float matAlpha;
#endregion
#region Autoplay Settings
/// <summary>
/// Speed of camera movement during autoplay.
/// </summary>
public float autoplayCamSpeed = 2f;
/// <summary>
/// Duration of horizontal auto-rotation.
/// </summary>
public float xAutoRotateTime = 5f;
/// <summary>
/// Duration of vertical auto-rotation.
/// </summary>
public float yAutoRotateTime = 5f;
/// <summary>
/// Coroutine for autoplay functionality.
/// </summary>
private Coroutine autoplayRoutine;
#endregion
#region Camera Presets
/// <summary>
/// Represents a preset camera position and rotation.
/// </summary>
[System.Serializable] [System.Serializable]
public struct CameraPreset public struct CameraPreset
{ {
@ -18,60 +181,57 @@ public class InputManager : MonoBehaviour
public Quaternion rotation; public Quaternion rotation;
} }
public float autoplayCamSpeed = 2f; /// <summary>
public float xAutoRotateTime = 5f; /// Preset camera position for key 4.
public float yAutoRotateTime = 5f; /// </summary>
private Coroutine autoplayRoutine;
public bool lockUserInput = false;
private float _cameraSpeed;
public float _cameraSpeedNormal = 5.0f;
public float _cameraSpeedMax = 10.0f;
public float _speedH = 2.0f;
public float _speedV = 2.0f;
private float _yaw = 0.0f;
private float _pitch = 0.0f;
private float reloadModifier;
// Orbit controller
public bool autoRotate = false;
public Transform target;
public Renderer targetRenderer;
public Renderer floorRenderer;
public float matAlpha;
public float orbitDistance = 5.0f;
public float orbitXSpeed = 120.0f;
public float orbitYSpeed = 120.0f;
public float orbitYMinLimit = -20f;
public float orbitYMaxLimit = 80f;
public float orbitDistanceMin = .5f;
public float orbitDistanceMax = 15f;
private Rigidbody _rigidbody;
float x = 0.0f;
float y = 0.0f;
CameraPreset fourPos = new CameraPreset(); CameraPreset fourPos = new CameraPreset();
/// <summary>
/// Preset camera position for key 5.
/// </summary>
CameraPreset fivePos = new CameraPreset(); CameraPreset fivePos = new CameraPreset();
/// <summary>
/// Preset camera position for key 6.
/// </summary>
CameraPreset sixPos = new CameraPreset(); CameraPreset sixPos = new CameraPreset();
#endregion
#region Movement
/// <summary>
/// Mapping of translation inputs to movement vectors.
/// </summary>
private Dictionary<TranslationInput, Vector3> _translationInputToVectorMap;
/// <summary>
/// Forward movement vector.
/// </summary>
Vector3 wVector = Vector3.forward; Vector3 wVector = Vector3.forward;
/// <summary>
/// Left movement vector.
/// </summary>
Vector3 aVector = Vector3.left; Vector3 aVector = Vector3.left;
/// <summary>
/// Backward movement vector.
/// </summary>
Vector3 sVector = Vector3.back; Vector3 sVector = Vector3.back;
/// <summary>
/// Right movement vector.
/// </summary>
Vector3 dVector = Vector3.right; Vector3 dVector = Vector3.right;
/// <summary>
/// Angle between forward vector and camera direction.
/// </summary>
public float forwardToCameraAngle; public float forwardToCameraAngle;
#endregion
void SetCameraRotation(Quaternion rotation) void SetCameraRotation(Quaternion rotation)
{ {
transform.rotation = rotation; transform.rotation = rotation;
@ -96,6 +256,15 @@ public class InputManager : MonoBehaviour
} else { } else {
Destroy(gameObject); Destroy(gameObject);
} }
_translationInputToVectorMap = new Dictionary<TranslationInput, Vector3> {
{TranslationInput.Forward, wVector},
{TranslationInput.Left, aVector},
{TranslationInput.Back, sVector},
{TranslationInput.Right, dVector},
{TranslationInput.Up, Vector3.up},
{TranslationInput.Down, Vector3.down}
};
} }
// Start is called before the first frame update // Start is called before the first frame update
@ -109,18 +278,12 @@ public class InputManager : MonoBehaviour
sixPos.rotation = Quaternion.Euler(0, 0, 0); sixPos.rotation = Quaternion.Euler(0, 0, 0);
Vector3 angles = transform.eulerAngles; Vector3 angles = transform.eulerAngles;
x = angles.y; _orbitX = angles.y;
y = angles.x; _orbitY = angles.x;
UpdateTargetAlpha(); UpdateTargetAlpha();
} }
// Update is called once per frame
void Update()
{
HandleInput();
}
IEnumerator AutoPlayRoutine() IEnumerator AutoPlayRoutine()
{ {
while (true) while (true)
@ -128,32 +291,32 @@ public class InputManager : MonoBehaviour
float elapsedTime = 0f; float elapsedTime = 0f;
while (elapsedTime <= xAutoRotateTime) while (elapsedTime <= xAutoRotateTime)
{ {
x += Time.unscaledDeltaTime * autoplayCamSpeed * orbitDistance * 0.02f; _orbitX += Time.unscaledDeltaTime * autoplayCamSpeed * _orbitDistance * 0.02f;
UpdateCamPosition(); UpdateCamPosition(_orbitX, _orbitY);
elapsedTime += Time.unscaledDeltaTime; elapsedTime += Time.unscaledDeltaTime;
yield return null; yield return null;
} }
elapsedTime = 0f; elapsedTime = 0f;
while (elapsedTime <= yAutoRotateTime) while (elapsedTime <= yAutoRotateTime)
{ {
y -= Time.unscaledDeltaTime * autoplayCamSpeed * orbitDistance * 0.02f; _orbitY -= Time.unscaledDeltaTime * autoplayCamSpeed * _orbitDistance * 0.02f;
UpdateCamPosition(); UpdateCamPosition(_orbitX, _orbitY);
elapsedTime += Time.unscaledDeltaTime; elapsedTime += Time.unscaledDeltaTime;
yield return null; yield return null;
} }
elapsedTime = 0f; elapsedTime = 0f;
while (elapsedTime <= xAutoRotateTime) while (elapsedTime <= xAutoRotateTime)
{ {
x -= Time.unscaledDeltaTime * autoplayCamSpeed * orbitDistance * 0.02f; _orbitX -= Time.unscaledDeltaTime * autoplayCamSpeed * _orbitDistance * 0.02f;
UpdateCamPosition(); UpdateCamPosition(_orbitX, _orbitY);
elapsedTime += Time.unscaledDeltaTime; elapsedTime += Time.unscaledDeltaTime;
yield return null; yield return null;
} }
elapsedTime = 0f; elapsedTime = 0f;
while (elapsedTime <= yAutoRotateTime) while (elapsedTime <= yAutoRotateTime)
{ {
y += Time.unscaledDeltaTime * autoplayCamSpeed * orbitDistance * 0.02f; _orbitY += Time.unscaledDeltaTime * autoplayCamSpeed * _orbitDistance * 0.02f;
UpdateCamPosition(); UpdateCamPosition(_orbitX, _orbitY);
elapsedTime += Time.unscaledDeltaTime; elapsedTime += Time.unscaledDeltaTime;
yield return null; yield return null;
} }
@ -167,19 +330,19 @@ public class InputManager : MonoBehaviour
if(Physics.Raycast(transform.position, transform.forward, out hit, float.MaxValue, LayerMask.GetMask("Floor"), QueryTriggerInteraction.Ignore)) if(Physics.Raycast(transform.position, transform.forward, out hit, float.MaxValue, LayerMask.GetMask("Floor"), QueryTriggerInteraction.Ignore))
{ {
target.transform.position = hit.point; target.transform.position = hit.point;
orbitDistance = hit.distance; _orbitDistance = hit.distance;
Vector3 angles = transform.eulerAngles; Vector3 angles = transform.eulerAngles;
x = angles.y; _orbitX = angles.y;
y = angles.x; _orbitY = angles.x;
UpdateCamPosition(); UpdateCamPosition(_orbitX, _orbitY);
} }
else else
{ {
target.transform.position = transform.position + (transform.forward * 100); target.transform.position = transform.position + (transform.forward * 100);
orbitDistance = 100; _orbitDistance = 100;
Vector3 angles = transform.eulerAngles; Vector3 angles = transform.eulerAngles;
x = angles.y; _orbitX = angles.y;
y = angles.x; _orbitY = angles.x;
//UpdateCamPosition(); //UpdateCamPosition();
} }
} }
@ -188,44 +351,34 @@ public class InputManager : MonoBehaviour
public void EnableFloorGridRenderer(bool enable) { floorRenderer.enabled = enable; } public void EnableFloorGridRenderer(bool enable) { floorRenderer.enabled = enable; }
private void HandleMouseInput()
{ public void OrbitCamera(float xOrbit, float yOrbit) {
// Orbit
if (target) if (target)
{ {
if (Input.GetMouseButton(0)) _orbitX += xOrbit * _orbitXSpeed * _orbitDistance * 0.02f;
{ _orbitY -= yOrbit * _orbitYSpeed * _orbitDistance * 0.02f;
x += Input.GetAxis("Mouse X") * orbitXSpeed * orbitDistance * 0.02f;
y -= Input.GetAxis("Mouse Y") * orbitYSpeed * orbitDistance * 0.02f;
y = ClampAngle(y, orbitYMinLimit, orbitYMaxLimit);
UpdateCamPosition();
_orbitY = ClampAngle(_orbitY, orbitYMinLimit, orbitYMaxLimit);
UpdateCamPosition(_orbitX, _orbitY);
}
} }
// Rotate
else if (Input.GetMouseButton(1))
{
_yaw += _speedH * Input.GetAxis("Mouse X");
_pitch -= _speedV * Input.GetAxis("Mouse Y");
public void RotateCamera(float xRotate, float yRotate) {
_yaw += xRotate * _speedH;
_pitch -= yRotate * _speedV;
transform.eulerAngles = new Vector3(_pitch, _yaw, 0.0f); transform.eulerAngles = new Vector3(_pitch, _yaw, 0.0f);
} }
} private void UpdateCamPosition(float x, float y)
}
private void UpdateCamPosition()
{ {
Quaternion rotation = Quaternion.Euler(y, x, 0); Quaternion rotation = Quaternion.Euler(y, x, 0);
RaycastHit hit; RaycastHit hit;
//Debug.DrawLine(target.position, transform.position, Color.red); //Debug.DrawLine(target.position, transform.position, Color.red);
if (Physics.Linecast(target.position, transform.position, out hit, ~LayerMask.GetMask("Floor"), QueryTriggerInteraction.Ignore)) if (Physics.Linecast(target.position, transform.position, out hit, ~LayerMask.GetMask("Floor"), QueryTriggerInteraction.Ignore))
{ {
orbitDistance -= hit.distance; _orbitDistance -= hit.distance;
} }
Vector3 negDistance = new Vector3(0.0f, 0.0f, -orbitDistance); Vector3 negDistance = new Vector3(0.0f, 0.0f, -_orbitDistance);
Vector3 position = rotation * negDistance + target.position; Vector3 position = rotation * negDistance + target.position;
UpdateTargetAlpha(); UpdateTargetAlpha();
@ -233,27 +386,16 @@ public class InputManager : MonoBehaviour
transform.position = position; transform.position = position;
} }
private void HandleInput()
{
if (!lockUserInput)
{
HandleLockableInput();
}
HandleNonLockableInput();
}
void HandleScrollWheelInput() public void ZoomCamera(float zoom)
{ {
if (Input.GetAxis("Mouse ScrollWheel") != 0) _orbitDistance = Mathf.Clamp(_orbitDistance - zoom * _zoomSpeed, _orbitDistanceMin, _orbitDistanceMax);
{ UpdateCamPosition(_orbitX, _orbitY);
orbitDistance = Mathf.Clamp(orbitDistance - Input.GetAxis("Mouse ScrollWheel") * 500, orbitDistanceMin, orbitDistanceMax);
UpdateCamPosition();
}
} }
void UpdateTargetAlpha() void UpdateTargetAlpha()
{ {
matAlpha = (orbitDistance - orbitDistanceMin) / (orbitDistanceMax - orbitDistanceMin); matAlpha = (_orbitDistance - _orbitDistanceMin) / (_orbitDistanceMax - _orbitDistanceMin);
matAlpha = Mathf.Max(Mathf.Sqrt(matAlpha) - 0.5f, 0); matAlpha = Mathf.Max(Mathf.Sqrt(matAlpha) - 0.5f, 0);
Color matColor = targetRenderer.material.color; Color matColor = targetRenderer.material.color;
matColor.a = matAlpha; matColor.a = matAlpha;
@ -297,88 +439,40 @@ public class InputManager : MonoBehaviour
} }
public enum TranslationInput {
Forward,
Left,
Back,
Right,
Up,
Down
}
public void TranslateCamera(TranslationInput input) {
UpdateDirectionVectors();
target.Translate(_translationInputToVectorMap[input] * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition(_orbitX, _orbitY);
}
void HandleLockableInput() void HandleLockableInput()
{ {
HandleMouseInput();
if (Input.GetKey(KeyCode.LeftShift)) if (Input.GetKey(KeyCode.LeftShift))
{ {
reloadModifier = -.1f;
_cameraSpeed = _cameraSpeedMax; _cameraSpeed = _cameraSpeedMax;
} }
else else
{ {
reloadModifier = .1f;
_cameraSpeed = _cameraSpeedNormal; _cameraSpeed = _cameraSpeedNormal;
} }
// TRANSLATIONAL MOVEMENT
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
UpdateDirectionVectors();
//transform.Translate(Vector3.forward * Time.deltaTime * _cameraSpeed);
target.Translate(wVector * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
UpdateDirectionVectors();
//transform.Translate(Vector3.left * Time.deltaTime * _cameraSpeed);
target.Translate(aVector * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
UpdateDirectionVectors();
//transform.Translate(Vector3.back * Time.deltaTime * _cameraSpeed);
target.Translate(sVector * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
UpdateDirectionVectors();
//transform.Translate(Vector3.right * Time.deltaTime * _cameraSpeed);
target.Translate(dVector * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
if (Input.GetKey(KeyCode.Q))
{
//transform.Translate(Vector3.up * Time.deltaTime * _cameraSpeed);
target.Translate(Vector3.up * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
if (Input.GetKey(KeyCode.E))
{
//transform.Translate(Vector3.down * Time.deltaTime * _cameraSpeed);
target.Translate(Vector3.down * Time.unscaledDeltaTime * _cameraSpeed);
UpdateCamPosition();
}
} }
void HandleNonLockableInput() void HandleNonLockableInput()
{ {
HandleScrollWheelInput();
if (Input.GetKeyDown(KeyCode.I))
if (Input.GetKeyDown(KeyCode.C))
{
}
if (Input.GetKeyDown(KeyCode.Space))
{
// Pause the time
if (SimManager.Instance.IsSimulationRunning()) {
SimManager.Instance.PauseSimulation();
} else {
SimManager.Instance.ResumeSimulation();
}
}
if (Input.GetKeyDown(KeyCode.P)) if (Input.GetKeyDown(KeyCode.P))
{ {
autoRotate = !autoRotate; autoRotate = !autoRotate;

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b9e222cf9df32df4196f08036d68d740
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 27829404610ae9a479fd6f44c6da81ca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BotStatusDialog : UIDialog
{
// Start is called before the first frame update
public override void Start()
{
base.Start();
UISelectableEntry missiles = CreateSelectableEntry();
missiles.SetTextContent(new List<string>(new string[] { "Missiles" }));
missiles.SetIsSelectable(false);
UISelectableEntry submunitions = CreateSelectableEntry();
submunitions.SetTextContent(new List<string>(new string[] { "Submunitions" }));
submunitions.SetIsSelectable(false);
UISelectableEntry targets = CreateSelectableEntry();
targets.SetTextContent(new List<string>(new string[] { "Targets" }));
targets.SetIsSelectable(false);
SetDialogEntries(new List<UISelectableEntry>(new UISelectableEntry[] { missiles, submunitions, targets }));
AddDialogTab("All", () => { });
}
// Update is called once per frame
void Update()
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a404f59a5c2ba814a9c1ca121b596df9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
using UnityEngine;
public static class RectTransformExtensions
{
public static void SetLeft(this RectTransform rt, float left)
{
rt.offsetMin = new Vector2(left, rt.offsetMin.y);
}
public static void SetRight(this RectTransform rt, float right)
{
rt.offsetMax = new Vector2(-right, rt.offsetMax.y);
}
public static void SetTop(this RectTransform rt, float top)
{
rt.offsetMax = new Vector2(rt.offsetMax.x, -top);
}
public static void SetBottom(this RectTransform rt, float bottom)
{
rt.offsetMin = new Vector2(rt.offsetMin.x, bottom);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c991d4191b4586742a5d8dfc8ece23bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIBuildButton : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56ea3cedd2ebcbc42a98ea19ebc61632
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,213 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System;
using UnityEngine.UI;
public class UIDialog : MonoBehaviour
{
[SerializeField]
private string dialogTitle;
[SerializeField]
private TextMeshProUGUI dialogTitleHandle;
[SerializeField]
private RectTransform contentHandle;
/// TABS
[SerializeField]
private float tabWidth = 50f;
[SerializeField]
private float tabHeight = 16f;
// List of dialog tabs
private List<GameObject> dialogTabs;
/// ENTRIES
private List<UISelectableEntry> entries;
private float entryHeight = 20f;
private float entryIndentWidth= 10f;
private List<UISelectableEntry> cleanupPool;
private bool isOpen;
// Start is called before the first frame update
public virtual void Start()
{
dialogTitleHandle.text = dialogTitle;
dialogTitleHandle.font = UIManager.Instance.Font;
isOpen = gameObject.activeSelf;
dialogTabs = new List<GameObject>();
entries = new List<UISelectableEntry>();
cleanupPool = new List<UISelectableEntry>();
}
internal RectTransform GetContentHandle()
{
return contentHandle;
}
public bool IsOpen()
{
return isOpen;
}
protected virtual void OnEnable() { isOpen = true; }
protected virtual void OnDisable() { isOpen = false; }
public float GetTabWidth() { return tabWidth; }
public float GetTabHeight() { return tabHeight; }
/// <summary>
/// Returns the height of the dialog title bar
/// </summary>
public float GetTitleBarHeight() { return dialogTitleHandle.rectTransform.sizeDelta.y; }
/// <summary>
/// Adds a new tab to the dialog, when clicked it will call the given callback
/// </summary>
public void AddDialogTab(string tabName, Action onClick)
{
dialogTabs.Add(AddTabButton(tabName, onClick));
}
/// <summary>
/// Add the tab button to the right of the existing tabs
/// </summary>
private GameObject AddTabButton(string tabName, Action onClick)
{
GameObject tabButton = new GameObject("TabButton", typeof(RectTransform));
tabButton.transform.SetParent(transform); // worldPositionStays ?
// RectTransform anchors to the right of the content handle
RectTransform rTransform = tabButton.GetComponent<RectTransform>();
rTransform.anchorMin = new Vector2(0, 1);
rTransform.anchorMax = new Vector2(0, 1);
rTransform.pivot = new Vector2(0, 1);
rTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
// Count tabs * tabSize to get the position from the left
rTransform.anchoredPosition = new Vector2(tabWidth * dialogTabs.Count, -(GetTitleBarHeight()));
// Add the onClick callback to the button
Button button = tabButton.AddComponent<Button>();
button.onClick.AddListener(() => onClick());
// Add the image to the button and link it to the tab
button.targetGraphic = tabButton.AddComponent<Image>();
AddTabText(tabName, tabButton);
return tabButton;
}
/// <summary>
/// Add text as a child of the tab's button object
/// </summary>
private void AddTabText(string tabName, GameObject tabButton)
{
GameObject tabText = new GameObject("TabText", typeof(RectTransform));
tabText.transform.SetParent(tabButton.transform);
// RectTransform anchors to the center of the button
RectTransform textRectTransform = tabText.GetComponent<RectTransform>();
textRectTransform.anchorMin = new Vector2(0.5f, 0.5f);
textRectTransform.anchorMax = new Vector2(0.5f, 0.5f);
textRectTransform.pivot = new Vector2(0.5f, 0.5f);
textRectTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
// Text position
textRectTransform.anchoredPosition = new Vector2(0, 0);
TextMeshProUGUI buttonText = tabText.AddComponent<TextMeshProUGUI>();
buttonText.text = tabName;
buttonText.font = UIManager.Instance.Font;
buttonText.fontSize = 12;
buttonText.color = Color.black;
buttonText.alignment = TextAlignmentOptions.Center;
buttonText.verticalAlignment = VerticalAlignmentOptions.Middle;
}
public virtual UISelectableEntry CreateSelectableEntry()
{
// Create a new entry object with content handle as parent
GameObject go = Instantiate(Resources.Load<GameObject>("Prefabs/EmptyObject"), contentHandle);
go.name = "UISelectableEntry";
UISelectableEntry entry = go.AddComponent<UISelectableEntry>();
entry.SetParent(this);
// add to cleanup pool so we can clear later in clear dialog entries
cleanupPool.Add(entry);
return entry;
}
public void ClearDialogEntries()
{
if (cleanupPool == null)
return;
foreach (UISelectableEntry entry in cleanupPool)
{
GameObject.Destroy(entry.gameObject);
}
cleanupPool.Clear();
if (entries != null)
entries.Clear();
}
/// <summary>
/// Clears, sets, and prints the dialog entries in the order they were added
/// </summary>
public virtual void SetDialogEntries(List<UISelectableEntry> entries)
{
this.entries = entries;
// calculate total height of the content
float heightHead = -1*GetTabHeight();
int count = 0;
foreach (UISelectableEntry entry in this.entries)
{
(heightHead, count) = RecursiveContentPrint(entry, 1, heightHead, count);
}
contentHandle.sizeDelta = new Vector2(contentHandle.sizeDelta.x, count * entryHeight + Mathf.Abs(heightHead));
}
public virtual void SetDialogEntries(UISelectableEntry entry)
{
SetDialogEntries(new List<UISelectableEntry>() { entry });
}
private (float, int) RecursiveContentPrint(UISelectableEntry entry, int depth, float heightHead, int count)
{
RectTransform rTransform = entry.GetComponent<RectTransform>();
rTransform.anchorMin = new Vector2(0, 1);
rTransform.anchorMax = new Vector2(1, 1);
rTransform.pivot = new Vector2(0.5f, 1f);
rTransform.anchoredPosition = new Vector2(0, heightHead); // positioning from top
rTransform.sizeDelta = new Vector2(0, entryHeight);
float padding = 5f;
rTransform.SetRight(padding);
rTransform.SetLeft(padding);
// actually indent the text
entry.GetTextTransform().anchoredPosition = new Vector2(entryIndentWidth * depth, 0);
heightHead -= entryHeight;
count++;
// Print the children
if (entry.GetChildEntries() != null)
{
foreach (UISelectableEntry child in entry.GetChildEntries())
{
(heightHead, count) = RecursiveContentPrint(child, depth + 1, heightHead, count);
}
}
return (heightHead, count);
}
// Update is called once per frame
void Update()
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28b8de234a5dab849bce341b844ea8e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
[RequireComponent(typeof(UIElementMouseCapturer))]
public class UIElementDragger : EventTrigger
{
public override void OnDrag(PointerEventData eventData)
{
transform.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08d6199088fb8554fa7335c18db3ace4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIElementMouseCapturer : EventTrigger
{
public override void OnPointerEnter(PointerEventData eventData)
{
InputManager.Instance.mouseActive = false;
base.OnPointerEnter(eventData);
}
public override void OnPointerExit(PointerEventData eventData)
{
InputManager.Instance.mouseActive = true;
base.OnPointerExit(eventData);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b4602e26cd6ff342a532880fc8ac6b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,82 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using TMPro;
public class UIManager : MonoBehaviour
{
public static UIManager Instance { get; private set; }
public GameObject botPanel;
public TextMeshProUGUI agentPanelText;
public TMP_FontAsset Font;
private UIMode curMode = UIMode.NONE;
// Start is called before the first frame update
void Awake()
{
// singleton
if (Instance == null)
Instance = this;
else
Destroy(gameObject);
}
void Start()
{
//inputManager = InputManager.Instance;
//worldManager = WorldManager.Instance;
}
public void SetUIMode(UIMode mode){
curMode = mode;
}
public UIMode GetUIMode(){
return curMode;
}
public void SetAgentPanelText(string text)
{
agentPanelText.text = text;
}
public string GetAgentPanelText()
{
return agentPanelText.text;
}
private void UpdateAgentPanel()
{
string agentPanelText = "";
foreach(Agent agent in SimManager.Instance.GetActiveAgents())
{
string jobText = agent.name + "| Phase: " + agent.GetFlightPhase().ToString();
agentPanelText += jobText + "\n";
}
SetAgentPanelText(agentPanelText);
}
// Update is called once per frame
void Update()
{
UpdateAgentPanel();
}
}
public enum UIMode {
NONE,
BUILD,
MINE
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b078e3e02b9c70645a97175561678909
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,119 @@
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.EventSystems;
public class UISelectableEntry : EventTrigger {
private List<UISelectableEntry> children;
private List<string> textContent;
private UIDialog parentDialog;
private RectTransform rectTransform;
private CanvasRenderer canvasRenderer;
private Image image;
private TextMeshProUGUI textHandle;
private bool isSelectable = true;
private static Color baseColor = new Color32(31, 31, 45, 140);
private Action<object> OnClickCallback;
private object callbackArgument;
public void Awake() {
rectTransform = gameObject.AddComponent<RectTransform>();
textHandle = Instantiate(Resources.Load<GameObject>("Prefabs/EmptyObject"), rectTransform).AddComponent<TextMeshProUGUI>();
textHandle.gameObject.name = "UISelectableEntry::Text";
textHandle.fontSize = 12;
textHandle.font = UIManager.Instance.Font;
textHandle.alignment = TextAlignmentOptions.MidlineLeft;
textHandle.GetComponent<RectTransform>().anchorMin = new Vector2(0, 0.5f);
textHandle.GetComponent<RectTransform>().anchorMax = new Vector2(1, 0.5f);
textHandle.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 0.5f);
textHandle.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 0);
textHandle.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 20);
image = gameObject.AddComponent<Image>();
image.type = Image.Type.Sliced;
image.color = baseColor;
}
public void SetClickCallback(Action<object> callback, object argument)
{
OnClickCallback = callback;
callbackArgument = argument;
}
public override void OnPointerEnter(PointerEventData eventData)
{
if(isSelectable)
image.color = baseColor + new Color32(20, 20, 20, 40);
base.OnPointerEnter(eventData);
}
public override void OnPointerDown(PointerEventData eventData)
{
if(isSelectable && OnClickCallback != null)
{
OnClickCallback(callbackArgument);
image.color = baseColor + new Color32(40, 40, 40, 40);
}
base.OnPointerClick(eventData);
}
public override void OnPointerExit(PointerEventData eventData)
{
if(isSelectable)
image.color = baseColor;
base.OnPointerExit(eventData);
}
public void SetIsSelectable(bool isSelectable) {
if(isSelectable)
image.enabled = true;
else
image.enabled = false;
this.isSelectable = isSelectable;
}
public bool GetIsSelectable() {
return isSelectable;
}
public void AddChildEntry(UISelectableEntry child) {
if (children == null) {
children = new List<UISelectableEntry>();
}
children.Add(child);
}
public void SetParent(UIDialog parentDialog) {
this.parentDialog = parentDialog;
}
public void SetChildEntries(List<UISelectableEntry> children) {
this.children = children;
}
// Get the children of this entry
public List<UISelectableEntry> GetChildEntries() {
return children;
}
public void SetTextContent(List<string> textContent) {
this.textContent = textContent;
textHandle.text = string.Join("\t", textContent);
}
public RectTransform GetTextTransform() {
return textHandle.GetComponent<RectTransform>();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1f58db020114a64fb94cf47d775a20f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5dfa88d362db21f42acf701d3d3e326a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,108 @@
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.EventSystems;
[RequireComponent(typeof(UIElementMouseCapturer))]
[RequireComponent(typeof(UIElementDragger))]
[RequireComponent(typeof(Image))]
public class UIWindow : MonoBehaviour
{
// Window title
[SerializeField]
private string windowTitle = "Window";
// Close button
private GameObject closeButton;
[SerializeField]
private CloseButtonCallback closeButtonCallback;
[Serializable]
private enum CloseButtonCallback
{
CLOSE_WINDOW,
TOGGLE_WINDOW
}
// IsOpen property
private bool isOpen;
private void OnEnable() { isOpen = true; }
private void OnDisable() { isOpen = false; }
public void ToggleWindow()
{
gameObject.SetActive(!gameObject.activeSelf);
}
public void CloseWindow()
{
Destroy(gameObject);
isOpen = false;
}
/// <summary>
/// Called when the UIWindow component is created in the editor
/// We will use it to configure the image component
/// </summary>
private void Reset()
{
// 18 16 28 125
GetComponent<Image>().color = new Color32(18, 16, 28, 125);
}
public virtual void Start()
{
isOpen = gameObject.activeSelf;
CreateCloseButton();
CreateWindowTitle();
if (closeButtonCallback == CloseButtonCallback.CLOSE_WINDOW)
closeButton.AddComponent<Button>().onClick.AddListener(CloseWindow);
else if (closeButtonCallback == CloseButtonCallback.TOGGLE_WINDOW)
closeButton.AddComponent<Button>().onClick.AddListener(ToggleWindow);
}
private void CreateWindowTitle()
{
GameObject windowTitleObject = new GameObject("WindowTitle", typeof(RectTransform));
windowTitleObject.transform.SetParent(transform);
TextMeshProUGUI windowTitleHandle = windowTitleObject.AddComponent<TextMeshProUGUI>();
windowTitleHandle.text = windowTitle;
windowTitleHandle.font = UIManager.Instance.Font;
windowTitleHandle.fontSize = 14;
windowTitleHandle.color = Color.white;
windowTitleHandle.alignment = TextAlignmentOptions.Left;
windowTitleHandle.rectTransform.anchorMin = new Vector2(0, 1);
windowTitleHandle.rectTransform.anchorMax = new Vector2(1, 1);
windowTitleHandle.rectTransform.pivot = new Vector2(0, 1);
windowTitleHandle.rectTransform.sizeDelta = new Vector2(0, 30);
windowTitleHandle.rectTransform.anchoredPosition = new Vector2(5, 0);
windowTitleHandle.rectTransform.SetRight(30); // Give spacing to the close button
}
/// <summary>
/// Create the close [x] button in the top right corner of the window
/// </summary>
private void CreateCloseButton()
{
closeButton = new GameObject("CloseButton", typeof(RectTransform));
RectTransform buttonTransform = closeButton.GetComponent<RectTransform>();
buttonTransform.SetParent(transform);
// anchor top right
buttonTransform.anchorMin = new Vector2(1, 1);
buttonTransform.anchorMax = new Vector2(1, 1);
buttonTransform.pivot = new Vector2(1, 1);
// position top right
buttonTransform.anchoredPosition = new Vector2(0, 0);
// size
buttonTransform.sizeDelta = new Vector2(30, 30);
// add button component
TextMeshProUGUI textbox = closeButton.AddComponent<TextMeshProUGUI>();
textbox.text = "X";
textbox.font = UIManager.Instance.Font;
textbox.fontSize = 12;
textbox.alignment = TextAlignmentOptions.Center;
textbox.verticalAlignment = VerticalAlignmentOptions.Middle;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0399a7d56c753d241812497084561817
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: