ccl4/blueberryPeak/Assets/Wwise/MonoBehaviour/Editor/AkPortalManager.cs
AgentSchmisch 9144907a10 ANGST
2025-06-12 18:45:34 +02:00

216 lines
7.4 KiB
C#

#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2025 Audiokinetic Inc.
*******************************************************************************/
using UnityEngine;
[UnityEditor.InitializeOnLoad]
public class AkPortalManager
{
private static AkPortalManager s_portalManager;
public System.Collections.Generic.List<AkEnvironment> EnvironmentList =
new System.Collections.Generic.List<AkEnvironment>();
public System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>[]
IntersectingEnvironments =
{
//All environments on the negative side of each portal(opposite to the direction of the chosen axis)
new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>(),
//All environments on the positive side of each portal(same direction as the chosen axis)
new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>()
};
private float m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
public System.Collections.Generic.List<AkEnvironmentPortal> PortalList =
new System.Collections.Generic.List<AkEnvironmentPortal>();
static AkPortalManager()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
//This constructor is called before any game object is created when there is a compilation which makes the 'FindObjectsOfType' function return null.
//So we register the init function to be called at hte first update.
UnityEditor.EditorApplication.update += Init;
}
public static void Init()
{
//Do nothing if Manager exists
if (s_portalManager == null)
{
s_portalManager = new AkPortalManager();
s_portalManager.Populate();
//Register the update function to be called at each frame
UnityEditor.EditorApplication.update += s_portalManager.UpdateEnvironments;
}
//Unregister in case we were registered
UnityEditor.EditorApplication.update -= Init;
}
public static AkPortalManager GetManager()
{
return s_portalManager;
}
public void Populate()
{
//Add all environments in the scene to the environment list
#if UNITY_6000_0_OR_NEWER
var akEnv = Object.FindObjectsByType<AkEnvironment>(FindObjectsSortMode.None);
#else
var akEnv = Object.FindObjectsOfType<AkEnvironment>();
#endif
s_portalManager.EnvironmentList.Clear();
s_portalManager.EnvironmentList.AddRange(akEnv);
//Add all portals in the scene to the portal list
#if UNITY_6000_0_OR_NEWER
var akPortals = Object.FindObjectsByType<AkEnvironmentPortal>(FindObjectsSortMode.None);
#else
var akPortals = Object.FindObjectsOfType<AkEnvironmentPortal>();
#endif
s_portalManager.PortalList.Clear();
s_portalManager.PortalList.AddRange(akPortals);
//check for portal-environment intersections and populate the IntersectingEnvironments dictionary
for (var i = 0; i < s_portalManager.PortalList.Count; i++)
s_portalManager.UpdatePortal(s_portalManager.PortalList[i]);
}
public void UpdatePortal(AkEnvironmentPortal in_portal)
{
var envList = new System.Collections.Generic.List<AkEnvironment>[2];
for (var i = 0; i < 2; i++)
{
if (!IntersectingEnvironments[i].TryGetValue(in_portal.GetInstanceID(), out envList[i]))
{
envList[i] = new System.Collections.Generic.List<AkEnvironment>();
IntersectingEnvironments[i][in_portal.GetInstanceID()] = envList[i];
}
else
envList[i].Clear();
}
//We check if a portal intersects any environment
//Iterate in reverse order for safe removal form list while iterating
for (var i = EnvironmentList.Count - 1; i >= 0; i--)
{
if (EnvironmentList[i] != null)
{
//if there is an intersection
if (in_portal.GetComponent<UnityEngine.Collider>().bounds
.Intersects(EnvironmentList[i].GetComponent<UnityEngine.Collider>().bounds))
{
if (UnityEngine.Vector3.Dot(in_portal.transform.rotation * in_portal.axis,
EnvironmentList[i].transform.position - in_portal.transform.position) >= 0)
envList[1].Add(EnvironmentList[i]);
else
envList[0].Add(EnvironmentList[i]);
}
}
else
EnvironmentList.RemoveAt(i);
}
}
private void UpdateEnvironment(AkEnvironment in_env)
{
for (var i = PortalList.Count - 1; i >= 0; i--) //Iterate in reverse order for safe removal form list while iterating
{
if (PortalList[i] != null)
{
if (in_env.GetComponent<UnityEngine.Collider>().bounds
.Intersects(PortalList[i].GetComponent<UnityEngine.Collider>().bounds))
{
System.Collections.Generic.List<AkEnvironment> envList = null;
//Get index of the list that should contain this environment
//Index = 0 means that the enviroment is on the negative side of the portal (opposite to the direction of the chosen axis)
//Index = 1 means that the enviroment is on the positive side of the portal (same direction as the chosen axis)
var index = UnityEngine.Vector3.Dot(PortalList[i].transform.rotation * PortalList[i].axis,
in_env.transform.position - PortalList[i].transform.position) >= 0
? 1
: 0;
if (!IntersectingEnvironments[index].TryGetValue(PortalList[i].GetInstanceID(), out envList))
{
envList = new System.Collections.Generic.List<AkEnvironment>();
envList.Add(in_env);
IntersectingEnvironments[index][PortalList[i].GetInstanceID()] = envList;
}
else if (!envList.Contains(in_env))
envList.Add(in_env);
}
}
else
PortalList.RemoveAt(i);
}
}
public void UpdateEnvironments()
{
//Timer is reset when starting play mode and when coming back to editor mode
if (UnityEngine.Time.realtimeSinceStartup < m_timeStamp)
{
m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
//The PortalManager object doesn't get destroyed but all game objects in our lists become null
//So we populate
Populate();
return;
}
//The update is done once every second
if (UnityEngine.Time.realtimeSinceStartup - m_timeStamp < 1.0f)
return;
m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
var portals = UnityEditor.Selection.GetFiltered(typeof(AkEnvironmentPortal), UnityEditor.SelectionMode.Unfiltered);
if (portals != null)
{
for (var i = 0; i < portals.Length; i++)
{
if (!PortalList.Contains((AkEnvironmentPortal) portals[i]))
PortalList.Add((AkEnvironmentPortal) portals[i]);
UpdatePortal((AkEnvironmentPortal) portals[i]);
}
}
var envs = UnityEditor.Selection.GetFiltered(typeof(AkEnvironment), UnityEditor.SelectionMode.Unfiltered);
if (envs != null)
{
for (var i = 0; i < envs.Length; i++)
{
if (!EnvironmentList.Contains((AkEnvironment) envs[i]))
EnvironmentList.Add((AkEnvironment) envs[i]);
UpdateEnvironment((AkEnvironment) envs[i]);
}
}
}
}
#endif