public static EmulatorConfiguration UpdateMasterGamelistFromEmulatorConfiguration(EmulatorConfiguration emulatorConfiguration, UnityEngine.UI.Slider slider = null)
        {
            List<ModelProperties> masterGamelist;
            Debug.Log("Updating emulator configuration " + emulatorConfiguration.emulator.descriptiveName + " with id " + emulatorConfiguration.emulator.id);
            // Mame xml?
            string fileName = emulatorConfiguration.emulator.id + ".xml";
            string filePath = ArcadeManager.applicationPath + "/3darcade~/Configuration/MasterGamelists/mame/";
            if (FileManager.FileExists(filePath, fileName) != null)
            {
                var md5 = FileManager.FileMD5Changed(emulatorConfiguration.md5MasterGamelist, filePath, fileName);
                if (md5 != null)
                {
                    masterGamelist = GetGamelistFromMameXML(filePath, fileName, emulatorConfiguration.emulator, slider);
                    if (masterGamelist != null)
                    {
                        emulatorConfiguration.lastMasterGamelistUpdate = DateTime.Now.ToString();
                        emulatorConfiguration.masterGamelist = masterGamelist;
                        emulatorConfiguration.md5MasterGamelist = md5;
                        Debug.Log("MasterGamelist updated from mame xml");
                    }
                    else
                    {
                        Debug.Log("MasterGamelist update failed from mame xml");
                    }
                }
                else
                {
                    Debug.Log("MasterGamelist is current, updated from mame xml is not needed");
                }
                return emulatorConfiguration;
            }

            // Hyperspin xml?
            fileName = emulatorConfiguration.emulator.id + ".xml";
            filePath = ArcadeManager.applicationPath + "/3darcade~/Configuration/MasterGamelists/hyperspin/";
            if (FileManager.FileExists(filePath, fileName) != null)
            {
                var md5 = FileManager.FileMD5Changed(emulatorConfiguration.md5MasterGamelist, filePath, fileName);
                if (md5 != null)
                {
                    masterGamelist = GetGamelistFromHyperspinXML(filePath, fileName, emulatorConfiguration.emulator, slider);
                    if (masterGamelist != null)
                    {
                        emulatorConfiguration.lastMasterGamelistUpdate = DateTime.Now.ToString();
                        emulatorConfiguration.masterGamelist = masterGamelist;
                        emulatorConfiguration.md5MasterGamelist = md5;
                        Debug.Log("MasterGamelist updated from atf");
                    }
                    else
                    {
                        Debug.Log("MasterGamelist update failed from hyperpsin xml");
                    }
                }
                else
                {
                    Debug.Log("MasterGamelist is current, updated from hyperspin xml is not needed");
                }
                return emulatorConfiguration;
            }

            // 3darcade atf?
            fileName = emulatorConfiguration.emulator.id + ".atf";
            filePath = ArcadeManager.applicationPath + "/3darcade~/Configuration/MasterGamelists/atf/";
            if (FileManager.FileExists(filePath, fileName) != null)
            {
                var md5 = FileManager.FileMD5Changed(emulatorConfiguration.md5MasterGamelist, filePath, fileName);
                if (md5 != null)
                {
                    masterGamelist = GetGamelistFrom3DArcadeATF(filePath, fileName, emulatorConfiguration.emulator, slider);
                    if (masterGamelist != null)
                    {
                        emulatorConfiguration.lastMasterGamelistUpdate = DateTime.Now.ToString();
                        emulatorConfiguration.masterGamelist = masterGamelist;
                        emulatorConfiguration.md5MasterGamelist = md5;
                        Debug.Log("MasterGamelist updated from 3darcade atf");
                    }
                    else
                    {
                        Debug.Log("MasterGamelist update failed from 3darcade atf");
                    }
                }
                else
                {
                    Debug.Log("MasterGamelist is current, updated from 3darcade atf is not needed");
                }
                return emulatorConfiguration;
            }

            // from folder?
            string gamePath = emulatorConfiguration.emulator.gamePath.Trim();
            filePath = ArcadeManager.applicationPath + gamePath;
           
          
            // if (FileManager.DirectoryExists(filePath) != null)
            //  {
            masterGamelist = GetGamelistFromGamePath(filePath, emulatorConfiguration.emulator, slider);
                if (masterGamelist != null)
                {
                    emulatorConfiguration.lastMasterGamelistUpdate = DateTime.Now.ToString();
                    emulatorConfiguration.masterGamelist = masterGamelist;
                    emulatorConfiguration.md5MasterGamelist = "";
                    Debug.Log("MasterGamelist updated from game path");
                    return emulatorConfiguration;
                }
                else
                {
                    Debug.Log("MasterGamelist update failed from game path");
                }
          //  }
            Debug.Log("MasterGamelist not found");
            return emulatorConfiguration;
        }
        public GameObject AddModelToArcade(ModelType modelType, ModelProperties modelProperties, ArcadeType arcadeType, bool addTrigger)
        {
            AssetBundle tAsset;
            GameObject  tObj;

            tAsset = GetExternalModel(modelProperties.model);
            if (tAsset != null)
            {
                return(addExternalModel(tAsset));
            }
            tObj = GetInternalModel(modelProperties.model);
            if (tObj != null)
            {
                return(AddInternalModel(tObj));
            }
            tAsset = GetExternalModel(modelProperties.id);
            if (tAsset != null)
            {
                return(addExternalModel(tAsset));
            }
            tObj = GetInternalModel(modelProperties.id);
            if (tObj != null)
            {
                return(AddInternalModel(tObj));
            }
            tAsset = GetExternalModel(modelProperties.idParent);
            if (tAsset != null)
            {
                return(addExternalModel(tAsset));
            }
            tObj = GetInternalModel(modelProperties.idParent);
            if (tObj != null)
            {
                return(AddInternalModel(tObj));
            }

            // Now check for defaultmodels
            // First defaultmodel filters in the emulator
            List <EmulatorConfiguration> emulatorConfiguration = ArcadeManager.emulatorsConfigurationList.Where(x => x.emulator.id == modelProperties.emulator).ToList();

            if (emulatorConfiguration.Count > 1)
            {
                List <DefaultModelFilter> defaultModelFilters = emulatorConfiguration[0].emulator.defaultModelFilters;
                foreach (DefaultModelFilter defaultModel in defaultModelFilters)
                {
                    bool success = true;
                    foreach (ModelFilter filter in defaultModel.modelFilters)
                    {
                        success &= FilterModel(filter, modelProperties);
                    }
                    if (success)
                    {
                        tAsset = GetExternalModel(defaultModel.model);
                        if (tAsset != null)
                        {
                            return(addExternalModel(tAsset));
                        }
                        tObj = GetInternalModel(defaultModel.model);
                        if (tObj != null)
                        {
                            return(AddInternalModel(tObj));
                        }
                    }
                }
            }

            // Generic defaultmodel filters
            if (arcadeManager.generalConfiguration != null)
            {
                List <DefaultModelFilter> defaultModelFilters = arcadeManager.generalConfiguration.defaultModelFilters;
                foreach (DefaultModelFilter defaultModel in defaultModelFilters)
                {
                    bool success = true;
                    foreach (ModelFilter filter in defaultModel.modelFilters)
                    {
                        success &= FilterModel(filter, modelProperties);
                    }
                    if (success)
                    {
                        tAsset = GetExternalModel(defaultModel.model);
                        if (tAsset != null)
                        {
                            return(addExternalModel(tAsset));
                        }
                        tObj = GetInternalModel(defaultModel.model);
                        if (tObj != null)
                        {
                            return(AddInternalModel(tObj));
                        }
                    }
                }
            }

            // defaultmodel
            string[]      defaultModels = { "default70hor", "default70vert", "default80hor", "default80vert", "default90hor", "default90vert" };
            System.Random rnd           = new System.Random();
            tObj = GetInternalModel(defaultModels[rnd.Next(defaultModels.Length)]);
            if (tObj != null)
            {
                return(AddInternalModel(tObj));
            }

            return(null);

            AssetBundle GetExternalModel(string modelName)
            {
                List <AssetBundle> prefab = ArcadeManager.modelAssets.Where(x => x.name == modelName).ToList();

                if (prefab.Count < 1)
                {
                    var file = FileManager.FileExists(ArcadeManager.applicationPath + "/3darcade~/Configuration/Assets/" + ArcadeManager.currentOS.ToString() + "/" + modelType.ToString() + "s/", modelName + ".unity3d");
                    if (file != null)
                    {
                        var asset = AssetBundle.LoadFromFile(file);
                        if (asset != null && asset.name != null && asset.name != "")
                        {
                            ArcadeManager.modelAssets.Add(asset);
                            prefab.Add(asset);
                            return(asset);
                        }
                    }
                }
                return(prefab.Count == 1 ? prefab[0] : null);
            }

            GameObject addExternalModel(AssetBundle asset)
            {
                GameObject me    = asset.LoadAsset(asset.name) as GameObject;
                GameObject child = UnityEngine.Object.Instantiate(me);

                return(AddModel(child, modelProperties));
            }

            GameObject GetInternalModel(string modelName)
            {
                GameObject obj = (UnityEngine.GameObject)Resources.Load(modelType.ToString() + "s/" + modelName, typeof(GameObject));

                // TODO: NBNB remove this hack to be able to use gamelist models as prop models
                if (obj == null)
                {
                    obj = (UnityEngine.GameObject)Resources.Load(ModelType.Game.ToString() + "s/" + modelName, typeof(GameObject));
                }
                return(obj == null ? null : obj);
            }

            GameObject AddInternalModel(GameObject obj)
            {
                GameObject child = UnityEngine.Object.Instantiate(obj);

                return(AddModel(child, modelProperties));
            }

            GameObject AddModel(GameObject obj, ModelProperties model)
            {
                GameObject dummyNode;

                if (Application.isPlaying)
                {
                    dummyNode = new GameObject("dummy");
                    obj.transform.SetParent(dummyNode.transform);
                }
                else
                {
                    dummyNode = obj;
                }

                var modelSetup = dummyNode.GetComponent <ModelSetup>();

                if (modelSetup == null)
                {
                    dummyNode.AddComponent <ModelSetup>();
                    modelSetup = dummyNode.GetComponent <ModelSetup>();
                }
                //Rigidbody rigidbody = obj.GetComponent<Rigidbody>();
                //if (rigidbody != null)
                //{
                //    rigidbody.isKinematic = true;
                //}
                dummyNode.transform.position   = model.position; // model is redundant you aleady have access to modelProperties
                dummyNode.transform.rotation   = model.rotation;
                dummyNode.transform.localScale = model.scale;
                if (modelType == ModelType.Arcade)
                {
                    dummyNode.tag = "arcademodel";
                }
                if (modelType == ModelType.Game)
                {
                    dummyNode.tag = "gamemodel";
                }
                if (modelType == ModelType.Prop)
                {
                    dummyNode.tag = "propmodel";
                }
                bool   isArcadeLayer = arcadeType == ArcadeType.FpsArcade || arcadeType == ArcadeType.CylArcade || arcadeType == ArcadeType.None ? true : false;
                string layer         = (isArcadeLayer ? "Arcade/" : "Menu/") + modelType.ToString() + "Models";

                dummyNode.layer = LayerMask.NameToLayer(layer);
                dummyNode.RunOnChildrenRecursive(tChild => tChild.layer = LayerMask.NameToLayer(layer));

                GameObject node = null;

                if (isArcadeLayer)
                {
                    node = GameObject.Find("Arcade/" + modelType.ToString() + "Models");
                }
                else
                {
                    node = GameObject.Find("Menu/" + modelType.ToString() + "Models");
                }

                if (node != null)
                {
                    dummyNode.transform.SetParent(node.transform);
                }
                else
                {
                    Debug.Log("Error: Could not find the models parent node...");
                }

                // Zoning
                if (arcadeType == ArcadeType.FpsArcade || arcadeType == ArcadeType.FpsMenu)
                {
                    if (!ArcadeManager.visibleZones[arcadeType].ContainsKey(modelProperties.zone))
                    {
                        ArcadeManager.visibleZones[arcadeType][modelProperties.zone] = new List <GameObject>();
                    }

                    if (modelProperties.zone != 0)
                    {
                        ArcadeManager.visibleZones[arcadeType][modelProperties.zone].Add(dummyNode);
                    }
                    else
                    {
                        if (Physics.Raycast(dummyNode.transform.position, -dummyNode.transform.up, out RaycastHit vision, 100.0f))
                        {
                            GameObject objectHit = vision.transform.gameObject;
                            if (objectHit != null)
                            {
                                ModelSetup hitModelSetup = objectHit.transform.parent.gameObject.GetComponent <ModelSetup>();
                                if (hitModelSetup != null)
                                {
                                    //Debug.Log("zonemodel " + modelSetup.descriptiveName);
                                    ArcadeManager.visibleZones[arcadeType][hitModelSetup.zone].Add(dummyNode);
                                }
                            }
                        }
                    }
                }

                ArcadeConfiguration arcadeConfiguration = isArcadeLayer ? ArcadeManager.arcadeConfiguration : ArcadeManager.menuConfiguration;

                modelSetup.Setup(model, arcadeConfiguration.modelSharedProperties);
                if (addTrigger && modelSetup.triggers.Count > 0 && Application.isPlaying)
                {
                    TriggerManager.Add(modelSetup, arcadeType);
                }
                return(dummyNode);
            }
        }