AvatarButton/holder, rename ThumbnailBroker for more general purposes

This commit is contained in:
Simon Robertshaw 2013-03-10 18:08:34 +00:00
parent 6090f0b0aa
commit e6bca489c9
15 changed files with 306 additions and 40 deletions

View File

@ -138,6 +138,21 @@ std::vector<char> format::VideoBufferToPTI(const VideoBuffer & vidBuf)
return data;
}
VideoBuffer * format::PTIToVideoBuffer(std::vector<char> & data)
{
int newWidth, newHeight;
pixel * buffer = Graphics::ptif_unpack(&data[0], data.size(), &newWidth, &newHeight);
if(buffer)
{
VideoBuffer * vb = new VideoBuffer(buffer, newWidth, newHeight);
free(buffer);
return vb;
}
return NULL;
}
std::vector<char> format::VideoBufferToPPM(const VideoBuffer & vidBuf)
{
std::vector<char> data;

View File

@ -33,5 +33,6 @@ namespace format
std::vector<char> VideoBufferToPNG(const VideoBuffer & vidBuf);
std::vector<char> VideoBufferToPPM(const VideoBuffer & vidBuf);
std::vector<char> VideoBufferToPTI(const VideoBuffer & vidBuf);
VideoBuffer * PTIToVideoBuffer(std::vector<char> & data);
unsigned long CalculateCRC(unsigned char * data, int length);
}

View File

