// Note: Assumes that server communication object was previously polled by the activity script to check when it has RoutineStatus.READY.
    //       the script has confirmed that the generator can go ahead.
    public SHLevelConfigGeneratorServer(ActivityServerCommunication para_serverCommunication)
    {
        List<PackagedNextWord> list = null;
        LevelParameters level = new LevelParameters("");

        if(para_serverCommunication!=null){
            list = para_serverCommunication.loadSentences();
        //			list = para_serverCommunication.loadWords();
            level = new LevelParameters(para_serverCommunication.getLevel());

            instruction = LocalisationMang.instructions(para_serverCommunication.getDifficulty()[0],para_serverCommunication.getLevel(),ApplicationID.SERENADE_HERO);

            /*TextAsset ta = (TextAsset) Resources.Load("Localisation_Files/"+para_serverCommunication.language.ToString()+"/Instructions_"+para_serverCommunication.language.ToString(),typeof(TextAsset));
            if(ta != null){

            string text = ta.text;

            foreach(string line in text.Split('\n')){

                string[] values = line.Split(',');

                if(System.Convert.ToInt32(values[0])==(int)ApplicationID.SERENADE_HERO){

                    if(System.Convert.ToInt32(values[1])==level.mode){
                        Debug.Log(line);

                        if((TtsType)System.Enum.Parse(typeof(TtsType), values[2])==level.ttsType){

                            instruction = values[3];
                        }
                    }
                }
            }
            }
            if (instruction==""){
                instruction = "Instructions not available";
            }*/
        }

        int speed = level.speed;

        if (list==null){
            WorldViewServerCommunication.setError("Did not find words");
            return;
        }else if(list.Count==0){
            WorldViewServerCommunication.setError("List of words is empty");
            return;
        }

        if (error){
            list = WordDBCreator.createListPackagedNextWords("SERENADE_HERO");
            level = new LevelParameters(WordDBCreator.getLevel("SERENADE_HERO"));
        }

        lvlArr = new SHeroLevelConfig[list.Count];

        try{

        for(int i=0; i<list.Count; i++)
        {

            AnnotatedSentence sentence = list[i].getAnnotatedSentence();

            bool isWord = false;
            string[] text;
            List<int> indexes = new List<int>();

            isWord = true;
            text = sentence.theSentence.Split(new char[] { '{', '}' }, System.StringSplitOptions.RemoveEmptyEntries);

            List<int> positions = new List<int>();
            int j = -1;

                Debug.Log(sentence.theSentence);
            while ((j = sentence.theSentence.IndexOf('{', j+1)) != -1)
                {
                    positions.Add(j);
                    //Debug.Log(j);
                }

            int total_length = 0;

            for( j = 0;j<text.Length;j++){
                    if (positions.Contains(total_length)){
                        indexes.Add(j);
                        total_length +=2; //Opening and closing brakets
                    }

                    total_length += text[j].Length;
            }

                Debug.Log(sentence.theSentence+" "+indexes.Count+" "+sentence.fillerWords.Count);
                for(int jj =0;jj<sentence.fillerWords.Count;jj++){

                    Debug.Log(sentence.fillerWords[jj]);

                }

                if(sentence.fillerWords.Count>4){
                    List<string> needHaveFillers = new List<string>();//The last fillers are the correct syllables

                    for(int jj=0;jj<indexes.Count;jj++){
                        needHaveFillers.Add(sentence.fillerWords[sentence.fillerWords.Count-1]);
                        sentence.fillerWords.Remove(needHaveFillers[jj]);
                    }

                    while((sentence.fillerWords.Count+indexes.Count)>4){
                        sentence.fillerWords.RemoveAt(Random.Range(0,sentence.fillerWords.Count));
                        Debug.Log("Remove! "+sentence.fillerWords.Count);
                    }

                    foreach(string needFiller in needHaveFillers)
                        sentence.fillerWords.Add(needFiller);

                }

            for(int jj =0;jj<sentence.fillerWords.Count;jj++){

                int k = Random.Range(0,sentence.fillerWords.Count);
                sentence.fillerWords.Add(sentence.fillerWords[k]);
                sentence.fillerWords.Remove(sentence.fillerWords[k]);

            }

            Debug.Log(text+" "+list[i].getAnnotatedSentence().languageArea+" "+list[i].getAnnotatedSentence().difficulty);

            lvlArr[i] = new SHeroLevelConfig(text,indexes.ToArray(),sentence.fillerWords.ToArray(),isWord,speed, list[i].getAnnotatedSentence().languageArea,list[i].getAnnotatedSentence().difficulty  );
        }

        for(int j=1;j<lvlArr.Length;j++){
            int r_j = Random.Range(1,lvlArr.Length);
            SHeroLevelConfig aux = lvlArr[r_j];
            lvlArr[r_j] = lvlArr[j];
            lvlArr[j] = aux;
        }
        }catch(System.Exception e){

        WorldViewServerCommunication.setError(e.Message);
        return;
        }
    }
    private List<SentenceSegment> extractMinimalSentenceSegments(SHeroLevelConfig para_config)
    {
        List<SentenceSegment> retSegmentList = new List<SentenceSegment>();

        string fullSentence = para_config.getLevelSentence(true);
        int sentenceCharLengthWhite = fullSentence.Replace("'","").Length;
        //fullSentence = fullSentence.Replace(" ","");
        //int sentenceCharLength = fullSentence.Replace("'","").Length;

        //Debug.Log(fullSentence+" "+sentenceCharLengthWhite+" characters");

        SentenceSegment regSeg = new SentenceSegment("",0,currLvlConfig.positionIsHole(0),0);
        string[] sentenceWordArr = para_config.sentenceWords;

        int maxHoleCharacters = 0;
        List<int> holeSizes = new List<int>();

        float tmpTotPerc = 0;
        for(int i=0; i<sentenceWordArr.Length; i++)
        {
            string tmpSentenceWord = sentenceWordArr[i];
            bool currIsHole = currLvlConfig.positionIsHole(i);

            if((regSeg.isHole == false)&&(currIsHole == false))
            {
                regSeg.segmentText += (tmpSentenceWord);
                regSeg.sentenceCharPerc = (regSeg.segmentText.Length * 1.0f) / (sentenceCharLengthWhite * 1.0f);
                regSeg.isHole = false;
                //Debug.Log("Accumulated *"+regSeg.segmentText+"* "+regSeg.sentenceCharPerc+ " False");

            }
            else
                /*if(((regSeg.isHole == false)&&(currIsHole == true))
                ||((regSeg.isHole == true)&&(currIsHole == false))
                ||((regSeg.isHole = true)&&(currIsHole == true)))*/
            {
                //Debug.Log("Done");

                retSegmentList.Add(regSeg);

                if(regSeg.isHole){

                    holeSizes.Add(regSeg.segmentText.Length);
                    if(regSeg.segmentText.Length>maxHoleCharacters)
                        maxHoleCharacters = regSeg.segmentText.Length;
                }

                tmpTotPerc += regSeg.sentenceCharPerc;
                regSeg = new SentenceSegment(tmpSentenceWord, ((tmpSentenceWord.Length) * 1.0f ) / (sentenceCharLengthWhite * 1.0f) ,currIsHole,tmpSentenceWord.Length);

                //Debug.Log("accumulated (hole) *"+regSeg.segmentText+"* "+regSeg.sentenceCharPerc+" "+currIsHole);

            }

            if(i == (sentenceWordArr.Length-1))
            {
                retSegmentList.Add(regSeg);
                tmpTotPerc += regSeg.sentenceCharPerc;
                if(regSeg.isHole){

                    holeSizes.Add(regSeg.segmentText.Length);
                    if(regSeg.segmentText.Length>maxHoleCharacters)
                        maxHoleCharacters = regSeg.segmentText.Length;
                }

                //Debug.Log("Done");
            }
        }

        //Replaces the length of each hole for the maximum length, to avoid recognition of correct answer based on size
        foreach(int holeWidth in holeSizes){
            sentenceCharLengthWhite += (maxHoleCharacters-holeWidth);
        }

        if(retSegmentList[0].segmentText.Length == 0)
        {
            retSegmentList.RemoveAt(0);
        }

        tmpTotPerc = 0.0f;
        foreach(SentenceSegment segment in retSegmentList){
            if(segment.isHole)
                segment.numCharacters = maxHoleCharacters;
            else
                segment.numCharacters = segment.segmentText.Length;

            segment.sentenceCharPerc = segment.numCharacters/(1.0f*sentenceCharLengthWhite);
            tmpTotPerc+=segment.sentenceCharPerc;

        }

        //Debug.Log("Overflow? "+tmpTotPerc);
        // If we have a perc overflow due to floating point precision then fix to 1 and redistribute the remainder.
        /*if(tmpTotPerc > 1)
        {
            float remainder = 1 - tmpTotPerc;
            float removalFactor = remainder / (retSegmentList.Count * 1.0f);

            tmpTotPerc = 0;
            for(int i=0; i<retSegmentList.Count; i++)
            {
                retSegmentList[i].sentenceCharPerc -= removalFactor;
                tmpTotPerc += retSegmentList[i].sentenceCharPerc;
            }

            if(tmpTotPerc > 1)
            {
                float subTotal = 0;
                for(int i=0; i<retSegmentList.Count-1; i++)
                {
                    subTotal += retSegmentList[i].sentenceCharPerc;
                }

                retSegmentList[retSegmentList.Count-1].sentenceCharPerc = 1 - subTotal;
            }
        }*/

        return retSegmentList;
    }
    protected override void genNextLevel()
    {
        // Destroy old objects.
        for(int i=0; i<currLvlItems.Count; i++)
        {
            DestroyImmediate(GameObject.Find(currLvlItems[i]));
        }

        // Generate new sentence.
        currLvlConfig = (SHeroLevelConfig) lvlConfigGen.getNextLevelConfig(wordPoolMaxCapacity);

        musicMarkerSpeedPerWord_InSec = (3-currLvlConfig.speed)*5f;

        //debugFullSentence = currLvlConfig.getLevelSentence(true);
        recordPresentedConfig(currLvlConfig);

        if(serverCommunication != null) { serverCommunication.wordDisplayed(currLvlConfig.getLevelSentence(false),currLvlConfig.languageArea,currLvlConfig.difficulty); }

        // Show new song sentence.
        renderSongSentence();

        // Populate word pool.
        renderWordPool();

        playerSelectedHoleItems = new Dictionary<int, string>();

        mistakesInCurrSentence = 0;

        //musicMarkerIndex = -1;
        triggerMusicMarkerStartDelay();
    }
    protected override void initWorld()
    {
        this.initLevelConfigGenerator();
        reqMaxSentencesForWin = lvlConfigGen.getConfigCount();
        currLvlConfig = null;

        currLvlItems = new List<string>();

        // Auto Adjust.

        GameObject personPortrait = GameObject.Find("PersonPortrait");
        GameObject pauseBtn = GameObject.Find("PauseButton");
        GameObject continueBtn = GameObject.Find("AutoCompleteButtonLocation");
        GameObject bkgrnd = GameObject.Find("Background");
        GameObject musicBtn = GameObject.Find("MusicButton");

        SpawnNormaliser.adjustGameObjectsToNwBounds(SpawnNormaliser.get2DBounds(bkgrnd.renderer.bounds),
                                                    WorldSpawnHelper.getCameraViewWorldBounds(bkgrnd.transform.position.z + 2,true),
                                                    new List<GameObject>() { personPortrait, pauseBtn, continueBtn,musicBtn });

        Transform mainCamObj = GameObject.Find("Main Camera").transform;
        continueBtn.transform.parent = mainCamObj;
        personPortrait.transform.parent = mainCamObj;
        pauseBtn.transform.parent = mainCamObj;
        musicBtn.transform.parent = mainCamObj;
        musicBtn.renderer.material.color = Color.red;

        uiBounds.Add("ContinueBtn",WorldSpawnHelper.getWorldToGUIBounds(continueBtn.renderer.bounds,upAxisArr));
        uiBounds.Add("PersonPortrait",WorldSpawnHelper.getWorldToGUIBounds(personPortrait.renderer.bounds,upAxisArr));
        uiBounds.Add("PauseBtn",WorldSpawnHelper.getWorldToGUIBounds(pauseBtn.renderer.bounds,upAxisArr));
        uiBounds.Add("MusicBtn",WorldSpawnHelper.getWorldToGUIBounds(musicBtn.renderer.bounds,upAxisArr));

        pauseBtnVisible = false;
        pauseBtn.renderer.enabled = false;

        continueBtnVisible = false;
        continueBtn.renderer.enabled = false;

        // Adjust the song banner elements.

        GameObject wordScrollObj = GameObject.Find("WordScroll");
        Transform wordScrollLeftObj = wordScrollObj.transform.FindChild("WordScroll_Left");
        Transform wordScrollMidObj = wordScrollObj.transform.FindChild("WordScroll_Middle");
        Transform wordScrollRightObj = wordScrollObj.transform.FindChild("WordScroll_Right");

        Rect cameraWorldBounds = WorldSpawnHelper.getCameraViewWorldBounds(1,true);
        wordScrollLeftObj.position = new Vector3(cameraWorldBounds.x + (wordScrollLeftObj.renderer.bounds.size.x/2f), wordScrollLeftObj.position.y, wordScrollLeftObj.position.z);
        wordScrollRightObj.position = new Vector3(cameraWorldBounds.x + cameraWorldBounds.width - (wordScrollRightObj.renderer.bounds.size.x/2f), wordScrollRightObj.position.y, wordScrollRightObj.position.z);

        // Create merged and adjusted song banner text area.
        List<Bounds> scrollTAPartBounds = new List<Bounds>();
        scrollTAPartBounds.Add(wordScrollLeftObj.FindChild("TextArea").renderer.bounds);
        scrollTAPartBounds.Add(wordScrollMidObj.FindChild("TextArea").renderer.bounds);
        scrollTAPartBounds.Add(wordScrollRightObj.FindChild("TextArea").renderer.bounds);
        Bounds maxScrollPartBounds = CommonUnityUtils.findMaxBounds(scrollTAPartBounds);
        Rect maxScrollPartBoundsRect = CommonUnityUtils.get2DBounds(maxScrollPartBounds);
        maxScrollPartBoundsRect = CommonUnityUtils.rescaleRect(maxScrollPartBoundsRect,0.85f,1f);
        GameObject songWordDisplayArea = WorldSpawnHelper.initObjWithinWorldBounds(debugPrefab,"SongWordDisplayArea",maxScrollPartBoundsRect,-1,upAxisArr);
        songWordDisplayArea.renderer.enabled = false;
        songWordDisplayArea.transform.parent = wordScrollObj.transform;

        wordScrollLeftObj.FindChild("TextArea").renderer.enabled = false;
        wordScrollLeftObj.FindChild("MusicMarkerStart").renderer.enabled = false;
        wordScrollMidObj.FindChild("TextArea").renderer.enabled = false;
        wordScrollRightObj.FindChild("TextArea").renderer.enabled = false;
        wordScrollRightObj.FindChild("MusicMarkerEnd").renderer.enabled = false;

        // Adjust word pool size.

        GameObject wordPoolGObj = GameObject.Find("WordPool");

        Vector2 nwWordPoolTopLeft = new Vector2(personPortrait.transform.position.x + (personPortrait.renderer.bounds.size.x/2f), continueBtn.transform.position.y + (continueBtn.renderer.bounds.size.y/2f));
        float availableWidthForWPool = (continueBtn.transform.position.x - (continueBtn.renderer.bounds.size.x/2f)) - nwWordPoolTopLeft.x;
        Rect nwWordPoolBounds = new Rect(nwWordPoolTopLeft.x,nwWordPoolTopLeft.y,availableWidthForWPool, continueBtn.renderer.bounds.size.y);
        Vector3 nwWordPoolCentrePt = new Vector3(nwWordPoolTopLeft.x + (nwWordPoolBounds.width/2f), nwWordPoolTopLeft.y - (nwWordPoolBounds.height/2f), wordPoolGObj.transform.position.z);

        float desiredWordPoolWidth = availableWidthForWPool * 0.95f;
        float desiredWordPoolHeight = nwWordPoolBounds.height * 0.9f;
        nwWordPoolBounds = new Rect(nwWordPoolBounds.x + (nwWordPoolBounds.width/2f) - (desiredWordPoolWidth/2f),
                                    nwWordPoolBounds.y - (nwWordPoolBounds.height/2f) + (desiredWordPoolHeight/2f),
                                    desiredWordPoolWidth,
                                    desiredWordPoolHeight);

        wordPoolGObj.transform.position = nwWordPoolCentrePt;
        Vector3 tmpWPoolScale = wordPoolGObj.transform.localScale;
        tmpWPoolScale.x = (tmpWPoolScale.x * (nwWordPoolBounds.width/wordPoolGObj.renderer.bounds.size.x));
        tmpWPoolScale.y = (tmpWPoolScale.y * (nwWordPoolBounds.height/wordPoolGObj.renderer.bounds.size.y));
        wordPoolGObj.transform.localScale = tmpWPoolScale;

        wordPoolGObj.renderer.enabled = false;

        // Game band Characters.

        currCharacterCount = 0;
        characterGObjMap = new Dictionary<string, GameObject>();
        characterScenePositions = new List<Vector3>();

        Rect totWorldBnds = WorldSpawnHelper.getGuiToWorldBounds(new Rect(0,0,Screen.width,Screen.height),Camera.main.transform.position.z,upAxisArr);

        for(int i=0; i<characters.Length; i++)
        {
            GameObject charObj = GameObject.Find(characters[i]);
            if(charObj == null)
            {
                characterScenePositions.Add(Vector3.zero);
            }
            else
            {
                characterScenePositions.Add(new Vector3(charObj.transform.position.x,charObj.transform.position.y,charObj.transform.position.z));
            }

            charObj.transform.position = new Vector3(totWorldBnds.x - 7,charObj.transform.position.y,charObj.transform.position.z);
            charObj.SetActive(false);
            characterGObjMap.Add(characters[i],charObj);
        }

        // Hide the people in the windows.
        for(int i=1; i<10; i++)
        {
            hidePersonAtWindow("Window"+i);
        }

        // Sound Channel Objects from the Intro Script instead.
        //initSoundChannels();

        // Player action log.
        playerSelectedHoleItems = new Dictionary<int, string>();

        // Music Marker.
        GameObject musicMarkerStartObj = wordScrollLeftObj.transform.FindChild("MusicMarkerStart").gameObject;
        Vector3 musicMarkerStartPos = new Vector3(musicMarkerStartObj.transform.position.x,musicMarkerStartObj.transform.position.y,Camera.main.transform.position.z + 2);
        GameObject musicMarkerObj = GameObject.Find("MusicMarker");
        musicMarkerObj.transform.position = musicMarkerStartPos;

        // Init intro sequence script.
        transform.gameObject.AddComponent<AcSHIntroSequenceScript>();

        // Night Ambience Sound Effect.
        triggerSoundAtCamera("NightAmbience",true);
    }
    public void renderSongSentence()
    {
        // Create world items representing the sentence.

        if(currLvlConfig == null)
        {
            //Debug.LogWarning("DEPRECATED");
            currLvlConfig = (SHeroLevelConfig) lvlConfigGen.getNextLevelConfig(wordPoolMaxCapacity);
            musicMarkerSpeedPerWord_InSec = (3-currLvlConfig.speed)*5f;

            recordPresentedConfig(currLvlConfig);
            if(serverCommunication != null) { serverCommunication.wordDisplayed(currLvlConfig.getLevelSentence(false),currLvlConfig.languageArea,currLvlConfig.difficulty); }
        }

        GameObject songBannerObj = GameObject.Find("WordScroll");
        GameObject songWordDisplayAreaObj = songBannerObj.transform.FindChild("SongWordDisplayArea").gameObject;
        Rect sentenceAreaBounds = CommonUnityUtils.get2DBounds(songWordDisplayAreaObj.renderer.bounds);

        List<SentenceSegment> sentenceSegments = extractMinimalSentenceSegments(currLvlConfig);

        float totalSentencePercForHoles = 0;
        float tmpTotal = 0;
        int numHoles = 0;
        for(int i=0; i<sentenceSegments.Count; i++)
        {
            SentenceSegment tmpSeg = sentenceSegments[i];
            if(tmpSeg.isHole)
            {
                numHoles++;
                totalSentencePercForHoles += tmpSeg.sentenceCharPerc;
            }
            tmpTotal += tmpSeg.sentenceCharPerc;
        }
        //Debug.Log("100%:"+tmpTotal);
        float allocatedWidthPercPerHole = totalSentencePercForHoles / (numHoles * 1.0f);

        List<GameObject> tmpWordBoxes = new List<GameObject>();
        List<GameObject> tmpWordBoxesAndHoles = new List<GameObject>();
        List<int> holeIdxs = new List<int>();
        songBannerItemPositions = new List<Vector3>();

        //Debug.Log("Total area: "+sentenceAreaBounds.x+" "+sentenceAreaBounds.y+" "+sentenceAreaBounds.height+" "+sentenceAreaBounds.width);

        Vector3 currSegWorldTopLeft = new Vector3(sentenceAreaBounds.x,sentenceAreaBounds.y,songWordDisplayAreaObj.transform.position.z);
        int nxtHoleIDArrIndex = 0;
        for(int i=0; i<sentenceSegments.Count; i++)
        {
            SentenceSegment tmpSeg = sentenceSegments[i];
            float blockWidth = sentenceAreaBounds.width * tmpSeg.sentenceCharPerc;
            if(tmpSeg.isHole) {
                blockWidth = sentenceAreaBounds.width * allocatedWidthPercPerHole; }

            Rect blockBounds = new Rect(currSegWorldTopLeft.x,currSegWorldTopLeft.y,blockWidth,sentenceAreaBounds.height);

            if( ! tmpSeg.isHole)
            {
                // Create text block.

                //Debug.Log(tmpSeg.segmentText+" Width: "+blockBounds.width+" from "+currSegWorldTopLeft.x);

                GameObject nwWordBox = WordBuilderHelper.buildWordBox(99,tmpSeg.segmentText,blockBounds,currSegWorldTopLeft.z,upAxisArr,wordBoxPrefab);
                Destroy(nwWordBox.GetComponent<BoxCollider>());
                Destroy(nwWordBox.transform.FindChild("Board").gameObject);
                nwWordBox.transform.FindChild("Text").gameObject.renderer.sortingOrder = 1000;
                //Debug.Log("TextMeshWidth-"+i+"-"+(nwWordBox.transform.FindChild("Text").renderer.bounds.size.x));

                tmpWordBoxes.Add(nwWordBox);
                tmpWordBoxesAndHoles.Add(nwWordBox);
                songBannerItemPositions.Add(nwWordBox.transform.position);
                currLvlItems.Add(nwWordBox.name);
            }
            else
            {
                // Create hole block.

                //Debug.Log(tmpSeg.segmentText+" Width: "+blockBounds.width+" from "+currSegWorldTopLeft.x);

                string text =tmpSeg.segmentText;
                while(text.Length<tmpSeg.numCharacters)
                    text+="*";
                //Debug.Log(text);
                GameObject nwWordBoxHole = WordBuilderHelper.buildWordBox(99,text,blockBounds,currSegWorldTopLeft.z,upAxisArr,wordBoxPrefab);
                Destroy(nwWordBoxHole.GetComponent<BoxCollider>());
                Destroy(nwWordBoxHole.transform.FindChild("Board").gameObject);
                nwWordBoxHole.transform.FindChild("Text").gameObject.renderer.sortingOrder = 1000;
                //Debug.Log("TextMeshWidth-"+i+"-"+(nwWordBox.transform.FindChild("Text").renderer.bounds.size.x));

                holeIdxs.Add(tmpWordBoxesAndHoles.Count);
                tmpWordBoxesAndHoles.Add(nwWordBoxHole);

            }

            currSegWorldTopLeft.x += blockBounds.width;
        }

        //songBannerFontCharacterSize = WordBuilderHelper.setBoxesToUniformTextSize(tmpWordBoxesAndHoles,0.10f);
        songBannerFontCharacterSize = WordBuilderHelper.setBoxesToTextSizeInRange(tmpWordBoxesAndHoles,0.04f,0.1f);

        Debug.Log("WorldBoxes font "+songBannerFontCharacterSize);

        float holeNewWidth = 0f;

        tmpTotal = 0;
        for(int i=0; i<tmpWordBoxesAndHoles.Count; i++)
        {
            GameObject nxtWordBox = tmpWordBoxesAndHoles[i];
            Transform textChild = nxtWordBox.transform.FindChild("Text");
            Transform boardChild = nxtWordBox.transform.FindChild("Board");

            float origBoardWidth = boardChild.renderer.bounds.size.x;

            float reqBoardWidth = textChild.renderer.bounds.size.x;

            if(sentenceSegments[i].isHole){

                if(reqBoardWidth>holeNewWidth)
                    holeNewWidth = reqBoardWidth;
            }else{

            float reqXScale = reqBoardWidth / origBoardWidth;

            Vector3 tmpScaleVect = boardChild.localScale;
            tmpScaleVect.x *= reqXScale;
            boardChild.localScale = tmpScaleVect;

            tmpTotal += boardChild.renderer.bounds.size.x;
            //freedWidth += (origBoardWidth - reqBoardWidth);
            //Debug.Log("Adjust word "+nxtWordBox.transform.FindChild("Text").gameObject.GetComponent<TextMesh>().text+" by "+reqXScale+ " (size: "+ (boardChild.renderer.bounds.size.x) +")");
            }
        }

        for(int i=0; i<tmpWordBoxesAndHoles.Count; i++)
        {

            if(!sentenceSegments[i].isHole)
                continue;

            GameObject nxtWordBox = tmpWordBoxesAndHoles[i];
            Transform textChild = nxtWordBox.transform.FindChild("Text");

            float origTextWidth = textChild.renderer.bounds.size.x;

            float reqXScale = holeNewWidth / origTextWidth;

            Vector3 tmpScaleVect = textChild.localScale;
            tmpScaleVect.x *= reqXScale;
            textChild.localScale = tmpScaleVect;

            tmpTotal += textChild.renderer.bounds.size.x;
                //freedWidth += (origBoardWidth - reqBoardWidth);
            Debug.Log("Adjust hole "+nxtWordBox.transform.FindChild("Text").gameObject.GetComponent<TextMesh>().text+" by "+reqXScale+ " (size: "+ (textChild.renderer.bounds.size.x) +")");
        }

        //Destroy holeWords and replace them with holes of the same size
        for(int i = 0;i<holeIdxs.Count;i++){
            GameObject holeWord = tmpWordBoxesAndHoles[ holeIdxs[i] ];

            Bounds bounds = holeWord.transform.FindChild("Text").renderer.bounds;
            Rect blockBounds = CommonUnityUtils.get2DBounds(bounds);

            GameObject nwHole = WorldSpawnHelper.initObjWithinWorldBounds(holePrefab,1,1,"Hole-"+currLvlConfig.holeList[nxtHoleIDArrIndex],blockBounds,null,songWordDisplayAreaObj.transform.position.z,upAxisArr);
            nxtHoleIDArrIndex++;

            HoleScript hs = nwHole.GetComponent<HoleScript>();
            hs.registerListener("AcScen",this);

            nwHole.transform.renderer.material.color = Color.gray;
            nwHole.transform.GetComponent<BoxCollider>().size = new Vector3(1,1,50);

            songBannerItemPositions.Add(nwHole.transform.position);
            songWordWorldScale = nwHole.transform.renderer.bounds.size;

            currLvlItems.Add(nwHole.name);

            DestroyImmediate(holeWord);

        }

        /*float addedWidthPerHole = freedWidth / (numHoles * 1.0f);
        if((numHoles == 1)&&(currLvlConfig.isWord)) { addedWidthPerHole = 0; }
        for(int i=0; i<numHoles; i++)
        {
            GameObject nxtHoldObj = GameObject.Find("Hole-"+currLvlConfig.holeList[i]);

            float addition = addedWidthPerHole;
            float origHoleWidth = nxtHoldObj.renderer.bounds.size.x;

            if(i == (numHoles-1))
            {
                if((tmpTotal + addition) > sentenceAreaBounds.width)
                {
                    addition = sentenceAreaBounds.width - tmpTotal;
                }
            }

            float reqHoleWidth = origHoleWidth + addition;

            Vector3 tmpScaleVect = nxtHoldObj.transform.localScale;
            tmpScaleVect.x *= (reqHoleWidth / origHoleWidth);
            nxtHoldObj.transform.localScale = tmpScaleVect;

            tmpTotal += reqHoleWidth;
        }*/

        //Position the boxes
        currSegWorldTopLeft = new Vector3(sentenceAreaBounds.x + (sentenceAreaBounds.width/2f) - (tmpTotal/2f),sentenceAreaBounds.y,songWordDisplayAreaObj.transform.position.z);
        int nxtWordBoxArrIndex = 0;
        int nxtHoleArrIndex = 0;

        for(int i=0; i<sentenceSegments.Count; i++)
        {
            SentenceSegment tmpSeg = sentenceSegments[i];

            float boxWidth = 0;

            if( ! tmpSeg.isHole)
            {
                GameObject reqBox = tmpWordBoxes[nxtWordBoxArrIndex];
                boxWidth = reqBox.transform.FindChild("Board").renderer.bounds.size.x;
                reqBox.transform.position = new Vector3(currSegWorldTopLeft.x + (boxWidth/2f),reqBox.transform.position.y,reqBox.transform.position.z);
                nxtWordBoxArrIndex++;
            }
            else
            {
                GameObject reqBox = GameObject.Find("Hole-"+currLvlConfig.holeList[nxtHoleArrIndex]);
                boxWidth = reqBox.renderer.bounds.size.x;
                reqBox.transform.position = new Vector3(currSegWorldTopLeft.x + (boxWidth/2f),reqBox.transform.position.y,reqBox.transform.position.z);
                nxtHoleArrIndex++;
            }

            currSegWorldTopLeft.x += boxWidth;
        }

        // Apply hole asthetics (shirnk slightly)
        /*for(int i=0; i<currLvlConfig.holeList.Length; i++)
        {
            GameObject holeObj = GameObject.Find("Hole-"+currLvlConfig.holeList[i]);

            Vector3 tmpScale = holeObj.transform.localScale;
            tmpScale.x *= 0.9f;
            tmpScale.y *= 0.8f;
            holeObj.transform.localScale = tmpScale;

            songWordWorldScale = holeObj.transform.localScale;
        }*/

        AcSHIntroSequenceScript introScript = transform.gameObject.GetComponent<AcSHIntroSequenceScript>();
        if(introScript != null)
        {
            introScript.respondToEvent("AcScen","SentenceDisplayed",null);
        }
    }