Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using UnityEditor;
- using UnityEngine;
- using Sirenix.Utilities.Editor;
- using Sirenix.OdinInspector.Editor;
- using BehaviorDesigner.Editor;
- using BehaviorDesigner.Runtime;
- using MyGame.Gameplay.AI.BehaviorTree;
- namespace MyGame.Gameplay.Agents.Controllers.Editor {
- [CustomEditor(typeof(NPCController))]
- public class NPCControllerEditor : OdinEditor {
- public override void OnInspectorGUI() {
- base.OnInspectorGUI();
- if (!GUILayout.Button("Update Behavior Tree Mapped Properties", SirenixGUIStyles.Button)) { return; }
- NPCController npcController = (NPCController)target;
- BehaviorTree[] behaviorTrees = npcController.GetComponents<BehaviorTree>();
- for (int i = 0; i < behaviorTrees.Length; i++) {
- Debug.LogWarningFormat("Updating Behavior Tree: {0}", i);
- BehaviorTree behaviorTree = behaviorTrees[i];
- BehaviorSource behaviorSource = behaviorTree.GetBehaviorSource();
- BehaviorSource externalBehaviorSource = behaviorTree.ExternalBehavior != null ? behaviorTree.ExternalBehavior.GetBehaviorSource() : null;
- UpdateBehaviorTreeMappedProperties<NPCController>(npcController.gameObject, behaviorSource, externalBehaviorSource);
- if (behaviorTree.ExternalBehavior != null) { EditorUtility.SetDirty(behaviorTree.ExternalBehavior); }
- EditorUtility.SetDirty(behaviorTree);
- }
- EditorUtility.SetDirty(npcController.gameObject);
- }
- static void UpdateBehaviorTreeMappedProperties<T>(GameObject gameObject, BehaviorSource behaviorSource, BehaviorSource externalBehaviorSource) {
- Type type = typeof(T);
- PropertyInfo[] properties = type.GetProperties();
- string propertyFormat = type.FullName + "/{0}";
- bool hasExternal = externalBehaviorSource != null;
- List<SharedVariable> sharedVariables = behaviorSource.GetAllVariables() ?? new List<SharedVariable>();
- List<SharedVariable> externalSharedVariables = hasExternal ? (externalBehaviorSource.GetAllVariables() ?? new List<SharedVariable>()) : null;
- List<PropertyInfo> mappedProperties = new List<PropertyInfo>();
- List<string> newPropertyNames = new List<string>();
- foreach (PropertyInfo property in properties) {
- MappedPropertyAttribute attribute = (MappedPropertyAttribute)property.GetCustomAttributes(typeof(MappedPropertyAttribute), false).FirstOrDefault();
- if (attribute == null) { continue; }
- if (!UpdateSharedVariable(gameObject, propertyFormat, sharedVariables, newPropertyNames, property, true)) { continue; }
- if (hasExternal) { UpdateSharedVariable(gameObject, propertyFormat, externalSharedVariables, newPropertyNames, property, false); }
- mappedProperties.Add(property);
- }
- string[] unmappedSharedVariableNames = sharedVariables.Where(variable => variable.Name != "NPCController" && mappedProperties.All(mappedProperty => mappedProperty.Name != variable.Name)).Select(variable => variable.Name).ToArray();
- if (hasExternal) { SerializeBehaviorTree(externalBehaviorSource, SortSharedVariablesByMappedProperties(externalSharedVariables, mappedProperties, unmappedSharedVariableNames)); }
- SerializeBehaviorTree(behaviorSource, SortSharedVariablesByMappedProperties(sharedVariables, mappedProperties, unmappedSharedVariableNames));
- if (newPropertyNames.Count > 0) { Debug.LogFormat("{0} new properties created: {1}", newPropertyNames.Count, string.Join(", ", newPropertyNames.ToArray())); }
- if (unmappedSharedVariableNames.Length > 0) { Debug.LogFormat("Unmapped shared variables: {0}", string.Join(", ", unmappedSharedVariableNames)); }
- }
- static bool UpdateSharedVariable(GameObject gameObject, string propertyFormat, List<SharedVariable> sharedVariables, List<string> newPropertyNames, PropertyInfo property, bool isPropertyMapped) {
- SharedVariable sharedVariable = sharedVariables.FirstOrDefault(variable => variable.Name == property.Name);
- bool isNew = sharedVariable == null;
- if (isNew) {
- if (!CreateSharedVariable(property, ref sharedVariable)) { return false; }
- sharedVariables.Add(sharedVariable);
- if (!newPropertyNames.Contains(property.Name)) { newPropertyNames.Add(property.Name); };
- } else {
- if (!IsSharedVariableForPropertyType(sharedVariable.GetType(), property.PropertyType)) {
- Debug.LogErrorFormat("Type mismatch on property {0}: MappedProperty type: {1}, SharedVariable type: {2}", property.Name, property.PropertyType, sharedVariable.GetType());
- return false;
- }
- }
- if (isPropertyMapped) {
- sharedVariable.PropertyMapping = string.Format(propertyFormat, property.Name);
- sharedVariable.PropertyMappingOwner = gameObject;
- }
- return true;
- }
- static bool CreateSharedVariable(PropertyInfo property, ref SharedVariable sharedVariable) {
- Type sharedVariableType = GetSharedVariableForPropertyType(property.PropertyType);
- if (sharedVariableType == null) {
- Debug.LogErrorFormat("Cannot find SharedVariable class for {0} (property type: {1})", property.Name, property.PropertyType);
- return false;
- }
- sharedVariable = (SharedVariable)Activator.CreateInstance(sharedVariableType);
- sharedVariable.IsShared = true;
- sharedVariable.IsGlobal = false;
- sharedVariable.IsDynamic = false;
- sharedVariable.Name = property.Name;
- return true;
- }
- static Type GetSharedVariableForPropertyType(Type propertyType) {
- Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
- return assemblies.Select(assembly => assembly.GetTypes().FirstOrDefault(type => IsSharedVariableForPropertyType(type, propertyType)))
- .FirstOrDefault(sharedType => sharedType != null);
- }
- static bool IsSharedVariableForPropertyType(Type type, Type propertyType) {
- Type baseType = type.BaseType;
- return baseType != null &&
- baseType.IsGenericType &&
- baseType.GetGenericTypeDefinition() == typeof(SharedVariable<>) &&
- baseType.GetGenericArguments()[0] == propertyType;
- }
- static List<SharedVariable> SortSharedVariablesByMappedProperties(List<SharedVariable> sharedVariables, List<PropertyInfo> mappedProperties, string[] unmappedSharedVariableNames) {
- return sharedVariables.OrderBy(variable => variable.Name != "NPCController")
- .ThenBy(variable => unmappedSharedVariableNames.Contains(variable.Name))
- .ThenBy(variable => mappedProperties.FindIndex(mappedProperty => mappedProperty.Name == variable.Name))
- .ToList();
- }
- static void SerializeBehaviorTree(BehaviorSource behaviorSource, List<SharedVariable> variables) {
- behaviorSource.SetAllVariables(variables);
- behaviorSource.HasSerialized = false;
- if (BehaviorDesignerPreferences.GetBool(BDPreferences.BinarySerialization)) {
- BinarySerialization.Save(behaviorSource);
- } else {
- JSONSerialization.Save(behaviorSource);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement