diff --git a/src/client/AvatarRequest.h b/src/client/AvatarRequest.h index fb8a3a988..c9afc5a28 100644 --- a/src/client/AvatarRequest.h +++ b/src/client/AvatarRequest.h @@ -4,8 +4,6 @@ #include "ImageRequest.h" #include "common/String.h" -#include - namespace http { class AvatarRequest : public ImageRequest diff --git a/src/client/Client.cpp b/src/client/Client.cpp index b3fcd392b..c007ecce8 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -940,6 +940,14 @@ void Client::Shutdown() Client::~Client() { + if (versionCheckRequest) + { + versionCheckRequest->Cancel(); + } + if (alternateVersionCheckRequest) + { + alternateVersionCheckRequest->Cancel(); + } } diff --git a/src/client/ThumbnailRenderer.cpp b/src/client/ThumbnailRenderer.cpp new file mode 100644 index 000000000..126497e78 --- /dev/null +++ b/src/client/ThumbnailRenderer.cpp @@ -0,0 +1,54 @@ +#include "ThumbnailRenderer.h" + +#include + +#include "graphics/Graphics.h" +#include "simulation/SaveRenderer.h" +#include "client/GameSave.h" + +ThumbnailRendererTask::ThumbnailRendererTask(GameSave *save, int width, int height, bool autoRescale, bool decorations, bool fire) : + Save(new GameSave(*save)), + Width(width), + Height(height), + Decorations(decorations), + Fire(fire), + AutoRescale(autoRescale) +{ +} + +ThumbnailRendererTask::~ThumbnailRendererTask() +{ +} + +bool ThumbnailRendererTask::doWork() +{ + thumbnail = std::unique_ptr(SaveRenderer::Ref().Render(Save.get(), Decorations, Fire)); + if (thumbnail) + { + if (AutoRescale) + { + int scaleX = (int)std::ceil((float)thumbnail->Width / Width); + int scaleY = (int)std::ceil((float)thumbnail->Height / Height); + int scale = scaleX > scaleY ? scaleX : scaleY; + int newWidth = thumbnail->Width / scale, newHeight = thumbnail->Height / scale; + thumbnail->Resize(newWidth, newHeight, true); + Width = newWidth; + Height = newHeight; + } + else + { + thumbnail->Resize(Width, Height, true); + } + return true; + } + else + { + return false; + } +} + +std::unique_ptr ThumbnailRendererTask::GetThumbnail() +{ + return std::move(thumbnail); +} + diff --git a/src/client/ThumbnailRenderer.h b/src/client/ThumbnailRenderer.h new file mode 100644 index 000000000..8a8b5ae2d --- /dev/null +++ b/src/client/ThumbnailRenderer.h @@ -0,0 +1,28 @@ +#ifndef THUMBNAILRENDERER_H +#define THUMBNAILRENDERER_H + +#include "tasks/Task.h" + +#include + +class GameSave; +class VideoBuffer; +class ThumbnailRendererTask : public Task +{ + std::unique_ptr Save; + int Width, Height; + bool Decorations; + bool Fire; + bool AutoRescale; + std::unique_ptr thumbnail; + +public: + ThumbnailRendererTask(GameSave *save, int width, int height, bool autoRescale = false, bool decorations = true, bool fire = true); + virtual ~ThumbnailRendererTask(); + + virtual bool doWork() override; + std::unique_ptr GetThumbnail(); +}; + +#endif // THUMBNAILRENDERER_H + diff --git a/src/client/ThumbnailRequest.cpp b/src/client/ThumbnailRequest.cpp new file mode 100644 index 000000000..0ef2ab6ef --- /dev/null +++ b/src/client/ThumbnailRequest.cpp @@ -0,0 +1,15 @@ +#include "ThumbnailRequest.h" +#include "Config.h" + +namespace http +{ + ThumbnailRequest::ThumbnailRequest(int saveID, int saveDate, int width, int height) : + ImageRequest(( + saveDate + ? ByteString::Build("http://" STATICSERVER "/", saveID, "_", saveDate, "_small.pti") + : ByteString::Build("http://" STATICSERVER "/", saveID, "_small.pti") + ), width, height) + { + } +} + diff --git a/src/client/ThumbnailRequest.h b/src/client/ThumbnailRequest.h new file mode 100644 index 000000000..c405e8b6b --- /dev/null +++ b/src/client/ThumbnailRequest.h @@ -0,0 +1,17 @@ +#ifndef THUMBNAILREQUEST2_H +#define THUMBNAILREQUEST2_H + +#include "ImageRequest.h" +#include "common/String.h" + +namespace http +{ + class ThumbnailRequest : public ImageRequest + { + public: + ThumbnailRequest(int saveID, int saveDate, int width, int height); + }; +} + +#endif // THUMBNAILREQUEST2_H + diff --git a/src/gui/interface/AvatarButton.h b/src/gui/interface/AvatarButton.h index 431192f7b..867a3f6b6 100644 --- a/src/gui/interface/AvatarButton.h +++ b/src/gui/interface/AvatarButton.h @@ -6,7 +6,6 @@ #include "Component.h" #include "graphics/Graphics.h" #include "gui/interface/Colour.h" -#include "client/requestbroker/RequestListener.h" #include diff --git a/src/gui/interface/SaveButton.cpp b/src/gui/interface/SaveButton.cpp index b2eced197..fd1275a38 100644 --- a/src/gui/interface/SaveButton.cpp +++ b/src/gui/interface/SaveButton.cpp @@ -8,9 +8,11 @@ #include "SaveButton.h" #include "client/Client.h" #include "client/SaveInfo.h" +#include "client/ThumbnailRequest.h" +#include "client/ThumbnailRenderer.h" #include "graphics/Graphics.h" #include "simulation/SaveRenderer.h" -#include "client/requestbroker/RequestBroker.h" +#include "client/GameSave.h" namespace ui { @@ -18,11 +20,11 @@ SaveButton::SaveButton(Point position, Point size, SaveInfo * save): Component(position, size), file(NULL), save(save), - thumbnail(NULL), - waitingForThumb(false), + triedThumbnail(false), isMouseInsideAuthor(false), isMouseInsideHistory(false), showVotes(false), + thumbnailRequest(nullptr), isButtonDown(false), isMouseInside(false), selected(false), @@ -91,12 +93,12 @@ SaveButton::SaveButton(Point position, Point size, SaveFile * file): Component(position, size), file(file), save(NULL), - thumbnail(NULL), wantsDraw(false), - waitingForThumb(false), + triedThumbnail(false), isMouseInsideAuthor(false), isMouseInsideHistory(false), showVotes(false), + thumbnailRequest(nullptr), isButtonDown(false), isMouseInside(false), selected(false), @@ -117,50 +119,66 @@ SaveButton::SaveButton(Point position, Point size, SaveFile * file): SaveButton::~SaveButton() { - RequestBroker::Ref().DetachRequestListener(this); + if (thumbnailRequest) + { + thumbnailRequest->Cancel(); + } - delete thumbnail; delete actionCallback; delete save; delete file; } -void SaveButton::OnResponseReady(void * imagePtr, int identifier) -{ - VideoBuffer * image = (VideoBuffer*)imagePtr; - if (image) - { - delete thumbnail; - thumbnail = image; - waitingForThumb = false; - if (file) - thumbSize = ui::Point(thumbnail->Width, thumbnail->Height); - } -} - void SaveButton::Tick(float dt) { - if(!thumbnail && !waitingForThumb) + if (!thumbnail) { - float scaleFactor = (Size.Y-25)/((float)YRES); - ui::Point thumbBoxSize = ui::Point(((float)XRES)*scaleFactor, ((float)YRES)*scaleFactor); - if(save) + if (!triedThumbnail) { - if(save->GetGameSave()) + float scaleFactor = (Size.Y-25)/((float)YRES); + ui::Point thumbBoxSize = ui::Point(((float)XRES)*scaleFactor, ((float)YRES)*scaleFactor); + if (save) { - waitingForThumb = true; - RequestBroker::Ref().RenderThumbnail(save->GetGameSave(), thumbBoxSize.X, thumbBoxSize.Y, this); + if(save->GetGameSave()) + { + thumbnailRenderer = std::unique_ptr(new ThumbnailRendererTask(save->GetGameSave(), thumbBoxSize.X, thumbBoxSize.Y)); + thumbnailRenderer->Start(); + triedThumbnail = true; + } + else if (save->GetID()) + { + thumbnailRequest = new http::ThumbnailRequest(save->GetID(), save->GetVersion(), thumbBoxSize.X, thumbBoxSize.Y); + thumbnailRequest->Start(); + triedThumbnail = true; + } } - else if(save->GetID()) + else if (file && file->GetGameSave()) { - waitingForThumb = true; - RequestBroker::Ref().RetrieveThumbnail(save->GetID(), save->GetVersion(), thumbBoxSize.X, thumbBoxSize.Y, this); + thumbnailRenderer = std::unique_ptr(new ThumbnailRendererTask(file->GetGameSave(), thumbBoxSize.X, thumbBoxSize.Y, true, true, false)); + thumbnailRenderer->Start(); + triedThumbnail = true; } } - else if(file && file->GetGameSave()) + + if (thumbnailRequest && thumbnailRequest->CheckDone()) { - waitingForThumb = true; - RequestBroker::Ref().RenderThumbnail(file->GetGameSave(), true, false, thumbBoxSize.X, thumbBoxSize.Y, true, this); + thumbnail = thumbnailRequest->Finish(); + thumbnailRequest = nullptr; + } + + if (thumbnailRenderer) + { + thumbnailRenderer->Poll(); + if (thumbnailRenderer->GetDone()) + { + thumbnail = thumbnailRenderer->GetThumbnail(); + thumbnailRenderer.reset(); + } + } + + if (thumbnail && file) + { + thumbSize = ui::Point(thumbnail->Width, thumbnail->Height); } } } @@ -182,9 +200,9 @@ void SaveButton::Draw(const Point& screenPos) { //thumbBoxSize = ui::Point(thumbnail->Width, thumbnail->Height); if (save && save->id) - g->draw_image(thumbnail, screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, 255); + g->draw_image(thumbnail.get(), screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, 255); else - g->draw_image(thumbnail, screenPos.X+(Size.X-thumbSize.X)/2, screenPos.Y+(Size.Y-21-thumbSize.Y)/2, 255); + g->draw_image(thumbnail.get(), screenPos.X+(Size.X-thumbSize.X)/2, screenPos.Y+(Size.Y-21-thumbSize.Y)/2, 255); } else if (file && !file->GetGameSave()) g->drawtext(screenPos.X+(Size.X-Graphics::textwidth("Error loading save"))/2, screenPos.Y+(Size.Y-28)/2, "Error loading save", 180, 180, 180, 255); diff --git a/src/gui/interface/SaveButton.h b/src/gui/interface/SaveButton.h index b2da22096..08932597d 100644 --- a/src/gui/interface/SaveButton.h +++ b/src/gui/interface/SaveButton.h @@ -6,10 +6,16 @@ #include "Component.h" #include "client/SaveFile.h" #include "client/SaveInfo.h" -#include "client/requestbroker/RequestListener.h" #include "graphics/Graphics.h" #include "gui/interface/Colour.h" +#include + +class ThumbnailRendererTask; +namespace http +{ + class ThumbnailRequest; +} namespace ui { class SaveButton; @@ -23,11 +29,11 @@ public: virtual ~SaveButtonAction() {} }; -class SaveButton : public Component, public RequestListener +class SaveButton : public Component { SaveFile * file; SaveInfo * save; - VideoBuffer * thumbnail; + std::unique_ptr thumbnail; ui::Point thumbSize = ui::Point(0, 0); String name; String votesString; @@ -36,10 +42,12 @@ class SaveButton : public Component, public RequestListener int voteBarHeightUp; int voteBarHeightDown; bool wantsDraw; - bool waitingForThumb; + bool triedThumbnail; bool isMouseInsideAuthor; bool isMouseInsideHistory; bool showVotes; + std::unique_ptr thumbnailRenderer; + http::ThumbnailRequest *thumbnailRequest; public: SaveButton(Point position, Point size, SaveInfo * save); SaveButton(Point position, Point size, SaveFile * file); @@ -59,8 +67,6 @@ public: void Draw(const Point& screenPos) override; void Tick(float dt) override; - void OnResponseReady(void * imagePtr, int identifier) override; - void SetSelected(bool selected_) { selected = selected_; } bool GetSelected() { return selected; } void SetSelectable(bool selectable_) { selectable = selectable_; } diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp index a8fe1c193..67232715a 100644 --- a/src/simulation/SaveRenderer.cpp +++ b/src/simulation/SaveRenderer.cpp @@ -29,10 +29,14 @@ SaveRenderer::SaveRenderer(){ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding glDisable(GL_TEXTURE_2D); #endif + + pthread_mutex_init(&renderMutex, NULL); } VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire) { + pthread_mutex_lock(&renderMutex); + int width, height; VideoBuffer * tempThumb = NULL; width = save->blockWidth; @@ -145,11 +149,15 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire) if(doCollapse) save->Collapse(); g->Release(); + + pthread_mutex_unlock(&renderMutex); return tempThumb; } VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool decorations, bool fire) { + pthread_mutex_lock(&renderMutex); + GameSave * tempSave; try { tempSave = new GameSave((char*)saveData, dataSize); @@ -159,13 +167,17 @@ VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool VideoBuffer * buffer = new VideoBuffer(64, 64); buffer->BlendCharacter(32, 32, 'x', 255, 255, 255, 255); + pthread_mutex_unlock(&renderMutex); return buffer; } VideoBuffer * thumb = Render(tempSave, decorations, fire); delete tempSave; + + pthread_mutex_unlock(&renderMutex); return thumb; } SaveRenderer::~SaveRenderer() { + pthread_mutex_destroy(&renderMutex); } diff --git a/src/simulation/SaveRenderer.h b/src/simulation/SaveRenderer.h index 3294f4ed7..d1e9cc871 100644 --- a/src/simulation/SaveRenderer.h +++ b/src/simulation/SaveRenderer.h @@ -4,6 +4,7 @@ #include "graphics/OpenGLHeaders.h" #endif #include "common/Singleton.h" +#include "common/tpt-thread.h" class GameSave; class VideoBuffer; @@ -15,6 +16,7 @@ class SaveRenderer: public Singleton { Graphics * g; Simulation * sim; Renderer * ren; + pthread_mutex_t renderMutex; public: SaveRenderer(); VideoBuffer * Render(GameSave * save, bool decorations = true, bool fire = true);