feat: added fmod

This commit is contained in:
Gerard Gascón 2024-04-17 23:19:16 +02:00
parent c803300dce
commit 3471c31c32
416 changed files with 39455 additions and 171 deletions

View file

@ -0,0 +1,85 @@
using System;
using UnityEngine.Serialization;
namespace FMODUnity
{
[Serializable]
public struct AutomatableSlots
{
public const int Count = 16;
[FormerlySerializedAs("slot00")]
public float Slot00;
[FormerlySerializedAs("slot01")]
public float Slot01;
[FormerlySerializedAs("slot02")]
public float Slot02;
[FormerlySerializedAs("slot03")]
public float Slot03;
[FormerlySerializedAs("slot04")]
public float Slot04;
[FormerlySerializedAs("slot05")]
public float Slot05;
[FormerlySerializedAs("slot06")]
public float Slot06;
[FormerlySerializedAs("slot07")]
public float Slot07;
[FormerlySerializedAs("slot08")]
public float Slot08;
[FormerlySerializedAs("slot09")]
public float Slot09;
[FormerlySerializedAs("slot10")]
public float Slot10;
[FormerlySerializedAs("slot11")]
public float Slot11;
[FormerlySerializedAs("slot12")]
public float Slot12;
[FormerlySerializedAs("slot13")]
public float Slot13;
[FormerlySerializedAs("slot14")]
public float Slot14;
[FormerlySerializedAs("slot15")]
public float Slot15;
public float GetValue(int index)
{
switch(index)
{
case 0:
return Slot00;
case 1:
return Slot01;
case 2:
return Slot02;
case 3:
return Slot03;
case 4:
return Slot04;
case 5:
return Slot05;
case 6:
return Slot06;
case 7:
return Slot07;
case 8:
return Slot08;
case 9:
return Slot09;
case 10:
return Slot10;
case 11:
return Slot11;
case 12:
return Slot12;
case 13:
return Slot13;
case 14:
return Slot14;
case 15:
return Slot15;
default:
throw new ArgumentException(string.Format("Invalid slot index: {0}", index));
}
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
using UnityEngine;
namespace FMODUnity
{
public class BankRefAttribute : PropertyAttribute
{
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a8ab5f38e7776644297d8b3687c39b49
timeCreated: 1445488716
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,124 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FMODUnity
{
public static class CodeGeneration
{
public static void GenerateStaticPluginRegistration(string filePath, Platform platform,
Action<string> reportError)
{
List<string> validatedPlugins = ValidateStaticPlugins(platform.StaticPlugins, reportError);
using (StreamWriter file = new StreamWriter(filePath))
{
WriteStaticPluginRegistration(file, platform.IsFMODStaticallyLinked, validatedPlugins);
}
}
private static void WriteStaticPluginRegistration(StreamWriter file, bool isFMODStaticallyLinked,
IEnumerable<string> pluginFunctions)
{
file.WriteLine("#if ENABLE_IL2CPP");
file.WriteLine();
file.WriteLine("// This file was generated by FMOD for Unity from the Static Plugins list in the FMOD settings.");
file.WriteLine();
file.WriteLine("using System;");
file.WriteLine("using System.Runtime.InteropServices;");
file.WriteLine();
file.WriteLine("namespace FMODUnity");
file.WriteLine("{");
file.WriteLine(" class {0}", Platform.RegisterStaticPluginsClassName);
file.WriteLine(" {");
// Import the plugin functions
foreach (string pluginFunction in pluginFunctions)
{
file.WriteLine(" [DllImport(\"__Internal\")]");
file.WriteLine(" private static extern IntPtr {0}();", pluginFunction);
file.WriteLine();
}
// Import the RegisterDSP function
file.WriteLine(" [DllImport(FMOD.VERSION.dll)]");
file.WriteLine(" private static extern FMOD.RESULT FMOD5_System_RegisterDSP(IntPtr system, IntPtr description, IntPtr handle);");
file.WriteLine();
file.WriteLine(" public static void {0}(FMOD.System coreSystem, Action<FMOD.RESULT, string> reportResult)",
Platform.RegisterStaticPluginsFunctionName);
file.WriteLine(" {");
if (pluginFunctions.Any())
{
file.WriteLine(" FMOD.RESULT result;");
foreach (string pluginFunction in pluginFunctions)
{
file.WriteLine();
file.WriteLine(" result = FMOD5_System_RegisterDSP(coreSystem.handle, {0}(), IntPtr.Zero);", pluginFunction);
file.WriteLine(" reportResult(result, \"Registering static plugin '{0}'\");", pluginFunction);
}
}
file.WriteLine(" }");
file.WriteLine(" }");
file.WriteLine("}");
file.WriteLine("");
file.WriteLine("#endif // ENABLE_IL2CPP");
}
private static List<string> ValidateStaticPlugins(List<string> staticPlugins, Action<string> reportError)
{
List<string> result = new List<string>();
for (int i = 0; i < staticPlugins.Count; ++i)
{
string functionName = staticPlugins[i];
string trimmedName = (functionName != null) ? functionName.Trim() : null;
if (string.IsNullOrEmpty(trimmedName))
{
reportError(string.Format("Static plugin {0} has no name and will be ignored.", i + 1));
}
else if (IsValidFunctionName(trimmedName, reportError))
{
result.Add(trimmedName);
}
}
return result;
}
private static bool IsValidFunctionName(string name, Action<string> reportError)
{
if (!(char.IsLetter(name[0]) || name[0] == '_'))
{
reportError(string.Format(
"Plugin name '{0}' is not valid. Names must start with a letter or an underscore ('_').", name));
return false;
}
for (int i = 1; i < name.Length; ++i)
{
if (!(char.IsLetterOrDigit(name[i]) || name[i] == '_'))
{
reportError(string.Format(
"Plugin name '{0}' is not valid. " +
"Character '{1}' at position {2} is invalid - it must be a letter, a number, or an underscore ('_').",
name, name[i], i));
return false;
}
}
return true;
}
}
}
#endif

View file

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

View file

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

View file

@ -0,0 +1,66 @@
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomPropertyDrawer(typeof(BankRefAttribute))]
public class BankRefDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Texture browseIcon = EditorUtils.LoadImage("SearchIconBlack.png");
SerializedProperty pathProperty = property;
EditorGUI.BeginProperty(position, label, property);
Event e = Event.current;
if (e.type == EventType.DragPerform && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorBankRef))
{
pathProperty.stringValue = ((EditorBankRef)DragAndDrop.objectReferences[0]).Name;
e.Use();
}
}
if (e.type == EventType.DragUpdated && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorBankRef))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
DragAndDrop.AcceptDrag();
e.Use();
}
}
float baseHeight = GUI.skin.textField.CalcSize(new GUIContent()).y;
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
var buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.padding.top = buttonStyle.padding.bottom = 1;
Rect searchRect = new Rect(position.x + position.width - browseIcon.width - 15, position.y, browseIcon.width + 10, baseHeight);
Rect pathRect = new Rect(position.x, position.y, searchRect.x - position.x - 5, baseHeight);
EditorGUI.PropertyField(pathRect, pathProperty, GUIContent.none);
if (GUI.Button(searchRect, new GUIContent(browseIcon, "Select FMOD Bank"), buttonStyle))
{
var eventBrowser = ScriptableObject.CreateInstance<EventBrowser>();
eventBrowser.ChooseBank(property);
var windowRect = position;
windowRect.position = GUIUtility.GUIToScreenPoint(windowRect.position);
windowRect.height = searchRect.height + 1;
eventBrowser.ShowAsDropDown(windowRect, new Vector2(windowRect.width, 400));
}
EditorGUI.EndProperty();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 49ebe6fea5e4bfc4bb492bba062b2afe
timeCreated: 1433209573
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,237 @@
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
public class BankRefreshWindow : EditorWindow
{
private static BankRefreshWindow instance = null;
private SerializedObject serializedSettings;
private SerializedProperty cooldown;
private SerializedProperty showWindow;
private bool readyToRefreshBanks = false;
private float closeTime = float.MaxValue;
private string lastRefreshError = null;
private const float CloseDelay = 5;
public static bool IsVisible { get { return instance != null; } }
public static bool ReadyToRefreshBanks { get { return instance == null || instance.readyToRefreshBanks; } }
public static void ShowWindow()
{
if (instance == null)
{
instance = CreateInstance<BankRefreshWindow>();
instance.titleContent = new GUIContent("FMOD Bank Refresh Status");
instance.minSize = new Vector2(400, 200);
instance.maxSize = new Vector2(1000, 200);
instance.ShowUtility();
}
}
private void OnEnable()
{
serializedSettings = new SerializedObject(Settings.Instance);
cooldown = serializedSettings.FindProperty("BankRefreshCooldown");
showWindow = serializedSettings.FindProperty("ShowBankRefreshWindow");
// instance is set to null when scripts are recompiled
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Close();
}
}
private void OnDestroy()
{
if (instance == this)
{
instance = null;
}
}
private void OnInspectorUpdate()
{
Repaint();
if (BankRefresher.TimeUntilBankRefresh() != float.MaxValue)
{
closeTime = float.MaxValue;
}
if (Time.realtimeSinceStartup > closeTime)
{
Close();
}
}
public static void HandleBankRefresh(string error)
{
if (error != null)
{
RuntimeUtils.DebugLogErrorFormat("FMOD: Bank refresh failed: {0}", error);
}
if (instance != null)
{
instance.readyToRefreshBanks = false;
instance.lastRefreshError = error;
if (error == null)
{
instance.closeTime = Time.realtimeSinceStartup + CloseDelay;
}
}
}
private void OnGUI()
{
serializedSettings.Update();
DrawStatus();
GUILayout.FlexibleSpace();
SettingsEditor.DisplayBankRefreshSettings(cooldown, showWindow, false);
DrawButtons();
serializedSettings.ApplyModifiedProperties();
}
private bool ConsumeEscapeKey()
{
if ((focusedWindow == this) && Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
{
Event.current.Use();
return true;
}
else
{
return false;
}
}
private void DrawStatus()
{
GUIStyle labelStyle = new GUIStyle(EditorStyles.whiteLargeLabel);
labelStyle.alignment = TextAnchor.MiddleCenter;
GUIStyle largeErrorStyle = new GUIStyle(labelStyle);
largeErrorStyle.normal.textColor = Color.red;
GUIStyle errorStyle = new GUIStyle(GUI.skin.box);
errorStyle.alignment = TextAnchor.UpperLeft;
errorStyle.wordWrap = true;
errorStyle.normal.textColor = Color.red;
float timeSinceFileChange = BankRefresher.TimeSinceSourceFileChange();
if (timeSinceFileChange != float.MaxValue)
{
GUILayout.Label(string.Format("The FMOD source banks changed {0} ago.",
EditorUtils.DurationString(timeSinceFileChange)), labelStyle);
float timeUntilBankRefresh = BankRefresher.TimeUntilBankRefresh();
if (timeUntilBankRefresh == 0)
{
GUILayout.Label("Refreshing banks now...", labelStyle);
readyToRefreshBanks = true;
}
else if (timeUntilBankRefresh != float.MaxValue)
{
if (DrawCountdown("Refreshing banks", timeUntilBankRefresh, Settings.Instance.BankRefreshCooldown, labelStyle)
|| ConsumeEscapeKey())
{
BankRefresher.DisableAutoRefresh();
}
}
else
{
GUILayout.Label("Would you like to refresh banks?", labelStyle);
}
}
else
{
if (lastRefreshError == null)
{
GUILayout.Label("The FMOD banks are up to date.", labelStyle);
}
else
{
GUILayout.Label("Bank refresh failed:", largeErrorStyle);
GUILayout.Box(lastRefreshError, errorStyle, GUILayout.ExpandWidth(true));
}
}
if (closeTime != float.MaxValue)
{
float timeUntilClose = Mathf.Max(0, closeTime - Time.realtimeSinceStartup);
if (DrawCountdown("Closing", timeUntilClose, CloseDelay, labelStyle) || ConsumeEscapeKey())
{
closeTime = float.MaxValue;
}
}
}
private static bool DrawCountdown(string text, float remainingTime, float totalTime, GUIStyle labelStyle)
{
GUILayout.Label(string.Format("{0} in {1}...", text, EditorUtils.DurationString(remainingTime)), labelStyle);
const float boxHeight = 2;
Rect controlRect = EditorGUILayout.GetControlRect(false, boxHeight * 2);
Rect boxRect = controlRect;
boxRect.width *= remainingTime / totalTime;
boxRect.x += (controlRect.width - boxRect.width) / 2;
boxRect.height = 2;
GUI.DrawTexture(boxRect, EditorGUIUtility.whiteTexture);
GUIContent cancelContent = new GUIContent("Cancel");
controlRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 2);
Rect buttonRect = controlRect;
buttonRect.width = 100;
buttonRect.x += (controlRect.width - buttonRect.width) / 2;
return GUI.Button(buttonRect, cancelContent);
}
private void DrawButtons()
{
Rect rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 2);
int buttonCount = 2;
Rect closeRect = rect;
closeRect.width = rect.width / buttonCount;
Rect refreshRect = rect;
refreshRect.xMin = closeRect.xMax;
if (GUI.Button(closeRect, "Close"))
{
Close();
}
if (GUI.Button(refreshRect, "Refresh Banks Now"))
{
EventManager.RefreshBanks();
}
}
}
}

View file

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

View file

@ -0,0 +1,167 @@
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
public class BankRefresher
{
private static string currentWatchPath;
private static FileSystemWatcher sourceFileWatcher;
private static bool sourceFilesChanged = false;
private static float lastSourceFileChange = float.MaxValue;
private static bool autoRefresh = true;
private static float nextFilePollTime = float.MinValue;
private const int FilePollPeriod = 5;
public static void DisableAutoRefresh()
{
autoRefresh = false;
}
public static void Startup()
{
sourceFileWatcher = new FileSystemWatcher();
sourceFileWatcher.IncludeSubdirectories = true;
sourceFileWatcher.NotifyFilter = NotifyFilters.LastWrite;
sourceFileWatcher.Changed += OnSourceFileChanged;
sourceFileWatcher.Created += OnSourceFileChanged;
sourceFileWatcher.Deleted += OnSourceFileChanged;
EditorApplication.update += Update;
}
private static void OnSourceFileChanged(object source, FileSystemEventArgs e)
{
sourceFilesChanged = true;
}
private static void Update()
{
UpdateFileWatcherPath();
CheckSourceFilesChanged();
CheckCacheFileExists();
RefreshBanksIfReady();
}
private static void UpdateFileWatcherPath()
{
string sourceBankPath = Settings.Instance.SourceBankPath;
string pathToWatch;
if (Path.IsPathRooted(sourceBankPath))
{
pathToWatch = Path.GetFullPath(sourceBankPath);
}
else
{
pathToWatch = Path.GetFullPath(Environment.CurrentDirectory + "/" + sourceBankPath);
}
if (currentWatchPath != pathToWatch)
{
currentWatchPath = pathToWatch;
try {
sourceFileWatcher.EnableRaisingEvents = false;
sourceFilesChanged = false;
if (!string.IsNullOrEmpty(sourceBankPath))
{
sourceFileWatcher.Path = pathToWatch;
sourceFileWatcher.EnableRaisingEvents = true;
}
}
catch (ArgumentException e)
{
RuntimeUtils.DebugLogWarningFormat("Error watching {0}: {1}", pathToWatch, e.Message);
}
}
}
private static void CheckSourceFilesChanged()
{
if (sourceFilesChanged)
{
lastSourceFileChange = Time.realtimeSinceStartup;
sourceFilesChanged = false;
if (!BankRefreshWindow.IsVisible)
{
autoRefresh = true;
}
if (IsWindowEnabled())
{
BankRefreshWindow.ShowWindow();
}
}
}
private static void CheckCacheFileExists()
{
if (Time.realtimeSinceStartup >= nextFilePollTime)
{
if (!File.Exists(EventManager.CacheAssetFullName))
{
EventManager.RefreshBanks();
}
nextFilePollTime = Time.realtimeSinceStartup + FilePollPeriod;
}
}
private static void RefreshBanksIfReady()
{
if (TimeUntilBankRefresh() == 0 && BankRefreshWindow.ReadyToRefreshBanks)
{
EventManager.RefreshBanks();
}
}
public static void HandleBankRefresh(string result)
{
lastSourceFileChange = float.MaxValue;
BankRefreshWindow.HandleBankRefresh(result);
}
private static bool IsWindowEnabled()
{
Settings settings = Settings.Instance;
return settings.BankRefreshCooldown == Settings.BankRefreshPrompt
|| (settings.BankRefreshCooldown >= 0 && settings.ShowBankRefreshWindow);
}
public static float TimeSinceSourceFileChange()
{
if (lastSourceFileChange == float.MaxValue)
{
return float.MaxValue;
}
else
{
return Mathf.Max(0, Time.realtimeSinceStartup - lastSourceFileChange);
}
}
public static float TimeUntilBankRefresh()
{
if (!autoRefresh
|| lastSourceFileChange == float.MaxValue
|| Settings.Instance.BankRefreshCooldown < 0)
{
return float.MaxValue;
}
else
{
float nextRefreshTime = lastSourceFileChange + Settings.Instance.BankRefreshCooldown;
return Mathf.Max(0, nextRefreshTime - Time.realtimeSinceStartup);
}
}
}
}

View file

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

View file

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEditor;
#if (UNITY_VISUALSCRIPTING_EXIST)
using Unity.VisualScripting;
#elif (UNITY_BOLT_EXIST)
using Ludiq;
using Bolt;
#endif
namespace FMODUnity
{
public class BoltIntegration : MonoBehaviour
{
[MenuItem("FMOD/Generate Visual Scripting Units")]
public static void GenerateBoltUnitOptions()
{
#if (UNITY_BOLT_EXIST || UNITY_VISUALSCRIPTING_EXIST)
BuildBoltUnitOptions();
#else
TriggerBuild();
#endif
}
#if !(UNITY_BOLT_EXIST || UNITY_VISUALSCRIPTING_EXIST)
[MenuItem("FMOD/Generate Visual Scripting Units", true)]
private static bool IsBoltPresent()
{
Assembly ludiqCoreRuntimeAssembly = null;
Assembly boltFlowEditorAssembly = null;
try
{
ludiqCoreRuntimeAssembly = Assembly.Load("Ludiq.Core.Runtime");
boltFlowEditorAssembly = Assembly.Load("Bolt.Flow.Editor");
}
catch (FileNotFoundException)
{
return false;
}
return true;
}
private static void TriggerBuild()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
string previousSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
if (!previousSymbols.Contains("UNITY_BOLT_EXIST"))
{
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, previousSymbols + ";UNITY_BOLT_EXIST");
}
Settings.Instance.BoltUnitOptionsBuildPending = true;
AssetDatabase.Refresh();
}
#else
private static void BuildBoltUnitOptions()
{
#if (UNITY_BOLT_EXIST)
DictionaryAsset projectSettings = AssetDatabase.LoadAssetAtPath(PathUtility.FromProject(LudiqCore.Paths.projectSettings), typeof(DictionaryAsset)) as DictionaryAsset;
List<LooseAssemblyName> assemblyOptions = projectSettings.dictionary["assemblyOptions"] as List<LooseAssemblyName>;
#else
List<LooseAssemblyName> assemblyOptions = BoltCore.Configuration.assemblyOptions;
#endif
if (!assemblyOptions.Contains("FMODUnity"))
{
assemblyOptions.Add("FMODUnity");
}
if (!assemblyOptions.Contains("FMODUnityResonance"))
{
assemblyOptions.Add("FMODUnityResonance");
}
#if (UNITY_BOLT_EXIST)
List<Type> typeOptions = projectSettings.dictionary["typeOptions"] as List<Type>;
#else
List<Type> typeOptions = BoltCore.Configuration.typeOptions;
#endif
Assembly fmodUnityAssembly = Assembly.Load("FMODUnity");
Assembly fmodUnityResonanceAssembly = Assembly.Load("FMODUnityResonance");
List<Type> allTypes = new List<Type>(GetTypesForNamespace(fmodUnityAssembly, "FMOD"));
allTypes.AddRange(GetTypesForNamespace(fmodUnityAssembly, "FMOD.Studio"));
foreach (Type type in allTypes)
{
if (!typeOptions.Contains(type))
{
typeOptions.Add(type);
}
}
Codebase.UpdateSettings();
#if (UNITY_BOLT_EXIST)
UnitBase.Build();
#else
UnitBase.Rebuild();
#endif
}
private static IEnumerable<Type> GetTypesForNamespace(Assembly assembly, string requestedNamespace)
{
return assembly.GetTypes()
.Where(t => string.Equals(t.Namespace, requestedNamespace, StringComparison.Ordinal));
}
#endif
public static void Startup()
{
#if (UNITY_BOLT_EXIST || UNITY_VISUALSCRIPTING_EXIST)
if (Settings.Instance.BoltUnitOptionsBuildPending)
{
Settings.Instance.BoltUnitOptionsBuildPending = false;
BuildBoltUnitOptions();
}
#endif
}
}
}

View file

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

View file

@ -0,0 +1,404 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace FMODUnity
{
public class CreateEventPopup : EditorWindow
{
private class FolderEntry
{
public FolderEntry parent;
public string name;
public string guid;
public List<FolderEntry> entries = new List<FolderEntry>();
public Rect rect;
}
private SerializedProperty outputProperty;
private FolderEntry rootFolder;
private FolderEntry currentFolder;
private List<BankEntry> banks;
private int lastHover = 0;
private string eventFolder = "/";
private string eventName = "";
private string currentFilter = "";
private int selectedBank = 0;
private bool resetCursor = true;
private Vector2 scrollPos = new Vector2();
private Rect scrollRect = new Rect();
private bool isConnected = false;
internal void SelectEvent(SerializedProperty property)
{
outputProperty = property;
}
private class BankEntry
{
public string name;
public string guid;
}
public CreateEventPopup()
{
}
private void BuildTree()
{
var rootGuid = EditorUtils.GetScriptOutput("studio.project.workspace.masterEventFolder.id");
rootFolder = new FolderEntry();
rootFolder.guid = rootGuid;
BuildTreeItem(rootFolder);
wantsMouseMove = true;
banks = new List<BankEntry>();
const string buildBankTreeFunc =
@"function() {
var output = """";
const items = [ studio.project.workspace.masterBankFolder ];
while (items.length > 0) {
var currentItem = items.shift();
if (currentItem.isOfType(""BankFolder"")) {
currentItem.items.reverse().forEach(function(val) {
items.unshift(val);
});
} else {
output += "","" + currentItem.id + currentItem.getPath().replace(""bank:/"", """");
}
}
return output;
}";
string bankList = EditorUtils.GetScriptOutput(string.Format("({0})()", buildBankTreeFunc));
string[] bankListSplit = bankList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var bank in bankListSplit)
{
var entry = new BankEntry();
entry.guid = bank.Substring(0, 38);
entry.name = bank.Substring(38);
banks.Add(entry);
}
}
private void BuildTreeItem(FolderEntry entry)
{
// lookup the entry
EditorUtils.GetScriptOutput(string.Format("cur = studio.project.lookup(\"{0}\");", entry.guid));
// get child count
string itemCountString = EditorUtils.GetScriptOutput("cur.items.length;");
int itemCount;
Int32.TryParse(itemCountString, out itemCount);
// iterate children looking for folder
for (int item = 0; item < itemCount; item++)
{
EditorUtils.GetScriptOutput(String.Format("child = cur.items[{0}]", item));
// check if it's a folder
string isFolder = EditorUtils.GetScriptOutput("child.isOfExactType(\"EventFolder\")");
if (isFolder == "false")
{
continue;
}
// Get guid and name
string info = EditorUtils.GetScriptOutput("child.id + child.name");
var childEntry = new FolderEntry();
childEntry.guid = info.Substring(0, 38);
childEntry.name = info.Substring(38);
childEntry.parent = entry;
entry.entries.Add(childEntry);
}
// Recurse for child entries
foreach(var childEntry in entry.entries)
{
BuildTreeItem(childEntry);
}
}
public void OnGUI()
{
var borderIcon = EditorUtils.LoadImage("Border.png");
var border = new GUIStyle(GUI.skin.box);
border.normal.background = borderIcon;
GUI.Box(new Rect(1, 1, position.width - 1, position.height - 1), GUIContent.none, border);
if (Event.current.type == EventType.Layout)
{
isConnected = EditorUtils.IsConnectedToStudio();
}
if (!isConnected)
{
this.ShowNotification(new GUIContent("FMOD Studio not running"));
return;
}
this.RemoveNotification();
if (rootFolder == null)
{
BuildTree();
currentFolder = rootFolder;
}
var arrowIcon = EditorUtils.LoadImage("ArrowIcon.png");
var hoverIcon = EditorUtils.LoadImage("SelectedAlt.png");
var titleIcon = EditorGUIUtility.Load("IN BigTitle") as Texture2D;
var nextEntry = currentFolder;
var filteredEntries = currentFolder.entries.FindAll((x) => x.name.StartsWith(currentFilter, StringComparison.CurrentCultureIgnoreCase));
// Process key strokes for the folder list
{
if (Event.current.keyCode == KeyCode.UpArrow)
{
if (Event.current.type == EventType.KeyDown)
{
lastHover = Math.Max(lastHover - 1, 0);
if (filteredEntries[lastHover].rect.y < scrollPos.y)
{
scrollPos.y = filteredEntries[lastHover].rect.y;
}
}
Event.current.Use();
}
if (Event.current.keyCode == KeyCode.DownArrow)
{
if (Event.current.type == EventType.KeyDown)
{
lastHover = Math.Min(lastHover + 1, filteredEntries.Count - 1);
if (filteredEntries[lastHover].rect.y + filteredEntries[lastHover].rect.height > scrollPos.y + scrollRect.height)
{
scrollPos.y = filteredEntries[lastHover].rect.y - scrollRect.height + filteredEntries[lastHover].rect.height * 2;
}
}
Event.current.Use();
}
if (Event.current.keyCode == KeyCode.RightArrow)
{
if (Event.current.type == EventType.KeyDown)
nextEntry = filteredEntries[lastHover];
Event.current.Use();
}
if (Event.current.keyCode == KeyCode.LeftArrow)
{
if (Event.current.type == EventType.KeyDown)
if (currentFolder.parent != null)
{
nextEntry = currentFolder.parent;
}
Event.current.Use();
}
}
bool disabled = eventName.Length == 0;
EditorGUI.BeginDisabledGroup(disabled);
if (GUILayout.Button("Create Event"))
{
CreateEventInStudio();
this.Close();
}
EditorGUI.EndDisabledGroup();
{
GUI.SetNextControlName("name");
EditorGUILayout.LabelField("Name");
eventName = EditorGUILayout.TextField(eventName);
}
{
EditorGUILayout.LabelField("Bank");
selectedBank = EditorGUILayout.Popup(selectedBank, banks.Select(x => x.name).ToArray());
}
bool updateEventPath = false;
{
GUI.SetNextControlName("folder");
EditorGUI.BeginChangeCheck();
EditorGUILayout.LabelField("Path");
eventFolder = GUILayout.TextField(eventFolder);
if (EditorGUI.EndChangeCheck())
{
updateEventPath = true;
}
}
if (resetCursor)
{
resetCursor = false;
var textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
if (textEditor != null)
{
textEditor.MoveCursorToPosition(new Vector2(9999, 9999));
}
}
// Draw the current folder as a title bar, click to go back one level
{
Rect currentRect = EditorGUILayout.GetControlRect();
var bg = new GUIStyle(GUI.skin.box);
bg.normal.background = titleIcon;
Rect bgRect = new Rect(currentRect);
bgRect.x = 2;
bgRect.width = position.width-4;
GUI.Box(bgRect, GUIContent.none, bg);
Rect textureRect = currentRect;
textureRect.width = arrowIcon.width;
if (currentFolder.name != null)
{
GUI.DrawTextureWithTexCoords(textureRect, arrowIcon, new Rect(1, 1, -1, -1));
}
Rect labelRect = currentRect;
labelRect.x += arrowIcon.width + 50;
labelRect.width -= arrowIcon.width + 50;
GUI.Label(labelRect, currentFolder.name != null ? currentFolder.name : "Folders", EditorStyles.boldLabel);
if (Event.current.type == EventType.MouseDown && currentRect.Contains(Event.current.mousePosition) &&
currentFolder.parent != null)
{
nextEntry = currentFolder.parent;
Event.current.Use();
}
}
var normal = new GUIStyle(GUI.skin.label);
normal.padding.left = 14;
var hover = new GUIStyle(normal);
hover.normal.background = hoverIcon;
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
for (int i = 0; i < filteredEntries.Count; i++)
{
var entry = filteredEntries[i];
var content = new GUIContent(entry.name);
var rect = EditorGUILayout.GetControlRect();
if ((rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseMove) || i == lastHover)
{
lastHover = i;
GUI.Label(rect, content, hover);
if (rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDown)
{
nextEntry = entry;
}
}
else
{
GUI.Label(rect, content, normal);
}
Rect textureRect = rect;
textureRect.x = textureRect.width - arrowIcon.width;
textureRect.width = arrowIcon.width;
GUI.DrawTexture(textureRect, arrowIcon);
if (Event.current.type == EventType.Repaint)
{
entry.rect = rect;
}
}
EditorGUILayout.EndScrollView();
if (Event.current.type == EventType.Repaint)
{
scrollRect = GUILayoutUtility.GetLastRect();
}
if (currentFolder != nextEntry)
{
lastHover = 0;
currentFolder = nextEntry;
UpdateTextFromList();
Repaint();
}
if (updateEventPath)
{
UpdateListFromText();
}
if (Event.current.type == EventType.MouseMove)
{
Repaint();
}
}
private void CreateEventInStudio()
{
string eventGuid = EditorUtils.CreateStudioEvent(eventFolder, eventName);
if (!string.IsNullOrEmpty(eventGuid))
{
EditorUtils.GetScriptOutput(String.Format("studio.project.lookup(\"{0}\").relationships.banks.add(studio.project.lookup(\"{1}\"));", eventGuid, banks[selectedBank].guid));
EditorUtils.GetScriptOutput("studio.project.build();");
if (!eventFolder.EndsWith("/"))
{
eventFolder += "/";
}
string fullPath = "event:" + eventFolder + eventName;
outputProperty.SetEventReference(FMOD.GUID.Parse(eventGuid), fullPath);
EditorUtils.UpdateParamsOnEmitter(outputProperty.serializedObject, fullPath);
outputProperty.serializedObject.ApplyModifiedProperties();
}
}
private void UpdateListFromText()
{
int endFolders = eventFolder.LastIndexOf("/");
currentFilter = eventFolder.Substring(endFolders + 1);
var folders = eventFolder.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
FolderEntry entry = rootFolder;
int i;
for (i = 0; i < folders.Length; i++)
{
var newEntry = entry.entries.Find((x) => x.name.Equals(folders[i], StringComparison.CurrentCultureIgnoreCase));
if (newEntry == null)
{
break;
}
entry = newEntry;
}
currentFolder = entry;
// Treat an exact filter match as being in that folder and clear the filter
if (entry.name != null && entry.name.Equals(currentFilter, StringComparison.CurrentCultureIgnoreCase))
{
currentFilter = "";
}
}
private void UpdateTextFromList()
{
string path = "";
var entry = currentFolder;
while (entry.parent != null)
{
path = entry.name + "/" + path;
entry = entry.parent;
}
eventFolder = "/" + path;
resetCursor = true;
currentFilter = "";
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9c9773a32ed4a2b429fd42645175c32b
timeCreated: 1455063674
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FMODUnity
{
public class EditorBankRef : ScriptableObject
{
[SerializeField]
public string Path;
[SerializeField]
public string Name;
[SerializeField]
public string StudioPath;
[SerializeField]
private Int64 lastModified;
[SerializeField]
public List<NameValuePair> FileSizes;
public bool Exists;
public DateTime LastModified
{
get { return new DateTime(lastModified); }
set { lastModified = value.Ticks; }
}
public static string CalculateName(string filePath, string basePath)
{
string relativePath = filePath.Substring(basePath.Length + 1);
string extension = System.IO.Path.GetExtension(relativePath);
string name = relativePath.Substring(0, relativePath.Length - extension.Length);
name = RuntimeUtils.GetCommonPlatformPath(name);
return name;
}
public void SetPath(string filePath, string basePath)
{
Path = RuntimeUtils.GetCommonPlatformPath(filePath);
Name = CalculateName(filePath, basePath);
base.name = "bank:/" + Name + System.IO.Path.GetExtension(filePath);
}
public void SetStudioPath(string studioPath)
{
string stringCmp;
stringCmp = System.IO.Path.GetFileName(Name);
if (!studioPath.Contains(stringCmp))
{
// No match means localization
studioPath = studioPath.Substring(0, studioPath.LastIndexOf("/") + 1);
studioPath += stringCmp;
}
StudioPath = studioPath;
}
[Serializable]
public class NameValuePair
{
public string Name;
public long Value;
public NameValuePair(string name, long value)
{
Name = name;
Value = value;
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c18180ecb35941f4682ae60107b85b7c
timeCreated: 1432775088
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace FMODUnity
{
public class EditorEventRef : ScriptableObject
{
[SerializeField]
public string Path;
[SerializeField]
public FMOD.GUID Guid;
[SerializeField]
public List<EditorBankRef> Banks;
[SerializeField]
public bool IsStream;
[SerializeField]
public bool Is3D;
[SerializeField]
public bool IsOneShot;
[SerializeField]
public List<EditorParamRef> Parameters;
[SerializeField]
public float MinDistance;
[SerializeField]
public float MaxDistance;
[SerializeField]
public int Length;
public List<EditorParamRef> LocalParameters
{
get { return Parameters.Where(p => p.IsGlobal == false).OrderBy(p => p.Name).ToList(); }
}
public List<EditorParamRef> GlobalParameters
{
get { return Parameters.Where(p => p.IsGlobal == true).OrderBy(p => p.Name).ToList(); }
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ceb653cd98e289a4e8697a1af55201f2
timeCreated: 1432775088
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
public enum ParameterType
{
Continuous,
Discrete,
Labeled,
}
public class EditorParamRef : ScriptableObject
{
[SerializeField]
public string Name;
[SerializeField]
public string StudioPath;
[SerializeField]
public float Min;
[SerializeField]
public float Max;
[SerializeField]
public float Default;
[SerializeField]
public ParameterID ID;
[SerializeField]
public ParameterType Type;
[SerializeField]
public bool IsGlobal;
[SerializeField]
public string[] Labels = { };
public bool Exists;
[Serializable]
public struct ParameterID
{
public static implicit operator ParameterID(FMOD.Studio.PARAMETER_ID source)
{
return new ParameterID {
data1 = source.data1,
data2 = source.data2,
};
}
public static implicit operator FMOD.Studio.PARAMETER_ID(ParameterID source)
{
return new FMOD.Studio.PARAMETER_ID {
data1 = source.data1,
data2 = source.data2,
};
}
public bool Equals(FMOD.Studio.PARAMETER_ID other)
{
return data1 == other.data1 && data2 == other.data2;
}
public uint data1;
public uint data2;
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fecb8ef7f94ca804a8ab72049b86782e
timeCreated: 1432775088
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,682 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
namespace FMODUnity
{
[InitializeOnLoad]
public class EditorSettings : IEditorSettings
{
static EditorSettings()
{
Settings.EditorSettings = new EditorSettings();
}
public const string DownloadURL = "https://www.fmod.com/download";
// This is used to find the platform that implements the current Unity build target.
private Dictionary<BuildTarget, Platform> PlatformForBuildTarget = new Dictionary<BuildTarget, Platform>();
private static string FMODFolderFull => $"Assets/{RuntimeUtils.PluginBasePath}";
private const string CacheFolderName = "Cache";
private static string CacheFolderRelative => $"{RuntimeUtils.PluginBasePath}/{CacheFolderName}";
private static string CacheFolderFull => $"{FMODFolderFull}/{CacheFolderName}";
private const string RegisterStaticPluginsFile = "RegisterStaticPlugins.cs";
private static string RegisterStaticPluginsAssetPathRelative => $"{CacheFolderRelative}/{RegisterStaticPluginsFile}";
private static string RegisterStaticPluginsAssetPathFull => $"{CacheFolderFull}/{RegisterStaticPluginsFile}";
[NonSerialized]
private Dictionary<string, bool> binaryCompatibilitiesBeforeBuild;
public static EditorSettings Instance
{
get
{
return Settings.EditorSettings as EditorSettings;
}
}
public Settings RuntimeSettings { get; set; }
[MenuItem("FMOD/Edit Settings", priority = 0)]
public static void EditSettings()
{
Selection.activeObject = Settings.Instance;
EditorApplication.ExecuteMenuItem("Window/General/Inspector");
}
public void CreateSettingsAsset(string assetName)
{
string resourcesPath = $"{FMODFolderFull}/Resources";
if (!Directory.Exists(resourcesPath))
{
AssetDatabase.CreateFolder(FMODFolderFull, "Resources");
}
AssetDatabase.CreateAsset(RuntimeSettings, $"{resourcesPath}/{assetName}.asset");
AddPlatformsToAsset();
}
public void AddPlatformForBuildTargets(Platform platform)
{
foreach (BuildTarget buildTarget in platform.GetBuildTargets())
{
if (buildTarget != BuildTarget.NoTarget)
{
PlatformForBuildTarget.Add(buildTarget, platform);
}
}
}
// Adds a new platform group to the set of platforms.
public PlatformGroup AddPlatformGroup(string displayName, int sortOrder)
{
PlatformGroup group = PlatformGroup.Create(displayName, Legacy.Platform.None);
group.DisplaySortOrder = sortOrder;
RuntimeSettings.AddPlatform(group);
AssetDatabase.AddObjectToAsset(group, RuntimeSettings);
RuntimeSettings.LinkPlatform(group);
return group;
}
private void ClearPlatformSettings()
{
RemovePlatformFromAsset(RuntimeSettings.DefaultPlatform);
RemovePlatformFromAsset(RuntimeSettings.PlayInEditorPlatform);
RuntimeSettings.ForEachPlatform(RemovePlatformFromAsset);
foreach (Platform platform in Resources.LoadAll<Platform>(Settings.SettingsAssetName))
{
RemovePlatformFromAsset(platform);
}
RuntimeSettings.DefaultPlatform = null;
RuntimeSettings.PlayInEditorPlatform = null;
RuntimeSettings.Platforms.Clear();
PlatformForBuildTarget.Clear();
RuntimeSettings.PlatformForRuntimePlatform.Clear();
}
// Testing function: Resets all platform settings.
public void ResetPlatformSettings()
{
ClearPlatformSettings();
RuntimeSettings.OnEnable();
}
// Testing function: Reimports legacy platform settings.
public void ReimportLegacyPlatforms()
{
ClearPlatformSettings();
RuntimeSettings.MigratedPlatforms.Clear();
RuntimeSettings.OnEnable();
}
public void UpdateMigratedPlatform(Platform platform)
{
if (!RuntimeSettings.MigratedPlatforms.Contains(platform.LegacyIdentifier))
{
RuntimeSettings.MigratedPlatforms.Add(platform.LegacyIdentifier);
}
}
// Adds any missing platforms:
// * From the template collection
// * From the legacy settings
public void AddMissingPlatforms()
{
var newPlatforms = new List<Platform>();
foreach (Settings.PlatformTemplate template in Settings.PlatformTemplates)
{
if (!RuntimeSettings.PlatformExists(template.Identifier))
{
newPlatforms.Add(template.CreateInstance());
}
}
// Ensure that the default platform exists
if (!RuntimeSettings.DefaultPlatform)
{
RuntimeSettings.DefaultPlatform = ScriptableObject.CreateInstance<PlatformDefault>();
newPlatforms.Add(RuntimeSettings.DefaultPlatform);
}
// Ensure that the Play In Editor platform exists
if (!RuntimeSettings.PlayInEditorPlatform)
{
RuntimeSettings.PlayInEditorPlatform = ScriptableObject.CreateInstance<PlatformPlayInEditor>();
newPlatforms.Add(RuntimeSettings.PlayInEditorPlatform);
}
// Ensure that the default and Play In Editor platforms have properties
AffirmPlatformProperties(RuntimeSettings.DefaultPlatform);
AffirmPlatformProperties(RuntimeSettings.PlayInEditorPlatform);
// Migrate plugins if necessary
var PluginsProperty = Platform.PropertyAccessors.Plugins;
if (!RuntimeSettings.MigratedPlatforms.Contains(RuntimeSettings.DefaultPlatform.LegacyIdentifier))
{
PluginsProperty.Set(RuntimeSettings.DefaultPlatform, RuntimeSettings.Plugins);
}
else if (!PluginsProperty.HasValue(RuntimeSettings.DefaultPlatform))
{
PluginsProperty.Set(RuntimeSettings.DefaultPlatform, new List<string>());
}
// Migrate LiveUpdatePort
if (!Platform.PropertyAccessors.LiveUpdatePort.HasValue(RuntimeSettings.DefaultPlatform))
{
Platform.PropertyAccessors.LiveUpdatePort.Set(RuntimeSettings.DefaultPlatform, RuntimeSettings.LiveUpdatePort);
}
// Create a map for migrating legacy settings
var platformMap = new Dictionary<Legacy.Platform, Platform>();
foreach (Platform platform in RuntimeSettings.Platforms.Concat(newPlatforms))
{
if (platform.LegacyIdentifier != Legacy.Platform.None)
{
platformMap.Add(platform.LegacyIdentifier, platform);
}
}
Func<Legacy.Platform, Platform> AffirmPlatform = null;
// Ensures that all of the platform's ancestors exist.
Action<Platform> AffirmAncestors = (platform) =>
{
Legacy.Platform legacyParent = Legacy.Parent(platform.LegacyIdentifier);
if (legacyParent != Legacy.Platform.None)
{
platform.ParentIdentifier = AffirmPlatform(legacyParent).Identifier;
}
};
// Gets the platform corresponding to legacyPlatform (or creates it if it is a group),
// and ensures that it has properties and all of its ancestors exist.
// Returns null if legacyPlatform is unknown.
AffirmPlatform = (legacyPlatform) =>
{
Platform platform;
if (platformMap.TryGetValue(legacyPlatform, out platform))
{
platform.AffirmProperties();
}
else if (Legacy.IsGroup(legacyPlatform))
{
PlatformGroup group = PlatformGroup.Create(Legacy.DisplayName(legacyPlatform), legacyPlatform);
platformMap.Add(legacyPlatform, group);
newPlatforms.Add(group);
platform = group;
}
else
{
// This is an unknown platform
return null;
}
AffirmAncestors(platform);
return platform;
};
// Gets the target plaform to use when migrating settings from legacyPlatform.
// Returns null if legacyPlatform is unknown or has already been migrated.
Func<Legacy.Platform, Platform> getMigrationTarget = (legacyPlatform) =>
{
if (RuntimeSettings.MigratedPlatforms.Contains(legacyPlatform))
{
// Already migrated
return null;
}
return AffirmPlatform(legacyPlatform);
};
var speakerModeSettings = RuntimeSettings.SpeakerModeSettings.ConvertAll(
setting => new Legacy.PlatformSetting<FMOD.SPEAKERMODE>()
{
Value = (FMOD.SPEAKERMODE)setting.Value,
Platform = setting.Platform
}
);
// Migrate all the legacy settings, creating platforms as we need them via AffirmPlatform
MigrateLegacyPlatforms(speakerModeSettings, Platform.PropertyAccessors.SpeakerMode, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.SampleRateSettings, Platform.PropertyAccessors.SampleRate, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.LiveUpdateSettings, Platform.PropertyAccessors.LiveUpdate, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.OverlaySettings, Platform.PropertyAccessors.Overlay, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.BankDirectorySettings, Platform.PropertyAccessors.BuildDirectory, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.VirtualChannelSettings, Platform.PropertyAccessors.VirtualChannelCount, getMigrationTarget);
MigrateLegacyPlatforms(RuntimeSettings.RealChannelSettings, Platform.PropertyAccessors.RealChannelCount, getMigrationTarget);
// Now we ensure that if a legacy group has settings, all of its descendants exist
// and inherit from it (even if they have no settings of their own), so that the
// inheritance structure matches the old system.
// We look at all groups (not just newly created ones), because a newly created platform
// may need to inherit from a preexisting group.
var groupsToProcess = new Queue<Platform>(platformMap.Values.Where(
platform => platform is PlatformGroup
&& platform.LegacyIdentifier != Legacy.Platform.None
&& platform.HasAnyOverriddenProperties));
while (groupsToProcess.Count > 0)
{
Platform group = groupsToProcess.Dequeue();
// Ensure that all descendants exist
foreach (var child in platformMap.Values)
{
if (child.Active)
{
// Don't overwrite existing settings
continue;
}
var legacyPlatform = child.LegacyIdentifier;
if (legacyPlatform == Legacy.Platform.iOS || legacyPlatform == Legacy.Platform.Android)
{
// These platforms were overridden by MobileHigh and MobileLow in the old system
continue;
}
if (RuntimeSettings.MigratedPlatforms.Contains(legacyPlatform))
{
// The user may have deleted this platform since migration, so don't mess with it
continue;
}
if (Legacy.Parent(legacyPlatform) == group.LegacyIdentifier)
{
child.AffirmProperties();
child.ParentIdentifier = group.Identifier;
if (child is PlatformGroup)
{
groupsToProcess.Enqueue(child as PlatformGroup);
}
}
}
}
// Add all of the new platforms to the set of known platforms
foreach (Platform platform in newPlatforms)
{
RuntimeSettings.AddPlatform(platform);
}
RuntimeSettings.ForEachPlatform(UpdateMigratedPlatform);
}
private void MigrateLegacyPlatforms<TValue, TSetting>(List<TSetting> settings,
Platform.PropertyAccessor<TValue> property, Func<Legacy.Platform, Platform> getMigrationTarget)
where TSetting : Legacy.PlatformSetting<TValue>
{
foreach (TSetting setting in settings)
{
Platform platform = getMigrationTarget(setting.Platform);
if (platform != null)
{
property.Set(platform, setting.Value);
}
}
}
// The platform that implements the current Unity build target.
public Platform CurrentEditorPlatform
{
get
{
return GetPlatform(EditorUserBuildSettings.activeBuildTarget);
}
}
public Platform GetPlatform(BuildTarget buildTarget)
{
if (PlatformForBuildTarget.ContainsKey(buildTarget))
{
return PlatformForBuildTarget[buildTarget];
}
else
{
return RuntimeSettings.DefaultPlatform;
}
}
public void SetPlatformParent(Platform platform, Platform newParent)
{
Platform oldParent = RuntimeSettings.FindPlatform(platform.ParentIdentifier);
if (oldParent != null)
{
oldParent.ChildIdentifiers.Remove(platform.Identifier);
}
if (newParent != null)
{
platform.ParentIdentifier = newParent.Identifier;
newParent.ChildIdentifiers.Add(platform.Identifier);
SortPlatformChildren(newParent);
}
else
{
platform.ParentIdentifier = null;
}
}
public void SetPlatformSortOrder(Platform platform, float sortOrder)
{
if (platform.DisplaySortOrder != sortOrder)
{
platform.DisplaySortOrder = sortOrder;
if (platform.Parent != null)
{
SortPlatformChildren(platform.Parent);
}
}
}
public void SortPlatformChildren(Platform platform)
{
platform.ChildIdentifiers.Sort((a, b) => {
Platform platformA = RuntimeSettings.FindPlatform(a);
Platform platformB = RuntimeSettings.FindPlatform(b);
return platformA.DisplaySortOrder.CompareTo(platformB.DisplaySortOrder);
});
}
// Ensures that the given platform has valid properties.
private void AffirmPlatformProperties(Platform platform)
{
if (!platform.Active)
{
RuntimeUtils.DebugLogFormat("[FMOD] Cannot find properties for platform {0}, creating default properties", platform.Identifier);
RuntimeSettings.AddPlatformProperties(platform);
}
}
private void RemovePlatformFromAsset(Platform platform)
{
if (AssetDatabase.Contains(platform))
{
UnityEngine.Object.DestroyImmediate(platform, true);
}
}
public bool CanBuildTarget(BuildTarget target, Platform.BinaryType binaryType, out string error)
{
if (Settings.Instance == null)
{
error = "Settings instance has not been initialized. Unable to continue build.";
return false;
}
Platform platform;
if (!PlatformForBuildTarget.TryGetValue(target, out platform))
{
error = string.Format("No FMOD platform found for build target {0}.\n" +
"You may need to install a platform specific integration package from {1}.",
target, DownloadURL);
return false;
}
IEnumerable<string> missingPathsQuery = platform.GetBinaryFilePaths(target, binaryType)
.Where(path => !File.Exists(path) && !Directory.Exists(path));
if (missingPathsQuery.Any())
{
string[] missingPaths = missingPathsQuery.Select(path => "- " + path).ToArray();
string summary;
if (missingPaths.Length == 1)
{
summary = string.Format("There is an FMOD binary missing for build target {0}", target);
}
else
{
summary = string.Format("There are {0} FMOD binaries missing for build target {1}",
missingPaths.Length, target);
}
if (binaryType == Platform.BinaryType.Logging)
{
summary += " (development build)";
}
error = string.Format(
"{0}:\n" +
"{1}\n" +
"Please run the {2} menu command.\n",
summary, string.Join("\n", missingPaths), FileReorganizer.ReorganizerMenuItemPath);
return false;
}
error = null;
return true;
}
public void PreprocessBuild(BuildTarget target, Platform.BinaryType binaryType)
{
Platform platform = PlatformForBuildTarget[target];
PreprocessStaticPlugins(platform, target);
SelectBinaries(platform, target, binaryType);
}
private void PostprocessBuild(BuildTarget target)
{
foreach(string path in binaryCompatibilitiesBeforeBuild.Keys)
{
PluginImporter importer = AssetImporter.GetAtPath(path) as PluginImporter;
if (importer != null)
{
importer.SetCompatibleWithPlatform(target, binaryCompatibilitiesBeforeBuild[path]);
}
}
}
private void PreprocessStaticPlugins(Platform platform, BuildTarget target)
{
// Ensure we don't have leftover temporary changes from a previous build.
CleanTemporaryFiles();
BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(target);
ScriptingImplementation scriptingBackend = PlayerSettings.GetScriptingBackend(buildTargetGroup);
if (platform.StaticPlugins.Count > 0)
{
if (scriptingBackend == ScriptingImplementation.IL2CPP)
{
Action<string> reportError = message => {
RuntimeUtils.DebugLogWarningFormat("FMOD: Error processing static plugins for platform {0}: {1}",
platform.DisplayName, message);
};
if (!AssetDatabase.IsValidFolder(CacheFolderFull))
{
RuntimeUtils.DebugLogFormat("Creating {0}", CacheFolderFull);
AssetDatabase.CreateFolder(FMODFolderFull, CacheFolderName);
}
// Generate registration code and import it so it's included in the build.
RuntimeUtils.DebugLogFormat("FMOD: Generating static plugin registration code in {0}", RegisterStaticPluginsAssetPathFull);
string filePath = Application.dataPath + "/" + RegisterStaticPluginsAssetPathRelative;
CodeGeneration.GenerateStaticPluginRegistration(filePath, platform, reportError);
AssetDatabase.ImportAsset(RegisterStaticPluginsAssetPathFull);
}
else
{
RuntimeUtils.DebugLogWarningFormat(
"FMOD: Platform {0} has {1} static plugins specified, " +
"but static plugins are only supported on the IL2CPP scripting backend",
platform.DisplayName, platform.StaticPlugins.Count);
}
}
}
public void CleanTemporaryFiles()
{
DeleteTemporaryFile(RegisterStaticPluginsAssetPathFull);
}
public void DeleteTemporaryFile(string assetPath)
{
bool assetExists = !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(assetPath));
if (assetExists && AssetDatabase.DeleteAsset(assetPath))
{
RuntimeUtils.DebugLogFormat("FMOD: Removed temporary file {0}", assetPath);
}
}
private static void SelectBinaries(Platform platform, BuildTarget target, Platform.BinaryType binaryType)
{
string message = string.Format("FMOD: Selected binaries for platform {0}{1}:", target,
(binaryType == Platform.BinaryType.Logging) ? " (development build)" : string.Empty);
Instance.binaryCompatibilitiesBeforeBuild = new Dictionary<string, bool>();
HashSet<string> enabledPaths = new HashSet<string>();
foreach (string path in platform.GetBinaryAssetPaths(target, binaryType | Platform.BinaryType.Optional))
{
PluginImporter importer = AssetImporter.GetAtPath(path) as PluginImporter;
if (importer is PluginImporter)
{
Instance.binaryCompatibilitiesBeforeBuild.Add(path, importer.GetCompatibleWithPlatform(target));
importer.SetCompatibleWithPlatform(target, true);
enabledPaths.Add(path);
message += string.Format("\n- Enabled {0}", path);
}
}
foreach (string path in platform.GetBinaryAssetPaths(target, Platform.BinaryType.All))
{
if (!enabledPaths.Contains(path))
{
PluginImporter importer = AssetImporter.GetAtPath(path) as PluginImporter;
if (importer is PluginImporter)
{
Instance.binaryCompatibilitiesBeforeBuild.Add(path, importer.GetCompatibleWithPlatform(target));
importer.SetCompatibleWithPlatform(target, false);
message += string.Format("\n- Disabled {0}", path);
}
}
}
RuntimeUtils.DebugLog(message);
}
public bool ForceLoggingBinaries { get; private set; } = false;
public class BuildProcessor : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(BuildReport report)
{
Platform.BinaryType binaryType;
if ((report.summary.options & BuildOptions.Development) == BuildOptions.Development
|| EditorSettings.Instance.ForceLoggingBinaries)
{
binaryType = Platform.BinaryType.Logging;
}
else
{
binaryType = Platform.BinaryType.Release;
}
string error;
if (!EditorSettings.Instance.CanBuildTarget(report.summary.platform, binaryType, out error))
{
throw new BuildFailedException(error);
}
EditorSettings.Instance.PreprocessBuild(report.summary.platform, binaryType);
}
public void OnPostprocessBuild(BuildReport report)
{
Instance.PostprocessBuild(report.summary.platform);
}
}
public class BuildTargetChecker : IActiveBuildTargetChanged
{
public int callbackOrder { get { return 0; } }
public void OnActiveBuildTargetChanged(BuildTarget previous, BuildTarget current)
{
Settings.EditorSettings.CleanTemporaryFiles();
Platform.BinaryType binaryType = EditorUserBuildSettings.development
? Platform.BinaryType.Logging
: Platform.BinaryType.Release;
string error;
if (!Settings.EditorSettings.CanBuildTarget(current, binaryType, out error))
{
RuntimeUtils.DebugLogWarning(error);
if (EditorWindow.HasOpenInstances<BuildPlayerWindow>())
{
GUIContent message =
new GUIContent("FMOD detected issues with this platform!\nSee the Console for details.");
EditorWindow.GetWindow<BuildPlayerWindow>().ShowNotification(message, 10);
}
}
}
}
// Adds all platforms to the settings asset, so they get stored in the same file as the main
// Settings object.
public void AddPlatformsToAsset()
{
RuntimeSettings.ForEachPlatform(AddPlatformToAsset);
}
private void AddPlatformToAsset(Platform platform)
{
if (!AssetDatabase.Contains(platform))
{
AssetDatabase.AddObjectToAsset(platform, RuntimeSettings);
}
}
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2bb4068641d1f71478f95a9b73533f51
timeCreated: 1432608272
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5332ad2baabb58844975479e906001c8
timeCreated: 1432613753
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FMODUnity
{
public class EventCache : ScriptableObject
{
[SerializeField]
public List<EditorBankRef> EditorBanks;
[SerializeField]
public List<EditorEventRef> EditorEvents;
[SerializeField]
public List<EditorParamRef> EditorParameters;
[SerializeField]
public List<EditorBankRef> MasterBanks;
[SerializeField]
public List<EditorBankRef> StringsBanks;
[SerializeField]
private Int64 cacheTime;
[SerializeField]
public int cacheVersion;
public DateTime CacheTime
{
get { return new DateTime(cacheTime); }
set { cacheTime = value.Ticks; }
}
public EventCache()
{
EditorBanks = new List<EditorBankRef>();
EditorEvents = new List<EditorEventRef>();
EditorParameters = new List<EditorParamRef>();
MasterBanks = new List<EditorBankRef>();
StringsBanks = new List<EditorBankRef>();
cacheTime = 0;
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d32cf7c32a3ed8347bac48ef5ed56d82
timeCreated: 1432775088
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1fc38201a5edb994c874a4a61e96053b
timeCreated: 1432600216
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,513 @@
using System;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEditor;
namespace FMODUnity
{
[CustomPropertyDrawer(typeof(EventReference))]
public class EventReferenceDrawer : PropertyDrawer
{
private static readonly Texture RepairIcon = EditorUtils.LoadImage("Wrench.png");
private static readonly Texture WarningIcon = EditorUtils.LoadImage("NotFound.png");
private static readonly GUIContent NotFoundWarning = new GUIContent("Event Not Found", WarningIcon);
private static GUIStyle buttonStyle;
private static Vector2 WarningSize()
{
return GUI.skin.label.CalcSize(NotFoundWarning);
}
private static float GetBaseHeight()
{
return GUI.skin.textField.CalcSize(GUIContent.none).y;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (buttonStyle == null)
{
buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.padding.top = 1;
buttonStyle.padding.bottom = 1;
}
Texture browseIcon = EditorUtils.LoadImage("SearchIconBlack.png");
Texture openIcon = EditorUtils.LoadImage("BrowserIcon.png");
Texture addIcon = EditorUtils.LoadImage("AddIcon.png");
Texture copyIcon = EditorUtils.LoadImage("CopyIcon.png");
using (new EditorGUI.PropertyScope(position, label, property))
{
HandleDragEvents(position, property);
EventReference eventReference = property.GetEventReference();
EditorEventRef editorEventRef = GetEditorEventRef(eventReference);
float baseHeight = GetBaseHeight();
Rect headerRect = position;
headerRect.width = EditorGUIUtility.labelWidth;
headerRect.height = baseHeight;
if (editorEventRef != null)
{
property.isExpanded = EditorGUI.Foldout(headerRect, property.isExpanded, label, true);
}
else
{
EditorGUI.LabelField(headerRect, label);
}
Rect addRect = new Rect(position.xMax - addIcon.width - 7, position.y, addIcon.width + 7, baseHeight);
Rect openRect = new Rect(addRect.x - openIcon.width - 7, position.y, openIcon.width + 6, baseHeight);
Rect searchRect = new Rect(openRect.x - browseIcon.width - 9, position.y, browseIcon.width + 8, baseHeight);
Rect pathRect = position;
pathRect.xMin = headerRect.xMax;
pathRect.xMax = searchRect.x - 3;
pathRect.height = baseHeight;
SerializedProperty pathProperty = GetPathProperty(property);
using (var scope = new EditorGUI.ChangeCheckScope())
{
EditorGUI.PropertyField(pathRect, pathProperty, GUIContent.none);
if (scope.changed)
{
SetEvent(property, pathProperty.stringValue);
}
}
if (GUI.Button(searchRect, new GUIContent(browseIcon, "Search"), buttonStyle))
{
var eventBrowser = ScriptableObject.CreateInstance<EventBrowser>();
eventBrowser.ChooseEvent(property);
var windowRect = position;
windowRect.xMin = pathRect.xMin;
windowRect.position = GUIUtility.GUIToScreenPoint(windowRect.position);
windowRect.height = openRect.height + 1;
eventBrowser.ShowAsDropDown(windowRect, new Vector2(windowRect.width, 400));
}
if (GUI.Button(addRect, new GUIContent(addIcon, "Create New Event in Studio"), buttonStyle))
{
var addDropdown = EditorWindow.CreateInstance<CreateEventPopup>();
addDropdown.SelectEvent(property);
var windowRect = position;
windowRect.xMin = pathRect.xMin;
windowRect.position = GUIUtility.GUIToScreenPoint(windowRect.position);
windowRect.height = openRect.height + 1;
addDropdown.ShowAsDropDown(windowRect, new Vector2(windowRect.width, 500));
}
if (GUI.Button(openRect, new GUIContent(openIcon, "Open In Browser"), buttonStyle) &&
!string.IsNullOrEmpty(pathProperty.stringValue) &&
EventManager.EventFromPath(pathProperty.stringValue) != null
)
{
EventBrowser.ShowWindow();
EventBrowser eventBrowser = EditorWindow.GetWindow<EventBrowser>();
eventBrowser.FrameEvent(pathProperty.stringValue);
}
if (editorEventRef != null)
{
float labelY = headerRect.y + baseHeight;
MismatchInfo mismatch = GetMismatch(eventReference, editorEventRef);
if (mismatch != null)
{
Rect warningRect = pathRect;
warningRect.xMax = position.xMax;
warningRect.y = labelY;
warningRect.height = WarningSize().y;
DrawMismatchUI(warningRect, openRect.x, openRect.width, mismatch, property);
labelY = warningRect.yMax;
}
if (property.isExpanded)
{
using (new EditorGUI.IndentLevelScope())
{
Rect labelRect = EditorGUI.IndentedRect(headerRect);
labelRect.y = labelY;
Rect valueRect = labelRect;
valueRect.xMin = labelRect.xMax;
valueRect.xMax = position.xMax - copyIcon.width - 7;
GUI.Label(labelRect, new GUIContent("GUID"));
GUI.Label(valueRect, eventReference.Guid.ToString());
Rect copyRect = valueRect;
copyRect.xMin = valueRect.xMax;
copyRect.xMax = position.xMax;
if (GUI.Button(copyRect, new GUIContent(copyIcon, "Copy To Clipboard")))
{
EditorGUIUtility.systemCopyBuffer = eventReference.Guid.ToString();
}
valueRect.xMax = position.xMax;
labelRect.y += baseHeight;
valueRect.y += baseHeight;
GUI.Label(labelRect, new GUIContent("Banks"));
GUI.Label(valueRect, string.Join(", ", editorEventRef.Banks.Select(x => x.Name).ToArray()));
labelRect.y += baseHeight;
valueRect.y += baseHeight;
GUI.Label(labelRect, new GUIContent("Panning"));
GUI.Label(valueRect, editorEventRef.Is3D ? "3D" : "2D");
labelRect.y += baseHeight;
valueRect.y += baseHeight;
GUI.Label(labelRect, new GUIContent("Stream"));
GUI.Label(valueRect, editorEventRef.IsStream.ToString());
labelRect.y += baseHeight;
valueRect.y += baseHeight;
GUI.Label(labelRect, new GUIContent("Oneshot"));
GUI.Label(valueRect, editorEventRef.IsOneShot.ToString());
labelRect.y += baseHeight;
valueRect.y += baseHeight;
}
}
}
else
{
EditorEventRef renamedEvent = GetRenamedEventRef(eventReference);
if (renamedEvent != null)
{
MismatchInfo mismatch = new MismatchInfo() {
Message = string.Format("Moved to {0}", renamedEvent.Path),
HelpText = string.Format(
"This event has been moved in FMOD Studio.\n" +
"You can click the repair button to update the path to the new location, or run " +
"the <b>{0}</b> command to scan your project for similar issues and fix them all.",
EventReferenceUpdater.MenuPath),
RepairTooltip = string.Format("Repair: set path to {0}", renamedEvent.Path),
RepairAction = (p) => {
p.FindPropertyRelative("Path").stringValue = renamedEvent.Path;
},
};
using (new EditorGUI.IndentLevelScope())
{
Rect mismatchRect = pathRect;
mismatchRect.xMin = position.xMin;
mismatchRect.xMax = position.xMax;
mismatchRect.y += baseHeight;
mismatchRect.height = baseHeight;
mismatchRect = EditorGUI.IndentedRect(mismatchRect);
DrawMismatchUI(mismatchRect, openRect.x, openRect.width, mismatch, property);
}
}
else
{
Rect labelRect = pathRect;
labelRect.xMax = position.xMax;
labelRect.y += baseHeight;
labelRect.height = WarningSize().y;
GUI.Label(labelRect, NotFoundWarning);
}
}
}
}
private static void HandleDragEvents(Rect position, SerializedProperty property)
{
Event e = Event.current;
if (e.type == EventType.DragPerform && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorEventRef))
{
EditorEventRef eventRef = DragAndDrop.objectReferences[0] as EditorEventRef;
property.SetEventReference(eventRef.Guid, eventRef.Path);
GUI.changed = true;
e.Use();
}
}
if (e.type == EventType.DragUpdated && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorEventRef))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
DragAndDrop.AcceptDrag();
e.Use();
}
}
}
private class MismatchInfo
{
public string Message;
public string HelpText;
public string RepairTooltip;
public Action<SerializedProperty> RepairAction;
}
private static void DrawMismatchUI(Rect rect, float repairButtonX, float repairButtonWidth,
MismatchInfo mismatch, SerializedProperty property)
{
rect = EditorUtils.DrawHelpButton(rect, () => new SimpleHelp(mismatch.HelpText, 400));
Rect repairRect = new Rect(repairButtonX, rect.y, repairButtonWidth, GetBaseHeight());
if (GUI.Button(repairRect, new GUIContent(RepairIcon, mismatch.RepairTooltip), buttonStyle))
{
mismatch.RepairAction(property);
}
Rect labelRect = rect;
labelRect.xMax = repairRect.xMin;
GUI.Label(labelRect, new GUIContent(mismatch.Message, WarningIcon));
}
private static MismatchInfo GetMismatch(EventReference eventReference, EditorEventRef editorEventRef)
{
if (EventManager.GetEventLinkage(eventReference) == EventLinkage.Path)
{
if (eventReference.Guid != editorEventRef.Guid)
{
return new MismatchInfo() {
Message = "GUID doesn't match path",
HelpText = string.Format(
"The GUID on this EventReference doesn't match the path.\n" +
"You can click the repair button to update the GUID to match the path, or run the " +
"<b>{0}</b> command to scan your project for similar issues and fix them all.",
EventReferenceUpdater.MenuPath),
RepairTooltip = string.Format("Repair: set GUID to {0}", editorEventRef.Guid),
RepairAction = (property) => {
property.FindPropertyRelative("Guid").SetGuid(editorEventRef.Guid);
},
};
}
}
else // EventLinkage.GUID
{
if (eventReference.Path != editorEventRef.Path)
{
return new MismatchInfo() {
Message = "Path doesn't match GUID",
HelpText = string.Format(
"The path on this EventReference doesn't match the GUID.\n" +
"You can click the repair button to update the path to match the GUID, or run the " +
"<b>{0}</b> command to scan your project for similar issues and fix them all.",
EventReferenceUpdater.MenuPath),
RepairTooltip = string.Format("Repair: set path to '{0}'", editorEventRef.Path),
RepairAction = (property) => {
property.FindPropertyRelative("Path").stringValue = editorEventRef.Path;
},
};
}
}
return null;
}
private static void SetEvent(SerializedProperty property, string path)
{
EditorEventRef eventRef = EventManager.EventFromPath(path);
if (eventRef != null)
{
property.SetEventReference(eventRef.Guid, eventRef.Path);
}
else
{
property.SetEventReference(new FMOD.GUID(), path);
}
}
private static SerializedProperty GetGuidProperty(SerializedProperty property)
{
return property.FindPropertyRelative("Guid");
}
private static SerializedProperty GetPathProperty(SerializedProperty property)
{
return property.FindPropertyRelative("Path");
}
private static EditorEventRef GetEditorEventRef(EventReference eventReference)
{
if (EventManager.GetEventLinkage(eventReference) == EventLinkage.Path)
{
return EventManager.EventFromPath(eventReference.Path);
}
else // Assume EventLinkage.GUID
{
return EventManager.EventFromGUID(eventReference.Guid);
}
}
private static EditorEventRef GetRenamedEventRef(EventReference eventReference)
{
if (Settings.Instance.EventLinkage == EventLinkage.Path && !eventReference.Guid.IsNull)
{
EditorEventRef editorEventRef = EventManager.EventFromGUID(eventReference.Guid);
if (editorEventRef != null && editorEventRef.Path != eventReference.Path)
{
return editorEventRef;
}
}
return null;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float baseHeight = GetBaseHeight();
EventReference eventReference = property.GetEventReference();
EditorEventRef editorEventRef = GetEditorEventRef(eventReference);
if (editorEventRef == null)
{
return baseHeight + WarningSize().y;
}
else
{
float height;
if (property.isExpanded)
{
height = baseHeight * 6; // 5 lines of info
}
else
{
height = baseHeight;
}
if (GetMismatch(eventReference, editorEventRef) != null)
{
height += WarningSize().y;
}
return height;
}
}
}
#pragma warning disable 0618 // Suppress the warning about using the obsolete EventRefAttribute class
[CustomPropertyDrawer(typeof(EventRefAttribute))]
#pragma warning restore 0618
public class LegacyEventRefDrawer : PropertyDrawer
{
private GUIStyle RichTextStyle;
private const string HelpText =
"This field has the <b>[EventRef]</b> attribute, which is obsolete.\n" +
"To resolve this issue:\n" +
"* Add a field of type <b>EventReference</b> to this class\n" +
"* Set the <b>MigrateTo</b> property on the <b>[EventRef]</b> attribute: " +
"<b>[EventRef(MigrateTo=\"<fieldname>\")]</b>\n" +
"* Run the <b>" + EventReferenceUpdater.MenuPath + "</b> command to " +
"automatically migrate values from this field to the <b>EventReference</b> field";
private static readonly Texture InfoIcon = EditorGUIUtility.IconContent("console.infoicon.sml").image;
private static readonly Texture WarningIcon = EditorUtils.LoadImage("NotFound.png");
private void AffirmStyles()
{
if (RichTextStyle == null)
{
RichTextStyle = new GUIStyle(GUI.skin.label) { richText = true };
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
AffirmStyles();
label = EditorGUI.BeginProperty(position, label, property);
Rect pathRect = position;
pathRect.height = EditorGUIUtility.singleLineHeight;
pathRect = EditorGUI.PrefixLabel(pathRect, label);
EditorGUI.PropertyField(pathRect, property, GUIContent.none);
using (new EditorGUI.IndentLevelScope())
{
GUIContent content = StatusContent(property);
Rect infoRect = EditorGUI.IndentedRect(position);
infoRect.y = pathRect.yMax;
infoRect.height = StatusSize(content).y;
infoRect = EditorUtils.DrawHelpButton(infoRect, () => new SimpleHelp(HelpText, 400));
GUI.Label(infoRect, content, RichTextStyle);
}
EditorGUI.EndProperty();
}
private GUIContent StatusContent(SerializedProperty property)
{
#pragma warning disable 0618 // Suppress the warning about using the obsolete EventRefAttribute class
string migrationTarget = (attribute as EventRefAttribute).MigrateTo;
#pragma warning restore 0618
if (string.IsNullOrEmpty(migrationTarget))
{
return new GUIContent("<b>[EventRef]</b> is obsolete - use the <b>EventReference</b> type instead.",
WarningIcon);
}
else
{
SerializedProperty targetProperty = property.serializedObject.FindProperty(migrationTarget);
if (targetProperty != null)
{
return new GUIContent(string.Format("Will be migrated to <b>{0}</b>", targetProperty.displayName),
InfoIcon);
}
else
{
return new GUIContent(string.Format("Migration target <b>{0}</b> is missing", migrationTarget),
WarningIcon);
}
}
}
private Vector2 StatusSize(GUIContent content)
{
AffirmStyles();
return Vector2.Max(RichTextStyle.CalcSize(content), EditorUtils.GetHelpButtonSize());
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight + StatusSize(StatusContent(property)).y;
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 29a86a77bf7568e499243d9b47b7e88e
timeCreated: 1432696197
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,501 @@
#if UNITY_TIMELINE_EXIST
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Timeline;
using UnityEngine;
using UnityEngine.Timeline;
using System;
using System.Linq;
using System.Reflection;
namespace FMODUnity
{
[CustomEditor(typeof(FMODEventPlayable))]
public class FMODEventPlayableEditor : Editor
{
private FMODEventPlayable eventPlayable;
private EditorEventRef editorEventRef;
private List<EditorParamRef> missingInitialParameterValues = new List<EditorParamRef>();
private List<EditorParamRef> missingParameterAutomations = new List<EditorParamRef>();
private SerializedProperty parametersProperty;
private SerializedProperty parameterLinksProperty;
private SerializedProperty parameterAutomationProperty;
private ListView parameterLinksView;
private ListView initialParameterValuesView;
private string eventPath;
public void OnEnable()
{
eventPlayable = target as FMODEventPlayable;
parametersProperty = serializedObject.FindProperty("Template.Parameters");
parameterLinksProperty = serializedObject.FindProperty("Template.ParameterLinks");
parameterAutomationProperty = serializedObject.FindProperty("Template.ParameterAutomation");
parameterLinksView = new ListView(parameterLinksProperty);
parameterLinksView.drawElementWithLabelCallback = DrawParameterLink;
parameterLinksView.onCanAddCallback = (list) => missingParameterAutomations.Count > 0;
parameterLinksView.onAddDropdownCallback = DoAddParameterLinkMenu;
parameterLinksView.onRemoveCallback = (list) => DeleteParameterAutomation(list.index);
initialParameterValuesView = new ListView(parametersProperty);
initialParameterValuesView.drawElementWithLabelCallback = DrawInitialParameterValue;
initialParameterValuesView.onCanAddCallback = (list) => missingInitialParameterValues.Count > 0;
initialParameterValuesView.onAddDropdownCallback = DoAddInitialParameterValueMenu;
initialParameterValuesView.onRemoveCallback = (list) => DeleteInitialParameterValue(list.index);
RefreshEventRef();
Undo.undoRedoPerformed += OnUndoRedo;
}
public void OnDestroy()
{
Undo.undoRedoPerformed -= OnUndoRedo;
}
private void OnUndoRedo()
{
RefreshMissingParameterLists();
// This is in case the undo/redo modified any curves on the Playable's clip
RefreshTimelineEditor();
}
private void RefreshEventRef()
{
if (eventPath != eventPlayable.EventReference.Path)
{
eventPath = eventPlayable.EventReference.Path;
if (!string.IsNullOrEmpty(eventPath))
{
editorEventRef = EventManager.EventFromPath(eventPath);
}
else
{
editorEventRef = null;
}
if (editorEventRef != null)
{
eventPlayable.UpdateEventDuration(
editorEventRef.IsOneShot ? editorEventRef.Length : float.PositiveInfinity);
}
ValidateParameterSettings();
RefreshMissingParameterLists();
}
}
private void ValidateParameterSettings()
{
if (editorEventRef != null)
{
List<string> namesToDelete = new List<string>();
for (int i = 0; i < parametersProperty.arraySize; ++i)
{
SerializedProperty current = parametersProperty.GetArrayElementAtIndex(i);
SerializedProperty name = current.FindPropertyRelative("Name");
EditorParamRef paramRef = editorEventRef.LocalParameters.FirstOrDefault(p => p.Name == name.stringValue);
if (paramRef != null)
{
SerializedProperty value = current.FindPropertyRelative("Value");
value.floatValue = Mathf.Clamp(value.floatValue, paramRef.Min, paramRef.Max);
}
else
{
namesToDelete.Add(name.stringValue);
}
}
foreach(string name in namesToDelete)
{
DeleteInitialParameterValue(name);
}
namesToDelete.Clear();
for (int i = 0; i < parameterLinksProperty.arraySize; ++i)
{
SerializedProperty current = parameterLinksProperty.GetArrayElementAtIndex(i);
SerializedProperty name = current.FindPropertyRelative("Name");
if (!editorEventRef.LocalParameters.Any(p => p.Name == name.stringValue))
{
namesToDelete.Add(name.stringValue);
}
}
foreach(string name in namesToDelete)
{
DeleteParameterAutomation(name);
}
}
}
private void RefreshMissingParameterLists()
{
if (editorEventRef != null)
{
serializedObject.Update();
missingInitialParameterValues =
editorEventRef.LocalParameters.Where(p => !InitialParameterValueExists(p.Name)).ToList();
missingParameterAutomations =
editorEventRef.LocalParameters.Where(p => !ParameterLinkExists(p.Name)).ToList();
}
else
{
missingInitialParameterValues.Clear();
missingParameterAutomations.Clear();
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
RefreshEventRef();
var eventReference = serializedObject.FindProperty("EventReference");
var stopType = serializedObject.FindProperty("StopType");
const string EventReferenceLabel = "Event";
EditorUtils.DrawLegacyEvent(serializedObject.FindProperty("eventName"), EventReferenceLabel);
EditorGUILayout.PropertyField(eventReference, new GUIContent(EventReferenceLabel));
EditorGUILayout.PropertyField(stopType, new GUIContent("Stop Mode"));
DrawInitialParameterValues();
DrawParameterAutomations();
eventPlayable.OnValidate();
serializedObject.ApplyModifiedProperties();
}
private void DrawInitialParameterValues()
{
if (editorEventRef != null)
{
parametersProperty.isExpanded =
EditorGUILayout.Foldout(parametersProperty.isExpanded, "Initial Parameter Values", true);
if (parametersProperty.isExpanded)
{
initialParameterValuesView.DrawLayout();
}
}
}
private void DoAddInitialParameterValueMenu(Rect rect, UnityEditorInternal.ReorderableList list)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("All"), false, () =>
{
foreach (EditorParamRef parameter in missingInitialParameterValues)
{
AddInitialParameterValue(parameter);
}
});
menu.AddSeparator(string.Empty);
foreach (EditorParamRef parameter in missingInitialParameterValues)
{
string text = parameter.Name;
if (ParameterLinkExists(parameter.Name))
{
text += " (automated)";
}
menu.AddItem(new GUIContent(text), false,
(userData) =>
{
AddInitialParameterValue(userData as EditorParamRef);
},
parameter);
}
menu.DropDown(rect);
}
private void DrawInitialParameterValue(Rect rect, float labelRight, int index, bool active, bool focused)
{
if (editorEventRef == null)
{
return;
}
SerializedProperty property = parametersProperty.GetArrayElementAtIndex(index);
string name = property.FindPropertyRelative("Name").stringValue;
EditorParamRef paramRef = editorEventRef.LocalParameters.FirstOrDefault(p => p.Name == name);
if (paramRef == null)
{
return;
}
Rect nameLabelRect = rect;
nameLabelRect.xMax = labelRight;
Rect sliderRect = rect;
sliderRect.xMin = nameLabelRect.xMax;
SerializedProperty valueProperty = property.FindPropertyRelative("Value");
GUI.Label(nameLabelRect, name);
using (new NoIndentScope())
{
valueProperty.floatValue =
EditorGUI.Slider(sliderRect, valueProperty.floatValue, paramRef.Min, paramRef.Max);
}
}
private void DrawParameterAutomations()
{
if (editorEventRef != null)
{
parameterLinksProperty.isExpanded =
EditorGUILayout.Foldout(parameterLinksProperty.isExpanded, "Parameter Automations", true);
if (parameterLinksProperty.isExpanded)
{
parameterLinksView.DrawLayout();
}
}
}
private void DoAddParameterLinkMenu(Rect rect, UnityEditorInternal.ReorderableList list)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("All"), false, () =>
{
foreach (EditorParamRef parameter in missingParameterAutomations)
{
AddParameterAutomation(parameter.Name);
}
});
menu.AddSeparator(string.Empty);
foreach (EditorParamRef parameter in missingParameterAutomations)
{
string text = parameter.Name;
if (InitialParameterValueExists(parameter.Name))
{
text += " (has initial value)";
}
menu.AddItem(new GUIContent(text), false,
(userData) =>
{
AddParameterAutomation(userData as string);
},
parameter.Name);
}
menu.DropDown(rect);
}
private void DrawParameterLink(Rect rect, float labelRight, int index, bool active, bool focused)
{
if (editorEventRef == null)
{
return;
}
SerializedProperty linkProperty = parameterLinksProperty.GetArrayElementAtIndex(index);
string name = linkProperty.FindPropertyRelative("Name").stringValue;
EditorParamRef paramRef = editorEventRef.LocalParameters.FirstOrDefault(p => p.Name == name);
if (paramRef == null)
{
return;
}
int slot = linkProperty.FindPropertyRelative("Slot").intValue;
string slotName = string.Format("Slot{0:D2}", slot);
SerializedProperty valueProperty = parameterAutomationProperty.FindPropertyRelative(slotName);
GUIStyle slotStyle = GUI.skin.label;
Rect slotRect = rect;
slotRect.width = slotStyle.CalcSize(new GUIContent("slot 00:")).x;
Rect nameRect = rect;
nameRect.xMin = slotRect.xMax;
nameRect.xMax = labelRight;
Rect valueRect = rect;
valueRect.xMin = nameRect.xMax;
using (new EditorGUI.PropertyScope(rect, GUIContent.none, valueProperty))
{
GUI.Label(slotRect, string.Format("slot {0:D2}:", slot), slotStyle);
GUI.Label(nameRect, name);
using (new NoIndentScope())
{
valueProperty.floatValue =
EditorGUI.Slider(valueRect, valueProperty.floatValue, paramRef.Min, paramRef.Max);
}
}
}
private bool InitialParameterValueExists(string name)
{
return parametersProperty.ArrayContains("Name", p => p.stringValue == name);
}
private bool ParameterLinkExists(string name)
{
return parameterLinksProperty.ArrayContains("Name", p => p.stringValue == name);
}
private void AddInitialParameterValue(EditorParamRef editorParamRef)
{
serializedObject.Update();
if (!InitialParameterValueExists(editorParamRef.Name))
{
DeleteParameterAutomation(editorParamRef.Name);
parametersProperty.ArrayAdd(p => {
p.FindPropertyRelative("Name").stringValue = editorParamRef.Name;
p.FindPropertyRelative("Value").floatValue = editorParamRef.Default;
});
serializedObject.ApplyModifiedProperties();
RefreshMissingParameterLists();
}
}
private void DeleteInitialParameterValue(string name)
{
serializedObject.Update();
int index = parametersProperty.FindArrayIndex("Name", p => p.stringValue == name);
if (index >= 0)
{
DeleteInitialParameterValue(index);
}
}
private void DeleteInitialParameterValue(int index)
{
serializedObject.Update();
parametersProperty.DeleteArrayElementAtIndex(index);
serializedObject.ApplyModifiedProperties();
RefreshMissingParameterLists();
}
private void AddParameterAutomation(string name)
{
serializedObject.Update();
if (!ParameterLinkExists(name))
{
int slot = -1;
for (int i = 0; i < AutomatableSlots.Count; ++i)
{
if (!parameterLinksProperty.ArrayContains("Slot", p => p.intValue == i))
{
slot = i;
break;
}
}
if (slot >= 0)
{
DeleteInitialParameterValue(name);
parameterLinksProperty.ArrayAdd(p => {
p.FindPropertyRelative("Name").stringValue = name;
p.FindPropertyRelative("Slot").intValue = slot;
});
serializedObject.ApplyModifiedProperties();
RefreshMissingParameterLists();
RefreshTimelineEditor();
}
}
}
private void DeleteParameterAutomation(string name)
{
serializedObject.Update();
int index = parameterLinksProperty.FindArrayIndex("Name", p => p.stringValue == name);
if (index >= 0)
{
DeleteParameterAutomation(index);
}
}
private void DeleteParameterAutomation(int index)
{
serializedObject.Update();
if (eventPlayable.OwningClip.hasCurves)
{
SerializedProperty linkProperty = parameterLinksProperty.GetArrayElementAtIndex(index);
SerializedProperty slotProperty = linkProperty.FindPropertyRelative("Slot");
AnimationClip curvesClip = eventPlayable.OwningClip.curves;
Undo.RecordObject(curvesClip, string.Empty);
AnimationUtility.SetEditorCurve(curvesClip, GetParameterCurveBinding(slotProperty.intValue), null);
}
parameterLinksProperty.DeleteArrayElementAtIndex(index);
serializedObject.ApplyModifiedProperties();
RefreshMissingParameterLists();
RefreshTimelineEditor();
}
private static EditorCurveBinding GetParameterCurveBinding(int index)
{
EditorCurveBinding result = new EditorCurveBinding() {
path = string.Empty,
type = typeof(FMODEventPlayable),
propertyName = string.Format("parameterAutomation.slot{0:D2}", index),
};
return result;
}
private static void RefreshTimelineEditor()
{
TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
}
}
}
#endif

View file

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: fa325be8441506c4bb1462c8333ccce9
timeCreated: 1523230773
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
#if UNITY_TIMELINE_EXIST
using UnityEditor;
using UnityEditor.Timeline;
using UnityEngine;
using UnityEngine.Timeline;
namespace FMODUnity
{
[CustomTimelineEditor(typeof(FMODEventTrack))]
public class FMODEventTrackEditor : TrackEditor
{
private static readonly Texture2D icon = EditorUtils.LoadImage("StudioIcon.png");
public override TrackDrawOptions GetTrackOptions(TrackAsset track, Object binding)
{
TrackDrawOptions options = base.GetTrackOptions(track, binding);
options.icon = icon;
return options;
}
}
// This custom property drawer is here to draw the volume property at the
// top level of the inspector, rather than in a Template foldout.
[CustomPropertyDrawer(typeof(FMODEventMixerBehaviour))]
public class FMODEventMixerBehaviourInspector : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty volumeProperty = property.FindPropertyRelative("volume");
EditorGUI.PropertyField(position, volumeProperty);
}
}
}
#endif

View file

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

View file

@ -0,0 +1,39 @@
{
"name": "FMODUnityEditor",
"references": [
"FMODUnity",
"Unity.Timeline.Editor",
"Unity.Timeline",
"Unity.VisualScripting.Core",
"Unity.VisualScripting.Core.Editor",
"Unity.VisualScripting.Flow.Editor",
"Unity.ScriptableBuildPipeline.Editor"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.timeline",
"expression": "1.0.0",
"define": "UNITY_TIMELINE_EXIST"
},
{
"name": "com.unity.addressables",
"expression": "1.0.0",
"define": "UNITY_ADDRESSABLES_EXIST"
},
{
"name": "com.unity.visualscripting",
"expression": "1.0.0",
"define": "UNITY_VISUALSCRIPTING_EXIST"
}
],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: aab3caaf43456d6449a3e035348ff798
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,191 @@
using System;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
namespace FMODUnity
{
public class FindAndReplace : EditorWindow
{
private bool levelScope = true;
private bool prefabScope;
private string findText;
private string replaceText;
private string message = "";
private MessageType messageType = MessageType.None;
private int lastMatch = -1;
private List<StudioEventEmitter> emitters;
private bool first = true;
[MenuItem("FMOD/Find and Replace", priority = 2)]
private static void ShowFindAndReplace()
{
var window = CreateInstance<FindAndReplace>();
window.titleContent = new GUIContent("FMOD Find and Replace");
window.OnHierarchyChange();
var position = window.position;
window.maxSize = window.minSize = position.size = new Vector2(400, 170);
window.position = position;
window.ShowUtility();
}
private void OnHierarchyChange()
{
emitters = new List<StudioEventEmitter>(Resources.FindObjectsOfTypeAll<StudioEventEmitter>());
if (!levelScope)
{
emitters.RemoveAll(x => PrefabUtility.GetPrefabAssetType(x) == PrefabAssetType.NotAPrefab);
}
if (!prefabScope)
{
emitters.RemoveAll(x => PrefabUtility.GetPrefabAssetType(x) == PrefabAssetType.NotAPrefab);
}
}
private void OnGUI()
{
bool doFind = false;
if ((Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return))
{
Event.current.Use();
doFind = true;
}
GUI.SetNextControlName("find");
EditorGUILayout.PrefixLabel("Find:");
EditorGUI.BeginChangeCheck();
findText = EditorGUILayout.TextField(findText);
if (EditorGUI.EndChangeCheck())
{
lastMatch = -1;
message = null;
}
EditorGUILayout.PrefixLabel("Replace:");
replaceText = EditorGUILayout.TextField(replaceText);
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
levelScope = EditorGUILayout.ToggleLeft("Current Level", levelScope, GUILayout.ExpandWidth(false));
prefabScope = EditorGUILayout.ToggleLeft("Prefabs", prefabScope, GUILayout.ExpandWidth(false));
if (EditorGUI.EndChangeCheck())
{
OnHierarchyChange();
}
EditorGUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Find") || doFind)
{
message = "";
{
FindNext();
}
if (lastMatch == -1)
{
message = "Finished Search";
messageType = MessageType.Warning;
}
}
if (GUILayout.Button("Replace"))
{
message = "";
if (lastMatch == -1)
{
FindNext();
}
else
{
Replace();
}
if (lastMatch == -1)
{
message = "Finished Search";
messageType = MessageType.Warning;
}
}
if (GUILayout.Button("Replace All"))
{
if (EditorUtility.DisplayDialog("Replace All", "Are you sure you wish to replace all in the current hierachy?", "yes", "no"))
{
ReplaceAll();
}
}
GUILayout.EndHorizontal();
if (!string.IsNullOrEmpty(message))
{
EditorGUILayout.HelpBox(message, messageType);
}
else
{
EditorGUILayout.HelpBox("\n\n", MessageType.None);
}
if (first)
{
first = false;
EditorGUI.FocusTextInControl("find");
}
}
private void FindNext()
{
for (int i = lastMatch + 1; i < emitters.Count; i++)
{
if (emitters[i].EventReference.Path.IndexOf(findText, 0, StringComparison.CurrentCultureIgnoreCase) >= 0)
{
lastMatch = i;
EditorGUIUtility.PingObject(emitters[i]);
Selection.activeGameObject = emitters[i].gameObject;
message = "Found object";
messageType = MessageType.Info;
return;
}
}
lastMatch = -1;
}
private void ReplaceAll()
{
int replaced = 0;
for (int i = 0; i < emitters.Count; i++)
{
if (ReplaceText(emitters[i]))
{
replaced++;
}
}
message = string.Format("{0} replaced", replaced);
messageType = MessageType.Info;
}
private bool ReplaceText(StudioEventEmitter emitter)
{
int findLength = findText.Length;
int replaceLength = replaceText.Length;
int position = 0;
var serializedObject = new SerializedObject(emitter);
var pathProperty = serializedObject.FindProperty("Event");
string path = pathProperty.stringValue;
position = path.IndexOf(findText, position, StringComparison.CurrentCultureIgnoreCase);
while (position >= 0)
{
path = path.Remove(position, findLength).Insert(position, replaceText);
position += replaceLength;
position = path.IndexOf(findText, position, StringComparison.CurrentCultureIgnoreCase);
}
pathProperty.stringValue = path;
return serializedObject.ApplyModifiedProperties();
}
private void Replace()
{
ReplaceText(emitters[lastMatch]);
FindNext();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a3d0ed60438564241a4e62b152836893
timeCreated: 1453876443
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,45 @@
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
public class ListView : UnityEditorInternal.ReorderableList
{
private const float ElementPadding = 2;
public DrawElementWithLabelDelegate drawElementWithLabelCallback;
public delegate void DrawElementWithLabelDelegate(Rect rect, float labelRight, int index,
bool active, bool focused);
private float labelRight;
public ListView(SerializedProperty property)
: base(property.serializedObject, property, true, false, true, true)
{
headerHeight = 3;
elementHeight = EditorGUIUtility.singleLineHeight + ElementPadding;
drawElementCallback = DrawElementWrapper;
}
public void DrawLayout()
{
Rect rect = EditorGUILayout.GetControlRect(false, GetHeight());
labelRight = rect.x + EditorGUIUtility.labelWidth;
DoList(EditorGUI.IndentedRect(rect));
}
private void DrawElementWrapper(Rect rect, int index, bool active, bool focused)
{
if (drawElementWithLabelCallback != null)
{
rect.height -= ElementPadding;
drawElementWithLabelCallback(rect, labelRight, index, active, focused);
}
}
}
}

View file

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

View file

@ -0,0 +1,6 @@
/* This class is now legacy. Keep the definition here for the migration to work */
using UnityEditor;
public class LogViewer : EditorWindow
{
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 255133e2dd4fbd9449ba729ddbb2f77f
timeCreated: 1433383105
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,81 @@
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomPropertyDrawer(typeof(ParamRefAttribute))]
public class ParamRefDrawer : PropertyDrawer
{
public bool MouseDrag(Event e)
{
bool isDragging = false;
if (e.type == EventType.DragPerform)
{
isDragging = true;
}
return isDragging;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Texture browseIcon = EditorUtils.LoadImage("SearchIconBlack.png");
Texture openIcon = EditorUtils.LoadImage("BrowserIcon.png");
Texture addIcon = EditorUtils.LoadImage("AddIcon.png");
EditorGUI.BeginProperty(position, label, property);
SerializedProperty pathProperty = property;
Event e = Event.current;
if (MouseDrag(e) && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorParamRef))
{
pathProperty.stringValue = ((EditorParamRef)DragAndDrop.objectReferences[0]).Name;
GUI.changed = true;
e.Use();
}
}
if (e.type == EventType.DragUpdated && position.Contains(e.mousePosition))
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorParamRef))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
DragAndDrop.AcceptDrag();
e.Use();
}
}
float baseHeight = GUI.skin.textField.CalcSize(new GUIContent()).y;
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
GUIStyle buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.padding.top = 1;
buttonStyle.padding.bottom = 1;
Rect addRect = new Rect(position.x + position.width - addIcon.width - 7, position.y, addIcon.width + 7, baseHeight);
Rect openRect = new Rect(addRect.x - openIcon.width - 7, position.y, openIcon.width + 6, baseHeight);
Rect searchRect = new Rect(openRect.x - browseIcon.width - 9, position.y, browseIcon.width + 8, baseHeight);
Rect pathRect = new Rect(position.x, position.y, searchRect.x - position.x - 3, baseHeight);
EditorGUI.PropertyField(pathRect, pathProperty, GUIContent.none);
if (GUI.Button(searchRect, new GUIContent(browseIcon, "Search"), buttonStyle))
{
var eventBrowser = ScriptableObject.CreateInstance<EventBrowser>();
eventBrowser.ChooseParameter(property);
var windowRect = position;
windowRect.position = GUIUtility.GUIToScreenPoint(windowRect.position);
windowRect.height = openRect.height + 1;
eventBrowser.ShowAsDropDown(windowRect, new Vector2(windowRect.width, 400));
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ea88808aa26cd614db1c5c1dcbb14d4e
timeCreated: 1444197074
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 353a9c870c318f74fa5fdcd475129bae
timeCreated: 1432530253
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,101 @@
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomEditor(typeof(StudioBankLoader))]
[CanEditMultipleObjects]
public class StudioBankLoaderEditor : Editor
{
public override void OnInspectorGUI()
{
var load = serializedObject.FindProperty("LoadEvent");
var unload = serializedObject.FindProperty("UnloadEvent");
var tag = serializedObject.FindProperty("CollisionTag");
var banks = serializedObject.FindProperty("Banks");
var preload = serializedObject.FindProperty("PreloadSamples");
EditorGUILayout.PropertyField(load, new GUIContent("Load"));
EditorGUILayout.PropertyField(unload, new GUIContent("Unload"));
if ((load.enumValueIndex >= 3 && load.enumValueIndex <= 6) ||
(unload.enumValueIndex >= 3 && unload.enumValueIndex <= 6))
{
tag.stringValue = EditorGUILayout.TagField("Collision Tag", tag.stringValue);
}
EditorGUILayout.PropertyField(preload, new GUIContent("Preload Sample Data"));
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Banks");
EditorGUILayout.BeginVertical();
if (GUILayout.Button("Add Bank", GUILayout.ExpandWidth(false)))
{
banks.InsertArrayElementAtIndex(banks.arraySize);
SerializedProperty newBank = banks.GetArrayElementAtIndex(banks.arraySize - 1);
newBank.stringValue = "";
EventBrowser browser = CreateInstance<EventBrowser>();
browser.titleContent = new GUIContent("Select FMOD Bank");
browser.ChooseBank(newBank);
browser.ShowUtility();
}
Texture deleteTexture = EditorUtils.LoadImage("Delete.png");
GUIContent deleteContent = new GUIContent(deleteTexture, "Delete Bank");
var buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.padding.top = buttonStyle.padding.bottom = 1;
buttonStyle.margin.top = 2;
buttonStyle.padding.left = buttonStyle.padding.right = 4;
buttonStyle.fixedHeight = GUI.skin.textField.CalcSize(new GUIContent()).y;
for (int i = 0; i < banks.arraySize; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(banks.GetArrayElementAtIndex(i), GUIContent.none);
if (GUILayout.Button(deleteContent, buttonStyle, GUILayout.ExpandWidth(false)))
{
banks.DeleteArrayElementAtIndex(i);
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
Event e = Event.current;
if (e.type == EventType.DragPerform)
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorBankRef))
{
int pos = banks.arraySize;
banks.InsertArrayElementAtIndex(pos);
var pathProperty = banks.GetArrayElementAtIndex(pos);
pathProperty.stringValue = ((EditorBankRef)DragAndDrop.objectReferences[0]).Name;
e.Use();
}
}
if (e.type == EventType.DragUpdated)
{
if (DragAndDrop.objectReferences.Length > 0 &&
DragAndDrop.objectReferences[0] != null &&
DragAndDrop.objectReferences[0].GetType() == typeof(EditorBankRef))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
DragAndDrop.AcceptDrag();
e.Use();
}
}
serializedObject.ApplyModifiedProperties();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f7f61e03a350e1e428dba6c562f3d64a
timeCreated: 1434691856
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,528 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomEditor(typeof(StudioEventEmitter))]
[CanEditMultipleObjects]
public class StudioEventEmitterEditor : Editor
{
private ParameterValueView parameterValueView;
public void OnEnable()
{
parameterValueView = new ParameterValueView(serializedObject);
}
public void OnSceneGUI()
{
var emitter = target as StudioEventEmitter;
EditorEventRef editorEvent = EventManager.EventFromGUID(emitter.EventReference.Guid);
if (editorEvent != null && editorEvent.Is3D)
{
EditorGUI.BeginChangeCheck();
float minDistance = emitter.OverrideAttenuation ? emitter.OverrideMinDistance : editorEvent.MinDistance;
float maxDistance = emitter.OverrideAttenuation ? emitter.OverrideMaxDistance : editorEvent.MaxDistance;
minDistance = Handles.RadiusHandle(Quaternion.identity, emitter.transform.position, minDistance);
maxDistance = Handles.RadiusHandle(Quaternion.identity, emitter.transform.position, maxDistance);
if (EditorGUI.EndChangeCheck() && emitter.OverrideAttenuation)
{
Undo.RecordObject(emitter, "Change Emitter Bounds");
emitter.OverrideMinDistance = Mathf.Clamp(minDistance, 0, emitter.OverrideMaxDistance);
emitter.OverrideMaxDistance = Mathf.Max(emitter.OverrideMinDistance, maxDistance);
}
}
}
public override void OnInspectorGUI()
{
var begin = serializedObject.FindProperty("PlayEvent");
var end = serializedObject.FindProperty("StopEvent");
var tag = serializedObject.FindProperty("CollisionTag");
var eventReference = serializedObject.FindProperty("EventReference");
var eventPath = eventReference.FindPropertyRelative("Path");
var fadeout = serializedObject.FindProperty("AllowFadeout");
var once = serializedObject.FindProperty("TriggerOnce");
var preload = serializedObject.FindProperty("Preload");
var overrideAtt = serializedObject.FindProperty("OverrideAttenuation");
var minDistance = serializedObject.FindProperty("OverrideMinDistance");
var maxDistance = serializedObject.FindProperty("OverrideMaxDistance");
EditorGUILayout.PropertyField(begin, new GUIContent("Play Event"));
EditorGUILayout.PropertyField(end, new GUIContent("Stop Event"));
if ((begin.enumValueIndex >= (int)EmitterGameEvent.TriggerEnter && begin.enumValueIndex <= (int)EmitterGameEvent.TriggerExit2D) ||
(end.enumValueIndex >= (int)EmitterGameEvent.TriggerEnter && end.enumValueIndex <= (int)EmitterGameEvent.TriggerExit2D))
{
tag.stringValue = EditorGUILayout.TagField("Collision Tag", tag.stringValue);
}
EditorGUI.BeginChangeCheck();
const string EventReferenceLabel = "Event";
EditorUtils.DrawLegacyEvent(serializedObject.FindProperty("Event"), EventReferenceLabel);
EditorGUILayout.PropertyField(eventReference, new GUIContent(EventReferenceLabel));
EditorEventRef editorEvent = EventManager.EventFromPath(eventPath.stringValue);
if (EditorGUI.EndChangeCheck())
{
EditorUtils.UpdateParamsOnEmitter(serializedObject, eventPath.stringValue);
}
// Attenuation
if (editorEvent != null)
{
{
EditorGUI.BeginDisabledGroup(editorEvent == null || !editorEvent.Is3D);
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(overrideAtt);
if (EditorGUI.EndChangeCheck() ||
(minDistance.floatValue == -1 && maxDistance.floatValue == -1) // never been initialiased
)
{
minDistance.floatValue = editorEvent.MinDistance;
maxDistance.floatValue = editorEvent.MaxDistance;
}
EditorGUI.BeginDisabledGroup(!overrideAtt.boolValue);
EditorGUIUtility.labelWidth = 30;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(minDistance, new GUIContent("Min"));
if (EditorGUI.EndChangeCheck())
{
minDistance.floatValue = Mathf.Clamp(minDistance.floatValue, 0, maxDistance.floatValue);
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(maxDistance, new GUIContent("Max"));
if (EditorGUI.EndChangeCheck())
{
maxDistance.floatValue = Mathf.Max(minDistance.floatValue, maxDistance.floatValue);
}
EditorGUIUtility.labelWidth = 0;
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndHorizontal();
EditorGUI.EndDisabledGroup();
}
parameterValueView.OnGUI(editorEvent, !eventReference.hasMultipleDifferentValues);
fadeout.isExpanded = EditorGUILayout.Foldout(fadeout.isExpanded, "Advanced Controls");
if (fadeout.isExpanded)
{
EditorGUILayout.PropertyField(preload, new GUIContent("Preload Sample Data"));
EditorGUILayout.PropertyField(fadeout, new GUIContent("Allow Fadeout When Stopping"));
EditorGUILayout.PropertyField(once, new GUIContent("Trigger Once"));
}
}
serializedObject.ApplyModifiedProperties();
}
private class ParameterValueView
{
// The "Params" property from the SerializedObject we're editing in the inspector,
// so we can expand/collapse it or revert to prefab.
private SerializedProperty paramsProperty;
// This holds one SerializedObject for each object in the current selection.
private List<SerializedObject> serializedTargets = new List<SerializedObject>();
// Mappings from EditorParamRef to initial parameter value property for all properties
// found in the current selection.
private List<PropertyRecord> propertyRecords = new List<PropertyRecord>();
// Any parameters that are in the current event but are missing from some objects in
// the current selection, so we can put them in the "Add" menu.
private List<EditorParamRef> missingParameters = new List<EditorParamRef>();
// A mapping from EditorParamRef to the initial parameter value properties in the
// current selection that have the same name.
// We need this because some objects may be missing some properties, and properties with
// the same name may be at different array indices in different objects.
private class PropertyRecord
{
public string name { get { return paramRef.Name; } }
public EditorParamRef paramRef;
public List<SerializedProperty> valueProperties;
}
public ParameterValueView(SerializedObject serializedObject)
{
paramsProperty = serializedObject.FindProperty("Params");
foreach (UnityEngine.Object target in serializedObject.targetObjects)
{
serializedTargets.Add(new SerializedObject(target));
}
}
// Rebuilds the propertyRecords and missingParameters collections.
private void RefreshPropertyRecords(EditorEventRef eventRef)
{
propertyRecords.Clear();
foreach (SerializedObject serializedTarget in serializedTargets)
{
SerializedProperty paramsProperty = serializedTarget.FindProperty("Params");
foreach (SerializedProperty parameterProperty in paramsProperty)
{
string name = parameterProperty.FindPropertyRelative("Name").stringValue;
SerializedProperty valueProperty = parameterProperty.FindPropertyRelative("Value");
PropertyRecord record = propertyRecords.Find(r => r.name == name);
if (record != null)
{
record.valueProperties.Add(valueProperty);
}
else
{
EditorParamRef paramRef = eventRef.LocalParameters.Find(p => p.Name == name);
if (paramRef != null)
{
propertyRecords.Add(
new PropertyRecord() {
paramRef = paramRef,
valueProperties = new List<SerializedProperty>() { valueProperty },
});
}
}
}
}
// Only sort if there is a multi-selection. If there is only one object selected,
// the user can revert to prefab, and the behaviour depends on the array order,
// so it's helpful to show the true order.
if (serializedTargets.Count > 1)
{
propertyRecords.Sort((a, b) => EditorUtility.NaturalCompare(a.name, b.name));
}
missingParameters.Clear();
missingParameters.AddRange(eventRef.LocalParameters.Where(
p => {
PropertyRecord record = propertyRecords.Find(r => r.name == p.Name);
return record == null || record.valueProperties.Count < serializedTargets.Count;
}));
}
public void OnGUI(EditorEventRef eventRef, bool matchingEvents)
{
foreach (SerializedObject serializedTarget in serializedTargets)
{
serializedTarget.Update();
}
if (Event.current.type == EventType.Layout)
{
RefreshPropertyRecords(eventRef);
}
DrawHeader(matchingEvents);
if (paramsProperty.isExpanded)
{
if (matchingEvents)
{
DrawValues();
}
else
{
GUILayout.Box("Cannot change parameters when different events are selected", GUILayout.ExpandWidth(true));
}
}
foreach (SerializedObject serializedTarget in serializedTargets)
{
serializedTarget.ApplyModifiedProperties();
}
}
private void DrawHeader(bool enableAddButton)
{
Rect controlRect = EditorGUILayout.GetControlRect();
Rect titleRect = controlRect;
titleRect.width = EditorGUIUtility.labelWidth;
// Let the user revert the whole Params array to prefab by context-clicking the title.
EditorGUI.BeginProperty(titleRect, GUIContent.none, paramsProperty);
paramsProperty.isExpanded = EditorGUI.Foldout(titleRect, paramsProperty.isExpanded,
"Initial Parameter Values");
EditorGUI.EndProperty();
Rect buttonRect = controlRect;
buttonRect.xMin = titleRect.xMax;
EditorGUI.BeginDisabledGroup(!enableAddButton);
DrawAddButton(buttonRect);
EditorGUI.EndDisabledGroup();
}
private void DrawAddButton(Rect position)
{
EditorGUI.BeginDisabledGroup(missingParameters.Count == 0);
if (EditorGUI.DropdownButton(position, new GUIContent("Add"), FocusType.Passive))
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("All"), false, () =>
{
foreach (EditorParamRef parameter in missingParameters)
{
AddParameter(parameter);
}
});
menu.AddSeparator(string.Empty);
foreach (EditorParamRef parameter in missingParameters)
{
menu.AddItem(new GUIContent(parameter.Name), false,
(userData) =>
{
AddParameter(userData as EditorParamRef);
},
parameter);
}
menu.DropDown(position);
}
EditorGUI.EndDisabledGroup();
}
private void DrawValues()
{
// We use this to defer deletion so we don't mess with arrays while using
// SerializedProperties that refer to array elements, as this can throw exceptions.
string parameterToDelete = null;
foreach (PropertyRecord record in propertyRecords)
{
if (record.valueProperties.Count == serializedTargets.Count)
{
bool delete;
DrawValue(record, out delete);
if (delete)
{
parameterToDelete = record.name;
}
}
}
if (parameterToDelete != null)
{
DeleteParameter(parameterToDelete);
}
}
private void DrawValue(PropertyRecord record, out bool delete)
{
delete = false;
GUIContent removeLabel = new GUIContent("Remove");
Rect position = EditorGUILayout.GetControlRect();
Rect nameLabelRect = position;
nameLabelRect.width = EditorGUIUtility.labelWidth;
Rect removeButtonRect = position;
removeButtonRect.width = EditorStyles.miniButton.CalcSize(removeLabel).x;
removeButtonRect.x = position.xMax - removeButtonRect.width;
Rect sliderRect = position;
sliderRect.xMin = nameLabelRect.xMax;
sliderRect.xMax = removeButtonRect.xMin - EditorStyles.miniButton.margin.left;
GUIContent nameLabel = new GUIContent(record.name);
float value = 0;
bool mixedValues = false;
// We use EditorGUI.BeginProperty when there is a single object selected, so
// the user can revert the value to prefab by context-clicking the name.
// We handle multi-selections ourselves, so that we can deal with
// mismatched arrays nicely.
if (record.valueProperties.Count == 1)
{
value = record.valueProperties[0].floatValue;
EditorGUI.BeginProperty(position, nameLabel, record.valueProperties[0]);
}
else
{
bool first = true;
foreach (SerializedProperty property in record.valueProperties)
{
if (first)
{
value = property.floatValue;
first = false;
}
else if (property.floatValue != value)
{
mixedValues = true;
break;
}
}
}
EditorGUI.LabelField(nameLabelRect, nameLabel);
if (record.paramRef.Type == ParameterType.Labeled)
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = mixedValues;
int newValue = EditorGUI.Popup(sliderRect, (int)value, record.paramRef.Labels);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
foreach (SerializedProperty property in record.valueProperties)
{
property.floatValue = newValue;
}
}
}
else if (record.paramRef.Type == ParameterType.Discrete)
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = mixedValues;
int newValue = EditorGUI.IntSlider(sliderRect, (int)value, (int)record.paramRef.Min, (int)record.paramRef.Max);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
foreach (SerializedProperty property in record.valueProperties)
{
property.floatValue = newValue;
}
}
}
else
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = mixedValues;
float newValue = EditorGUI.Slider(sliderRect, value, record.paramRef.Min, record.paramRef.Max);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
foreach (SerializedProperty property in record.valueProperties)
{
property.floatValue = newValue;
}
}
}
delete = GUI.Button(removeButtonRect, removeLabel, EditorStyles.miniButton);
if (record.valueProperties.Count == 1)
{
EditorGUI.EndProperty();
}
else
{
// Context menu to set all values from one object in the multi-selection.
if (mixedValues && Event.current.type == EventType.ContextClick
&& nameLabelRect.Contains(Event.current.mousePosition))
{
GenericMenu menu = new GenericMenu();
foreach (SerializedProperty sourceProperty in record.valueProperties)
{
UnityEngine.Object targetObject = sourceProperty.serializedObject.targetObject;
menu.AddItem(new GUIContent(string.Format("Set to Value of '{0}'", targetObject.name)), false,
(userData) => CopyValueToAll(userData as SerializedProperty, record.valueProperties),
sourceProperty);
}
menu.DropDown(position);
}
}
}
// Copy the value from the source property to all target properties.
private void CopyValueToAll(SerializedProperty sourceProperty, List<SerializedProperty> targetProperties)
{
foreach (SerializedProperty targetProperty in targetProperties)
{
if (targetProperty != sourceProperty)
{
targetProperty.floatValue = sourceProperty.floatValue;
targetProperty.serializedObject.ApplyModifiedProperties();
}
}
}
// Add an initial value for the given parameter to all selected objects that don't have one.
private void AddParameter(EditorParamRef parameter)
{
foreach (SerializedObject serializedTarget in serializedTargets)
{
StudioEventEmitter emitter = serializedTarget.targetObject as StudioEventEmitter;
if (Array.FindIndex(emitter.Params, p => p.Name == parameter.Name) < 0)
{
SerializedProperty paramsProperty = serializedTarget.FindProperty("Params");
int index = paramsProperty.arraySize;
paramsProperty.InsertArrayElementAtIndex(index);
SerializedProperty arrayElement = paramsProperty.GetArrayElementAtIndex(index);
arrayElement.FindPropertyRelative("Name").stringValue = parameter.Name;
arrayElement.FindPropertyRelative("Value").floatValue = parameter.Default;
serializedTarget.ApplyModifiedProperties();
}
}
}
// Delete initial parameter values for the given name from all selected objects.
private void DeleteParameter(string name)
{
foreach (SerializedObject serializedTarget in serializedTargets)
{
SerializedProperty paramsProperty = serializedTarget.FindProperty("Params");
foreach (SerializedProperty child in paramsProperty)
{
if (child.FindPropertyRelative("Name").stringValue == name)
{
child.DeleteCommand();
break;
}
}
}
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2b044fd4ebf2c42468e1f41d5e2b879c
timeCreated: 1434696182
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using UnityEngine;
using UnityEditor;
namespace FMODUnity
{
public class StudioEventEmitterGizoDrawer
{
[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)]
private static void DrawGizmo(StudioEventEmitter studioEmitter, GizmoType gizmoType)
{
Gizmos.DrawIcon(studioEmitter.transform.position, "AudioSource Gizmo", true, Color.yellow);
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f09ba26caab55e048a2e596ff75b3eab
timeCreated: 1433142677
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomEditor(typeof(StudioGlobalParameterTrigger))]
public class StudioGlobalParameterTriggerEditor : Editor
{
private SerializedProperty param;
private SerializedProperty trigger;
private SerializedProperty tag;
private SerializedProperty value;
private SerializedProperty data1, data2;
private static GUIContent NotFoundWarning;
private string currentPath;
[SerializeField]
private EditorParamRef editorParamRef;
private void OnEnable()
{
param = serializedObject.FindProperty("Parameter");
trigger = serializedObject.FindProperty("TriggerEvent");
tag = serializedObject.FindProperty("CollisionTag");
value = serializedObject.FindProperty("Value");
}
public override void OnInspectorGUI()
{
if (NotFoundWarning == null)
{
Texture warningIcon = EditorUtils.LoadImage("NotFound.png");
NotFoundWarning = new GUIContent("Parameter Not Found", warningIcon);
}
EditorGUILayout.PropertyField(trigger, new GUIContent("Trigger"));
if (trigger.enumValueIndex >= (int)EmitterGameEvent.TriggerEnter && trigger.enumValueIndex <= (int)EmitterGameEvent.TriggerExit2D)
{
tag.stringValue = EditorGUILayout.TagField("Collision Tag", tag.stringValue);
}
EditorGUILayout.PropertyField(param, new GUIContent("Parameter"));
if (param.stringValue != currentPath)
{
currentPath = param.stringValue;
if (string.IsNullOrEmpty(param.stringValue))
{
editorParamRef = null;
}
else
{
editorParamRef = EventManager.ParamFromPath(param.stringValue);
value.floatValue = Mathf.Clamp(value.floatValue, editorParamRef.Min, editorParamRef.Max);
}
}
if (editorParamRef != null)
{
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel("Override Value");
value.floatValue = EditorUtils.DrawParameterValueLayout(value.floatValue, editorParamRef);
}
}
else
{
Rect rect = EditorGUILayout.GetControlRect();
rect.xMin += EditorGUIUtility.labelWidth;
GUI.Label(rect, NotFoundWarning);
}
serializedObject.ApplyModifiedProperties();
}
}
}

View file

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

View file

@ -0,0 +1,28 @@
using UnityEditor;
namespace FMODUnity
{
[CustomEditor(typeof(StudioListener))]
[CanEditMultipleObjects]
public class StudioListenerEditor : Editor
{
public SerializedProperty attenuationObject;
private void OnEnable()
{
attenuationObject = serializedObject.FindProperty("attenuationObject");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginDisabledGroup(true);
var index = serializedObject.FindProperty("ListenerNumber");
EditorGUILayout.IntSlider(index, 0, FMOD.CONSTANTS.MAX_LISTENERS - 1, "Listener Index");
EditorGUI.EndDisabledGroup();
EditorGUILayout.PropertyField(attenuationObject);
serializedObject.ApplyModifiedProperties();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 847f8505c25f5cf42adba68a26f2cda6
timeCreated: 1445576758
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,153 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace FMODUnity
{
[CustomEditor(typeof(StudioParameterTrigger))]
public class StudioParameterTriggerEditor : Editor
{
private StudioEventEmitter targetEmitter;
private SerializedProperty emitters;
private SerializedProperty trigger;
private SerializedProperty tag;
private bool[] expanded;
private void OnEnable()
{
emitters = serializedObject.FindProperty("Emitters");
trigger = serializedObject.FindProperty("TriggerEvent");
tag = serializedObject.FindProperty("CollisionTag");
targetEmitter = null;
for (int i = 0; i < emitters.arraySize; i++)
{
targetEmitter = emitters.GetArrayElementAtIndex(i).FindPropertyRelative("Target").objectReferenceValue as StudioEventEmitter;
if (targetEmitter != null)
{
expanded = new bool[targetEmitter.GetComponents<StudioEventEmitter>().Length];
break;
}
}
}
public override void OnInspectorGUI()
{
var newTargetEmitter = EditorGUILayout.ObjectField("Target", targetEmitter, typeof(StudioEventEmitter), true) as StudioEventEmitter;
if (newTargetEmitter != targetEmitter)
{
emitters.ClearArray();
targetEmitter = newTargetEmitter;
if (targetEmitter == null)
{
serializedObject.ApplyModifiedProperties();
return;
}
List<StudioEventEmitter> newEmitters = new List<StudioEventEmitter>();
targetEmitter.GetComponents(newEmitters);
expanded = new bool[newEmitters.Count];
foreach (var emitter in newEmitters)
{
emitters.InsertArrayElementAtIndex(0);
emitters.GetArrayElementAtIndex(0).FindPropertyRelative("Target").objectReferenceValue = emitter;
}
}
if (targetEmitter == null)
{
return;
}
EditorGUILayout.PropertyField(trigger, new GUIContent("Trigger"));
if (trigger.enumValueIndex >= (int)EmitterGameEvent.TriggerEnter && trigger.enumValueIndex <= (int)EmitterGameEvent.TriggerExit2D)
{
tag.stringValue = EditorGUILayout.TagField("Collision Tag", tag.stringValue);
}
var localEmitters = new List<StudioEventEmitter>();
targetEmitter.GetComponents(localEmitters);
int emitterIndex = 0;
foreach (var emitter in localEmitters)
{
SerializedProperty emitterProperty = null;
for(int i = 0; i < emitters.arraySize; i++)
{
if (emitters.GetArrayElementAtIndex(i).FindPropertyRelative("Target").objectReferenceValue == emitter)
{
emitterProperty = emitters.GetArrayElementAtIndex(i);
break;
}
}
// New emitter component added to game object since we last looked
if (emitterProperty == null)
{
emitters.InsertArrayElementAtIndex(0);
emitterProperty = emitters.GetArrayElementAtIndex(0);
emitterProperty.FindPropertyRelative("Target").objectReferenceValue = emitter;
}
if (!emitter.EventReference.IsNull)
{
expanded[emitterIndex] = EditorGUILayout.Foldout(expanded[emitterIndex], emitter.EventReference.Path);
if (expanded[emitterIndex])
{
var eventRef = EventManager.EventFromGUID(emitter.EventReference.Guid);
foreach (var paramRef in eventRef.LocalParameters)
{
bool set = false;
int index = -1;
for (int i = 0; i < emitterProperty.FindPropertyRelative("Params").arraySize; i++)
{
if (emitterProperty.FindPropertyRelative("Params").GetArrayElementAtIndex(i).FindPropertyRelative("Name").stringValue == paramRef.Name)
{
index = i;
set = true;
break;
}
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(paramRef.Name);
bool newSet = GUILayout.Toggle(set, "");
if (!set && newSet)
{
index = 0;
emitterProperty.FindPropertyRelative("Params").InsertArrayElementAtIndex(0);
emitterProperty.FindPropertyRelative("Params").GetArrayElementAtIndex(0).FindPropertyRelative("Name").stringValue = paramRef.Name;
emitterProperty.FindPropertyRelative("Params").GetArrayElementAtIndex(0).FindPropertyRelative("Value").floatValue = 0;
}
if (set && !newSet)
{
emitterProperty.FindPropertyRelative("Params").DeleteArrayElementAtIndex(index);
}
set = newSet;
if (set)
{
var valueProperty = emitterProperty.FindPropertyRelative("Params")
.GetArrayElementAtIndex(index).FindPropertyRelative("Value");
valueProperty.floatValue =
EditorUtils.DrawParameterValueLayout(valueProperty.floatValue, paramRef);
}
else
{
using (new EditorGUI.DisabledScope(true))
{
EditorUtils.DrawParameterValueLayout(0, paramRef);
}
}
EditorGUILayout.EndHorizontal();
}
}
}
emitterIndex++;
}
serializedObject.ApplyModifiedProperties();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: dc94d213814ef1a42b0ca8ee00dd4728
timeCreated: 1451968823
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,107 @@
using UnityEngine;
namespace FMODUnity
{
public abstract class EventHandler : MonoBehaviour
{
public string CollisionTag = "";
protected virtual void Start()
{
HandleGameEvent(EmitterGameEvent.ObjectStart);
}
protected virtual void OnDestroy()
{
HandleGameEvent(EmitterGameEvent.ObjectDestroy);
}
private void OnEnable()
{
HandleGameEvent(EmitterGameEvent.ObjectEnable);
}
private void OnDisable()
{
HandleGameEvent(EmitterGameEvent.ObjectDisable);
}
#if UNITY_PHYSICS_EXIST
private void OnTriggerEnter(Collider other)
{
if (string.IsNullOrEmpty(CollisionTag) || other.CompareTag(CollisionTag) || (other.attachedRigidbody && other.attachedRigidbody.CompareTag(CollisionTag)))
{
HandleGameEvent(EmitterGameEvent.TriggerEnter);
}
}
private void OnTriggerExit(Collider other)
{
if (string.IsNullOrEmpty(CollisionTag) || other.CompareTag(CollisionTag) || (other.attachedRigidbody && other.attachedRigidbody.CompareTag(CollisionTag)))
{
HandleGameEvent(EmitterGameEvent.TriggerExit);
}
}
#endif
#if UNITY_PHYSICS2D_EXIST
private void OnTriggerEnter2D(Collider2D other)
{
if (string.IsNullOrEmpty(CollisionTag) || other.CompareTag(CollisionTag))
{
HandleGameEvent(EmitterGameEvent.TriggerEnter2D);
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (string.IsNullOrEmpty(CollisionTag) || other.CompareTag(CollisionTag))
{
HandleGameEvent(EmitterGameEvent.TriggerExit2D);
}
}
#endif
private void OnCollisionEnter()
{
HandleGameEvent(EmitterGameEvent.CollisionEnter);
}
private void OnCollisionExit()
{
HandleGameEvent(EmitterGameEvent.CollisionExit);
}
private void OnCollisionEnter2D()
{
HandleGameEvent(EmitterGameEvent.CollisionEnter2D);
}
private void OnCollisionExit2D()
{
HandleGameEvent(EmitterGameEvent.CollisionExit2D);
}
private void OnMouseEnter()
{
HandleGameEvent(EmitterGameEvent.MouseEnter);
}
private void OnMouseExit()
{
HandleGameEvent(EmitterGameEvent.MouseExit);
}
private void OnMouseDown()
{
HandleGameEvent(EmitterGameEvent.MouseDown);
}
private void OnMouseUp()
{
HandleGameEvent(EmitterGameEvent.MouseUp);
}
protected abstract void HandleGameEvent(EmitterGameEvent gameEvent);
}
}

View file

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

View file

@ -0,0 +1,11 @@
using System;
using UnityEngine;
namespace FMODUnity
{
[Obsolete("Use the EventReference struct instead")]
public class EventRefAttribute : PropertyAttribute
{
public string MigrateTo = null;
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1b29a1189268c3b47aa2ec4b96a9e7ef
timeCreated: 1445311748
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,53 @@
using System;
using UnityEngine;
namespace FMODUnity
{
[Serializable]
public struct EventReference
{
public FMOD.GUID Guid;
#if UNITY_EDITOR
public string Path;
public static Func<string, FMOD.GUID> GuidLookupDelegate;
public override string ToString()
{
return string.Format("{0} ({1})", Guid, Path);
}
public bool IsNull
{
get
{
return string.IsNullOrEmpty(Path) && Guid.IsNull;
}
}
public static EventReference Find(string path)
{
if (GuidLookupDelegate == null)
{
throw new InvalidOperationException("EventReference.Find called before EventManager was initialized");
}
return new EventReference { Path = path, Guid = GuidLookupDelegate(path) };
}
#else
public override string ToString()
{
return Guid.ToString();
}
public bool IsNull
{
get
{
return Guid.IsNull;
}
}
#endif
}
}

View file

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

View file

@ -0,0 +1,286 @@
#if UNITY_TIMELINE_EXIST
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using UnityEngine.Serialization;
namespace FMODUnity
{
[System.Serializable]
public class FMODEventPlayable : PlayableAsset, ITimelineClipAsset
{
[FormerlySerializedAs("template")]
public FMODEventPlayableBehavior Template = new FMODEventPlayableBehavior();
[FormerlySerializedAs("eventLength")]
public float EventLength; //In seconds.
[Obsolete("Use the eventReference field instead")]
[SerializeField]
public string eventName;
[FormerlySerializedAs("eventReference")]
[SerializeField]
public EventReference EventReference;
[FormerlySerializedAs("stopType")]
[SerializeField]
public STOP_MODE StopType;
[FormerlySerializedAs("parameters")]
[SerializeField]
public ParamRef[] Parameters = new ParamRef[0];
[NonSerialized]
public bool CachedParameters = false;
private FMODEventPlayableBehavior behavior;
public GameObject TrackTargetObject { get; set; }
public override double duration
{
get
{
if (EventReference.IsNull)
{
return base.duration;
}
else
{
return EventLength;
}
}
}
public ClipCaps clipCaps
{
get { return ClipCaps.None; }
}
public TimelineClip OwningClip { get; set; }
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
#if UNITY_EDITOR
if (!EventReference.IsNull)
#else
if (!CachedParameters && !EventReference.IsNull)
#endif
{
FMOD.Studio.EventDescription eventDescription = RuntimeManager.GetEventDescription(EventReference);
for (int i = 0; i < Parameters.Length; i++)
{
FMOD.Studio.PARAMETER_DESCRIPTION parameterDescription;
eventDescription.getParameterDescriptionByName(Parameters[i].Name, out parameterDescription);
Parameters[i].ID = parameterDescription.id;
}
List<ParameterAutomationLink> parameterLinks = Template.ParameterLinks;
for (int i = 0; i < parameterLinks.Count; i++)
{
FMOD.Studio.PARAMETER_DESCRIPTION parameterDescription;
eventDescription.getParameterDescriptionByName(parameterLinks[i].Name, out parameterDescription);
parameterLinks[i].ID = parameterDescription.id;
}
CachedParameters = true;
}
var playable = ScriptPlayable<FMODEventPlayableBehavior>.Create(graph, Template);
behavior = playable.GetBehaviour();
behavior.TrackTargetObject = TrackTargetObject;
behavior.EventReference = EventReference;
behavior.StopType = StopType;
behavior.Parameters = Parameters;
behavior.OwningClip = OwningClip;
return playable;
}
#if UNITY_EDITOR
public void UpdateEventDuration(float duration)
{
EventLength = duration / 1000f;
}
public void OnValidate()
{
if (OwningClip != null && !EventReference.IsNull)
{
int index = EventReference.Path.LastIndexOf("/");
OwningClip.displayName = EventReference.Path.Substring(index + 1);
}
if (behavior != null && !behavior.EventReference.IsNull)
{
behavior.EventReference = EventReference;
}
}
#endif //UNITY_EDITOR
}
public enum STOP_MODE : int
{
AllowFadeout,
Immediate,
None
}
[Serializable]
public class ParameterAutomationLink
{
public string Name;
public FMOD.Studio.PARAMETER_ID ID;
public int Slot;
}
[Serializable]
public class FMODEventPlayableBehavior : PlayableBehaviour
{
[FormerlySerializedAs("eventReference")]
public EventReference EventReference;
[FormerlySerializedAs("stopType")]
public STOP_MODE StopType = STOP_MODE.AllowFadeout;
[FormerlySerializedAs("parameters")]
[NotKeyable]
public ParamRef[] Parameters = new ParamRef[0];
[FormerlySerializedAs("parameterLinks")]
public List<ParameterAutomationLink> ParameterLinks = new List<ParameterAutomationLink>();
[NonSerialized]
public GameObject TrackTargetObject;
[NonSerialized]
public TimelineClip OwningClip;
[FormerlySerializedAs("parameterAutomation")]
public AutomatableSlots ParameterAutomation;
private bool isPlayheadInside = false;
private FMOD.Studio.EventInstance eventInstance;
private float currentVolume = 1;
protected void PlayEvent()
{
if (!EventReference.IsNull)
{
eventInstance = RuntimeManager.CreateInstance(EventReference);
// Only attach to object if the game is actually playing, not auditioning.
if (Application.isPlaying && TrackTargetObject)
{
#if UNITY_PHYSICS_EXIST
if (TrackTargetObject.GetComponent<Rigidbody>())
{
RuntimeManager.AttachInstanceToGameObject(eventInstance, TrackTargetObject.transform, TrackTargetObject.GetComponent<Rigidbody>());
}
else
#endif
#if UNITY_PHYSICS2D_EXIST
if (TrackTargetObject.GetComponent<Rigidbody2D>())
{
RuntimeManager.AttachInstanceToGameObject(eventInstance, TrackTargetObject.transform, TrackTargetObject.GetComponent<Rigidbody2D>());
}
else
#endif
{
RuntimeManager.AttachInstanceToGameObject(eventInstance, TrackTargetObject.transform);
}
}
else
{
eventInstance.set3DAttributes(RuntimeUtils.To3DAttributes(Vector3.zero));
}
foreach (var param in Parameters)
{
eventInstance.setParameterByID(param.ID, param.Value);
}
eventInstance.setVolume(currentVolume);
eventInstance.start();
}
}
public void OnEnter()
{
if (!isPlayheadInside)
{
PlayEvent();
isPlayheadInside = true;
}
}
public void OnExit()
{
if (isPlayheadInside)
{
if (eventInstance.isValid())
{
if (StopType != STOP_MODE.None)
{
eventInstance.stop(StopType == STOP_MODE.Immediate ? FMOD.Studio.STOP_MODE.IMMEDIATE : FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
}
eventInstance.release();
}
isPlayheadInside = false;
}
}
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
if (eventInstance.isValid())
{
foreach (ParameterAutomationLink link in ParameterLinks)
{
float value = ParameterAutomation.GetValue(link.Slot);
eventInstance.setParameterByID(link.ID, value);
}
}
}
public void UpdateBehavior(float time, float volume)
{
if (volume != currentVolume)
{
currentVolume = volume;
if (eventInstance.isValid())
{
eventInstance.setVolume(volume);
}
}
if ((time >= OwningClip.start) && (time < OwningClip.end))
{
OnEnter();
}
else
{
OnExit();
}
}
public override void OnGraphStop(Playable playable)
{
isPlayheadInside = false;
if (eventInstance.isValid())
{
eventInstance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
eventInstance.release();
RuntimeManager.StudioSystem.update();
}
}
}
}
#endif

View file

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 987a467495df9d942b56b1b51381d095
timeCreated: 1523230466
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 392af304825cbe847bbf4e603852e4dd, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,83 @@
#if UNITY_TIMELINE_EXIST
using System;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMODUnity
{
[TrackColor(0.066f, 0.134f, 0.244f)]
[TrackClipType(typeof(FMODEventPlayable))]
[TrackBindingType(typeof(GameObject))]
[DisplayName("FMOD/Event Track")]
public class FMODEventTrack : TrackAsset
{
public FMODEventMixerBehaviour template = new FMODEventMixerBehaviour();
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
var director = go.GetComponent<PlayableDirector>();
var trackTargetObject = director.GetGenericBinding(this) as GameObject;
foreach (var clip in GetClips())
{
var playableAsset = clip.asset as FMODEventPlayable;
if (playableAsset)
{
playableAsset.TrackTargetObject = trackTargetObject;
playableAsset.OwningClip = clip;
}
}
var scriptPlayable = ScriptPlayable<FMODEventMixerBehaviour>.Create(graph, template, inputCount);
return scriptPlayable;
}
}
[Serializable]
public class FMODEventMixerBehaviour : PlayableBehaviour
{
[Range(0, 1)]
public float volume = 1;
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
#if UNITY_EDITOR
/*
* Process frame is called from OnGUI() when auditioning.
* Check playing to avoid retriggering sounds while scrubbing or repainting.
* Check IsQuitting to avoid accessing the RuntimeManager during the Play-In-Editor to Editor transition.
*/
bool playing = playable.GetGraph().IsPlaying();
if (!playing)
{
return;
}
/* When auditioning manually update the StudioSystem in place of the RuntimeManager. */
if (!Application.isPlaying)
{
FMODUnity.RuntimeManager.StudioSystem.update();
}
#endif //UNITY_EDITOR
int inputCount = playable.GetInputCount();
float time = (float)playable.GetGraph().GetRootPlayable(0).GetTime();
for (int i = 0; i < inputCount; i++)
{
ScriptPlayable<FMODEventPlayableBehavior> inputPlayable = (ScriptPlayable<FMODEventPlayableBehavior>)playable.GetInput(i);
FMODEventPlayableBehavior input = inputPlayable.GetBehaviour();
input.UpdateBehavior(time, volume);
}
}
}
}
#endif

View file

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 133253f56854570409c222a87786b263
timeCreated: 1523230466
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: a4edfa5854cdec34b98b1c55f0562bdd, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FMODUnity
{
public class FMODRuntimeManagerOnGUIHelper : MonoBehaviour
{
public RuntimeManager TargetRuntimeManager = null;
private void OnGUI()
{
if (TargetRuntimeManager)
{
TargetRuntimeManager.ExecuteOnGUI();
}
}
}
}

View file

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

View file

@ -0,0 +1,12 @@
using System;
namespace FMODUnity
{
[Serializable]
public class ParamRef
{
public string Name;
public float Value;
public FMOD.Studio.PARAMETER_ID ID;
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 00e1a9817a5d9844796d7c313b1ab197
timeCreated: 1444192631
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
using UnityEngine;
namespace FMODUnity
{
public class ParamRefAttribute : PropertyAttribute
{
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,64 @@
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMODUnity
{
public class PlatformDefault : Platform
{
public const string ConstIdentifier = "default";
public PlatformDefault()
{
Identifier = ConstIdentifier;
}
public override string DisplayName { get { return "Default"; } }
public override void DeclareRuntimePlatforms(Settings settings) { }
#if UNITY_EDITOR
public override IEnumerable<BuildTarget> GetBuildTargets()
{
yield break;
}
public override Legacy.Platform LegacyIdentifier { get { return Legacy.Platform.Default; } }
protected override BinaryAssetFolderInfo GetBinaryAssetFolder(BuildTarget buildTarget)
{
return null;
}
protected override IEnumerable<FileRecord> GetBinaryFiles(BuildTarget buildTarget, bool allVariants, string suffix)
{
yield break;
}
#endif
public override bool IsIntrinsic { get { return true; } }
public override void InitializeProperties()
{
base.InitializeProperties();
PropertyAccessors.Plugins.Set(this, new List<string>());
PropertyAccessors.StaticPlugins.Set(this, new List<string>());
}
public override void EnsurePropertiesAreValid()
{
base.EnsurePropertiesAreValid();
if (StaticPlugins == null)
{
PropertyAccessors.StaticPlugins.Set(this, new List<string>());
}
}
// null means no valid output types - don't display the field in the UI
#if UNITY_EDITOR
public override OutputType[] ValidOutputTypes { get { return null; } }
#endif
}
}

View file

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

View file

@ -0,0 +1,51 @@
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMODUnity
{
public class PlatformGroup : Platform
{
[SerializeField]
private string displayName;
[SerializeField]
private Legacy.Platform legacyIdentifier;
public override string DisplayName { get { return displayName; } }
public override void DeclareRuntimePlatforms(Settings settings) { }
#if UNITY_EDITOR
public override IEnumerable<BuildTarget> GetBuildTargets()
{
yield break;
}
public override Legacy.Platform LegacyIdentifier { get { return legacyIdentifier; } }
public static PlatformGroup Create(string displayName, Legacy.Platform legacyIdentifier)
{
PlatformGroup group = CreateInstance<PlatformGroup>();
group.Identifier = GUID.Generate().ToString();
group.displayName = displayName;
group.legacyIdentifier = legacyIdentifier;
group.AffirmProperties();
return group;
}
protected override BinaryAssetFolderInfo GetBinaryAssetFolder(BuildTarget buildTarget)
{
return null;
}
protected override IEnumerable<FileRecord> GetBinaryFiles(BuildTarget buildTarget, bool allVariants, string suffix)
{
yield break;
}
public override OutputType[] ValidOutputTypes { get { return null; } }
#endif
}
}

View file

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

View file

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMODUnity
{
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
public class PlatformMobileHigh : PlatformMobileLow
{
static PlatformMobileHigh()
{
Settings.AddPlatformTemplate<PlatformMobileHigh>("fd7c55dab0fce234b8c25f6ffca523c1");
}
public override string DisplayName { get { return "High-End Mobile"; } }
#if UNITY_EDITOR
public override Legacy.Platform LegacyIdentifier { get { return Legacy.Platform.MobileHigh; } }
#endif
public override float Priority { get { return base.Priority + 1; } }
public override bool MatchesCurrentEnvironment
{
get
{
if (!Active)
{
return false;
}
#if UNITY_IOS
switch (UnityEngine.iOS.Device.generation)
{
case UnityEngine.iOS.DeviceGeneration.iPad1Gen:
case UnityEngine.iOS.DeviceGeneration.iPad2Gen:
case UnityEngine.iOS.DeviceGeneration.iPad3Gen:
case UnityEngine.iOS.DeviceGeneration.iPadMini1Gen:
case UnityEngine.iOS.DeviceGeneration.iPhone:
case UnityEngine.iOS.DeviceGeneration.iPhone3G:
case UnityEngine.iOS.DeviceGeneration.iPhone3GS:
case UnityEngine.iOS.DeviceGeneration.iPhone4:
case UnityEngine.iOS.DeviceGeneration.iPhone4S:
return false;
default:
return true;
}
#elif UNITY_ANDROID
if (SystemInfo.processorCount <= 2)
{
return false;
}
else if (SystemInfo.processorCount >= 8)
{
return true;
}
else
{
// check the clock rate on quad core systems
string freqinfo = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
try
{
using (System.IO.TextReader reader = new System.IO.StreamReader(freqinfo))
{
string line = reader.ReadLine();
int khz = int.Parse(line) / 1000;
if (khz >= 1600)
{
return true;
}
else
{
return false;
}
}
}
catch
{
return false;
}
}
#else
return false;
#endif
}
}
}
}

View file

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

View file

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMODUnity
{
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
public class PlatformMobileLow : Platform
{
static PlatformMobileLow()
{
Settings.AddPlatformTemplate<PlatformMobileLow>("c88d16e5272a4e241b0ef0ac2e53b73d");
}
public override string DisplayName { get { return "Low-End Mobile"; } }
public override void DeclareRuntimePlatforms(Settings settings)
{
settings.DeclareRuntimePlatform(RuntimePlatform.IPhonePlayer, this);
settings.DeclareRuntimePlatform(RuntimePlatform.Android, this);
}
#if UNITY_EDITOR
public override IEnumerable<BuildTarget> GetBuildTargets()
{
yield break;
}
public override Legacy.Platform LegacyIdentifier { get { return Legacy.Platform.MobileLow; } }
protected override BinaryAssetFolderInfo GetBinaryAssetFolder(BuildTarget buildTarget)
{
return null;
}
protected override IEnumerable<FileRecord> GetBinaryFiles(BuildTarget buildTarget, bool allVariants, string suffix)
{
yield break;
}
public override bool SupportsAdditionalCPP(BuildTarget target)
{
if (target == BuildTarget.iOS)
{
return PlatformIOS.StaticSupportsAdditionalCpp();
}
else
{
return base.SupportsAdditionalCPP(target);
}
}
#endif
public override float Priority { get { return DefaultPriority + 1; } }
public override bool MatchesCurrentEnvironment
{
get
{
return Active;
}
}
#if UNITY_IOS
public override void LoadPlugins(FMOD.System coreSystem, Action<FMOD.RESULT, string> reportResult)
{
PlatformIOS.StaticLoadPlugins(this, coreSystem, reportResult);
}
#elif UNITY_ANDROID
public override string GetBankFolder()
{
return PlatformAndroid.StaticGetBankFolder();
}
public override string GetPluginPath(string pluginName)
{
return PlatformAndroid.StaticGetPluginPath(pluginName);
}
#endif
#if UNITY_EDITOR
public override OutputType[] ValidOutputTypes { get { return null; } }
#endif
}
}

View file

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

View file

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_EDITOR
namespace FMOD
{
public partial class VERSION
{
public const string dll = "fmodstudioL";
}
}
namespace FMOD.Studio
{
public partial class STUDIO_VERSION
{
public const string dll = "fmodstudioL";
}
}
#endif
namespace FMODUnity
{
public class PlatformPlayInEditor : Platform
{
public PlatformPlayInEditor()
{
Identifier = "playInEditor";
}
public override string DisplayName { get { return "Editor"; } }
public override void DeclareRuntimePlatforms(Settings settings)
{
settings.DeclareRuntimePlatform(RuntimePlatform.OSXEditor, this);
settings.DeclareRuntimePlatform(RuntimePlatform.WindowsEditor, this);
settings.DeclareRuntimePlatform(RuntimePlatform.LinuxEditor, this);
}
#if UNITY_EDITOR
public override IEnumerable<BuildTarget> GetBuildTargets()
{
yield break;
}
public override Legacy.Platform LegacyIdentifier { get { return Legacy.Platform.PlayInEditor; } }
protected override BinaryAssetFolderInfo GetBinaryAssetFolder(BuildTarget buildTarget)
{
return null;
}
protected override IEnumerable<FileRecord> GetBinaryFiles(BuildTarget buildTarget, bool allVariants, string suffix)
{
yield break;
}
#endif
public override bool IsIntrinsic { get { return true; } }
public override string GetBankFolder()
{
// Use original asset location because streaming asset folder will contain platform specific banks
Settings globalSettings = Settings.Instance;
string bankFolder = globalSettings.SourceBankPath;
if (globalSettings.HasPlatforms)
{
bankFolder = RuntimeUtils.GetCommonPlatformPath(Path.Combine(bankFolder, BuildDirectory));
}
return bankFolder;
}
#if UNITY_EDITOR
public override string GetPluginPath(string pluginName)
{
string platformsFolder = $"{Application.dataPath}/{RuntimeUtils.PluginBasePath}/platforms";
#if UNITY_EDITOR_WIN && UNITY_EDITOR_64
return string.Format("{0}/win/lib/x86_64/{1}.dll", platformsFolder, pluginName);
#elif UNITY_EDITOR_WIN
return string.Format("{0}/win/lib/x86/{1}.dll", platformsFolder, pluginName);
#elif UNITY_EDITOR_OSX
return string.Format("{0}/mac/lib/{1}.bundle", platformsFolder, pluginName);
#elif UNITY_EDITOR_LINUX && UNITY_EDITOR_64
return string.Format("{0}/linux/lib/x86_64/lib{1}.so", platformsFolder, pluginName);
#elif UNITY_EDITOR_LINUX
return string.Format("{0}/linux/lib/x86/lib{1}.so", platformsFolder, pluginName);
#endif
}
#endif
public override void LoadStaticPlugins(FMOD.System coreSystem, Action<FMOD.RESULT, string> reportResult)
{
// Ignore static plugins when playing in the editor
}
public override void InitializeProperties()
{
base.InitializeProperties();
PropertyAccessors.LiveUpdate.Set(this, TriStateBool.Enabled);
PropertyAccessors.Overlay.Set(this, TriStateBool.Enabled);
PropertyAccessors.SampleRate.Set(this, 48000);
PropertyAccessors.RealChannelCount.Set(this, 256);
PropertyAccessors.VirtualChannelCount.Set(this, 1024);
}
#if UNITY_EDITOR
public override OutputType[] ValidOutputTypes { get { return null; } }
#endif
public override List<CodecChannelCount> DefaultCodecChannels { get { return staticCodecChannels; } }
private static List<CodecChannelCount> staticCodecChannels = new List<CodecChannelCount>()
{
new CodecChannelCount { format = CodecType.FADPCM, channels = 0 },
new CodecChannelCount { format = CodecType.Vorbis, channels = 256 },
};
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5e5fb8ce07f0ce84b9d1852869527ea5
timeCreated: 1444628977
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 100
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,594 @@
using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FMOD
{
[Serializable]
public partial struct GUID : IEquatable<GUID>
{
public GUID(Guid guid)
{
byte[] bytes = guid.ToByteArray();
Data1 = BitConverter.ToInt32(bytes, 0);
Data2 = BitConverter.ToInt32(bytes, 4);
Data3 = BitConverter.ToInt32(bytes, 8);
Data4 = BitConverter.ToInt32(bytes, 12);
}
public static GUID Parse(string s)
{
return new GUID(new Guid(s));
}
public bool IsNull
{
get
{
return Data1 == 0
&& Data2 == 0
&& Data3 == 0
&& Data4 == 0;
}
}
public override bool Equals(object other)
{
return (other is GUID) && Equals((GUID)other);
}
public bool Equals(GUID other)
{
return Data1 == other.Data1
&& Data2 == other.Data2
&& Data3 == other.Data3
&& Data4 == other.Data4;
}
public static bool operator==(GUID a, GUID b)
{
return a.Equals(b);
}
public static bool operator!=(GUID a, GUID b)
{
return !a.Equals(b);
}
public override int GetHashCode()
{
return Data1 ^ Data2 ^ Data3 ^ Data4;
}
public static implicit operator Guid(GUID guid)
{
return new Guid(guid.Data1,
(short) ((guid.Data2 >> 0) & 0xFFFF),
(short) ((guid.Data2 >> 16) & 0xFFFF),
(byte) ((guid.Data3 >> 0) & 0xFF),
(byte) ((guid.Data3 >> 8) & 0xFF),
(byte) ((guid.Data3 >> 16) & 0xFF),
(byte) ((guid.Data3 >> 24) & 0xFF),
(byte) ((guid.Data4 >> 0) & 0xFF),
(byte) ((guid.Data4 >> 8) & 0xFF),
(byte) ((guid.Data4 >> 16) & 0xFF),
(byte) ((guid.Data4 >> 24) & 0xFF)
);
}
public override string ToString()
{
return ((Guid)this).ToString("B");
}
}
}
namespace FMODUnity
{
public class EventNotFoundException : Exception
{
public FMOD.GUID Guid;
public string Path;
public EventNotFoundException(string path)
: base("[FMOD] Event not found: '" + path + "'")
{
Path = path;
}
public EventNotFoundException(FMOD.GUID guid)
: base("[FMOD] Event not found: " + guid)
{
Guid = guid;
}
public EventNotFoundException(EventReference eventReference)
: base("[FMOD] Event not found: " + eventReference.ToString())
{
Guid = eventReference.Guid;
#if UNITY_EDITOR
Path = eventReference.Path;
#endif
}
}
public class BusNotFoundException : Exception
{
public string Path;
public BusNotFoundException(string path)
: base("[FMOD] Bus not found '" + path + "'")
{
Path = path;
}
}
public class VCANotFoundException : Exception
{
public string Path;
public VCANotFoundException(string path)
: base("[FMOD] VCA not found '" + path + "'")
{
Path = path;
}
}
public class BankLoadException : Exception
{
public string Path;
public FMOD.RESULT Result;
public BankLoadException(string path, FMOD.RESULT result)
: base(string.Format("[FMOD] Could not load bank '{0}' : {1} : {2}", path, result.ToString(), FMOD.Error.String(result)))
{
Path = path;
Result = result;
}
public BankLoadException(string path, string error)
: base(string.Format("[FMOD] Could not load bank '{0}' : {1}", path, error))
{
Path = path;
Result = FMOD.RESULT.ERR_INTERNAL;
}
}
public class SystemNotInitializedException : Exception
{
public FMOD.RESULT Result;
public string Location;
public SystemNotInitializedException(FMOD.RESULT result, string location)
: base(string.Format("[FMOD] Initialization failed : {2} : {0} : {1}", result.ToString(), FMOD.Error.String(result), location))
{
Result = result;
Location = location;
}
public SystemNotInitializedException(Exception inner)
: base("[FMOD] Initialization failed", inner)
{
}
}
public enum EmitterGameEvent : int
{
None,
ObjectStart,
ObjectDestroy,
TriggerEnter,
TriggerExit,
TriggerEnter2D,
TriggerExit2D,
CollisionEnter,
CollisionExit,
CollisionEnter2D,
CollisionExit2D,
ObjectEnable,
ObjectDisable,
MouseEnter,
MouseExit,
MouseDown,
MouseUp,
}
public enum LoaderGameEvent : int
{
None,
ObjectStart,
ObjectDestroy,
TriggerEnter,
TriggerExit,
TriggerEnter2D,
TriggerExit2D,
ObjectEnable,
ObjectDisable,
}
// We use our own enum to avoid serialization issues if FMOD.THREAD_TYPE changes
public enum ThreadType
{
Mixer,
Feeder,
Stream,
File,
Nonblocking,
Record,
Geometry,
Profiler,
Studio_Update,
Studio_Load_Bank,
Studio_Load_Sample,
Convolution_1,
Convolution_2,
}
// We use our own enum to avoid serialization issues if FMOD.THREAD_AFFINITY changes
[Flags]
public enum ThreadAffinity : uint
{
Any = 0,
Core0 = 1 << 0,
Core1 = 1 << 1,
Core2 = 1 << 2,
Core3 = 1 << 3,
Core4 = 1 << 4,
Core5 = 1 << 5,
Core6 = 1 << 6,
Core7 = 1 << 7,
Core8 = 1 << 8,
Core9 = 1 << 9,
Core10 = 1 << 10,
Core11 = 1 << 11,
Core12 = 1 << 12,
Core13 = 1 << 13,
Core14 = 1 << 14,
Core15 = 1 << 15,
}
// Using a separate enum to avoid serialization issues if FMOD.SOUND_TYPE changes.
public enum CodecType : int
{
FADPCM,
Vorbis,
AT9,
XMA,
Opus
}
[Serializable]
public class ThreadAffinityGroup
{
public List<ThreadType> threads = new List<ThreadType>();
public ThreadAffinity affinity = ThreadAffinity.Any;
public ThreadAffinityGroup()
{
}
public ThreadAffinityGroup(ThreadAffinityGroup other)
{
threads = new List<ThreadType>(other.threads);
affinity = other.affinity;
}
public ThreadAffinityGroup(ThreadAffinity affinity, params ThreadType[] threads)
{
this.threads = new List<ThreadType>(threads);
this.affinity = affinity;
}
}
[Serializable]
public class CodecChannelCount
{
public CodecType format;
public int channels;
public CodecChannelCount() { }
public CodecChannelCount(CodecChannelCount other)
{
format = other.format;
channels = other.channels;
}
}
public static class RuntimeUtils
{
#if UNITY_EDITOR
private static string pluginBasePath;
public const string BaseFolderGUID = "06ae579381df01a4a87bb149dec89954";
public const string PluginBasePathDefault = "Plugins/FMOD";
public static string PluginBasePath
{
get
{
if (pluginBasePath == null)
{
pluginBasePath = AssetDatabase.GUIDToAssetPath(BaseFolderGUID);
if (!string.IsNullOrEmpty(pluginBasePath))
{
const string AssetsFolder = "Assets/";
if (pluginBasePath.StartsWith(AssetsFolder))
{
pluginBasePath = pluginBasePath.Substring(AssetsFolder.Length);
}
}
else
{
pluginBasePath = PluginBasePathDefault;
DebugLogWarningFormat("FMOD: Couldn't find base folder with GUID {0}; defaulting to {1}",
BaseFolderGUID, pluginBasePath);
}
}
return pluginBasePath;
}
}
#endif
public static string GetCommonPlatformPath(string path)
{
if (string.IsNullOrEmpty(path))
{
return path;
}
return path.Replace('\\', '/');
}
public static FMOD.VECTOR ToFMODVector(this Vector3 vec)
{
FMOD.VECTOR temp;
temp.x = vec.x;
temp.y = vec.y;
temp.z = vec.z;
return temp;
}
public static FMOD.ATTRIBUTES_3D To3DAttributes(this Vector3 pos)
{
FMOD.ATTRIBUTES_3D attributes = new FMOD.ATTRIBUTES_3D();
attributes.forward = ToFMODVector(Vector3.forward);
attributes.up = ToFMODVector(Vector3.up);
attributes.position = ToFMODVector(pos);
return attributes;
}
public static FMOD.ATTRIBUTES_3D To3DAttributes(this Transform transform)
{
FMOD.ATTRIBUTES_3D attributes = new FMOD.ATTRIBUTES_3D();
attributes.forward = transform.forward.ToFMODVector();
attributes.up = transform.up.ToFMODVector();
attributes.position = transform.position.ToFMODVector();
return attributes;
}
public static FMOD.ATTRIBUTES_3D To3DAttributes(this GameObject go)
{
return go.transform.To3DAttributes();
}
#if UNITY_PHYSICS_EXIST
public static FMOD.ATTRIBUTES_3D To3DAttributes(Transform transform, Rigidbody rigidbody = null)
{
FMOD.ATTRIBUTES_3D attributes = transform.To3DAttributes();
if (rigidbody)
{
attributes.velocity = rigidbody.velocity.ToFMODVector();
}
return attributes;
}
public static FMOD.ATTRIBUTES_3D To3DAttributes(GameObject go, Rigidbody rigidbody)
{
FMOD.ATTRIBUTES_3D attributes = go.transform.To3DAttributes();
if (rigidbody)
{
attributes.velocity = rigidbody.velocity.ToFMODVector();
}
return attributes;
}
#endif
#if UNITY_PHYSICS2D_EXIST
public static FMOD.ATTRIBUTES_3D To3DAttributes(Transform transform, Rigidbody2D rigidbody)
{
FMOD.ATTRIBUTES_3D attributes = transform.To3DAttributes();
if (rigidbody)
{
FMOD.VECTOR vel;
vel.x = rigidbody.velocity.x;
vel.y = rigidbody.velocity.y;
vel.z = 0;
attributes.velocity = vel;
}
return attributes;
}
public static FMOD.ATTRIBUTES_3D To3DAttributes(GameObject go, Rigidbody2D rigidbody)
{
FMOD.ATTRIBUTES_3D attributes = go.transform.To3DAttributes();
if (rigidbody)
{
FMOD.VECTOR vel;
vel.x = rigidbody.velocity.x;
vel.y = rigidbody.velocity.y;
vel.z = 0;
attributes.velocity = vel;
}
return attributes;
}
#endif
public static FMOD.THREAD_TYPE ToFMODThreadType(ThreadType threadType)
{
switch (threadType)
{
case ThreadType.Mixer:
return FMOD.THREAD_TYPE.MIXER;
case ThreadType.Feeder:
return FMOD.THREAD_TYPE.FEEDER;
case ThreadType.Stream:
return FMOD.THREAD_TYPE.STREAM;
case ThreadType.File:
return FMOD.THREAD_TYPE.FILE;
case ThreadType.Nonblocking:
return FMOD.THREAD_TYPE.NONBLOCKING;
case ThreadType.Record:
return FMOD.THREAD_TYPE.RECORD;
case ThreadType.Geometry:
return FMOD.THREAD_TYPE.GEOMETRY;
case ThreadType.Profiler:
return FMOD.THREAD_TYPE.PROFILER;
case ThreadType.Studio_Update:
return FMOD.THREAD_TYPE.STUDIO_UPDATE;
case ThreadType.Studio_Load_Bank:
return FMOD.THREAD_TYPE.STUDIO_LOAD_BANK;
case ThreadType.Studio_Load_Sample:
return FMOD.THREAD_TYPE.STUDIO_LOAD_SAMPLE;
case ThreadType.Convolution_1:
return FMOD.THREAD_TYPE.CONVOLUTION1;
case ThreadType.Convolution_2:
return FMOD.THREAD_TYPE.CONVOLUTION2;
default:
throw new ArgumentException("Unrecognised thread type '" + threadType.ToString() + "'");
}
}
public static string DisplayName(this ThreadType thread)
{
return thread.ToString().Replace('_', ' ');
}
public static FMOD.THREAD_AFFINITY ToFMODThreadAffinity(ThreadAffinity affinity)
{
FMOD.THREAD_AFFINITY fmodAffinity = FMOD.THREAD_AFFINITY.CORE_ALL;
SetFMODAffinityBit(affinity, ThreadAffinity.Core0, FMOD.THREAD_AFFINITY.CORE_0, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core1, FMOD.THREAD_AFFINITY.CORE_1, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core2, FMOD.THREAD_AFFINITY.CORE_2, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core3, FMOD.THREAD_AFFINITY.CORE_3, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core4, FMOD.THREAD_AFFINITY.CORE_4, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core5, FMOD.THREAD_AFFINITY.CORE_5, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core6, FMOD.THREAD_AFFINITY.CORE_6, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core7, FMOD.THREAD_AFFINITY.CORE_7, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core8, FMOD.THREAD_AFFINITY.CORE_8, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core9, FMOD.THREAD_AFFINITY.CORE_9, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core10, FMOD.THREAD_AFFINITY.CORE_10, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core11, FMOD.THREAD_AFFINITY.CORE_11, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core12, FMOD.THREAD_AFFINITY.CORE_12, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core13, FMOD.THREAD_AFFINITY.CORE_13, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core14, FMOD.THREAD_AFFINITY.CORE_14, ref fmodAffinity);
SetFMODAffinityBit(affinity, ThreadAffinity.Core15, FMOD.THREAD_AFFINITY.CORE_15, ref fmodAffinity);
return fmodAffinity;
}
private static void SetFMODAffinityBit(ThreadAffinity affinity, ThreadAffinity mask,
FMOD.THREAD_AFFINITY fmodMask, ref FMOD.THREAD_AFFINITY fmodAffinity)
{
if ((affinity & mask) != 0)
{
fmodAffinity |= fmodMask;
}
}
public static void EnforceLibraryOrder()
{
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidJavaClass jSystem = new AndroidJavaClass("java.lang.System");
jSystem.CallStatic("loadLibrary", FMOD.VERSION.dll);
jSystem.CallStatic("loadLibrary", FMOD.Studio.STUDIO_VERSION.dll);
#endif
// Call a function in fmod.dll to make sure it's loaded before fmodstudio.dll
int temp1, temp2;
FMOD.Memory.GetStats(out temp1, out temp2);
FMOD.GUID temp3;
FMOD.Studio.Util.parseID("", out temp3);
}
public static void DebugLog(string message)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel == FMOD.DEBUG_FLAGS.LOG)
{
Debug.Log(message);
}
}
public static void DebugLogFormat(string format, params object[] args)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel == FMOD.DEBUG_FLAGS.LOG)
{
Debug.LogFormat(format, args);
}
}
public static void DebugLogWarning(string message)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel >= FMOD.DEBUG_FLAGS.WARNING)
{
Debug.LogWarning(message);
}
}
public static void DebugLogWarningFormat(string format, params object[] args)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel >= FMOD.DEBUG_FLAGS.WARNING)
{
Debug.LogWarningFormat(format, args);
}
}
public static void DebugLogError(string message)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel >= FMOD.DEBUG_FLAGS.ERROR)
{
Debug.LogError(message);
}
}
public static void DebugLogErrorFormat(string format, params object[] args)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel >= FMOD.DEBUG_FLAGS.ERROR)
{
Debug.LogErrorFormat(format, args);
}
}
public static void DebugLogException(Exception e)
{
if (Settings.Instance == null || Settings.Instance.LoggingLevel >= FMOD.DEBUG_FLAGS.ERROR)
{
Debug.LogException(e);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more