Files
2025-05-26 00:46:28 +02:00

222 lines
7.8 KiB
C#

using Fragilem17.MirrorsAndPortals;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if ENABLE_LEGACY_INPUT_MANAGER
using UnityEngine.XR;
#endif
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
using UnityEngine.InputSystem;
#endif
namespace Fragilem17.MirrorsAndPortals
{
public class PortalGunExample : MonoBehaviour
{
public LayerMask layerMask;
public Portal portal1;
public Portal portal2;
private Dictionary<Portal, Vector3> _portalSizes;
private Portal _targetPortal;
public new Light light;
private bool _shooting = false;
public bool alignWithViewDirectionOnHorizontalSurfaces = false;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
public InputAction ShootAction1;
public InputAction ShootAction2;
private void OnEnable()
{
ShootAction1.Enable();
ShootAction2.Enable();
}
private void OnDisable()
{
ShootAction1.Disable();
ShootAction2.Disable();
}
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
private UnityEngine.XR.InputDevice _rightHandDevice;
void OnEnable()
{
List<InputDevice> allDevices = new List<InputDevice>();
InputDevices.GetDevices(allDevices);
foreach (InputDevice device in allDevices)
InputDevices_deviceConnected(device);
InputDevices.deviceConnected += InputDevices_deviceConnected;
}
private void OnDisable()
{
InputDevices.deviceConnected -= InputDevices_deviceConnected;
}
private void InputDevices_deviceConnected(InputDevice device)
{
bool discardedValue;
if (device.TryGetFeatureValue(CommonUsages.primaryButton, out discardedValue))
{
if ((device.characteristics & InputDeviceCharacteristics.Right) == InputDeviceCharacteristics.Right)
{
_rightHandDevice = device;
}
}
}
#endif
private void Start()
{
_portalSizes = new Dictionary<Portal, Vector3>();
if (portal1 && portal2)
{
_portalSizes[portal1] = portal1.transform.localScale;
_portalSizes[portal2] = portal2.transform.localScale;
}
}
// Update is called once per frame
void Update()
{
_targetPortal = portal1;
bool shouldShoot = false;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
if (!_shooting && ShootAction1.ReadValue<float>() > 0)
{
shouldShoot = true;
_shooting = true;
}
if (!_shooting && ShootAction2.ReadValue<float>() > 0)
{
shouldShoot = true;
_shooting = true;
_targetPortal = portal2;
}
if (_shooting && ShootAction1.ReadValue<float>() == 0 && ShootAction2.ReadValue<float>() == 0)
{
_shooting = false;
}
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
bool buttonValue;
_rightHandDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primaryButton, out buttonValue);
//Debug.Log("buttonValue: " + buttonValue);
if (!_shooting && (Input.GetMouseButton(0) || (_rightHandDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primaryButton, out buttonValue) && buttonValue)))
{
shouldShoot = true;
_shooting = true;
}
if (!_shooting && (Input.GetMouseButton(1) || (_rightHandDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.secondaryButton, out buttonValue) && buttonValue)))
{
shouldShoot = true;
_shooting = true;
_targetPortal = portal2;
}
if (_shooting && !(Input.GetMouseButton(0) || Input.GetMouseButton(1) || (_rightHandDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.primaryButton, out buttonValue) && buttonValue) || (_rightHandDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.secondaryButton, out buttonValue) && buttonValue)))
{
_shooting = false;
}
#endif
if (shouldShoot)
{
//Debug.DrawRay(transform.position, transform.forward);
RaycastHit hit;
Ray ray = new Ray(transform.position, transform.forward);
if (Physics.Raycast(ray, out hit, 40, layerMask))
{
if (hit.collider)
{
StopAllCoroutines();
StartCoroutine(FadeInOut());
_targetPortal.transform.position = hit.point;
_targetPortal.transform.rotation = Quaternion.FromToRotation(Vector3.back, hit.normal);
_targetPortal.transform.localScale = Vector3.zero;
_targetPortal.wallCollider = hit.collider.gameObject.GetComponentInChildren<Collider>();
Vector3 euler = _targetPortal.transform.rotation.eulerAngles;
_targetPortal.transform.rotation = Quaternion.Euler(euler.x, euler.y, 0);
// is it a vertical wall?
float vertical = Mathf.Abs(Vector3.Dot(_targetPortal.transform.up, Vector3.up));
//Debug.Log("verical: " + vertical);
if (alignWithViewDirectionOnHorizontalSurfaces && vertical < 0.5f)
{
// Calculate the direction from the hit point to the player's position
Vector3 playerDirection = transform.position - hit.point;
// Calculate a new forward direction for the portal that is opposite to the direction towards the player
Vector3 portalForward = -playerDirection.normalized;
// Create a new rotation that aligns the portal's up direction with the direction towards the player, and its forward direction with the wall's normal
Quaternion finalRotation = Quaternion.LookRotation(hit.normal, portalForward);
// Set the rotation of the portal object
_targetPortal.transform.rotation = finalRotation;
_targetPortal.transform.Rotate(_targetPortal.transform.InverseTransformDirection(_targetPortal.transform.up), 180);
}
_targetPortal.transform.localScale = Vector3.zero;
StartCoroutine(Scale(_targetPortal, 1));
}
}
}
}
IEnumerator FadeInOut()
{
if (light != null)
{
light.enabled = true;
yield return StartCoroutine(Fade(5f));
yield return StartCoroutine(Fade(0));
light.enabled = false;
}
}
IEnumerator Fade(float to)
{
float diff = (to - light.intensity);
while (Mathf.Abs(diff) > 0.01f)
{
//Debug.Log("diff " + diff);
light.intensity += diff * 0.5f;
diff = (to - light.intensity);
yield return null;
}
}
IEnumerator Scale(Portal portal, float to)
{
float diff = ((to * _portalSizes[portal].x) - portal.transform.localScale.x);
while (Mathf.Abs(diff) > 0.01f)
{
//Debug.Log("diff " + diff);
portal.transform.localScale += _portalSizes[portal] * diff * 0.1f;
diff = ((to * _portalSizes[portal].x) - portal.transform.localScale.x);
yield return null;
}
}
}
}