private System.Type GetComponentType(ComponentInfo info)
        {
            var asms = System.AppDomain.CurrentDomain.GetAssemblies();

            foreach (var asm in asms)
            {
                var type = asm.GetTypes()
                           .Where(x => typeof(IStructComponentBase).IsAssignableFrom(x))
                           .Where(x => x.FullName.EndsWith(info.name)).OrderByDescending(x => x.Name).FirstOrDefault();
                if (type != null)
                {
                    return(type);
                }
            }

            return(null);
        }
        public object CreateComponentInstance(ME.ECS.DataConfigs.DataConfig config, ComponentInfo componentInfo, bool allValuesAreNull)
        {
            var field = config.GetType().GetField(componentInfo.name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

            if (field != null)
            {
                return(config);
            }

            var componentType = this.generator.GetComponentType(componentInfo);

            if (componentType == null)
            {
                if (allValuesAreNull == false)
                {
                    this.generator.LogError($"Component type `{componentInfo.name}` was not found");
                }
                return(null);
            }
            var instance = System.Activator.CreateInstance(componentType);

            return(instance);
        }
        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 ParseComponentField(ref bool allValuesAreNull, object instance, System.Type componentType, ComponentInfo componentInfo, string fieldName, string data)
        {
            var field = componentType.GetField(fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

            if (field == null)
            {
                this.generator.LogError($"Field `{fieldName}` was not found in component `{componentInfo.name}`");
                return;
            }

            var dataStr = data;

            if (string.IsNullOrEmpty(dataStr) == false)
            {
                allValuesAreNull = false;
            }
            else
            {
                return;
            }

            var result = this.generator.TryToConvert(dataStr, componentType, field.Name, field.FieldType, out var val);

            if (result == false)
            {
                this.generator.LogError($"Data `{dataStr}` couldn't been parsed because parser was not found for type `{field.FieldType}`. If you need to store custom struct type - use JSON format.");
            }
            else
            {
                field.SetValue(instance, val);
            }
        }
 public abstract void ParseComponentField(ref bool allValuesAreNull, object instance, System.Type componentType, ComponentInfo componentInfo, string fieldName, string data);
 public abstract object CreateComponentInstance(ME.ECS.DataConfigs.DataConfig config, ComponentInfo componentInfo, bool allValuesAreNull);