Advertisement
Guest User

Untitled

a guest
Jul 10th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.77 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using Sirenix.Utilities.Editor;
  8. using Sirenix.OdinInspector.Editor;
  9. using BehaviorDesigner.Editor;
  10. using BehaviorDesigner.Runtime;
  11. using MyGame.Gameplay.AI.BehaviorTree;
  12.  
  13. namespace MyGame.Gameplay.Agents.Controllers.Editor {
  14.     [CustomEditor(typeof(NPCController))]
  15.     public class NPCControllerEditor : OdinEditor {
  16.         public override void OnInspectorGUI() {
  17.             base.OnInspectorGUI();
  18.  
  19.             if (!GUILayout.Button("Update Behavior Tree Mapped Properties", SirenixGUIStyles.Button)) { return; }
  20.  
  21.             NPCController npcController = (NPCController)target;
  22.             BehaviorTree[] behaviorTrees = npcController.GetComponents<BehaviorTree>();
  23.  
  24.             for (int i = 0; i < behaviorTrees.Length; i++) {
  25.                 Debug.LogWarningFormat("Updating Behavior Tree: {0}", i);
  26.  
  27.                 BehaviorTree behaviorTree = behaviorTrees[i];
  28.                 BehaviorSource behaviorSource = behaviorTree.GetBehaviorSource();
  29.                 BehaviorSource externalBehaviorSource = behaviorTree.ExternalBehavior != null ? behaviorTree.ExternalBehavior.GetBehaviorSource() : null;
  30.  
  31.                 UpdateBehaviorTreeMappedProperties<NPCController>(npcController.gameObject, behaviorSource, externalBehaviorSource);
  32.  
  33.                 if (behaviorTree.ExternalBehavior != null) { EditorUtility.SetDirty(behaviorTree.ExternalBehavior); }
  34.                 EditorUtility.SetDirty(behaviorTree);
  35.             }
  36.  
  37.             EditorUtility.SetDirty(npcController.gameObject);
  38.         }
  39.  
  40.         static void UpdateBehaviorTreeMappedProperties<T>(GameObject gameObject, BehaviorSource behaviorSource, BehaviorSource externalBehaviorSource) {
  41.             Type type = typeof(T);
  42.             PropertyInfo[] properties = type.GetProperties();
  43.             string propertyFormat = type.FullName + "/{0}";
  44.  
  45.             bool hasExternal = externalBehaviorSource != null;
  46.             List<SharedVariable> sharedVariables = behaviorSource.GetAllVariables() ?? new List<SharedVariable>();
  47.             List<SharedVariable> externalSharedVariables = hasExternal ? (externalBehaviorSource.GetAllVariables() ?? new List<SharedVariable>()) : null;
  48.             List<PropertyInfo> mappedProperties = new List<PropertyInfo>();
  49.             List<string> newPropertyNames = new List<string>();
  50.  
  51.             foreach (PropertyInfo property in properties) {
  52.                 MappedPropertyAttribute attribute = (MappedPropertyAttribute)property.GetCustomAttributes(typeof(MappedPropertyAttribute), false).FirstOrDefault();
  53.  
  54.                 if (attribute == null) { continue; }
  55.  
  56.                 if (!UpdateSharedVariable(gameObject, propertyFormat, sharedVariables, newPropertyNames, property, true)) { continue; }
  57.                 if (hasExternal) { UpdateSharedVariable(gameObject, propertyFormat, externalSharedVariables, newPropertyNames, property, false); }
  58.  
  59.                 mappedProperties.Add(property);
  60.             }
  61.  
  62.             string[] unmappedSharedVariableNames = sharedVariables.Where(variable => variable.Name != "NPCController" && mappedProperties.All(mappedProperty => mappedProperty.Name != variable.Name)).Select(variable => variable.Name).ToArray();
  63.  
  64.             if (hasExternal) { SerializeBehaviorTree(externalBehaviorSource, SortSharedVariablesByMappedProperties(externalSharedVariables, mappedProperties, unmappedSharedVariableNames)); }
  65.             SerializeBehaviorTree(behaviorSource, SortSharedVariablesByMappedProperties(sharedVariables, mappedProperties, unmappedSharedVariableNames));
  66.  
  67.             if (newPropertyNames.Count > 0) { Debug.LogFormat("{0} new properties created: {1}", newPropertyNames.Count, string.Join(", ", newPropertyNames.ToArray())); }
  68.             if (unmappedSharedVariableNames.Length > 0) { Debug.LogFormat("Unmapped shared variables: {0}", string.Join(", ", unmappedSharedVariableNames)); }
  69.         }
  70.  
  71.         static bool UpdateSharedVariable(GameObject gameObject, string propertyFormat, List<SharedVariable> sharedVariables, List<string> newPropertyNames, PropertyInfo property, bool isPropertyMapped) {
  72.             SharedVariable sharedVariable = sharedVariables.FirstOrDefault(variable => variable.Name == property.Name);
  73.             bool isNew = sharedVariable == null;
  74.  
  75.             if (isNew) {
  76.                 if (!CreateSharedVariable(property, ref sharedVariable)) { return false; }
  77.  
  78.                 sharedVariables.Add(sharedVariable);
  79.                 if (!newPropertyNames.Contains(property.Name)) { newPropertyNames.Add(property.Name); };
  80.             } else {
  81.                 if (!IsSharedVariableForPropertyType(sharedVariable.GetType(), property.PropertyType)) {
  82.                     Debug.LogErrorFormat("Type mismatch on property {0}: MappedProperty type: {1}, SharedVariable type: {2}", property.Name, property.PropertyType, sharedVariable.GetType());
  83.  
  84.                     return false;
  85.                 }
  86.             }
  87.  
  88.             if (isPropertyMapped) {
  89.                 sharedVariable.PropertyMapping = string.Format(propertyFormat, property.Name);
  90.                 sharedVariable.PropertyMappingOwner = gameObject;
  91.             }
  92.  
  93.             return true;
  94.         }
  95.  
  96.         static bool CreateSharedVariable(PropertyInfo property, ref SharedVariable sharedVariable) {
  97.             Type sharedVariableType = GetSharedVariableForPropertyType(property.PropertyType);
  98.  
  99.             if (sharedVariableType == null) {
  100.                 Debug.LogErrorFormat("Cannot find SharedVariable class for {0} (property type: {1})", property.Name, property.PropertyType);
  101.  
  102.                 return false;
  103.             }
  104.  
  105.             sharedVariable = (SharedVariable)Activator.CreateInstance(sharedVariableType);
  106.             sharedVariable.IsShared = true;
  107.             sharedVariable.IsGlobal = false;
  108.             sharedVariable.IsDynamic = false;
  109.             sharedVariable.Name = property.Name;
  110.  
  111.             return true;
  112.         }
  113.  
  114.         static Type GetSharedVariableForPropertyType(Type propertyType) {
  115.             Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  116.  
  117.             return assemblies.Select(assembly => assembly.GetTypes().FirstOrDefault(type => IsSharedVariableForPropertyType(type, propertyType)))
  118.                              .FirstOrDefault(sharedType => sharedType != null);
  119.         }
  120.  
  121.         static bool IsSharedVariableForPropertyType(Type type, Type propertyType) {
  122.             Type baseType = type.BaseType;
  123.  
  124.             return baseType != null &&
  125.                    baseType.IsGenericType &&
  126.                    baseType.GetGenericTypeDefinition() == typeof(SharedVariable<>) &&
  127.                    baseType.GetGenericArguments()[0] == propertyType;
  128.         }
  129.  
  130.         static List<SharedVariable> SortSharedVariablesByMappedProperties(List<SharedVariable> sharedVariables, List<PropertyInfo> mappedProperties, string[] unmappedSharedVariableNames) {
  131.             return sharedVariables.OrderBy(variable => variable.Name != "NPCController")
  132.                                   .ThenBy(variable => unmappedSharedVariableNames.Contains(variable.Name))
  133.                                   .ThenBy(variable => mappedProperties.FindIndex(mappedProperty => mappedProperty.Name == variable.Name))
  134.                                   .ToList();
  135.         }
  136.  
  137.         static void SerializeBehaviorTree(BehaviorSource behaviorSource, List<SharedVariable> variables) {
  138.             behaviorSource.SetAllVariables(variables);
  139.             behaviorSource.HasSerialized = false;
  140.  
  141.             if (BehaviorDesignerPreferences.GetBool(BDPreferences.BinarySerialization)) {
  142.                 BinarySerialization.Save(behaviorSource);
  143.             } else {
  144.                 JSONSerialization.Save(behaviorSource);
  145.             }
  146.         }
  147.     }
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement