chore: Project Restructuring & Theatre
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
using UnityEngine;
|
||||
using Unheimlich.Features.Player;
|
||||
using Unheimlich.Features.DetectiveBoard.UI;
|
||||
|
||||
namespace Unheimlich.NonEuclidean
|
||||
{
|
||||
public class DetectiveBoardPortalHider : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float _checkInterval = 0.1f;
|
||||
[SerializeField] private float _hideDistance = 5f;
|
||||
[SerializeField] private bool _enableDebugLogs = true;
|
||||
|
||||
private Canvas _detectiveBoardCanvas;
|
||||
private NonEuclideanManager _manager;
|
||||
private float _checkTimer;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_manager = NonEuclideanManager.Instance;
|
||||
|
||||
if (DetectiveBoardCanvas.Instance != null)
|
||||
{
|
||||
_detectiveBoardCanvas = DetectiveBoardCanvas.Instance.GetComponent<Canvas>();
|
||||
}
|
||||
|
||||
if (_enableDebugLogs)
|
||||
{
|
||||
Debug.Log($"[DetectiveBoardPortalHider] Initialized - Manager: {_manager != null}, Canvas: {_detectiveBoardCanvas != null}");
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_detectiveBoardCanvas == null || _manager == null || PlayerController.Instance == null)
|
||||
{
|
||||
if (_enableDebugLogs && Time.frameCount % 300 == 0)
|
||||
{
|
||||
Debug.LogWarning($"[DetectiveBoardPortalHider] Missing references - Canvas: {_detectiveBoardCanvas != null}, Manager: {_manager != null}, Player: {PlayerController.Instance != null}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_checkTimer += Time.deltaTime;
|
||||
|
||||
if (_checkTimer >= _checkInterval)
|
||||
{
|
||||
_checkTimer = 0f;
|
||||
CheckAndToggleCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckAndToggleCanvas()
|
||||
{
|
||||
Vector3 playerPos = PlayerController.Instance.transform.position;
|
||||
NonEuclideanRoom currentRoom = _manager.ActiveRoom;
|
||||
|
||||
if (currentRoom == null)
|
||||
{
|
||||
if (_enableDebugLogs)
|
||||
Debug.LogWarning("[DetectiveBoardPortalHider] No active room");
|
||||
return;
|
||||
}
|
||||
|
||||
NonEuclideanRoom boardRoom = GetDetectiveBoardRoom();
|
||||
|
||||
if (boardRoom == null)
|
||||
{
|
||||
if (_enableDebugLogs && Time.frameCount % 300 == 0)
|
||||
Debug.LogWarning("[DetectiveBoardPortalHider] Could not find board room");
|
||||
_detectiveBoardCanvas.enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool isInBoardRoom = (currentRoom == boardRoom);
|
||||
|
||||
if (_enableDebugLogs)
|
||||
Debug.Log($"[DetectiveBoardPortalHider] Current room: {currentRoom.name}, Board room: {boardRoom.name}, In board room: {isInBoardRoom}, Portals count: {currentRoom.Portals.Length}");
|
||||
|
||||
foreach (var portal in currentRoom.Portals)
|
||||
{
|
||||
float distance = Vector3.Distance(playerPos, portal.transform.position);
|
||||
|
||||
bool shouldHide = false;
|
||||
|
||||
if (isInBoardRoom)
|
||||
{
|
||||
shouldHide = (distance < _hideDistance);
|
||||
|
||||
if (_enableDebugLogs && shouldHide)
|
||||
Debug.Log($"[DetectiveBoardPortalHider] In board room, close to portal '{portal.name}' (distance: {distance:F2}m) - hiding canvas");
|
||||
}
|
||||
else if (portal.TargetRoom == boardRoom)
|
||||
{
|
||||
shouldHide = (distance < _hideDistance);
|
||||
|
||||
if (_enableDebugLogs && shouldHide)
|
||||
Debug.Log($"[DetectiveBoardPortalHider] Close to portal '{portal.name}' leading to board room (distance: {distance:F2}m) - hiding canvas");
|
||||
}
|
||||
|
||||
if (shouldHide)
|
||||
{
|
||||
_detectiveBoardCanvas.enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_enableDebugLogs)
|
||||
Debug.Log("[DetectiveBoardPortalHider] Not close to any relevant portal - enabling canvas");
|
||||
_detectiveBoardCanvas.enabled = true;
|
||||
}
|
||||
|
||||
private NonEuclideanRoom GetDetectiveBoardRoom()
|
||||
{
|
||||
if (_detectiveBoardCanvas == null)
|
||||
return null;
|
||||
|
||||
Transform current = _detectiveBoardCanvas.transform;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
NonEuclideanRoom room = current.GetComponent<NonEuclideanRoom>();
|
||||
if (room != null)
|
||||
{
|
||||
if (_enableDebugLogs && Time.frameCount % 300 == 0)
|
||||
Debug.Log($"[DetectiveBoardPortalHider] Found board room: {room.name}");
|
||||
return room;
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16e1f1371a69f6d4db490054110293b7
|
||||
@@ -0,0 +1,236 @@
|
||||
using OctoCore;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Unheimlich.NonEuclidean
|
||||
{
|
||||
public class NonEuclideanManager : MonoBehaviour
|
||||
{
|
||||
public static NonEuclideanManager Instance { get; private set; }
|
||||
|
||||
[System.Serializable]
|
||||
private class Configuration
|
||||
{
|
||||
public NonEuclideanRoom StartRoom;
|
||||
public LayerMask InFrontOfPortalLayer = 1 << 0;
|
||||
public LayerMask BehindPortalLayer = 1 << 20;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class References
|
||||
{
|
||||
public NonEuclideanRoom[] Rooms;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class State
|
||||
{
|
||||
public NonEuclideanRoom ActiveRoom;
|
||||
public NonEuclideanPortal ActivePortal;
|
||||
}
|
||||
|
||||
[SerializeField] private Configuration _configuration;
|
||||
[SerializeField] private References _references;
|
||||
[SerializeField, OctoReadOnly] private State _state;
|
||||
|
||||
private int _bacwardLayer;
|
||||
private int _forwardLayer;
|
||||
private Camera _camera;
|
||||
|
||||
public int BackwardLayer => _bacwardLayer;
|
||||
public int ForwardLayer => _forwardLayer;
|
||||
public NonEuclideanRoom ActiveRoom => _state.ActiveRoom;
|
||||
public Camera Camera => _camera;
|
||||
public NonEuclideanPortal ActivePortal => _state.ActivePortal;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (!Instance)
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (Instance == this)
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
_camera = Camera.main;
|
||||
|
||||
if (_camera == null)
|
||||
{
|
||||
Debug.LogWarning("No MainCamera found");
|
||||
return;
|
||||
}
|
||||
|
||||
_bacwardLayer = GetFirstLayerFromMask(_configuration.InFrontOfPortalLayer);
|
||||
_forwardLayer = GetFirstLayerFromMask(_configuration.BehindPortalLayer);
|
||||
SetActiveRoom(_configuration.StartRoom);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
EvaluatePortals();
|
||||
}
|
||||
|
||||
void EvaluatePortals()
|
||||
{
|
||||
bool checkPortals = true;
|
||||
if (_state.ActivePortal)
|
||||
checkPortals = !_state.ActivePortal.IsPortalPassed();
|
||||
|
||||
if (checkPortals)
|
||||
{
|
||||
NonEuclideanPortal shouldBeActivatedPortal = _state.ActivePortal;
|
||||
float minDist = float.MaxValue;
|
||||
|
||||
foreach (NonEuclideanPortal portal in ActiveRoom.Portals)
|
||||
{
|
||||
// Is camera behind portal
|
||||
if (portal.transform.InverseTransformPoint(_camera.transform.position).z < 0)
|
||||
{
|
||||
Vector3 portalDir = (transform.position - _camera.transform.position).normalized;
|
||||
Vector3 viewDir = _camera.transform.forward;
|
||||
float angle = Vector3.Angle(viewDir, portalDir);
|
||||
|
||||
// Is camera pointing to portal
|
||||
if (angle < 80)
|
||||
{
|
||||
float dist = Vector3.Distance(portal.transform.position, _camera.transform.position);
|
||||
|
||||
// Is this portal nearest than other portal
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
shouldBeActivatedPortal = portal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_state.ActivePortal != shouldBeActivatedPortal)
|
||||
{
|
||||
if (_state.ActivePortal)
|
||||
_state.ActivePortal.Activate(false);
|
||||
|
||||
_state.ActivePortal = shouldBeActivatedPortal;
|
||||
|
||||
if (_state.ActivePortal)
|
||||
_state.ActivePortal.Activate(true);
|
||||
|
||||
ConfigureRooms();
|
||||
|
||||
Debug.Log($"[PortalManager] Portal activated: {_state.ActivePortal.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActiveRoom(NonEuclideanRoom activeRoom)
|
||||
{
|
||||
if (_state.ActivePortal)
|
||||
{
|
||||
_state.ActivePortal.Activate(false);
|
||||
_state.ActivePortal = null;
|
||||
}
|
||||
|
||||
_state.ActiveRoom = activeRoom;
|
||||
|
||||
ConfigureRooms();
|
||||
}
|
||||
|
||||
private void ConfigureRooms()
|
||||
{
|
||||
// Set active or not rooms
|
||||
|
||||
foreach (NonEuclideanRoom room in _references.Rooms)
|
||||
{
|
||||
bool isActiveRoom = room == _state.ActiveRoom;
|
||||
bool isTargetRoom = _state.ActivePortal ? room == _state.ActivePortal.TargetRoom : false;
|
||||
|
||||
room.gameObject.SetActive(isActiveRoom || isTargetRoom);
|
||||
}
|
||||
|
||||
// Configure Active & Target Rooms
|
||||
|
||||
ConfigureRoom(_state.ActiveRoom, false);
|
||||
if (_state.ActivePortal)
|
||||
ConfigureRoom(_state.ActivePortal.TargetRoom, true);
|
||||
}
|
||||
|
||||
private void ConfigureRoom(NonEuclideanRoom room, bool isBehindPortal)
|
||||
{
|
||||
if (room == null) return;
|
||||
|
||||
int layer = isBehindPortal ? _forwardLayer : _bacwardLayer;
|
||||
|
||||
SetLayerAndPropertyRecursive(room.gameObject, layer, isBehindPortal);
|
||||
|
||||
foreach (Light light in room.GetComponentsInChildren<Light>()) // TMP
|
||||
{
|
||||
bool isBehind = layer == NonEuclideanManager.Instance.ForwardLayer;
|
||||
|
||||
if (!light.TryGetComponent(out UniversalAdditionalLightData urp))
|
||||
urp = light.gameObject.AddComponent<UniversalAdditionalLightData>();
|
||||
urp.renderingLayers = 1u << (isBehind ? 1 : 0);
|
||||
|
||||
light.cullingMask = 1 << layer;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetLayerAndPropertyRecursive(GameObject obj, int layer, bool isBehindPortal)
|
||||
{
|
||||
if (obj == null) return;
|
||||
|
||||
int currentLayer = obj.layer;
|
||||
|
||||
bool shouldPreserveLayer =
|
||||
currentLayer == LayerMask.NameToLayer("UI") ||
|
||||
currentLayer == LayerMask.NameToLayer("DetectiveBoard") ||
|
||||
currentLayer == LayerMask.NameToLayer("Interactable") ||
|
||||
currentLayer == LayerMask.NameToLayer("Player") ||
|
||||
currentLayer == LayerMask.NameToLayer("Words") ||
|
||||
currentLayer == LayerMask.NameToLayer("Listenable") ||
|
||||
currentLayer == LayerMask.NameToLayer("HandsTouch");
|
||||
|
||||
if (!shouldPreserveLayer)
|
||||
{
|
||||
obj.layer = layer;
|
||||
}
|
||||
|
||||
Collider collider = obj.GetComponent<Collider>();
|
||||
if (collider)
|
||||
{
|
||||
collider.enabled = !isBehindPortal;
|
||||
}
|
||||
|
||||
Renderer renderer = obj.GetComponent<Renderer>();
|
||||
if (renderer && !(renderer is CanvasRenderer))
|
||||
{
|
||||
/*MaterialPropertyBlock block = new MaterialPropertyBlock();
|
||||
renderer.GetPropertyBlock(block);
|
||||
block.SetFloat(IsBehindPortalID, isBehindPortal ? 1 : 0);
|
||||
renderer.SetPropertyBlock(block);*/
|
||||
|
||||
if (isBehindPortal)
|
||||
renderer.renderingLayerMask = 1u << 1; // Light Layer 1
|
||||
else
|
||||
renderer.renderingLayerMask = 1u << 0; // Default
|
||||
}
|
||||
|
||||
foreach (Transform child in obj.transform)
|
||||
SetLayerAndPropertyRecursive(child.gameObject, layer, isBehindPortal);
|
||||
}
|
||||
|
||||
private int GetFirstLayerFromMask(LayerMask mask)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if ((mask & (1 << i)) != 0)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ea167d3810554b42995db5dfdcdbbb8
|
||||
@@ -0,0 +1,88 @@
|
||||
using OctoCore;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.NonEuclidean
|
||||
{
|
||||
public class NonEuclideanPortal : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
private class References
|
||||
{
|
||||
public NonEuclideanRoom OwnRoom;
|
||||
public NonEuclideanRoom TragetRoom;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class State
|
||||
{
|
||||
[OctoReadOnly] public bool Active;
|
||||
}
|
||||
|
||||
[SerializeField] private References _references;
|
||||
[SerializeField] private State _state;
|
||||
|
||||
public NonEuclideanRoom OwnRoom => _references.OwnRoom;
|
||||
public NonEuclideanRoom TargetRoom => _references.TragetRoom;
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.color = _state.Active ? new Color(0, 1, 1) : new Color(1, 1, 0);
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.DrawWireCube(Vector3.zero, new Vector3(1, 1, 0));
|
||||
Gizmos.DrawLine(new Vector3(0, -.4f, -.1f), new Vector3(0, -.4f, -.6f));
|
||||
Gizmos.DrawLine(new Vector3(0, -.4f, -.1f), new Vector3(.2f, -.4f, -.3f));
|
||||
Gizmos.DrawLine(new Vector3(0, -.4f, -.1f), new Vector3(-.2f, -.4f, -.3f));
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
//if (_state.Active)
|
||||
//{
|
||||
// Shader.SetGlobalMatrix("_PortalMatrix", Matrix4x4.identity);
|
||||
// Shader.SetGlobalMatrix("_CameraMatrix", Matrix4x4.identity);
|
||||
//}
|
||||
}
|
||||
|
||||
public bool IsPortalPassed()
|
||||
{
|
||||
if (_state.Active && NonEuclideanManager.Instance && NonEuclideanManager.Instance.Camera)
|
||||
{
|
||||
Shader.SetGlobalMatrix("_PortalMatrix", transform.worldToLocalMatrix);
|
||||
Shader.SetGlobalMatrix("_CameraMatrix", NonEuclideanManager.Instance.Camera.transform.localToWorldMatrix);
|
||||
|
||||
if (IsInsidePortalFrame(NonEuclideanManager.Instance.Camera))
|
||||
{
|
||||
Debug.Log($"Portal: {name} has been passed ({NonEuclideanManager.Instance.ActiveRoom.name} → {_references.TragetRoom.name}).");
|
||||
|
||||
NonEuclideanManager.Instance.SetActiveRoom(_references.TragetRoom);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Activate(bool activate)
|
||||
{
|
||||
if (!NonEuclideanManager.Instance || !NonEuclideanManager.Instance.ActiveRoom)
|
||||
{
|
||||
_state.Active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_state.Active = activate;
|
||||
}
|
||||
|
||||
private bool IsInsidePortalFrame(Camera camera)
|
||||
{
|
||||
Vector3 localCamPos = transform.InverseTransformPoint(camera.transform.position);
|
||||
|
||||
bool isInside = Mathf.Abs(localCamPos.x) < transform.localScale.x * .5f &&
|
||||
Mathf.Abs(localCamPos.y) < transform.localScale.y * .5f &&
|
||||
localCamPos.z > 0 &&
|
||||
localCamPos.z < transform.localScale.x * .5f;
|
||||
return isInside;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9977be9ea36a5e44c902d74b2fb468ea
|
||||
@@ -0,0 +1,10 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.NonEuclidean
|
||||
{
|
||||
public class NonEuclideanRoom : MonoBehaviour
|
||||
{
|
||||
public NonEuclideanPortal[] Portals;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51cd8846cf398f34daf0a6c100302e15
|
||||
Reference in New Issue
Block a user