From 5befe5c25f8f188e7588de44ab2c8bead22ae999 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Fri, 27 Jul 2012 20:06:17 +0100 Subject: Local file browser + some more interesting things like Progress bar UI component diff --git a/src/Misc.cpp b/src/Misc.cpp index 56e7370..c2963be 100644 --- a/src/Misc.cpp +++ b/src/Misc.cpp @@ -19,6 +19,35 @@ #include #endif +std::string URLEscape(std::string source) +{ + char * src = (char *)source.c_str(); + char * dst = (char *)calloc((source.length()*3)+2, 1); + char *d; + unsigned char *s; + + for (d=dst; *d; d++) ; + + for (s=(unsigned char *)src; *s; s++) + { + if ((*s>='0' && *s<='9') || + (*s>='a' && *s<='z') || + (*s>='A' && *s<='Z')) + *(d++) = *s; + else + { + *(d++) = '%'; + *(d++) = hex[*s>>4]; + *(d++) = hex[*s&15]; + } + } + *d = 0; + + std::string finalString(dst); + free(dst); + return finalString; +} + #if defined(USE_SDL) && (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11) #include SDL_SysWMinfo sdl_wminfo; @@ -212,35 +241,6 @@ void strcaturl(char *dst, char *src) *d = 0; } -std::string URLEscape(std::string source) -{ - char * src = (char *)source.c_str(); - char * dst = (char *)calloc((source.length()*3)+2, 1); - char *d; - unsigned char *s; - - for (d=dst; *d; d++) ; - - for (s=(unsigned char *)src; *s; s++) - { - if ((*s>='0' && *s<='9') || - (*s>='a' && *s<='z') || - (*s>='A' && *s<='Z')) - *(d++) = *s; - else - { - *(d++) = '%'; - *(d++) = hex[*s>>4]; - *(d++) = hex[*s&15]; - } - } - *d = 0; - - std::string finalString(dst); - free(dst); - return finalString; -} - void strappend(char *dst, char *src) { char *d; diff --git a/src/Misc.h b/src/Misc.h index db391b0..12b88bd 100644 --- a/src/Misc.h +++ b/src/Misc.h @@ -3,6 +3,7 @@ #include #include #include +#include #if defined(WIN32) && !defined(__GNUC__) #define x86_cpuid(func,af,bf,cf,df) \ diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 8fb9ea0..abfaaac 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -207,7 +207,6 @@ int main(int argc, char * argv[]) //glScaled(2.0f, 2.0f, 1.0f); #endif - ui::Engine::Ref().g = new Graphics(); //ui::Engine::Ref().g->AttachSDLSurface(SDLOpen()); diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 2e74c48..a9661ca 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -22,13 +22,19 @@ #include "Misc.h" #include "interface/Point.h" - #include "client/SaveInfo.h" - #include "ClientListener.h" - #include "Update.h" +extern "C" +{ +#if defined(WIN32) && !defined(__GNUC__) +#include +#else +#include +#endif +} + Client::Client(): authUser(0, ""), updateAvailable(false) @@ -117,6 +123,95 @@ Client::Client(): versionCheckRequest = http_async_req_start(NULL, SERVER "/Download/Version.json", NULL, 0, 1); } +std::vector Client::DirectorySearch(std::string directory, std::string search, std::string extension) +{ + std::vector extensions; + extensions.push_back(extension); + return DirectorySearch(directory, search, extensions); +} + +std::vector Client::DirectorySearch(std::string directory, std::string search, std::vector extensions) +{ + std::vector results; + + //Get full file listing + std::vector directoryList; +#if defined(WIN32) && !defined(__GNUC__) + //Windows + struct _finddata_t currentFile; + intptr_t findFileHandle; + std::string fileMatch = directory + "*.*"; + findFileHandle = _findfirst(fileMatch.c_str(), ¤tFile); + if (findFileHandle == -1L) + { + printf("Unable to open directory\n"); + return std::vector(); + } + do + { + std::string currentFileName = std::string(currentFile.name); + if(currentFileName.length()>4) + directoryList.push_back(directory+currentFileName); + } + while (_findnext(findFileHandle, ¤tFile) == 0); + _findclose(findFileHandle); +#else + //Linux or MinGW + struct dirent * directoryEntry; + DIR *directoryHandle = opendir(directory.c_str()); + if(!directoryHandle) + { + printf("Unable to open directory\n"); + return std::vector(); + } + while(directoryEntry = readdir(directoryHandle)) + { + std::string currentFileName = std::string(directoryEntry->d_name); + if(currentFileName.length()>4) + directoryList.push_back(directory+currentFileName); + } + closedir(directoryHandle); +#endif + + //Filter results + return directoryList; + return results; +} + +std::vector Client::ReadFile(std::string filename) +{ + try + { + std::ifstream fileStream; + fileStream.open(string(filename).c_str(), ios::binary); + if(fileStream.is_open()) + { + fileStream.seekg(0, ios::end); + size_t fileSize = fileStream.tellg(); + fileStream.seekg(0); + + unsigned char * tempData = new unsigned char[fileSize]; + fileStream.read((char *)tempData, fileSize); + fileStream.close(); + + std::vector fileData; + fileData.insert(fileData.end(), tempData, tempData+fileSize); + delete[] tempData; + + return fileData; + } + else + { + return std::vector(); + } + } + catch(std::exception & e) + { + std::cerr << "Readfile: " << e.what() << std::endl; + throw; + } +} + void Client::Tick() { //Check status on version check request diff --git a/src/client/Client.h b/src/client/Client.h index 7b94393..d7e1afb 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -81,6 +81,11 @@ public: Client(); ~Client(); + std::vector DirectorySearch(std::string directory, std::string search, std::vector extensions); + std::vector DirectorySearch(std::string directory, std::string search, std::string extension); + + std::vector ReadFile(std::string filename); + void AddListener(ClientListener * listener); void RemoveListener(ClientListener * listener); diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 1243ea0..f11b443 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -7,6 +7,7 @@ // #include +#include #include #include "Config.h" #include "bson/BSON.h" @@ -56,6 +57,50 @@ GameSave::GameSave(int width, int height) setSize(width, height); } +GameSave::GameSave(std::vector data) +{ + blockWidth = 0; + blockHeight = 0; + + blockMap = NULL; + blockMapPtr = NULL; + fanVelX = NULL; + fanVelXPtr = NULL; + fanVelY = NULL; + fanVelYPtr = NULL; + particles = NULL; + + try{ + read(&data[0], data.size()); + } catch (ParseException& e) { + std::cout << e.what() << std::endl; + this->~GameSave(); //Free any allocated memory + throw; + } +} + +GameSave::GameSave(std::vector data) +{ + blockWidth = 0; + blockHeight = 0; + + blockMap = NULL; + blockMapPtr = NULL; + fanVelX = NULL; + fanVelXPtr = NULL; + fanVelY = NULL; + fanVelYPtr = NULL; + particles = NULL; + + try{ + read((char*)(&data[0]), data.size()); + } catch (ParseException& e) { + std::cout << e.what() << std::endl; + this->~GameSave(); //Free any allocated memory + throw; + } +} + GameSave::GameSave(char * data, int dataSize) { blockWidth = 0; @@ -69,31 +114,36 @@ GameSave::GameSave(char * data, int dataSize) fanVelYPtr = NULL; particles = NULL; - try { - if(dataSize > 0) + try{ + read(data, dataSize); + } catch (ParseException& e) { + std::cout << e.what() << std::endl; + this->~GameSave(); //Free any allocated memory + throw; + } +} + +void GameSave::read(char * data, int dataSize) +{ + if(dataSize > 0) + { + if(data[0] == 0x50 || data[0] == 0x66) { - if(data[0] == 0x50 || data[0] == 0x66) - { - readPSv(data, dataSize); - } - else if(data[0] == 'O') - { - readOPS(data, dataSize); - } - else - { - std::cerr << "Got Magic number '" << data[0] << "'" << std::endl; - throw ParseException(ParseException::Corrupt, "Invalid save format"); - } + readPSv(data, dataSize); + } + else if(data[0] == 'O') + { + readOPS(data, dataSize); } else { - throw ParseException(ParseException::Corrupt, "No data"); + std::cerr << "Got Magic number '" << data[0] << "'" << std::endl; + throw ParseException(ParseException::Corrupt, "Invalid save format"); } - } catch (ParseException& e) { - std::cout << e.what() << std::endl; - this->~GameSave(); //Free any allocated memory - throw; + } + else + { + throw ParseException(ParseException::Corrupt, "No data"); } } @@ -895,8 +945,13 @@ void GameSave::readPSv(char * data, int dataLength) setSize(bw, bh); - if (BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+12), dataLength-12, 0, 0)) - throw ParseException(ParseException::Corrupt, "Cannot decompress"); + int bzStatus = 0; + if (bzStatus = BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+12), dataLength-12, 0, 0)) + { + std::stringstream bzStatusStr; + bzStatusStr << bzStatus; + throw ParseException(ParseException::Corrupt, "Cannot decompress: " + bzStatusStr.str()); + } dataLength = i; std::cout << "Parsing " << dataLength << " bytes of data, version " << ver << std::endl; diff --git a/src/client/GameSave.h b/src/client/GameSave.h index 1e5b514..a1bd1cf 100644 --- a/src/client/GameSave.h +++ b/src/client/GameSave.h @@ -59,6 +59,8 @@ public: GameSave(GameSave & save); GameSave(int width, int height); GameSave(char * data, int dataSize); + GameSave(std::vector data); + GameSave(std::vector data); ~GameSave(); void setSize(int width, int height); char * Serialise(int & dataSize); @@ -85,6 +87,7 @@ private: float * fanVelYPtr; unsigned char * blockMapPtr; + void read(char * data, int dataSize); void readOPS(char * data, int dataLength); void readPSv(char * data, int dataLength); char * serialiseOPS(int & dataSize); diff --git a/src/client/SaveFile.cpp b/src/client/SaveFile.cpp index 6675aae..7c35466 100644 --- a/src/client/SaveFile.cpp +++ b/src/client/SaveFile.cpp @@ -6,19 +6,35 @@ */ #include "SaveFile.h" +#include "Client.h" + #include "search/Thumbnail.h" SaveFile::SaveFile(SaveFile & save): - gameSave(NULL) + gameSave(NULL), + thumbnail(NULL) { if(save.gameSave) gameSave = new GameSave(*save.gameSave); + if(save.thumbnail) + thumbnail = new Thumbnail(*save.thumbnail); +} + +Thumbnail * SaveFile::GetThumbnail() +{ + return thumbnail; +} + +void SaveFile::SetThumbnail(Thumbnail * thumb) +{ + thumbnail = thumb; } SaveFile::SaveFile(string filename): filename(filename), - gameSave(NULL) - { - //Load file + gameSave(NULL), + thumbnail(NULL) +{ + } GameSave * SaveFile::GetGameSave() @@ -39,5 +55,7 @@ string SaveFile::GetName() SaveFile::~SaveFile() { if(gameSave) delete gameSave; + if(thumbnail) + delete thumbnail; } diff --git a/src/client/SaveFile.h b/src/client/SaveFile.h index 8b4005a..54a9290 100644 --- a/src/client/SaveFile.h +++ b/src/client/SaveFile.h @@ -11,19 +11,24 @@ #include #include "GameSave.h" + using namespace std; +class Thumbnail; class SaveFile { public: SaveFile(SaveFile & save); SaveFile(string filename); + Thumbnail * GetThumbnail(); GameSave * GetGameSave(); + void SetThumbnail(Thumbnail * thumb); void SetGameSave(GameSave * save); string GetName(); virtual ~SaveFile(); private: + Thumbnail * thumbnail; GameSave * gameSave; string filename; }; diff --git a/src/filebrowser/FileBrowserActivity.cpp b/src/filebrowser/FileBrowserActivity.cpp new file mode 100644 index 0000000..186ed6a --- /dev/null +++ b/src/filebrowser/FileBrowserActivity.cpp @@ -0,0 +1,238 @@ +#include +#include +#include "FileBrowserActivity.h" +#include "interface/Label.h" +#include "interface/Textbox.h" +#include "interface/ScrollPanel.h" +#include "interface/SaveButton.h" +#include "interface/ProgressBar.h" +#include "client/Client.h" +#include "client/SaveFile.h" +#include "Style.h" +#include "tasks/Task.h" +#include "simulation/SaveRenderer.h" + +class Thumbnail; + + +class SaveSelectedAction: public ui::SaveButtonAction +{ + FileBrowserActivity * a; +public: + SaveSelectedAction(FileBrowserActivity * _a) { a = _a; } + virtual void ActionCallback(ui::SaveButton * sender) + { + a->SelectSave(sender->GetSaveFile()); + } +}; + +//Currently, reading is done on another thread, we can't render outside the main thread due to some bullshit with OpenGL +class LoadFilesTask: public Task +{ + std::string directory; + std::vector saveFiles; + + virtual void before() + { + + } + + virtual void after() + { + + } + + virtual bool doWork() + { + std::vector files = Client::Ref().DirectorySearch(directory, "", ".cps"); + + + notifyProgress(-1); + for(std::vector::iterator iter = files.begin(), end = files.end(); iter != end; ++iter) + { + SaveFile * saveFile = new SaveFile(*iter); + try + { + std::vector data = Client::Ref().ReadFile(*iter); + GameSave * tempSave = new GameSave(data); + saveFile->SetGameSave(tempSave); + saveFiles.push_back(saveFile); + } + catch(std::exception & e) + { + //:( + } + } + return true; + } + +public: + std::vector GetSaveFiles() + { + return saveFiles; + } + + LoadFilesTask(std::string directory): + directory(directory) + { + + } +}; + +FileBrowserActivity::FileBrowserActivity(std::string directory, FileSelectedCallback * callback): + ui::Window(ui::Point(-1, -1), ui::Point(450, 300)), + callback(callback), + directory(directory), + totalFiles(0) +{ + ui::Engine::Ref().ShowWindow(this); + + ui::Label * titleLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 18), "Save Browser"); + titleLabel->SetTextColour(style::Colour::WarningTitle); + titleLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + titleLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(titleLabel); + + //ui::Textbox * textField = new ui::Textbox(ui::Point(8, 25), ui::Point(Size.X-16, 16), "", "[search]"); + //textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + //textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + //AddComponent(textField); + + itemList = new ui::ScrollPanel(ui::Point(4, 45), ui::Point(Size.X-8, Size.Y-53)); + AddComponent(itemList); + + progressBar = new ui::ProgressBar(ui::Point((Size.X-200)/2, 45+(Size.Y-66)/2), ui::Point(200, 17)); + AddComponent(progressBar); + + filesX = 4; + filesY = 3; + buttonPadding = 2; + fileX = 0; + fileY = 0; + + buttonXOffset = 0; + buttonYOffset = 0; + buttonAreaWidth = itemList->Size.X; + buttonAreaHeight = itemList->Size.Y;// - buttonYOffset - 18; + buttonWidth = (buttonAreaWidth/filesX) - buttonPadding*2; + buttonHeight = (buttonAreaHeight/filesY) - buttonPadding*2; + + loadDirectory(directory); +} + +void FileBrowserActivity::SelectSave(SaveFile * file) +{ + if(callback) + callback->FileSelected(new SaveFile(*file)); + Exit(); +} + +void FileBrowserActivity::loadDirectory(std::string directory) +{ + progressBar->Visible = true; + progressBar->SetProgress(-1); + progressBar->SetStatus("Loading files"); + loadFiles = new LoadFilesTask(directory); + loadFiles->AddTaskListener(this); + loadFiles->Start(); +} + +void FileBrowserActivity::NotifyDone(Task * task) +{ + for(int i = 0; i < components.size(); i++) + { + RemoveComponent(components[i]); + itemList->RemoveChild(components[i]); + delete components[i]; + } + fileX = 0; + fileY = 0; + files = ((LoadFilesTask*)task)->GetSaveFiles(); + totalFiles = files.size(); + delete task; + loadFiles = NULL; +} + +void FileBrowserActivity::OnMouseDown(int x, int y, unsigned button) +{ + if(!(x > Position.X && y > Position.Y && y < Position.Y+Size.Y && x < Position.X+Size.X)) //Clicked outside window + Exit(); +} + +void FileBrowserActivity::Exit() +{ + ui::Engine::Ref().CloseWindow(); + SelfDestruct(); +} + +void FileBrowserActivity::NotifyError(Task * task) +{ + +} + +void FileBrowserActivity::NotifyProgress(Task * task) +{ + progressBar->SetProgress(task->GetProgress()); +} + +void FileBrowserActivity::NotifyStatus(Task * task) +{ + +} + +void FileBrowserActivity::OnTick(float dt) +{ + if(loadFiles) + loadFiles->Poll(); + + if(files.size()) + { + SaveFile * saveFile = files.back(); + files.pop_back(); + + if(fileX == filesX) + { + fileX = 0; + fileY++; + } + ui::SaveButton * saveButton = new ui::SaveButton( + ui::Point( + buttonXOffset + buttonPadding + fileX*(buttonWidth+buttonPadding*2), + buttonYOffset + buttonPadding + fileY*(buttonHeight+buttonPadding*2) + ), + ui::Point(buttonWidth, buttonHeight), + saveFile); + saveButton->Tick(dt); + saveButton->SetActionCallback(new SaveSelectedAction(this)); + progressBar->SetStatus("Rendering thumbnails"); + progressBar->SetProgress((float(totalFiles-files.size())/float(totalFiles))*100.0f); + componentsQueue.push_back(saveButton); + fileX++; + } + else if(componentsQueue.size()) + { + for(std::vector::iterator iter = componentsQueue.begin(), end = componentsQueue.end(); iter != end; ++iter) + { + components.push_back(*iter); + itemList->AddChild(*iter); + } + componentsQueue.clear(); + itemList->InnerSize.Y = (buttonHeight+(buttonPadding*2))*fileY; + progressBar->Visible = false; + } +} + +void FileBrowserActivity::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + + //Window Background+Outline + g->clearrect(Position.X-2, Position.Y-2, Size.X+4, Size.Y+4); + g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 255, 255, 255, 255); +} + +FileBrowserActivity::~FileBrowserActivity() +{ + if(callback) + delete callback; +} \ No newline at end of file diff --git a/src/filebrowser/FileBrowserActivity.h b/src/filebrowser/FileBrowserActivity.h new file mode 100644 index 0000000..4a0020b --- /dev/null +++ b/src/filebrowser/FileBrowserActivity.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include "interface/Window.h" +#include "tasks/TaskListener.h" + + +class SaveFile; +class FileSelectedCallback +{ +public: + FileSelectedCallback() {} + virtual ~FileSelectedCallback() {} + virtual void FileSelected(SaveFile* file) {} +}; + +namespace ui +{ + class ScrollPanel; + class ProgressBar; +} + +class LoadFilesTask; +class FileBrowserActivity: public ui::Window, public TaskListener +{ + LoadFilesTask * loadFiles; + FileSelectedCallback * callback; + ui::ScrollPanel * itemList; + std::vector files; + std::vector components; + std::vector componentsQueue; + std::string directory; + + ui::ProgressBar * progressBar; + + int totalFiles; + int filesX, filesY, buttonPadding; + int fileX, fileY; + int buttonWidth, buttonHeight, buttonAreaWidth, buttonAreaHeight, buttonXOffset, buttonYOffset; + + void populateList(); +public: + FileBrowserActivity(std::string directory, FileSelectedCallback * callback); + virtual void OnDraw(); + virtual void OnTick(float dt); + virtual void OnMouseDown(int x, int y, unsigned button); + void loadDirectory(std::string directory); + void SelectSave(SaveFile * file); + virtual ~FileBrowserActivity(); + + virtual void NotifyDone(Task * task); + virtual void NotifyError(Task * task); + virtual void NotifyProgress(Task * task); + virtual void NotifyStatus(Task * task); + + void Exit(); +}; \ No newline at end of file diff --git a/src/game/GameController.cpp b/src/game/GameController.cpp index 4d13e52..db23bb8 100644 --- a/src/game/GameController.cpp +++ b/src/game/GameController.cpp @@ -16,6 +16,7 @@ #include "elementsearch/ElementSearchActivity.h" #include "update/UpdateActivity.h" #include "Notification.h" +#include "filebrowser/FileBrowserActivity.h" using namespace std; @@ -523,6 +524,32 @@ void GameController::OpenSearch() ui::Engine::Ref().ShowWindow(search->GetView()); } +void GameController::OpenLocalSaveWindow() +{ + +} + +void GameController::LoadSaveFile(SaveFile * file) +{ + gameModel->SetSaveFile(file); +} + +void GameController::OpenLocalBrowse() +{ + class LocalSaveOpenCallback: public FileSelectedCallback + { + GameController * c; + public: + LocalSaveOpenCallback(GameController * _c): c(_c) {} + virtual ~LocalSaveOpenCallback() {}; + virtual void FileSelected(SaveFile* file) + { + c->LoadSaveFile(file); + } + }; + new FileBrowserActivity(LOCAL_SAVE_DIR PATH_SEP, new LocalSaveOpenCallback(this)); +} + void GameController::OpenLogin() { loginWindow = new LoginController(new LoginCallback(this)); diff --git a/src/game/GameController.h b/src/game/GameController.h index 441aeeb..335e624 100644 --- a/src/game/GameController.h +++ b/src/game/GameController.h @@ -86,9 +86,12 @@ public: void SetActiveTool(int toolSelection, Tool * tool); void SetColour(ui::Colour colour); void SetToolStrength(float value); + void LoadSaveFile(SaveFile * file); void OpenSearch(); void OpenLogin(); void OpenTags(); + void OpenLocalSaveWindow(); + void OpenLocalBrowse(); void OpenOptions(); void OpenRenderOptions(); void OpenSaveWindow(); diff --git a/src/game/GameModel.cpp b/src/game/GameModel.cpp index 536ca42..fef4e61 100644 --- a/src/game/GameModel.cpp +++ b/src/game/GameModel.cpp @@ -308,6 +308,34 @@ void GameModel::SetSave(SaveInfo * newSave) notifySaveChanged(); } +void GameModel::SetSaveFile(SaveFile * newSave) +{ + SetSave(NULL); + + if(newSave && newSave->GetGameSave()) + { + GameSave * saveData = newSave->GetGameSave(); + SetPaused(saveData->paused & GetPaused()); + sim->gravityMode = saveData->gravityMode; + sim->air->airMode = saveData->airMode; + sim->legacy_enable = saveData->legacyEnable; + sim->water_equal_test = saveData->waterEEnabled; + if(saveData->gravityEnable && !sim->grav->ngrav_enable) + { + sim->grav->start_grav_async(); + } + else if(!saveData->gravityEnable && sim->grav->ngrav_enable) + { + sim->grav->stop_grav_async(); + } + sim->clear_sim(); + sim->Load(saveData); + } + delete newSave; + + notifySaveChanged(); +} + Simulation * GameModel::GetSimulation() { return sim; diff --git a/src/game/GameModel.h b/src/game/GameModel.h index 28b86e6..afe1960 100644 --- a/src/game/GameModel.h +++ b/src/game/GameModel.h @@ -95,6 +95,7 @@ public: SaveInfo * GetSave(); Brush * GetBrush(); void SetSave(SaveInfo * newSave); + void SetSaveFile(SaveFile * newSave); void AddObserver(GameView * observer); Tool * GetActiveTool(int selection); void SetActiveTool(int selection, Tool * tool); diff --git a/src/game/GameView.cpp b/src/game/GameView.cpp index 5bf7043..7e34b85 100644 --- a/src/game/GameView.cpp +++ b/src/game/GameView.cpp @@ -37,7 +37,8 @@ GameView::GameView(): toolTip(""), infoTip(""), infoTipPresence(0), - toolTipPosition(-1, -1) + toolTipPosition(-1, -1), + alternativeSaveSource(false) { int currentX = 1; @@ -49,7 +50,10 @@ GameView::GameView(): SearchAction(GameView * _v) { v = _v; } void ActionCallback(ui::Button * sender) { - v->c->OpenSearch(); + if(v->GetAlternativeSourceEnabled()) + v->c->OpenLocalBrowse(); + else + v->c->OpenSearch(); } }; @@ -89,7 +93,10 @@ GameView::GameView(): SaveSimulationAction(GameView * _v) { v = _v; } void ActionCallback(ui::Button * sender) { - v->c->OpenSaveWindow(); + if(v->GetAlternativeSourceEnabled()) + v->c->OpenLocalSaveWindow(); + else + v->c->OpenSaveWindow(); } }; saveSimulationButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(150, 15), "[untitled simulation]"); @@ -847,6 +854,7 @@ void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool drawMode = DrawFill; else drawMode = DrawRect; + enableHDDSave(); break; case KEY_SHIFT: if(drawModeReset) @@ -940,6 +948,9 @@ void GameView::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bo case KEY_ALT: drawSnap = false; break; + case KEY_CTRL: + disableHDDSave(); + break; case 'z': if(!zoomCursorFixed) c->SetZoomEnabled(false); @@ -1152,6 +1163,32 @@ void GameView::changeColour() c->SetColour(ui::Colour(colourRSlider->GetValue(), colourGSlider->GetValue(), colourBSlider->GetValue(), colourASlider->GetValue())); } +void GameView::enableHDDSave() +{ + if(!alternativeSaveSource) + { + alternativeSaveSource = true; + + saveSimulationButton->Appearance.BackgroundInactive = ui::Colour(255, 255, 255); + saveSimulationButton->Appearance.TextInactive = ui::Colour(0, 0, 0); + searchButton->Appearance.BackgroundInactive = ui::Colour(255, 255, 255); + searchButton->Appearance.TextInactive = ui::Colour(0, 0, 0); + } +} + +void GameView::disableHDDSave() +{ + if(alternativeSaveSource) + { + alternativeSaveSource = false; + + saveSimulationButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + saveSimulationButton->Appearance.TextInactive = ui::Colour(255, 255, 255); + searchButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + searchButton->Appearance.TextInactive = ui::Colour(255, 255, 255); + } +} + void GameView::OnDraw() { Graphics * g = ui::Engine::Ref().g; diff --git a/src/game/GameView.h b/src/game/GameView.h index ad9e095..2bf8e9e 100644 --- a/src/game/GameView.h +++ b/src/game/GameView.h @@ -37,6 +37,7 @@ private: bool zoomEnabled; bool zoomCursorFixed; bool drawSnap; + bool alternativeSaveSource; int toolIndex; int infoTipPresence; @@ -94,12 +95,16 @@ private: void changeColour(); virtual ui::Point lineSnapCoords(ui::Point point1, ui::Point point2); virtual ui::Point rectSnapCoords(ui::Point point1, ui::Point point2); + + void enableHDDSave(); + void disableHDDSave(); public: GameView(); //Breaks MVC, but any other way is going to be more of a mess. ui::Point GetMousePosition(); void SetSample(SimulationSample sample); + bool GetAlternativeSourceEnabled(){ return alternativeSaveSource; } void AttachController(GameController * _c){ c = _c; } void NotifyRendererChanged(GameModel * sender); diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 2bed5ee..2b12b1d 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -31,7 +31,6 @@ VideoBuffer::VideoBuffer(VideoBuffer * old): std::copy(old->Buffer, old->Buffer+(old->Width*old->Height), Buffer); }; - VideoBuffer::~VideoBuffer() { delete[] Buffer; diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index 3b25bb1..e74239e 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -135,6 +135,9 @@ public: static int textwidth(const char *s); static void textsize(const char * s, int & width, int & height); + void Acquire(); + void Release(); + void blendpixel(int x, int y, int r, int g, int b, int a); void addpixel(int x, int y, int r, int g, int b, int a); diff --git a/src/graphics/OpenGLGraphics.cpp b/src/graphics/OpenGLGraphics.cpp index 66a1753..43bff6b 100644 --- a/src/graphics/OpenGLGraphics.cpp +++ b/src/graphics/OpenGLGraphics.cpp @@ -1,11 +1,17 @@ #include "Graphics.h" #include "font.h" +#include #ifdef OGLI +static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER; + Graphics::Graphics(): sdl_scale(1) { + if(gMutex == PTHREAD_MUTEX_INITIALIZER) + pthread_mutex_init (&gMutex, NULL); + Reset(); glEnable(GL_BLEND); @@ -35,6 +41,16 @@ sdl_scale(1) glDisable(GL_TEXTURE_2D); } +void Graphics::Acquire() +{ + pthread_mutex_lock(&gMutex); +} + +void Graphics::Release() +{ + pthread_mutex_unlock(&gMutex); +} + Graphics::~Graphics() { } diff --git a/src/graphics/RasterDrawMethods.inl b/src/graphics/RasterDrawMethods.inl index 76b9dde..cce81d2 100644 --- a/src/graphics/RasterDrawMethods.inl +++ b/src/graphics/RasterDrawMethods.inl @@ -329,7 +329,7 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h) void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int a) { int i, j, r, g, b; - if (!img) return; + if (!img || y >= VIDYRES) return; if(y + h > VIDYRES) h = (VIDYRES)-y; //Adjust height to prevent drawing off the bottom if(a >= 255) for (j=0; jfillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundActive.Red, Appearance.BackgroundActive.Green, Appearance.BackgroundActive.Blue, 255); g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BorderActive.Red, Appearance.BorderActive.Green, Appearance.BorderActive.Blue, 255); g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, Appearance.TextActive.Red, Appearance.TextActive.Green, Appearance.TextActive.Blue, 255); } else { + bgColour = Appearance.BackgroundInactive; g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundInactive.Red, Appearance.BackgroundInactive.Green, Appearance.BackgroundInactive.Blue, 255); g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BorderInactive.Red, Appearance.BorderInactive.Green, Appearance.BorderInactive.Blue, 255); g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, Appearance.TextInactive.Red, Appearance.TextInactive.Green, Appearance.TextInactive.Blue, 255); @@ -102,23 +105,27 @@ void Button::Draw(const Point& screenPos) } else { + bgColour = Appearance.BackgroundInactive; g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundInactive.Red, Appearance.BackgroundInactive.Green, Appearance.BackgroundInactive.Blue, 180); g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BackgroundDisabled.Red, Appearance.BackgroundDisabled.Green, Appearance.BackgroundDisabled.Blue, Appearance.BackgroundDisabled.Alpha); g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, 180, 180, 180, 255); } + + bool iconInvert = (bgColour.Blue + (3*bgColour.Green) + (2*bgColour.Red))>544?true:false; + if(Appearance.icon) { if(Enabled) if(isButtonDown || (isTogglable && toggle)) { - g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 255, true); + g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 255, iconInvert); } else { - g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 255); + g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 255, iconInvert); } else - g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 180); + g->draw_icon(Position.X+iconPosition.X, Position.Y+iconPosition.Y, Appearance.icon, 180, iconInvert); } } diff --git a/src/interface/Engine.cpp b/src/interface/Engine.cpp index 07c4203..ddf29c6 100644 --- a/src/interface/Engine.cpp +++ b/src/interface/Engine.cpp @@ -170,6 +170,7 @@ void Engine::Draw() { if(lastBuffer && !(state_->Position.X == 0 && state_->Position.Y == 0 && state_->Size.X == width_ && state_->Size.Y == height_)) { + g->Acquire(); g->Clear(); #ifndef OGLI memcpy(g->vid, lastBuffer, (width_ * height_) * PIXELSIZE); @@ -188,6 +189,7 @@ void Engine::Draw() ui::Engine::Ref().g->drawtext(10, 10, fpsText, 255, 255, 255, 255); #endif g->Finalise(); + g->Release(); FrameIndex++; FrameIndex %= 7200; } diff --git a/src/interface/Panel.cpp b/src/interface/Panel.cpp index 3b9cfc1..d673037 100644 --- a/src/interface/Panel.cpp +++ b/src/interface/Panel.cpp @@ -161,7 +161,7 @@ void Panel::Draw(const Point& screenPos) //dst=(pixel *)sdl_scrn->pixels+y*sdl_scrn->pitch/PIXELSIZE+x; for (int row = 0; row < Size.Y; row++) { - std::copy(myVid+(row*Size.W), myVid+(row*Size.W)+Size.W, lastVid+(screenPos.Y*(XRES+BARSIZE))+screenPos.X); + std::copy(myVid+(row*(XRES+BARSIZE)), myVid+(row*(XRES+BARSIZE))+Size.X, lastVid+((screenPos.Y+row)*(XRES+BARSIZE))+screenPos.X); } #endif } diff --git a/src/interface/ProgressBar.cpp b/src/interface/ProgressBar.cpp new file mode 100644 index 0000000..8bc765b --- /dev/null +++ b/src/interface/ProgressBar.cpp @@ -0,0 +1,65 @@ +#include "ProgressBar.h" +#include "Style.h" + +using namespace ui; + +ProgressBar::ProgressBar(Point position, Point size): + Component(position, size), + intermediatePos(0.0f), + progressStatus("") +{ + progress = 0; +} + +void ProgressBar::SetProgress(int progress) +{ + this->progress = progress; +} + +void ProgressBar::SetStatus(std::string status) +{ + progressStatus = status; +} + +void ProgressBar::Draw(const Point & screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + + ui::Colour progressBarColour = style::Colour::WarningTitle; + + g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 255, 255, 255, 255); + + if(progress!=-1) + { + if(progress > 0) + { + float size = float(Size.X-4)*(float(progress)/100.0f); // TIL... + size = std::min(std::max(size, 0.0f), float(Size.X-4)); + g->fillrect(screenPos.X + 2, screenPos.Y + 2, size, Size.Y-4, progressBarColour.Red, progressBarColour.Green, progressBarColour.Blue, 255); + } + } else { + int size = 40, rsize = 0; + float position = float(Size.X-4)*(intermediatePos/100.0f); + if(position + size - 1 > Size.X-4) + { + size = (Size.X-4)-position+1; + rsize = 40-size; + } + g->fillrect(screenPos.X + 2 + position, screenPos.Y + 2, size, Size.Y-4, progressBarColour.Red, progressBarColour.Green, progressBarColour.Blue, 255); + if(rsize) + { + g->fillrect(screenPos.X + 2, screenPos.Y + 2, rsize, Size.Y-4, progressBarColour.Red, progressBarColour.Green, progressBarColour.Blue, 255); + } + } + if(progress<50) + g->drawtext(screenPos.X + ((Size.X-Graphics::textwidth(progressStatus.c_str()))/2), screenPos.Y + (Size.Y-8)/2, progressStatus, 255, 255, 255, 255); + else + g->drawtext(screenPos.X + ((Size.X-Graphics::textwidth(progressStatus.c_str()))/2), screenPos.Y + (Size.Y-8)/2, progressStatus, 0, 0, 0, 255); +} + +void ProgressBar::Tick(float dt) +{ + intermediatePos += 1.0f*dt; + if(intermediatePos>100.0f) + intermediatePos = 0.0f; +} \ No newline at end of file diff --git a/src/interface/ProgressBar.h b/src/interface/ProgressBar.h new file mode 100644 index 0000000..9d803cc --- /dev/null +++ b/src/interface/ProgressBar.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Component.h" + +namespace ui +{ + class ProgressBar: public Component + { + int progress; + float intermediatePos; + std::string progressStatus; + public: + ProgressBar(Point position, Point size); + virtual void SetProgress(int progress); + virtual void SetStatus(std::string status); + virtual void Draw(const Point & screenPos); + virtual void Tick(float dt); + }; +} diff --git a/src/interface/SaveButton.cpp b/src/interface/SaveButton.cpp index ee57e81..e3f7422 100644 --- a/src/interface/SaveButton.cpp +++ b/src/interface/SaveButton.cpp @@ -61,7 +61,8 @@ SaveButton::SaveButton(Point position, Point size, SaveFile * file): actionCallback(NULL), voteColour(255, 0, 0), selectable(false), - selected(false) + selected(false), + wantsDraw(false) { if(file) { @@ -91,7 +92,7 @@ void SaveButton::Tick(float dt) { Thumbnail * tempThumb; float scaleFactorY = 1.0f, scaleFactorX = 1.0f; - if(!thumbnail) + if(!thumbnail/* && wantsDraw*/) { if(save) { @@ -114,7 +115,11 @@ void SaveButton::Tick(float dt) } if(file) { - if(file->GetGameSave()) + if(file->GetThumbnail()) + { + thumbnail = new Thumbnail(*file->GetThumbnail()); + } + else if(file->GetGameSave()) { thumbnail = SaveRenderer::Ref().Render(file->GetGameSave()); } @@ -152,6 +157,8 @@ void SaveButton::Draw(const Point& screenPos) float scaleFactor; ui::Point thumbBoxSize(0, 0); + wantsDraw = true; + if(selected && selectable) { g->fillrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 100, 170, 255, 100); diff --git a/src/interface/SaveButton.h b/src/interface/SaveButton.h index 02795fb..faa85d7 100644 --- a/src/interface/SaveButton.h +++ b/src/interface/SaveButton.h @@ -27,6 +27,7 @@ class SaveButton : public Component SaveInfo * save; Thumbnail * thumbnail; std::string name; + bool wantsDraw; public: SaveButton(Point position, Point size, SaveInfo * save); SaveButton(Point position, Point size, SaveFile * file); diff --git a/src/interface/ScrollPanel.cpp b/src/interface/ScrollPanel.cpp index 36ce5f8..ecf527b 100644 --- a/src/interface/ScrollPanel.cpp +++ b/src/interface/ScrollPanel.cpp @@ -28,7 +28,7 @@ void ScrollPanel::XOnMouseWheelInside(int localx, int localy, int d) { if(!d) return; - yScrollVel -= d; + yScrollVel -= d*2; } void ScrollPanel::XDraw(const Point& screenPos) @@ -52,8 +52,8 @@ void ScrollPanel::XDraw(const Point& screenPos) void ScrollPanel::XTick(float dt) { - if(yScrollVel > 7.0f) yScrollVel = 7.0f; - if(yScrollVel < -7.0f) yScrollVel = -7.0f; + //if(yScrollVel > 7.0f) yScrollVel = 7.0f; + //if(yScrollVel < -7.0f) yScrollVel = -7.0f; if(yScrollVel > -0.5f && yScrollVel < 0.5) yScrollVel = 0; @@ -63,14 +63,16 @@ void ScrollPanel::XTick(float dt) xScrollVel = 0; maxOffset = InnerSize-Size; + maxOffset.Y = std::max(0, maxOffset.Y); + maxOffset.X = std::max(0, maxOffset.X); int oldOffsetY = offsetY; offsetY += yScrollVel; int oldOffsetX = offsetX; offsetX += xScrollVel; - yScrollVel*=0.99f; - xScrollVel*=0.99f; + yScrollVel*=0.98f; + xScrollVel*=0.98f; if(oldOffsetY!=int(offsetY)) { diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp index f3b419f..048a24e 100644 --- a/src/simulation/SaveRenderer.cpp +++ b/src/simulation/SaveRenderer.cpp @@ -42,6 +42,7 @@ Thumbnail * SaveRenderer::Render(GameSave * save) width = save->blockWidth; height = save->blockHeight; + g->Acquire(); g->Clear(); sim->clear_sim(); @@ -69,7 +70,7 @@ Thumbnail * SaveRenderer::Render(GameSave * save) pData = new pixel[XRES*YRES]; texData = new unsigned char[(XRES*YRES)*PIXELSIZE]; - std::fill(texData, texData+(XRES*YRES), 0xDD); + std::fill(texData, texData+(XRES*YRES)*PIXELSIZE, 0xDD); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); glDisable(GL_TEXTURE_2D); @@ -111,6 +112,7 @@ Thumbnail * SaveRenderer::Render(GameSave * save) free(pData); #endif } + g->Release(); return tempThumb; } diff --git a/src/tasks/Task.h b/src/tasks/Task.h index 76284ac..f11e0b9 100644 --- a/src/tasks/Task.h +++ b/src/tasks/Task.h @@ -23,7 +23,7 @@ public: std::string GetError(); std::string GetStatus(); void Poll(); - Task() {} + Task() { progress = 0; } virtual ~Task(); protected: int progress; -- cgit v0.9.2-21-gd62e