IDXWT3DH3C3X7PP4VVKUZTCGDALW6NH7KREI4E2VFQVMCBJKDMTAC HUULCHM5GFGZ7GKLCULFHC333LQ3LBI62VKII3YL5O4C5CDGCT4AC O236B5LO6PHJ4TPZGYXDVSLB5EGXXRRLYYVWI46DPL5LEGXEIHZQC XF52N4U7HWXOF4PDSCR7LCUENLTSXLWEZGS2IJ6562KYI567Z2GAC XIPU27GAVXMAKDP42DDSYNA6DSN5WBHH6AG4EK6YIIM43AQQHQAAC R5JJA7VQ5HCQ6TZEFMORFMPYBXTMIOBAH6YMDCG4QZKBJZCQLR4AC VPXUP5WZTVC3OVD73TNKPK43IAGFXGUGCEJT56JM4IT4APYQXUHAC CXQW7UICWDJFL3M44O2XVH6JNCRDGRBMPMYR2LEGFJCANPG4YASAC 3JTZIZGE6WPLZCIWXXLG3SQA2LVSVP26P7U52YBMBTY2VCC6LBLAC W2OVIBJVB5UOIM6SFCM7QS7YIPC6L2UICCXNUPS4XXOJEFJDKDQAC 6BA5NHNF3UWSL65KCWSXLRTPGYVS4N4NORDJ4FZTZ5SRRDPI4YZAC 6PTVYMJH7JKB54XWYGZG2TWYKC5Y2LP4FUN7GJKSW4LO33DE5OTQC CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC HXTSBPAP75A7EC4RKWYQMVPPHPNZFPHUORBZWDHGEB6MPAGI7G7AC S256EPZUSOF4TV2KGOFZDJXUFDD57GZFYTCARFJ3SD24RPC56PHAC fileFormatVersion: 2guid: 98e78fba19625ee419c9b9b712a790a2MonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
using TagFighter.Resources;using UnityEngine;namespace TagFighter.UI{public class LookAtCamera : MonoBehaviour{Transform _camera;protected void Awake() {_camera = Camera.main.transform;}protected void LateUpdate() {Vector3 dirToCamera = (_camera.position - transform.position).normalized;transform.LookAt(transform.position + dirToCamera * -1);}}}
fileFormatVersion: 2guid: 98e78fba19625ee419c9b9b712a790a2MonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
using UnityEngine;{}}}}}protected void LateUpdate() {Vector3 dirToCamera = (cameraTransform.position - transform.position).normalized;transform.LookAt(transform.position + dirToCamera * -1);protected void Start() {transform.Find($"RedTag").GetComponent<ResourceWatcher>().WatchedResource = GetComponentInParent<RedTag>();transform.Find($"GreenTag").GetComponent<ResourceWatcher>().WatchedResource = GetComponentInParent<GreenTag>();transform.Find($"BlueTag").GetComponent<ResourceWatcher>().WatchedResource = GetComponentInParent<BlueTag>();protected void Awake() {cameraTransform = Camera.main.transform;public class TagUIController : MonoBehaviour{Transform cameraTransform;namespace TagFighter.UIusing TagFighter.Resources;
objectReference: {fileID: 0}- target: {fileID: 5194998107043930577, guid: ffa8c2c800c07c74b951cc3710469917,type: 3}propertyPath: watch._classRefvalue: TagFighter.Resources.GreenTag, Assembly-CSharpobjectReference: {fileID: 0}- target: {fileID: 5194998107043930577, guid: ffa8c2c800c07c74b951cc3710469917,type: 3}propertyPath: _watch._classRefvalue: TagFighter.Resources.GreenTag, Assembly-CSharp
- target: {fileID: 5194998107043930577, guid: ffa8c2c800c07c74b951cc3710469917,type: 3}propertyPath: watch._classRefvalue: TagFighter.Resources.BlueTag, Assembly-CSharpobjectReference: {fileID: 0}- target: {fileID: 5194998107043930577, guid: ffa8c2c800c07c74b951cc3710469917,type: 3}propertyPath: _watch._classRefvalue: TagFighter.Resources.BlueTag, Assembly-CSharpobjectReference: {fileID: 0}
fileFormatVersion: 2guid: e3f7ebdc26195794b90ef4106fbb35abfolderAsset: yesDefaultImporter:externalObjects: {}userData:assetBundleName:assetBundleVariant:
fileFormatVersion: 2guid: c0d3a2bba6ec8f24a973ba83f00d99ecfolderAsset: yesDefaultImporter:externalObjects: {}userData:assetBundleName:assetBundleVariant:
fileFormatVersion: 2guid: 6a936c5e8011ef24db75cefabc58683aMonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
// Copyright (c) Rotorz Limited. All rights reserved.// Licensed under the MIT license. See LICENSE file in the project root.using System;using System.Collections.Generic;using System.Reflection;using UnityEditor;using UnityEngine;namespace TypeReferences {/// <summary>/// Custom property drawer for <see cref="ClassTypeReference"/> properties./// </summary>[CustomPropertyDrawer(typeof(ClassTypeReference))][CustomPropertyDrawer(typeof(ClassTypeConstraintAttribute), true)]public sealed class ClassTypeReferencePropertyDrawer : PropertyDrawer {#region Type Filtering/// <summary>/// Gets or sets a function that returns a collection of types that are/// to be excluded from drop-down. A value of <c>null</c> specifies that/// no types are to be excluded./// </summary>/// <remarks>/// <para>This property must be set immediately before presenting a class/// type reference property field using <see cref="EditorGUI.PropertyField"/>/// or <see cref="EditorGUILayout.PropertyField"/> since the value of this/// property is reset to <c>null</c> each time the control is drawn.</para>/// <para>Since filtering makes extensive use of <see cref="ICollection{Type}.Contains"/>/// it is recommended to use a collection that is optimized for fast/// lookups such as <see cref="HashSet{Type}"/> for better performance.</para>/// </remarks>/// <example>/// <para>Exclude a specific type from being selected:</para>/// <code language="csharp"><![CDATA[/// private SerializedProperty _someClassTypeReferenceProperty;////// public override void OnInspectorGUI() {/// serializedObject.Update();////// ClassTypeReferencePropertyDrawer.ExcludedTypeCollectionGetter = GetExcludedTypeCollection;/// EditorGUILayout.PropertyField(_someClassTypeReferenceProperty);////// serializedObject.ApplyModifiedProperties();/// }////// private ICollection<Type> GetExcludedTypeCollection() {/// var set = new HashSet<Type>();/// set.Add(typeof(SpecialClassToHideInDropdown));/// return set;/// }/// ]]></code>/// </example>public static Func<ICollection<Type>> ExcludedTypeCollectionGetter { get; set; }private static List<Type> GetFilteredTypes(ClassTypeConstraintAttribute filter) {var types = new List<Type>();var excludedTypes = (ExcludedTypeCollectionGetter != null ? ExcludedTypeCollectionGetter() : null);var assembly = Assembly.GetExecutingAssembly();FilterTypes(assembly, filter, excludedTypes, types);foreach (var referencedAssembly in assembly.GetReferencedAssemblies())FilterTypes(Assembly.Load(referencedAssembly), filter, excludedTypes, types);types.Sort((a, b) => a.FullName.CompareTo(b.FullName));return types;}private static void FilterTypes(Assembly assembly, ClassTypeConstraintAttribute filter, ICollection<Type> excludedTypes, List<Type> output) {foreach (var type in assembly.GetTypes()) {if (!type.IsVisible || !type.IsClass)continue;if (filter != null && !filter.IsConstraintSatisfied(type))continue;if (excludedTypes != null && excludedTypes.Contains(type))continue;output.Add(type);}}#endregion#region Type Utilityprivate static Dictionary<string, Type> s_TypeMap = new Dictionary<string, Type>();private static Type ResolveType(string classRef) {Type type;if (!s_TypeMap.TryGetValue(classRef, out type)) {type = !string.IsNullOrEmpty(classRef) ? Type.GetType(classRef) : null;s_TypeMap[classRef] = type;}return type;}#endregion#region Control Drawing / Event Handlingprivate static readonly int s_ControlHint = typeof(ClassTypeReferencePropertyDrawer).GetHashCode();private static GUIContent s_TempContent = new GUIContent();private static string DrawTypeSelectionControl(Rect position, GUIContent label, string classRef, ClassTypeConstraintAttribute filter) {if (label != null && label != GUIContent.none)position = EditorGUI.PrefixLabel(position, label);int controlID = GUIUtility.GetControlID(s_ControlHint, FocusType.Keyboard, position);bool triggerDropDown = false;switch (Event.current.GetTypeForControl(controlID)) {case EventType.ExecuteCommand:if (Event.current.commandName == "TypeReferenceUpdated") {if (s_SelectionControlID == controlID) {if (classRef != s_SelectedClassRef) {classRef = s_SelectedClassRef;GUI.changed = true;}s_SelectionControlID = 0;s_SelectedClassRef = null;}}break;case EventType.MouseDown:if (GUI.enabled && position.Contains(Event.current.mousePosition)) {GUIUtility.keyboardControl = controlID;triggerDropDown = true;Event.current.Use();}break;case EventType.KeyDown:if (GUI.enabled && GUIUtility.keyboardControl == controlID) {if (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.Space) {triggerDropDown = true;Event.current.Use();}}break;case EventType.Repaint:// Remove assembly name from content of popup control.var classRefParts = classRef.Split(',');s_TempContent.text = classRefParts[0].Trim();if (s_TempContent.text == "")s_TempContent.text = "(None)";else if (ResolveType(classRef) == null)s_TempContent.text += " {Missing}";EditorStyles.popup.Draw(position, s_TempContent, controlID);break;}if (triggerDropDown) {s_SelectionControlID = controlID;s_SelectedClassRef = classRef;var filteredTypes = GetFilteredTypes(filter);DisplayDropDown(position, filteredTypes, ResolveType(classRef), filter.Grouping);}return classRef;}private static void DrawTypeSelectionControl(Rect position, SerializedProperty property, GUIContent label, ClassTypeConstraintAttribute filter) {try {bool restoreShowMixedValue = EditorGUI.showMixedValue;EditorGUI.showMixedValue = property.hasMultipleDifferentValues;property.stringValue = DrawTypeSelectionControl(position, label, property.stringValue, filter);EditorGUI.showMixedValue = restoreShowMixedValue;}finally {ExcludedTypeCollectionGetter = null;}}private static void DisplayDropDown(Rect position, List<Type> types, Type selectedType, ClassGrouping grouping) {var menu = new GenericMenu();menu.AddItem(new GUIContent("(None)"), selectedType == null, s_OnSelectedTypeName, null);menu.AddSeparator("");for (int i = 0; i < types.Count; ++i) {var type = types[i];string menuLabel = FormatGroupedTypeName(type, grouping);if (string.IsNullOrEmpty(menuLabel))continue;var content = new GUIContent(menuLabel);menu.AddItem(content, type == selectedType, s_OnSelectedTypeName, type);}menu.DropDown(position);}private static string FormatGroupedTypeName(Type type, ClassGrouping grouping) {string name = type.FullName;switch (grouping) {default:case ClassGrouping.None:return name;case ClassGrouping.ByNamespace:return name.Replace('.', '/');case ClassGrouping.ByNamespaceFlat:int lastPeriodIndex = name.LastIndexOf('.');if (lastPeriodIndex != -1)name = name.Substring(0, lastPeriodIndex) + "/" + name.Substring(lastPeriodIndex + 1);return name;case ClassGrouping.ByAddComponentMenu:var addComponentMenuAttributes = type.GetCustomAttributes(typeof(AddComponentMenu), false);if (addComponentMenuAttributes.Length == 1)return ((AddComponentMenu)addComponentMenuAttributes[0]).componentMenu;return "Scripts/" + type.FullName.Replace('.', '/');}}private static int s_SelectionControlID;private static string s_SelectedClassRef;private static readonly GenericMenu.MenuFunction2 s_OnSelectedTypeName = OnSelectedTypeName;private static void OnSelectedTypeName(object userData) {var selectedType = userData as Type;s_SelectedClassRef = ClassTypeReference.GetClassRef(selectedType);var typeReferenceUpdatedEvent = EditorGUIUtility.CommandEvent("TypeReferenceUpdated");EditorWindow.focusedWindow.SendEvent(typeReferenceUpdatedEvent);}#endregionpublic override float GetPropertyHeight(SerializedProperty property, GUIContent label) {return EditorStyles.popup.CalcHeight(GUIContent.none, 0);}public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {DrawTypeSelectionControl(position, property.FindPropertyRelative("_classRef"), label, attribute as ClassTypeConstraintAttribute);}}}
fileFormatVersion: 2guid: bbeadb5396d227843b94f9b779273d08MonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
// Copyright (c) Rotorz Limited. All rights reserved.// Licensed under the MIT license. See LICENSE file in the project root.using System;using UnityEngine;namespace TypeReferences {/// <summary>/// Reference to a class <see cref="System.Type"/> with support for Unity serialization./// </summary>[Serializable]public sealed class ClassTypeReference : ISerializationCallbackReceiver {public static string GetClassRef(Type type) {return type != null? type.FullName + ", " + type.Assembly.GetName().Name: "";}/// <summary>/// Initializes a new instance of the <see cref="ClassTypeReference"/> class./// </summary>public ClassTypeReference() {}/// <summary>/// Initializes a new instance of the <see cref="ClassTypeReference"/> class./// </summary>/// <param name="assemblyQualifiedClassName">Assembly qualified class name.</param>public ClassTypeReference(string assemblyQualifiedClassName) {Type = !string.IsNullOrEmpty(assemblyQualifiedClassName)? Type.GetType(assemblyQualifiedClassName): null;}/// <summary>/// Initializes a new instance of the <see cref="ClassTypeReference"/> class./// </summary>/// <param name="type">Class type.</param>/// <exception cref="System.ArgumentException">/// If <paramref name="type"/> is not a class type./// </exception>public ClassTypeReference(Type type) {Type = type;}[SerializeField]private string _classRef;#region ISerializationCallbackReceiver Membersvoid ISerializationCallbackReceiver.OnAfterDeserialize() {if (!string.IsNullOrEmpty(_classRef)) {_type = System.Type.GetType(_classRef);if (_type == null)Debug.LogWarning(string.Format("'{0}' was referenced but class type was not found.", _classRef));}else {_type = null;}}void ISerializationCallbackReceiver.OnBeforeSerialize() {}#endregionprivate Type _type;/// <summary>/// Gets or sets type of class reference./// </summary>/// <exception cref="System.ArgumentException">/// If <paramref name="value"/> is not a class type./// </exception>public Type Type {get { return _type; }set {if (value != null && !value.IsClass)throw new ArgumentException(string.Format("'{0}' is not a class type.", value.FullName), "value");_type = value;_classRef = GetClassRef(value);}}public static implicit operator string(ClassTypeReference typeReference) {return typeReference._classRef;}public static implicit operator Type(ClassTypeReference typeReference) {return typeReference.Type;}public static implicit operator ClassTypeReference(Type type) {return new ClassTypeReference(type);}public override string ToString() {return Type != null ? Type.FullName : "(None)";}}}
fileFormatVersion: 2guid: 264b275c28ca9ab47b1e70d0cb885f43MonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
// Copyright (c) Rotorz Limited. All rights reserved.// Licensed under the MIT license. See LICENSE file in the project root.using System;using UnityEngine;namespace TypeReferences {/// <summary>/// Indicates how selectable classes should be collated in drop-down menu./// </summary>public enum ClassGrouping {/// <summary>/// No grouping, just show type names in a list; for instance, "Some.Nested.Namespace.SpecialClass"./// </summary>None,/// <summary>/// Group classes by namespace and show foldout menus for nested namespaces; for/// instance, "Some > Nested > Namespace > SpecialClass"./// </summary>ByNamespace,/// <summary>/// Group classes by namespace; for instance, "Some.Nested.Namespace > SpecialClass"./// </summary>ByNamespaceFlat,/// <summary>/// Group classes in the same way as Unity does for its component menu. This/// grouping method must only be used for <see cref="MonoBehaviour"/> types./// </summary>ByAddComponentMenu,}/// <summary>/// Base class for class selection constraints that can be applied when selecting/// a <see cref="ClassTypeReference"/> with the Unity inspector./// </summary>public abstract class ClassTypeConstraintAttribute : PropertyAttribute {private ClassGrouping _grouping = ClassGrouping.ByNamespaceFlat;private bool _allowAbstract = false;/// <summary>/// Gets or sets grouping of selectable classes. Defaults to <see cref="ClassGrouping.ByNamespaceFlat"/>/// unless explicitly specified./// </summary>public ClassGrouping Grouping {get { return _grouping; }set { _grouping = value; }}/// <summary>/// Gets or sets whether abstract classes can be selected from drop-down./// Defaults to a value of <c>false</c> unless explicitly specified./// </summary>public bool AllowAbstract {get { return _allowAbstract; }set { _allowAbstract = value; }}/// <summary>/// Determines whether the specified <see cref="Type"/> satisfies filter constraint./// </summary>/// <param name="type">Type to test.</param>/// <returns>/// A <see cref="bool"/> value indicating if the type specified by <paramref name="type"/>/// satisfies this constraint and should thus be selectable./// </returns>public virtual bool IsConstraintSatisfied(Type type) {return AllowAbstract || (!type.IsAbstract && !type.ContainsGenericParameters);}}/// <summary>/// Constraint that allows selection of classes that extend a specific class when/// selecting a <see cref="ClassTypeReference"/> with the Unity inspector./// </summary>[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]public sealed class ClassExtendsAttribute : ClassTypeConstraintAttribute {/// <summary>/// Initializes a new instance of the <see cref="ClassExtendsAttribute"/> class./// </summary>public ClassExtendsAttribute() {}/// <summary>/// Initializes a new instance of the <see cref="ClassExtendsAttribute"/> class./// </summary>/// <param name="baseType">Type of class that selectable classes must derive from.</param>public ClassExtendsAttribute(Type baseType) {BaseType = baseType;}/// <summary>/// Gets the type of class that selectable classes must derive from./// </summary>public Type BaseType { get; private set; }/// <inheritdoc/>public override bool IsConstraintSatisfied(Type type) {return base.IsConstraintSatisfied(type)&& BaseType.IsAssignableFrom(type) && type != BaseType;}}/// <summary>/// Constraint that allows selection of classes that implement a specific interface/// when selecting a <see cref="ClassTypeReference"/> with the Unity inspector./// </summary>[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]public sealed class ClassImplementsAttribute : ClassTypeConstraintAttribute {/// <summary>/// Initializes a new instance of the <see cref="ClassImplementsAttribute"/> class./// </summary>public ClassImplementsAttribute() {}/// <summary>/// Initializes a new instance of the <see cref="ClassImplementsAttribute"/> class./// </summary>/// <param name="interfaceType">Type of interface that selectable classes must implement.</param>public ClassImplementsAttribute(Type interfaceType) {InterfaceType = interfaceType;}/// <summary>/// Gets the type of interface that selectable classes must implement./// </summary>public Type InterfaceType { get; private set; }/// <inheritdoc/>public override bool IsConstraintSatisfied(Type type) {if (base.IsConstraintSatisfied(type)) {foreach (var interfaceType in type.GetInterfaces())if (interfaceType == InterfaceType)return true;}return false;}}}