public void SavePrefabInformation(GeneratablePrefab prefab, bool shouldRecomputePrefabInformation, bool replaceOld = true)
    {
        const string resPrefix = "Resources/";
        string assetPath = AssetDatabase.GetAssetPath(prefab);
        if (string.IsNullOrEmpty(assetPath))
            return;
        string newFileName = assetPath.Substring(assetPath.LastIndexOf(resPrefix) + resPrefix.Length);
        newFileName = newFileName.Substring(0, newFileName.LastIndexOf("."));
        int replaceIndex = -1;
        if (replaceOld)
        {
            replaceIndex = availablePrefabs.FindIndex( (PrefabDatabase.PrefabInfo testInfo)=>{
                return testInfo.fileName == newFileName;
            });
            if (replaceIndex >= 0)
                availablePrefabs.RemoveAt(replaceIndex);
        }

        if (prefab.shouldUse)
        {
            if (shouldRecomputePrefabInformation)
                prefab.ProcessPrefab();
            PrefabDatabase.PrefabInfo newInfo = new PrefabDatabase.PrefabInfo();
            newInfo.fileName = newFileName;
            newInfo.complexity = prefab.myComplexity;
            newInfo.bounds = prefab.myBounds;
            newInfo.isLight = prefab.isLight;
            newInfo.anchorType = prefab.attachMethod;
            foreach(GeneratablePrefab.StackableInfo stackRegion in prefab.stackableAreas)
                newInfo.stackableAreas.Add(stackRegion);
            if (replaceIndex < 0)
                availablePrefabs.Add(newInfo);
            else
                availablePrefabs.Insert(replaceIndex, newInfo);
        }
        EditorUtility.SetDirty(this);
    }
    public void Init()
    {
        // Reset the UID Color counter
        resetUIDColor();

        LitJson.JsonData json = SimulationManager.argsConfig;
        if (json != null)
        {
            // Override settings with those in config
            showProcGenDebug = json["debug_procedural_generation_logs"].ReadBool(showProcGenDebug);
            shouldUseGivenSeed = json["random_seed"].ReadInt(ref desiredRndSeed) || shouldUseGivenSeed;
            shouldUseStandardizedSize = json["should_use_standardized_size"].ReadBool(shouldUseStandardizedSize);
            standardizedSize = json["standardized_size"].ReadVector3(standardizedSize);
            json["disabled_items"].ReadList(ref disabledItems);
            json["permitted_items"].ReadList(ref permittedItems);
            complexityLevelToCreate = json["complexity"].ReadInt(complexityLevelToCreate);
            randomMaterials = json["random_materials"].ReadBool(false);
            numCeilingLights = json["num_ceiling_lights"].ReadInt(numCeilingLights);
            useStandardShader = json["use_standard_shader"].ReadBool(false);
            intensityCeilingLights = json["intensity_ceiling_lights"].ReadFloat(intensityCeilingLights);
            minStackingBases = json["minimum_stacking_base_objects"].ReadInt(minStackingBases);
            forceStackedItems = json["minimum_objects_to_stack"].ReadInt(forceStackedItems);
            roomDim.x = json["room_width"].ReadFloat(roomDim.x);
            roomDim.y = json["room_height"].ReadFloat(roomDim.y);
            roomDim.z = json["room_length"].ReadFloat(roomDim.z);
            WALL_WIDTH = json["wall_width"].ReadFloat(WALL_WIDTH);
            DOOR_WIDTH = json["door_width"].ReadFloat(DOOR_WIDTH);
            DOOR_HEIGHT = json["door_height"].ReadFloat(DOOR_HEIGHT);
            WINDOW_SIZE_WIDTH = json["window_size_width"].ReadFloat(WINDOW_SIZE_WIDTH);
            WINDOW_SIZE_HEIGHT = json["window_size_height"].ReadFloat(WINDOW_SIZE_HEIGHT);
            WINDOW_PLACEMENT_HEIGHT = json["window_placement_height"].ReadFloat(WINDOW_PLACEMENT_HEIGHT);
            WINDOW_SPACING = json["window_spacing"].ReadFloat(WINDOW_SPACING);
            WALL_TRIM_HEIGHT = json["wall_trim_height"].ReadFloat(WALL_TRIM_HEIGHT);
            WALL_TRIM_THICKNESS = json["wall_trim_thickness"].ReadFloat(WALL_TRIM_THICKNESS);
            MIN_HALLWAY_SPACING = json["min_hallway_width"].ReadFloat(MIN_HALLWAY_SPACING);
            NUM_ROOMS = json["number_rooms"].ReadInt(NUM_ROOMS);
            MAX_NUM_TWISTS = json["max_wall_twists"].ReadInt(MAX_NUM_TWISTS);
            maxPlacementAttempts = json["max_placement_attempts"].ReadInt(maxPlacementAttempts);
            gridDim = json["grid_size"].ReadFloat(gridDim);
            use_mongodb_inter   = json["use_mongodb_inter"].ReadInt(use_mongodb_inter);
            use_cache_self      = json["use_cache_self"].ReadInt(use_cache_self);
            cache_folder        = json["cache_folder"].ReadString(cache_folder);
            disable_rand_stacking   = json["disable_rand_stacking"].ReadInt(disable_rand_stacking);
            enable_global_unit_scale    = json["enable_global_unit_scale"].ReadInt(enable_global_unit_scale);
            try {
                scene_scale_seed    = json["global_scale_dict"]["seed"].ReadInt(scene_scale_seed);
                scene_scale_mean    = json["global_scale_dict"]["scale"].ReadFloat(scene_scale_mean);
                scene_scale_var     = json["global_scale_dict"]["var"].ReadFloat(scene_scale_var);
                scene_scale_con     = json["global_scale_dict"]["option"].ReadString(scene_scale_con);
            }
            catch{}
        }

        list_rands.Clear();
        list_rands.Add(new Random_help(scene_scale_seed));

        Debug.Log("Get mongodb inter:" + use_mongodb_inter);
        if (use_mongodb_inter==1){
            LitJson.JsonData config_for_prefabs = SimulationManager.sendMongoDBsearch(json["mongodb_items"]);
            //Debug.Log("Config for prefabs:" + config_for_prefabs.ToJSON());
            int count_prefabs   = config_for_prefabs.Count;
            Debug.Log("Config for prefabs:" + count_prefabs);
            //Debug.Log("Config for prefabs:" + config_for_prefabs.);
            //foreach (LitJson.JsonData elem in config_for_prefabs as IList){
            for (int indx_now=0; indx_now<count_prefabs; indx_now++){
                //Debug.Log("Current item: " + elem.ToJSON());
                //u'version': 2, u'anchor_type': u'Ground', u'synset': [u'n02924116'], u'has_texture': True, u'boundb_pos': [0.1, 0.1, 0.5], u'center_pos': [0.0, 0.0, 0.0], u'upright': [0.0, 0.0, 1.0], u'aws_address': u'http://threedworld.s3.amazonaws.com/1004ae81238886674d44f5db04bf14b8.bundle', u'complexity': 5, u'isLight': u'False', u'source': u'3dw', u'shapenet_synset': u'n02924116', u'front': [-1.0, 0.0, 0.0], u'_id': ObjectId('57b31b77f8b11f6bc2b97af9'), u'type': u'shapenet', u'id': u'1004ae81238886674d44f5db04bf14b8', u'name': u'Tour bus concept purple'
                LitJson.JsonData current_item    = config_for_prefabs[indx_now.ToString()];

                PrefabDatabase.PrefabInfo newInfo = new PrefabDatabase.PrefabInfo();
                newInfo.fileName = current_item["aws_address"].ReadString(newInfo.fileName);
                //newInfo.fileName = newInfo.fileName.Replace("\"", "");
                newInfo.complexity = current_item["complexity"].ReadInt(-1);
                newInfo.bounds.center   = current_item["center_pos"].ReadVector3(new Vector3(0f, 0f, 0f));
                newInfo.bounds.extents  = current_item["boundb_pos"].ReadVector3(new Vector3(0f, 0f, 0f));

                newInfo._id_str         = current_item["_id_str"].ReadString(newInfo._id_str);
                newInfo.aws_version     = current_item["aws_version"].ReadString(newInfo.aws_version);

                //newInfo.loaded          = 0;
                //Debug.Log("New info:" + newInfo.bounds + newInfo.complexity + newInfo.fileName);
                //Debug.Log("To cache into: " + newInfo._id_str + "_" + newInfo.aws_version + ".bundle");
                //Debug.Log(newInfo.fileName[0]);
                //Debug.Log(newInfo);
                availablePrefabs.Add(newInfo);

                //newInfo.bounds = prefab.myBounds;
                //newInfo.isLight = prefab.isLight;
                //newInfo.anchorType = prefab.attachMethod;
            }
            Debug.Log(availablePrefabs.Count);
            /*
            foreach(string itemName in config_for_prefabs){
                Debug.Log("Item " + itemName + ":" + config_for_prefabs[itemName].ToJSON());
            }
            */
        }

        _curRandSeed = UnityEngine.Random.Range (int.MinValue, int.MaxValue);
        if (shouldUseGivenSeed) {
            _rand = new System.Random (desiredRndSeed);
            _curRandSeed = desiredRndSeed;
        } else {
            _rand = new System.Random (_curRandSeed);
        }

        Debug.Log("Using random seed: " + _curRandSeed);

        //var database_bundle = AssetBundle.LoadFromFile("Assets/ScenePrefabs/PrefabDatabase.prefab");
        //PrefabDatabase database =  Resources.Load("Assets/ScenePrefabs/PrefabDatabase.prefab") as PrefabDatabase;
        //PrefabDatabase database =  AssetDatabase.LoadAssetAtPath<PrefabDatabase>
        //        ("Assets/ScenePrefabs/PrefabDatabase.prefab");

        /*
        var database_list = database_bundle.LoadAllAssets<PrefabDatabase>();
        Debug.Log("Test output: " + database_list);
        var database = database_list[0];
        if (database==null)
        {
            Debug.Log("Null database!" + database_list);
        }
        */
        if (use_mongodb_inter==0) {
            PrefabDatabase database = GameObject.FindObjectOfType<PrefabDatabase>();
            availablePrefabs = database.prefabs;
        }

        Debug.Log (availablePrefabs.Count);

        List<PrefabDatabase.PrefabInfo> filteredPrefabs = availablePrefabs.FindAll(((PrefabDatabase.PrefabInfo info)=>{
            // Remove items that have been disallowed
            foreach(string itemName in disabledItems)
            {
                if (info.fileName.ToLowerInvariant().Contains(itemName.ToLowerInvariant()))
                    return false;
            }

            // If we have a list, only use items that are allowed in the list
            if (permittedItems.Count > 0)
            {
                foreach(string itemName in permittedItems)
                {
                    if (info.fileName.ToLowerInvariant().Contains(itemName.ToLowerInvariant()))
                    {
                        // Get the option and scale from json message

                        try {
                            //info.option_scale   = json["scale_relat_dict"][itemName]["option"].ReadString(info.option_scale);
                            //info.dynamic_scale  = json["scale_relat_dict"][itemName]["scale"].ReadFloat(info.dynamic_scale);
                            //info.scale_var      = json["scale_relat_dict"][itemName][""]
                            info.set_scale(json["scale_relat_dict"][itemName]);
                            gen_rand_forinfo(ref info);
                            return true;
                        } catch {
                        }

                        // Get the option and scale via the Filename (recommend for http files)
                        try {
                            //info.option_scale   = json["scale_relat_dict"][info.fileName]["option"].ReadString(info.option_scale);
                            //info.dynamic_scale  = json["scale_relat_dict"][info.fileName]["scale"].ReadFloat(info.dynamic_scale);
                            info.set_scale(json["scale_relat_dict"][info.fileName]);
                            gen_rand_forinfo(ref info);
                            return true;
                        } catch {
                        }

                        return true;
                    }
                }
                return false;
            }

            // Get the option and scale via the Filename (recommend for http files)

            try {
                //info.option_scale   = json["scale_relat_dict"][info.fileName]["option"].ReadString(info.option_scale);
                //info.dynamic_scale  = json["scale_relat_dict"][info.fileName]["scale"].ReadFloat(info.dynamic_scale);
                info.set_scale(json["scale_relat_dict"][info.fileName]);
                gen_rand_forinfo(ref info);
            } catch {
            }

            return true;
        }));
        // TODO: We're not filtering the ceiling lights, since we currently only have 1 prefab that works
        //ceilingLightPrefabs = availablePrefabs.FindAll(((PrefabDatabase.PrefabInfo info)=>{return info.anchorType == GeneratablePrefab.AttachAnchor.Ceiling && info.isLight;}));
        groundPrefabs = filteredPrefabs.FindAll(((PrefabDatabase.PrefabInfo info)=>{return info.anchorType == GeneratablePrefab.AttachAnchor.Ground;}));
        stackingPrefabs = groundPrefabs.FindAll(((PrefabDatabase.PrefabInfo info)=>{return info.stackableAreas.Count > 0;}));
        List<PrefabDatabase.PrefabInfo> itemsForStacking = groundPrefabs.FindAll(((PrefabDatabase.PrefabInfo info)=>{return true;}));

        // Create grid to populate objects
        _curComplexity = 0;
        _failures = 0;
        _forceStackObject = false;

        // Create rooms
        roomDim.x = Mathf.Round(roomDim.x / gridDim) * gridDim;
        roomDim.z = Mathf.Round(roomDim.z / gridDim) * gridDim;
        Debug.Log ("Starting to create rooms...");
        CreateRoom(roomDim, new Vector3((roomDim.x-1) * 0.5f,0,(roomDim.z-1) * 0.5f));
        Debug.Log ("...created!");

        // Create lighting setup
        Debug.Log("Creating lights...");
        CreateLightingSetup(roomDim, new Vector3((roomDim.x-1) * 0.5f,0,(roomDim.z-1) * 0.5f));
        Debug.Log("...created!");

        _failures = 0;
        // Keep creating objects until we are supposed to stop
        // TODO: Create a separate plane to map ceiling placement
        // TODO: Replace ceilingLightPrefabs with Lighting setup
        /*for(int i = 0; (i - _failures) < numCeilingLights && _failures < maxPlacementAttempts; ++i)
            AddObjects(ceilingLightPrefabs);
        _failures = 0;*/

        if (showProcGenDebug && minStackingBases > 0)
            Debug.LogFormat("Stacking {0} objects bases: {1} types", minStackingBases, stackingPrefabs.Count);
        // Place stacking bases first so we can have more opportunities to stack on top
        for(int i = 0; (i - _failures) < minStackingBases && stackingPrefabs.Count > 0; ++i)
            AddObjects(stackingPrefabs);
        _failures = 0;

        if (showProcGenDebug && forceStackedItems > 0)
            Debug.LogFormat("Stacking {0} objects: {1} types", forceStackedItems, itemsForStacking.Count);
        // Place stacking bases first so we can have more opportunities to stack on top
        _forceStackObject = true;

        Debug.Log("Now plane number:" + _allHeightPlanes.Count);

        for(int i = 0; (i - _failures) < forceStackedItems && itemsForStacking.Count > 0; ++i)
            AddObjects(itemsForStacking);
        _failures = 0;
        _forceStackObject = false;

        if (showProcGenDebug)
            Debug.Log("Rest of objects");
        while (!IsDone ())
            if (!AddObjects (groundPrefabs)) {
                break;
            }

        for(int i = 0; i < _allHeightPlanes.Count; ++i)
            DrawTestGrid(_allHeightPlanes[i]);
        Debug.Log("Final complexity: " + _curComplexity);
    }