@ -42,7 +42,7 @@
#include "search/Thumbnail.h"
#include "preview/Comment.h"
#include "ClientListener.h"
#include "ThumbnailBroker.h"
#include "RequestBroker.h"
#include "cajun/reader.h"
#include "cajun/writer.h"
@ -617,7 +617,7 @@ std::vector<std::pair<std::string, std::string> > Client::GetServerNotifications
void Client::Tick()
{
//Check thumbnail queue
ThumbnailBroker::Ref().FlushThumbQueue();
RequestBroker::Ref().FlushThumbQueue();
//Check status on version check request
if(versionCheckRequest && http_async_req_status(versionCheckRequest))
@ -809,7 +809,7 @@ void Client::WritePrefs()
void Client::Shutdown()
{
ThumbnailBroker::Ref().Shutdown();
RequestBroker::Ref().Shutdown();
ClearThumbnailRequests();
http_done();
@ -1150,6 +1150,28 @@ std::vector<unsigned char> Client::GetSaveData(int saveID, int saveDate)
return saveData;
}
VideoBuffer * Client::GetAvatar(std::string username)
{
lastError = "";
int dataStatus;
int dataLength = 0;
unsigned char * data;
std::stringstream urlStream;
urlStream << "http://" << STATICSERVER << "/avatars/" << username << ".pti";
data = (unsigned char *)http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength);
if(data && dataStatus == 200)
{
std::vector<char> responseData(data, data+dataLength);
return format::PTIToVideoBuffer(responseData);
}
else if(data)
{
free(data);
}
return NULL;
}
LoginStatus Client::Login(std::string username, std::string password, User & user)
{
lastError = "";

View File

@ -17,6 +17,7 @@ class SaveInfo;
class SaveFile;
class SaveComment;
class GameSave;
class VideoBuffer;
enum LoginStatus {
LoginOkay, LoginError
@ -125,6 +126,8 @@ public:
RequestStatus AddComment(int saveID, std::string comment);
VideoBuffer * GetAvatar(std::string username);
unsigned char * GetSaveData(int saveID, int saveDate, int & dataLength);
std::vector<unsigned char> GetSaveData(int saveID, int saveDate);
LoginStatus Login(std::string username, std::string password, User & user);

View File

@ -2,7 +2,7 @@
#include <iostream>
#include <typeinfo>
#include <time.h>
#include "ThumbnailBroker.h"
#include "RequestBroker.h"
#include "ThumbnailListener.h"
#include "Client.h"
#include "HTTP.h"
@ -12,7 +12,7 @@
//Asynchronous Thumbnail render & request processing
ThumbnailBroker::ThumbnailBroker()
RequestBroker::RequestBroker()
{
thumbnailQueueRunning = false;
//thumbnailQueueMutex = PTHREAD_MUTEX_INITIALIZER;
@ -25,12 +25,12 @@ ThumbnailBroker::ThumbnailBroker()
pthread_mutex_init (&runningMutex, NULL);
}
ThumbnailBroker::~ThumbnailBroker()
RequestBroker::~RequestBroker()
{
}
void ThumbnailBroker::assureRunning()
void RequestBroker::assureRunning()
{
pthread_mutex_lock(&runningMutex);
bool running = thumbnailQueueRunning;
@ -42,11 +42,11 @@ void ThumbnailBroker::assureRunning()
#ifdef DEBUG
std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl;
#endif
pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this);
pthread_create(&thumbnailQueueThread, 0, &RequestBroker::thumbnailQueueProcessHelper, this);
}
}
void ThumbnailBroker::Shutdown()
void RequestBroker::Shutdown()
{
pthread_mutex_lock(&runningMutex);
if(thumbnailQueueRunning)
@ -69,12 +69,12 @@ void ThumbnailBroker::Shutdown()
}
}
void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, int width, int height, ThumbnailListener * tListener)
void RequestBroker::RenderThumbnail(GameSave * gameSave, int width, int height, ThumbnailListener * tListener)
{
RenderThumbnail(gameSave, true, true, width, height, tListener);
}
void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener)
void RequestBroker::RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener)
{
AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex);
@ -84,7 +84,7 @@ void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, bool decorations, boo
assureRunning();
}
void ThumbnailBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener)
void RequestBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener)
{
AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex);
@ -94,13 +94,13 @@ void ThumbnailBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int
assureRunning();
}
void * ThumbnailBroker::thumbnailQueueProcessHelper(void * ref)
void * RequestBroker::thumbnailQueueProcessHelper(void * ref)
{
((ThumbnailBroker*)ref)->thumbnailQueueProcessTH();
((RequestBroker*)ref)->thumbnailQueueProcessTH();
return NULL;
}
void ThumbnailBroker::FlushThumbQueue()
void RequestBroker::FlushThumbQueue()
{
pthread_mutex_lock(&thumbnailQueueMutex);
while(thumbnailComplete.size())
@ -121,7 +121,7 @@ void ThumbnailBroker::FlushThumbQueue()
pthread_mutex_unlock(&thumbnailQueueMutex);
}
void ThumbnailBroker::thumbnailQueueProcessTH()
void RequestBroker::thumbnailQueueProcessTH()
{
time_t lastAction = time(NULL);
pthread_mutex_lock(&runningMutex);
@ -354,12 +354,12 @@ void ThumbnailBroker::thumbnailQueueProcessTH()
pthread_mutex_unlock(&runningMutex);
}
void ThumbnailBroker::RetrieveThumbnail(int saveID, int width, int height, ThumbnailListener * tListener)
void RequestBroker::RetrieveThumbnail(int saveID, int width, int height, ThumbnailListener * tListener)
{
RetrieveThumbnail(saveID, 0, width, height, tListener);
}
bool ThumbnailBroker::CheckThumbnailListener(ListenerHandle handle)
bool RequestBroker::CheckThumbnailListener(ListenerHandle handle)
{
pthread_mutex_lock(&listenersMutex);
int count = std::count(validListeners.begin(), validListeners.end(), handle);
@ -368,14 +368,14 @@ bool ThumbnailBroker::CheckThumbnailListener(ListenerHandle handle)
return count;
}
void ThumbnailBroker::AttachThumbnailListener(ThumbnailListener * tListener)
void RequestBroker::AttachThumbnailListener(ThumbnailListener * tListener)
{
pthread_mutex_lock(&listenersMutex);
validListeners.push_back(ListenerHandle(tListener->ListenerRand, tListener));
pthread_mutex_unlock(&listenersMutex);
}
void ThumbnailBroker::DetachThumbnailListener(ThumbnailListener * tListener)
void RequestBroker::DetachThumbnailListener(ThumbnailListener * tListener)
{
pthread_mutex_lock(&listenersMutex);

View File

@ -12,7 +12,7 @@ class GameSave;
class Thumbnail;
class ThumbnailListener;
typedef std::pair<int, ThumbnailListener*> ListenerHandle;
class ThumbnailBroker: public Singleton<ThumbnailBroker>
class RequestBroker: public Singleton<RequestBroker>
{
private:
class ThumbnailSpec
@ -67,6 +67,15 @@ private:
ThumbRenderRequest() : Save(0), Decorations(true), Fire(true), Width(0), Height(0), CompletedListener(ListenerHandle(0, (ThumbnailListener*)NULL)) {}
};
class Request
{
enum RequestType { Thumbnail, ThumbnailRender, HTTP };
public:
RequestType Type;
void * RequestObject;
ListenerHandle Listener;
};
//Thumbnail retreival
/*int thumbnailCacheNextID;
Thumbnail * thumbnailCache[THUMB_CACHE_SIZE];
@ -87,16 +96,17 @@ private:
std::list<ThumbnailRequest> currentRequests;
std::deque<std::pair<ThumbnailID, Thumbnail*> > thumbnailCache;
std::vector<ListenerHandle> validListeners;
std::deque<Request> requestQueue;
static void * thumbnailQueueProcessHelper(void * ref);
void thumbnailQueueProcessTH();
void assureRunning();
public:
ThumbnailBroker();
virtual ~ThumbnailBroker();
RequestBroker();
virtual ~RequestBroker();
void Shutdown();
void FlushThumbQueue();

View File

@ -35,10 +35,25 @@ VideoBuffer::VideoBuffer(VideoBuffer * old):
std::copy(old->Buffer, old->Buffer+(old->Width*old->Height), Buffer);
};
VideoBuffer::VideoBuffer(pixel * buffer, int width, int height):
Width(width),
Height(height)
{
Buffer = new pixel[width*height];
std::copy(buffer, buffer+(width*height), Buffer);
}
void VideoBuffer::Resize(float factor, bool resample)
{
int newWidth = ((float)Width)*factor;
int newHeight = ((float)Height)*factor;
Resize(newWidth, newHeight);
}
void VideoBuffer::Resize(int width, int height, bool resample)
{
int newWidth = width;
int newHeight = height;
pixel * newBuffer;
if(resample)
newBuffer = Graphics::resample_img(Buffer, Width, Height, newWidth, newHeight);

View File

@ -110,8 +110,10 @@ public:
VideoBuffer(const VideoBuffer & old);
VideoBuffer(VideoBuffer * old);
VideoBuffer(pixel * buffer, int width, int height);
VideoBuffer(int width, int height);
void Resize(float factor, bool resample = false);
void Resize(int width, int height, bool resample = false);
TPT_INLINE void BlendPixel(int x, int y, int r, int g, int b, int a)
{
#ifdef PIX32OGL

View File

@ -0,0 +1,110 @@
#include <iostream>
#include <typeinfo>
#include "AvatarButton.h"
#include "Format.h"
#include "Engine.h"
#include "client/Client.h"
#include "graphics/Graphics.h"
#include "ContextMenu.h"
#include "Keys.h"
namespace ui {
AvatarButton::AvatarButton(Point position, Point size, std::string username):
Component(position, size),
name(username),
actionCallback(NULL),
avatar(NULL),
tried(false)
{
}
AvatarButton::~AvatarButton()
{
if(avatar)
delete avatar;
if(actionCallback)
delete actionCallback;
}
void AvatarButton::Tick(float dt)
{
if(!avatar && !tried && name.size() > 0)
{
tried = true;
avatar = Client::Ref().GetAvatar(name);
if(avatar) {
if(avatar->Width != Size.X && avatar->Height != Size.Y)
{
avatar->Resize(Size.X, Size.Y, true);
}
}
}
}
void AvatarButton::Draw(const Point& screenPos)
{
Graphics * g = ui::Engine::Ref().g;
if(avatar)
{
g->draw_image(avatar, screenPos.X, screenPos.Y, 255);
}
}
void AvatarButton::OnMouseUnclick(int x, int y, unsigned int button)
{
if(button != 1)
{
return; //left click only!
}
if(isButtonDown)
{
isButtonDown = false;
DoAction();
}
}
void AvatarButton::OnContextMenuAction(int item)
{
//Do nothing
}
void AvatarButton::OnMouseClick(int x, int y, unsigned int button)
{
if(button == BUTTON_RIGHT)
{
if(menu)
menu->Show(GetScreenPos() + ui::Point(x, y));
}
else
{
isButtonDown = true;
}
}
void AvatarButton::OnMouseEnter(int x, int y)
{
isMouseInside = true;
}
void AvatarButton::OnMouseLeave(int x, int y)
{
isMouseInside = false;
}
void AvatarButton::DoAction()
{
if(actionCallback)
actionCallback->ActionCallback(this);
}
void AvatarButton::SetActionCallback(AvatarButtonAction * action)
{
actionCallback = action;
}
} /* namespace ui */

View File

@ -0,0 +1,51 @@
#ifndef AVATARBUTTON_H_
#define AVATARBUTTON_H_
#include <string>
#include "Component.h"
#include "graphics/Graphics.h"
#include "interface/Colour.h"
namespace ui
{
class AvatarButton;
class AvatarButtonAction
{
public:
virtual void ActionCallback(ui::AvatarButton * sender) {}
virtual ~AvatarButtonAction() {}
};
class AvatarButton : public Component
{
VideoBuffer * avatar;
std::string name;
bool tried;
public:
AvatarButton(Point position, Point size, std::string username);
virtual ~AvatarButton();
virtual void OnMouseClick(int x, int y, unsigned int button);
virtual void OnMouseUnclick(int x, int y, unsigned int button);
virtual void OnMouseEnter(int x, int y);
virtual void OnMouseLeave(int x, int y);
virtual void OnContextMenuAction(int item);
virtual void Draw(const Point& screenPos);
virtual void Tick(float dt);
virtual void DoAction();
void SetUsername(std::string username) { name = username; }
std::string GetUsername() { return name; }
void SetActionCallback(AvatarButtonAction * action);
protected:
bool isMouseInside, isButtonDown;
AvatarButtonAction * actionCallback;
};
}
#endif /* AVATARBUTTON_H_ */

View File

@ -5,7 +5,7 @@
#include "client/SaveInfo.h"
#include "graphics/Graphics.h"
#include "Engine.h"
#include "client/ThumbnailBroker.h"
#include "client/RequestBroker.h"
#include "simulation/SaveRenderer.h"
#include "Format.h"
#include "ContextMenu.h"
@ -117,7 +117,7 @@ SaveButton::SaveButton(Point position, Point size, SaveFile * file):
SaveButton::~SaveButton()
{
ThumbnailBroker::Ref().DetachThumbnailListener(this);
RequestBroker::Ref().DetachThumbnailListener(this);
if(thumbnail)
delete thumbnail;
@ -149,18 +149,18 @@ void SaveButton::Tick(float dt)
if(save->GetGameSave())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RenderThumbnail(save->GetGameSave(), Size.X-3, Size.Y-25, this);
RequestBroker::Ref().RenderThumbnail(save->GetGameSave(), Size.X-3, Size.Y-25, this);
}
else if(save->GetID())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RetrieveThumbnail(save->GetID(), save->GetVersion(), Size.X-3, Size.Y-25, this);
RequestBroker::Ref().RetrieveThumbnail(save->GetID(), save->GetVersion(), Size.X-3, Size.Y-25, this);
}
}
else if(file && file->GetGameSave())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RenderThumbnail(file->GetGameSave(), Size.X-3, Size.Y-25, this);
RequestBroker::Ref().RenderThumbnail(file->GetGameSave(), Size.X-3, Size.Y-25, this);
}
}
}

