Reputation: 339
I have a scene where I'd like to show multiple images downloaded from a server. I'm trying to download the textures and store them in a List. When the for loop finish running, I sort the List by name and then I instantiate the RawImage from the List, but doesn't works. What am I doing wrong?
public GameObject contentRef;
public RawImage imgPrefab;
void Start()
{
StartCoroutine(DownloadtheFiles());
}
public IEnumerator DownloadtheFiles()
{
yield return null;
List<string> photolist = ES2.LoadList<string>("myPhotos.txt");
for (int i = 0; i < photolist.Count; i++)
{
//Don't capture i variable
int index = i;
bool reqDone = false;
new GetUploadedRequest()
.SetUploadId(photolist[index])
.Send((response) =>
{
StartCoroutine(DownloadImages(response.Url, index,
(status) => { reqDone = status; }));
//return null;
});
//Wait in the for loop until the current request is done
while (!reqDone)
yield return null;
}
}
public IEnumerator DownloadImages(string downloadUrl, int index, Action<bool> done)
{
var www = new WWW(downloadUrl);
yield return www;
//Get the downloaded image
Texture2D tex = new Texture2D(4, 4);
www.LoadImageIntoTexture(tex);
List <Texture2D> texList = new List <Texture2D> ();
for (int i = 0; i < tex.Count; i++)
{
texList.Add (tex);
}
texList = texList.OrderBy(mtex => mtex.name).ToList();
for (int i = 0; i < tex.Count; i++)
{
RawImage newImg = Instantiate(imgPrefab, contentRef.transform);
//Change the name
newImg.name = "Image-" + index;
//Apply the downloaded image
newImg.texture = tex;
}
//Done
if (done != null)
done(true);
}
}
Upvotes: 1
Views: 168
Reputation: 125305
Your RawImage
code should be done outside the DownloadImages
function because DownloadImages
is called to download image from the url in the for
loop. The RawImage
instantiation should be done only after the for
loop has completed.
Also, using texList.OrderBy(mtex => mtex.name).ToList();
wouldn't work because your string contains both string and int and is in this format "Image-" + 0;". You will need a custom function to do that by splitting the string
and int
then sorting with the int
.
Finally, after the for
loop has finished running, you need a way to determine that all images has finished downloading before instantiating the RawImages
. You can do this by using array or List of bool
with the size of the List<string> photolist
that contains the link of images to download. Pass that array of bool to the DownloadImages
and use the index
argument to set it to true
when each download is done.
public GameObject contentRef;
public RawImage imgPrefab;
List<Texture2D> downloadedTextures = new List<Texture2D>();
void Start()
{
DownloadtheFiles();
}
public void DownloadtheFiles()
{
List<string> photolist = ES2.LoadList<string>("myPhotos.txt");
//Used to determine when were done downloading
bool[] doneDownloading = new bool[photolist.Count];
//Download images only.Don't instantiate anything
for (int i = 0; i < photolist.Count; i++)
{
//Don't capture i variable
int index = i;
new GetUploadedRequest()
.SetUploadId(photolist[index])
.Send((response) =>
{
StartCoroutine(DownloadImages(response.Url, index, doneDownloading));
});
}
//Instantiate the download images
StartCoroutine(InstantiateImages(doneDownloading));
}
//Instantiates the downloaded images after they are done downloading
IEnumerator InstantiateImages(bool[] downloadStatus)
{
//Wait until all images are done downloading
for (int i = 0; i < downloadStatus.Length; i++)
{
while (!downloadStatus[i])
yield return null;
}
//Sort the images by string
sort(ref downloadedTextures);
//Now, instantiate the images
for (int i = 0; i < downloadedTextures.Count; i++)
{
//Instantiate the image prefab GameObject and make it a child of the contentRef
RawImage newImg = Instantiate(imgPrefab, contentRef.transform);
//Apply the downloaded image
newImg.texture = downloadedTextures[i];
//Update name so that we can see the names in the Hierarchy
newImg.name = downloadedTextures[i].name;
}
//Clear List for next use
downloadedTextures.Clear();
}
//Sort the downloaded Textures by name
void sort(ref List<Texture2D> targetList)
{
var ordered = targetList.Select(s => new { s, Str = s.name, Split = s.name.Split('-') })
.OrderBy(x => int.Parse(x.Split[1]))
.ThenBy(x => x.Split[0])
.Select(x => x.s)
.ToList();
targetList = ordered;
}
public IEnumerator DownloadImages(string downloadUrl, int index, bool[] downloadStatus)
{
//Download image
var www = new WWW(downloadUrl);
yield return www;
//Get the downloaded image and add it to the List
Texture2D tex = new Texture2D(4, 4);
//Change the name
tex.name = "Image-" + index;
www.LoadImageIntoTexture(tex);
downloadedTextures.Add(tex);
downloadStatus[index] = true;
}
Upvotes: 1