public ME.ECS.DataConfigs.DataConfig CreateConfigInstance(ConfigInfo configInfo)
        {
            if (string.IsNullOrEmpty(configInfo.comment) == false)
            {
                System.Type typeFound = null;
                foreach (var asm in System.AppDomain.CurrentDomain.GetAssemblies())
                {
                    var type = asm.GetTypes().FirstOrDefault(y => y.Name == configInfo.comment && typeof(ME.ECS.DataConfigs.DataConfig).IsAssignableFrom(y) == true);
                    if (type != null)
                    {
                        typeFound = type;
                        break;
                    }
                }
                ;

                if (typeFound != null)
                {
                    return((ME.ECS.DataConfigs.DataConfig)ME.ECS.DataConfigs.DataConfig.CreateInstance(typeFound));
                }
            }

            return(ME.ECS.DataConfigs.DataConfig.CreateInstance <ME.ECS.DataConfigs.DataConfig>());
        }
        public void UpdateConfig(string path, ConfigInfo configInfo)
        {
            var config = UnityEditor.AssetDatabase.LoadAssetAtPath <ME.ECS.DataConfigs.DataConfig>(path);

            config.name             = configInfo.name;
            config.structComponents = new IStructComponentBase[configInfo.data.Count];
            var templates = configInfo.templates;

            if (templates != null)
            {
                var templatePaths = UnityEditor.AssetDatabase.FindAssets("t:DataConfigTemplate").Select(UnityEditor.AssetDatabase.GUIDToAssetPath).ToArray();
                foreach (var template in templates)
                {
                    var templateName = template.Trim();
                    if (string.IsNullOrEmpty(templateName) == true)
                    {
                        continue;
                    }

                    var found = false;
                    foreach (var templatePath in templatePaths)
                    {
                        if (System.IO.Path.GetFileNameWithoutExtension(templatePath) == templateName)
                        {
                            var t = UnityEditor.AssetDatabase.LoadAssetAtPath <ME.ECS.DataConfigs.DataConfigTemplate>(templatePath);
                            config.AddTemplate(t);
                            found = true;
                            break;
                        }
                    }

                    if (found == false)
                    {
                        this.LogWarning($"Template `{templateName}` was not found");
                    }
                }
            }

            var i = 0;

            foreach (var kv in configInfo.data)
            {
                var componentInfo = kv.Key;
                var data          = kv.Value;
                var componentType = this.GetComponentType(componentInfo);
                if (componentType == null)
                {
                    this.LogError($"Component type `{componentInfo.name}` was not found");
                    continue;
                }

                var instance         = System.Activator.CreateInstance(componentType);
                var allValuesAreNull = true;
                var isTag            = false;
                if (componentInfo.fields.Count == 1 && string.IsNullOrEmpty(componentInfo.fields[0]) == true)
                {
                    // tag
                    isTag = true;
                    if (string.IsNullOrEmpty(data[0]) == false)
                    {
                        allValuesAreNull = false;
                    }
                }

                if (isTag == false)
                {
                    for (int j = 0; j < componentInfo.fields.Count; ++j)
                    {
                        var fieldName = componentInfo.fields[j];
                        var field     = componentType.GetField(fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                        if (field == null)
                        {
                            this.LogError($"Field `{fieldName}` was not found in component `{componentInfo.name}`");
                            continue;
                        }

                        var dataStr = data[j];
                        if (string.IsNullOrEmpty(dataStr) == false)
                        {
                            allValuesAreNull = false;
                        }
                        else
                        {
                            continue;
                        }

                        var result = this.TryToConvert(dataStr, componentType, field.Name, field.FieldType, out var val);
                        if (result == false)
                        {
                            this.LogError($"Data `{dataStr}` couldn't been parsed because deserializer was not found for type `{field.FieldType}`. If you need to store custom struct type - use JSON format.");
                        }
                        else
                        {
                            field.SetValue(instance, val);
                        }
                    }
                }

                if (allValuesAreNull == true)
                {
                    var list = config.structComponents.ToList();
                    list.RemoveAt(i);
                    config.structComponents = list.ToArray();
                    --i;
                }
                else
                {
                    config.structComponents[i] = (IStructComponentBase)instance;
                }

                ++i;
            }

            config.Save();
        }
        public DataConfigGenerator(int currentVersion, string csvData, HashSet <ConfigInfo> visitedConfigs = null, HashSet <string> visitedFiles = null)
        {
            this.visitedConfigs = visitedConfigs;
            this.visitedFiles   = visitedFiles;
            this.logs           = new List <LogItem>();

            System.Globalization.CultureInfo.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;

            this.allConfigs = UnityEditor.AssetDatabase.FindAssets("t:DataConfig").Where(x => {
                var path  = UnityEditor.AssetDatabase.GUIDToAssetPath(x);
                var asset = UnityEditor.AssetDatabase.LoadAssetAtPath <ME.ECS.DataConfigs.DataConfig>(path);
                if (asset is ME.ECS.DataConfigs.DataConfigTemplate)
                {
                    return(false);
                }
                return(true);
            }).Select(UnityEditor.AssetDatabase.GUIDToAssetPath).ToList();

            var reader = new CsvReader(new System.IO.StringReader(csvData));

            if (reader.Read() == false)
            {
                this.status = Status.Error;
                return;
            }

            var destinationDirectory = this.configsDirectory;

            if (System.IO.Directory.Exists(destinationDirectory) == false)
            {
                System.IO.Directory.CreateDirectory(destinationDirectory);
            }

            int.TryParse(reader[0], out var version);
            if (version > currentVersion)
            {
                this.version = version;
                if (currentVersion >= 0)
                {
                    this.Log($"Update version: {currentVersion} => {version}");
                }
                else
                {
                    this.Log($"Update version to {version}");
                }
            }
            else
            {
                this.Log($"Sheet is up to date (version: {currentVersion}).");
                this.status = Status.UpToDate;
                return;
            }

            //var fieldsCount = reader.FieldsCount;
            //UnityEngine.Debug.Log("Fields count: " + fieldsCount);

            var components = new Dictionary <int, ComponentInfo>();
            var prevOffset = -1;

            for (int i = 3; i < reader.FieldsCount; ++i)
            {
                var name = reader[i];
                if (string.IsNullOrEmpty(name) == true)
                {
                    continue;
                }

                var item = new ComponentInfo()
                {
                    name   = name,
                    offset = i,
                    length = reader.FieldsCount - i,
                    fields = new List <string>(),
                };
                if (components.ContainsValue(item) == false)
                {
                    if (prevOffset >= 0)
                    {
                        var last = components[prevOffset];
                        last.length            = item.offset - last.offset;
                        components[prevOffset] = last;
                    }

                    components.Add(i, item);
                    prevOffset = i;
                    //UnityEngine.Debug.Log("Component: " + name);
                }
                else
                {
                    this.LogError($"Duplicate entry `{name}`");
                }
            }

            // This line contains component field names
            reader.Read();
            foreach (var kv in components)
            {
                var info = kv.Value;
                //UnityEngine.Debug.Log("Read fields for: " + info.name + ", length: " + info.length);
                for (int j = 0; j < info.length; ++j)
                {
                    var fieldName = reader[info.offset + j];
                    info.fields.Add(fieldName);
                    //UnityEngine.Debug.Log("Field name: " + fieldName);
                }
            }

            // Other lines contain data configs
            var configs = new List <ConfigInfo>();

            while (reader.Read() == true)
            {
                var templates  = reader[1];
                var configName = reader[2];
                var item       = new ConfigInfo {
                    name      = configName,
                    templates = templates.Split(','),
                    data      = new Dictionary <ComponentInfo, List <string> >(),
                };
                foreach (var kv in components)
                {
                    var componentInfo = kv.Value;
                    var list          = new List <string>();

                    //UnityEngine.Debug.Log("Add component: " + componentInfo.name);
                    for (int j = 0; j < componentInfo.length; ++j)
                    {
                        var data = reader[componentInfo.offset + j];
                        list.Add(data);
                        //UnityEngine.Debug.Log("Set component field: " + componentInfo.fields[j] + " value " + data);
                    }

                    item.data.Add(componentInfo, list);
                }

                configs.Add(item);
            }

            this.configInfos = configs;

            this.status = Status.OK;
        }
        public void UpdateConfig(string path, ConfigInfo configInfo)
        {
            var config = UnityEditor.AssetDatabase.LoadAssetAtPath <ME.ECS.DataConfigs.DataConfig>(path);

            config.name             = configInfo.name;
            config.structComponents = new IComponentBase[configInfo.data.Count];

            var i = 0;

            foreach (var kv in configInfo.data)
            {
                var componentInfo = kv.Key;
                var data          = kv.Value;

                bool isTag            = componentInfo.fields.Count == 1 && string.IsNullOrEmpty(componentInfo.fields[0]) == true;
                var  allValuesAreNull = true;
                for (int j = 0; j < componentInfo.fields.Count; ++j)
                {
                    if (string.IsNullOrEmpty(data[j]) == false)
                    {
                        allValuesAreNull = false;
                        break;
                    }
                }

                var instance = this.behaviour.CreateComponentInstance(config, componentInfo, allValuesAreNull);
                if (instance == null)
                {
                    continue;
                }

                if (isTag == false)
                {
                    for (int j = 0; j < componentInfo.fields.Count; ++j)
                    {
                        var fieldName = componentInfo.fields[j];
                        this.behaviour.ParseComponentField(ref allValuesAreNull, instance, instance.GetType(), componentInfo, fieldName, data[j]);
                    }
                }

                if (instance is IComponentBase)
                {
                    if (allValuesAreNull == true)
                    {
                        var list = config.structComponents.ToList();
                        list.RemoveAt(i);
                        config.structComponents = list.ToArray();
                        --i;
                    }
                    else
                    {
                        config.structComponents[i] = (IComponentBase)instance;
                    }
                }

                ++i;
            }

            var templates = configInfo.templates;

            if (templates != null)
            {
                var templatePaths = UnityEditor.AssetDatabase.FindAssets("t:DataConfigTemplate").Select(UnityEditor.AssetDatabase.GUIDToAssetPath).ToArray();
                foreach (var template in templates)
                {
                    var templateName = template.Trim();
                    if (string.IsNullOrEmpty(templateName) == true)
                    {
                        continue;
                    }

                    var found = false;
                    foreach (var templatePath in templatePaths)
                    {
                        if (System.IO.Path.GetFileNameWithoutExtension(templatePath) == templateName)
                        {
                            var t    = UnityEditor.AssetDatabase.LoadAssetAtPath <ME.ECS.DataConfigs.DataConfigTemplate>(templatePath);
                            var guid = UnityEditor.AssetDatabase.AssetPathToGUID(templatePath);

                            t.UnUse(config);
                            if (config.templates == null)
                            {
                                config.templates = new string[0];
                            }
                            var tFound = false;
                            foreach (var temp in config.templates)
                            {
                                if (temp == guid)
                                {
                                    tFound = true;
                                    break;
                                }
                            }

                            if (tFound == false)
                            {
                                System.Array.Resize(ref config.templates, config.templates.Length + 1);
                                config.templates[config.templates.Length - 1] = guid;
                            }

                            config.AddTemplate(t);
                            found = true;

                            break;
                        }
                    }

                    if (found == false)
                    {
                        this.LogWarning($"Template `{templateName}` was not found");
                    }
                }
            }

            config.Save();
        }
 public abstract ME.ECS.DataConfigs.DataConfig CreateConfigInstance(ConfigInfo configInfo);