291 lines
7.9 KiB
Ucode
291 lines
7.9 KiB
Ucode
|
/**
|
||
|
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
|
||
|
*
|
||
|
*/
|
||
|
class OnlineImageDownloaderWeb extends Object
|
||
|
config(Engine);
|
||
|
|
||
|
`include(Engine\Classes\HttpStatusCodes.uci)
|
||
|
|
||
|
enum EOnlineImageDownloadState
|
||
|
{
|
||
|
/** Download has not been kicked off yet */
|
||
|
PIDS_NotStarted,
|
||
|
/** Currently waiting for download to finish */
|
||
|
PIDS_Downloading,
|
||
|
/** Downloaded successfully and Texture is ready to be used */
|
||
|
PIDS_Succeeded,
|
||
|
/** Download failed. Can't assume Texture contents are valid/updated */
|
||
|
PIDS_Failed
|
||
|
};
|
||
|
|
||
|
/** Entry for a cached FB profile image */
|
||
|
struct OnlineImageDownload
|
||
|
{
|
||
|
/** URL for the image */
|
||
|
var string URL;
|
||
|
/** HTTP request object used to download the image */
|
||
|
var HttpRequestInterface HTTPRequest;
|
||
|
/** Current download state */
|
||
|
var EOnlineImageDownloadState State;
|
||
|
/** Marked for deletion/reuse */
|
||
|
var bool bPendingRemoval;
|
||
|
/** Texture that will be updated with the downloaded image */
|
||
|
var Texture2DDynamic Texture;
|
||
|
};
|
||
|
/** Cache of textures images and the web requests used to download them */
|
||
|
var array<OnlineImageDownload> DownloadImages;
|
||
|
/** Maximum downloads that can be in flight at the same time */
|
||
|
var config int MaxSimultaneousDownloads;
|
||
|
|
||
|
/**
|
||
|
* Called whenever a download for an image has completed
|
||
|
*
|
||
|
* @param OnlineImageDownload cached entry that was downloaded
|
||
|
*/
|
||
|
delegate OnOnlineImageDownloaded(OnlineImageDownload CachedEntry);
|
||
|
|
||
|
/**
|
||
|
* Retrieve the texture for a given image URL if it has been successfully downloaded and is still cached
|
||
|
*
|
||
|
* @param URL original url of image request
|
||
|
*/
|
||
|
function Texture GetOnlineImageTexture(string URL)
|
||
|
{
|
||
|
local int FoundIdx;
|
||
|
|
||
|
FoundIdx = DownloadImages.Find('URL',URL);
|
||
|
if (FoundIdx != INDEX_NONE &&
|
||
|
DownloadImages[FoundIdx].State == PIDS_Succeeded)
|
||
|
{
|
||
|
return DownloadImages[FoundIdx].Texture;
|
||
|
}
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Start the downloading/caching of the images for the given list of URLs
|
||
|
*
|
||
|
* @param URLs list of addresses to download
|
||
|
*/
|
||
|
function RequestOnlineImages(array<string> URLs)
|
||
|
{
|
||
|
local string URL;
|
||
|
local int FoundIdx,Idx;
|
||
|
|
||
|
// Start by marking any entries no longer needed for removal
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
// If existing User id entry not in new list of user ids then mark for removal
|
||
|
DownloadImages[Idx].bPendingRemoval = URLs.Find(DownloadImages[Idx].URL) == INDEX_NONE;
|
||
|
}
|
||
|
// Update/Add new user ids that are not being processed
|
||
|
foreach URLs(URL)
|
||
|
{
|
||
|
FoundIdx = DownloadImages.Find('URL',URL);
|
||
|
// If found existing entry then just treat as if downloaded
|
||
|
if (FoundIdx != INDEX_NONE)
|
||
|
{
|
||
|
OnOnlineImageDownloaded(DownloadImages[FoundIdx]);
|
||
|
}
|
||
|
// If no existing cached entry then need to update/add
|
||
|
else
|
||
|
{
|
||
|
// Find an entry marked for removal
|
||
|
FoundIdx = DownloadImages.Find('bPendingRemoval',true);
|
||
|
if (FoundIdx == INDEX_NONE)
|
||
|
{
|
||
|
// Add a new entry since no empty spots
|
||
|
FoundIdx = DownloadImages.Length;
|
||
|
DownloadImages.Length = DownloadImages.Length+1;
|
||
|
}
|
||
|
// Setup new cached image entry for user
|
||
|
DownloadImages[FoundIdx].URL = URL;
|
||
|
DownloadImages[FoundIdx].HTTPRequest = None;
|
||
|
DownloadImages[FoundIdx].State = PIDS_NotStarted;
|
||
|
DownloadImages[FoundIdx].bPendingRemoval = false;
|
||
|
if (DownloadImages[FoundIdx].Texture == None)
|
||
|
{
|
||
|
DownloadImages[FoundIdx].Texture = class'Texture2DDynamic'.static.Create(50,50);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Remove the unused entries
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
if (DownloadImages[Idx].bPendingRemoval)
|
||
|
{
|
||
|
DownloadImages.Remove(Idx--,1);
|
||
|
}
|
||
|
}
|
||
|
// Try to start next download
|
||
|
DownloadNextImage();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return total # of entries that are still being downloaded
|
||
|
*/
|
||
|
function int GetNumPendingDownloads()
|
||
|
{
|
||
|
local int Idx,Count;
|
||
|
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
if (DownloadImages[Idx].State == PIDS_Downloading)
|
||
|
{
|
||
|
Count++;
|
||
|
}
|
||
|
}
|
||
|
return Count;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear out the cached entries for the given user ids
|
||
|
*
|
||
|
* @param FBUserIds list of FB ids to clear
|
||
|
*/
|
||
|
function ClearDownloads(array<string> URLs)
|
||
|
{
|
||
|
local int Idx;
|
||
|
|
||
|
// Remove the entries matching the FB user ids
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
if (URLs.Find(DownloadImages[Idx].URL) != INDEX_NONE)
|
||
|
{
|
||
|
DownloadImages.Remove(Idx--,1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear out all of the cached entries. Even if currently in flight
|
||
|
*/
|
||
|
function ClearAllDownloads()
|
||
|
{
|
||
|
DownloadImages.Length = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Kick off the download for the next image. Up to MaxSimultaneousDownloads can be in flight at once
|
||
|
*/
|
||
|
private function DownloadNextImage()
|
||
|
{
|
||
|
local int Idx,PendingDownloads;
|
||
|
|
||
|
// Current pending downloads
|
||
|
PendingDownloads = GetNumPendingDownloads();
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
// Stop if we cant download any more
|
||
|
if (PendingDownloads >= MaxSimultaneousDownloads)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
// Find next available entry that needs to be processed
|
||
|
if (DownloadImages[Idx].State == PIDS_NotStarted)
|
||
|
{
|
||
|
//`log("FacebookImage:DownloadNextImage:2");
|
||
|
|
||
|
DownloadImages[Idx].HTTPRequest = class'HttpFactory'.static.CreateRequest();
|
||
|
if (DownloadImages[Idx].HTTPRequest != None)
|
||
|
{
|
||
|
DownloadImages[Idx].HTTPRequest.SetVerb("GET");
|
||
|
DownloadImages[Idx].HTTPRequest.SetURL(DownloadImages[Idx].URL);
|
||
|
DownloadImages[Idx].HTTPRequest.SetProcessRequestCompleteDelegate(OnDownloadComplete);
|
||
|
if (DownloadImages[Idx].HTTPRequest.ProcessRequest())
|
||
|
{
|
||
|
DownloadImages[Idx].State = PIDS_Downloading;
|
||
|
PendingDownloads++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called when the download has completed for a single image
|
||
|
*
|
||
|
* @param OriginalRequest HTTP request object that was used to kick off the web request
|
||
|
* @param Response contains the response code, headers, and data from the GET
|
||
|
* @param bDidSucceed TRUE if the request completed
|
||
|
*/
|
||
|
private function OnDownloadComplete(HttpRequestInterface OriginalRequest, HttpResponseInterface Response, bool bDidSucceed)
|
||
|
{
|
||
|
local int FoundIdx;
|
||
|
local array<byte> JPEGData;
|
||
|
|
||
|
// Match up the request object in the list of cached entries
|
||
|
FoundIdx = DownloadImages.Find('HTTPRequest',OriginalRequest);
|
||
|
if (FoundIdx != INDEX_NONE)
|
||
|
{
|
||
|
// Check for valid/successful response, and that the contents are a JPEG file
|
||
|
if (bDidSucceed &&
|
||
|
Response != None &&
|
||
|
Response.GetResponseCode() == `HTTP_STATUS_OK &&
|
||
|
InStr(Response.GetHeader("Content-Type"),"jpeg",false,true) != INDEX_NONE)
|
||
|
{
|
||
|
// Mark successful completion
|
||
|
DownloadImages[FoundIdx].State = PIDS_Succeeded;
|
||
|
// Copy JPEG image data
|
||
|
Response.GetContent(JPEGData);
|
||
|
|
||
|
// Update the texture mip with the image data
|
||
|
DownloadImages[FoundIdx].Texture.UpdateMipFromJPEG(0,JPEGData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Failed to download
|
||
|
DownloadImages[FoundIdx].State = PIDS_Failed;
|
||
|
}
|
||
|
// Delegate called when download completed
|
||
|
OnOnlineImageDownloaded(DownloadImages[FoundIdx]);
|
||
|
// Done downloading so no longer need the request object
|
||
|
DownloadImages[FoundIdx].HTTPRequest = None;
|
||
|
}
|
||
|
// Try to start next download
|
||
|
DownloadNextImage();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Debug draw the images that have downloaded
|
||
|
*
|
||
|
* @param Canvas used to draw the profile image textures on screen
|
||
|
*/
|
||
|
function DebugDraw(Canvas Canvas)
|
||
|
{
|
||
|
local float PosX,PosY;
|
||
|
local int Idx;
|
||
|
|
||
|
PosX=0;
|
||
|
PosY=0;
|
||
|
for (Idx=0; Idx < DownloadImages.Length; Idx++)
|
||
|
{
|
||
|
if (DownloadImages[Idx].State == PIDS_Succeeded)
|
||
|
{
|
||
|
Canvas.SetDrawColor(255,255,255,255);
|
||
|
Canvas.SetPos(PosX,PosY);
|
||
|
Canvas.DrawTexture(DownloadImages[Idx].Texture,1);
|
||
|
Canvas.SetDrawColor(0,255,0,255);
|
||
|
Canvas.SetPos(PosX,PosY);
|
||
|
Canvas.DrawBox(DownloadImages[Idx].Texture.SizeX,DownloadImages[Idx].Texture.SizeY);
|
||
|
PosY += DownloadImages[Idx].Texture.SizeY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Canvas.DrawBox(50,50);
|
||
|
PosY += 50;
|
||
|
}
|
||
|
if (PosY > Canvas.ClipY)
|
||
|
{
|
||
|
PosY = 0;
|
||
|
PosX += 50;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
}
|
||
|
|