View File

@ -12,6 +12,7 @@
#include "search/Thumbnail.h"
#include "client/Client.h"
#include "interface/ScrollPanel.h"
#include "interface/AvatarButton.h"
#include "interface/Keys.h"
class PreviewView::LoginAction: public ui::ButtonAction
@ -52,7 +53,8 @@ PreviewView::PreviewView():
doOpen(false),
addCommentBox(NULL),
submitCommentButton(NULL),
commentBoxHeight(20)
commentBoxHeight(20),
showAvatars(true)
{
class FavAction: public ui::ButtonAction
{
@ -133,23 +135,38 @@ PreviewView::PreviewView():
browserOpenButton->SetActionCallback(new BrowserOpenAction(this));
AddComponent(browserOpenButton);
saveNameLabel = new ui::Label(ui::Point(5, (YRES/2)+4), ui::Point(100, 16), "");
if(showAvatars)
saveNameLabel = new ui::Label(ui::Point(39, (YRES/2)+4), ui::Point(100, 16), "");
else
saveNameLabel = new ui::Label(ui::Point(5, (YRES/2)+4), ui::Point(100, 16), "");
saveNameLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
saveNameLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(saveNameLabel);
saveDescriptionLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15+17), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+4+15+17)-21), "");
if(showAvatars)
saveDescriptionLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15+21), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+4+15+17)-25), "");
else
saveDescriptionLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15+19), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+4+15+17)-23), "");
saveDescriptionLabel->SetMultiline(true);
saveDescriptionLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
saveDescriptionLabel->Appearance.VerticalAlign = ui::Appearance::AlignTop;
saveDescriptionLabel->SetTextColour(ui::Colour(180, 180, 180));
AddComponent(saveDescriptionLabel);
authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15), ui::Point(200, 16), "");
if(showAvatars)
authorDateLabel = new ui::Label(ui::Point(39, (YRES/2)+4+15), ui::Point(180, 16), "");
else
authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15), ui::Point(200, 16), "");
authorDateLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
authorDateLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(authorDateLabel);
if(showAvatars)
{
avatarButton = new ui::AvatarButton(ui::Point(4, (YRES/2)+4), ui::Point(34, 34), "");
AddComponent(avatarButton);
}
viewsLabel = new ui::Label(ui::Point((XRES/2)-80, (YRES/2)+4+15), ui::Point(80, 16), "");
viewsLabel->Appearance.HorizontalAlign = ui::Appearance::AlignRight;
viewsLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
@ -373,7 +390,14 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender)
votesUp = save->votesUp;
votesDown = save->votesDown;
saveNameLabel->SetText(save->name);
authorDateLabel->SetText("\bgAuthor:\bw " + save->userName + " \bgDate:\bw " + format::UnixtimeToDateMini(save->date));
if(showAvatars) {
avatarButton->SetUsername(save->userName);
authorDateLabel->SetText("\bw" + save->userName + " \bgDate:\bw " + format::UnixtimeToDateMini(save->date));
}
else
{
authorDateLabel->SetText("\bgAuthor:\bw " + save->userName + " \bgDate:\bw " + format::UnixtimeToDateMini(save->date));
}
viewsLabel->SetText("\bgViews:\bw " + format::NumberToString<int>(save->Views));
saveDescriptionLabel->SetText(save->Description);
if(save->Favourite)
@ -513,10 +537,21 @@ void PreviewView::NotifyCommentsChanged(PreviewModel * sender)
int currentY = 0;//-yOffset;
ui::Label * tempUsername;
ui::Label * tempComment;
ui::AvatarButton * tempAvatar;
for(int i = 0; i < comments->size(); i++)
{
int usernameY = currentY+5, commentY;
tempUsername = new ui::Label(ui::Point(5, currentY+5), ui::Point(Size.X-((XRES/2) + 13), 16), comments->at(i)->authorName);
if(showAvatars)
{
tempAvatar = new ui::AvatarButton(ui::Point(4, currentY+4), ui::Point(26, 26), comments->at(i)->authorName);
commentComponents.push_back(tempAvatar);
commentsPanel->AddChild(tempAvatar);
}
if(showAvatars)
tempUsername = new ui::Label(ui::Point(31, currentY+5), ui::Point(Size.X-((XRES/2) + 13), 16), comments->at(i)->authorName);
else
tempUsername = new ui::Label(ui::Point(5, currentY+5), ui::Point(Size.X-((XRES/2) + 13), 16), comments->at(i)->authorName);
tempUsername->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
tempUsername->Appearance.VerticalAlign = ui::Appearance::AlignBottom;
currentY += 16;
@ -524,7 +559,6 @@ void PreviewView::NotifyCommentsChanged(PreviewModel * sender)
commentComponents.push_back(tempUsername);
commentsPanel->AddChild(tempUsername);
commentY = currentY+5;
tempComment = new ui::Label(ui::Point(5, currentY+5), ui::Point(Size.X-((XRES/2) + 13), -1), comments->at(i)->comment);
tempComment->SetMultiline(true);

View File

@ -14,6 +14,7 @@
namespace ui
{
class ScrollPanel;
class AvatarButton;
}
class PreviewModel;
@ -32,6 +33,7 @@ class PreviewView: public ui::Window {
ui::Textbox * addCommentBox;
ui::Label * saveNameLabel;
ui::Label * authorDateLabel;
ui::AvatarButton * avatarButton;
ui::Label * pageInfo;
ui::Label * saveDescriptionLabel;
ui::Label * viewsLabel;
@ -42,6 +44,7 @@ class PreviewView: public ui::Window {
int votesUp;
int votesDown;
bool doOpen;
bool showAvatars;
int commentBoxHeight;
float commentBoxPositionX;

View File

@ -3,7 +3,7 @@
#include "interface/Textbox.h"
#include "interface/Button.h"
#include "search/Thumbnail.h"
#include "client/ThumbnailBroker.h"
#include "client/RequestBroker.h"
#include "dialogues/ErrorMessage.h"
#include "dialogues/ConfirmPrompt.h"
#include "client/Client.h"
@ -67,7 +67,7 @@ LocalSaveActivity::LocalSaveActivity(SaveFile save, FileSavedCallback * callback
SetOkayButton(okayButton);
if(save.GetGameSave())
ThumbnailBroker::Ref().RenderThumbnail(save.GetGameSave(), true, false, Size.X-16, -1, this);
RequestBroker::Ref().RenderThumbnail(save.GetGameSave(), true, false, Size.X-16, -1, this);
}
void LocalSaveActivity::Save()

View File

@ -4,7 +4,7 @@
#include "interface/Button.h"
#include "interface/Checkbox.h"
#include "search/Thumbnail.h"
#include "client/ThumbnailBroker.h"
#include "client/RequestBroker.h"
#include "dialogues/ErrorMessage.h"
#include "dialogues/ConfirmPrompt.h"
#include "client/Client.h"
@ -132,7 +132,7 @@ ServerSaveActivity::ServerSaveActivity(SaveInfo save, ServerSaveActivity::SaveUp
SetOkayButton(okayButton);
if(save.GetGameSave())
ThumbnailBroker::Ref().RenderThumbnail(save.GetGameSave(), false, true, (Size.X/2)-16, -1, this);
RequestBroker::Ref().RenderThumbnail(save.GetGameSave(), false, true, (Size.X/2)-16, -1, this);
}
ServerSaveActivity::ServerSaveActivity(SaveInfo save, bool saveNow, ServerSaveActivity::SaveUploadedCallback * callback) :