diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-24 12:24:17 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-24 12:24:17 (GMT) |
| commit | 9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d (patch) | |
| tree | ac7d040253b459ce102e476cb19ab59e3cfa90d7 /src/gui/game | |
| parent | 6bf98ccdca39936a3c51367862eed7c49f8786ec (diff) | |
| parent | bdc69f31c0be94191015838886bdcc2bc67f1acb (diff) | |
| download | powder-9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d.zip powder-9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d.tar.gz | |
Merge branch 'reorganisation' of github.com:FacialTurd/The-Powder-Toy
Diffstat (limited to 'src/gui/game')
| -rw-r--r-- | src/gui/game/BitmapBrush.h | 96 | ||||
| -rw-r--r-- | src/gui/game/Brush.cpp | 51 | ||||
| -rw-r--r-- | src/gui/game/Brush.h | 108 | ||||
| -rw-r--r-- | src/gui/game/DecorationTool.h | 43 | ||||
| -rw-r--r-- | src/gui/game/EllipseBrush.h | 56 | ||||
| -rw-r--r-- | src/gui/game/GameController.cpp | 1426 | ||||
| -rw-r--r-- | src/gui/game/GameController.h | 155 | ||||
| -rw-r--r-- | src/gui/game/GameModel.cpp | 1151 | ||||
| -rw-r--r-- | src/gui/game/GameModel.h | 206 | ||||
| -rw-r--r-- | src/gui/game/GameModelException.h | 19 | ||||
| -rw-r--r-- | src/gui/game/GameView.cpp | 2140 | ||||
| -rw-r--r-- | src/gui/game/GameView.h | 189 | ||||
| -rw-r--r-- | src/gui/game/Menu.h | 51 | ||||
| -rw-r--r-- | src/gui/game/Notification.h | 16 | ||||
| -rw-r--r-- | src/gui/game/PropertyTool.cpp | 235 | ||||
| -rw-r--r-- | src/gui/game/QuickOption.h | 76 | ||||
| -rw-r--r-- | src/gui/game/QuickOptions.h | 120 | ||||
| -rw-r--r-- | src/gui/game/RenderPreset.h | 19 | ||||
| -rw-r--r-- | src/gui/game/SampleTool.cpp | 67 | ||||
| -rw-r--r-- | src/gui/game/SignTool.cpp | 278 | ||||
| -rw-r--r-- | src/gui/game/Tool.cpp | 215 | ||||
| -rw-r--r-- | src/gui/game/Tool.h | 183 | ||||
| -rw-r--r-- | src/gui/game/ToolButton.cpp | 91 | ||||
| -rw-r--r-- | src/gui/game/ToolButton.h | 18 | ||||
| -rw-r--r-- | src/gui/game/TriangleBrush.h | 46 |
25 files changed, 7055 insertions, 0 deletions
diff --git a/src/gui/game/BitmapBrush.h b/src/gui/game/BitmapBrush.h new file mode 100644 index 0000000..e1c0445 --- /dev/null +++ b/src/gui/game/BitmapBrush.h @@ -0,0 +1,96 @@ +/* + * BitmapBrush.h + * + * Created on: Nov 18, 2012 + * Author: Simon Robertshaw + */ + +#ifndef BTIMAPBRUSH_H_ +#define BTIMAPBRUSH_H_ + +#include <vector> +#include <cmath> +#include "Brush.h" + +class BitmapBrush: public Brush +{ +protected: + ui::Point origSize; + unsigned char * origBitmap; +public: + BitmapBrush(std::vector<unsigned char> newBitmap, ui::Point rectSize_): + Brush(ui::Point(0, 0)), + origSize(0, 0) + { + ui::Point newSize = rectSize_; + + //Ensure the rect has odd dimentions so we can pull an integer radius with a 1x1 centre + if(!(newSize.X % 2)) + newSize.X += 1; + if(!(newSize.Y % 2)) + newSize.Y += 1; + + radius = (newSize-ui::Point(1, 1))/2; + size = newSize; + origSize = size; + + origBitmap = new unsigned char[size.X*size.Y]; + std::fill(origBitmap, origBitmap+(size.X*size.Y), 0); + for(int y = 0; y < rectSize_.Y; y++) + { + for(int x = 0; x < rectSize_.X; x++) + { + if(newBitmap[(y*rectSize_.X)+x] >= 128) + origBitmap[(y*size.X)+x] = newBitmap[(y*rectSize_.X)+x]; + } + } + + SetRadius(radius); + }; + virtual void GenerateBitmap() + { + if(origBitmap) + { + if(bitmap) + delete[] bitmap; + bitmap = new unsigned char[size.X*size.Y]; + if(size == origSize) + std::copy(origBitmap, origBitmap+(origSize.X*origSize.Y), bitmap); + else + { + //Bilinear interpolation + float factorX = ((float)origSize.X)/((float)size.X); + float factorY = ((float)origSize.Y)/((float)size.Y); + for(int y = 0; y < size.Y; y++) + { + for(int x = 0; x < size.X; x++) + { + float originalY = ((float)y)*factorY; + float originalX = ((float)x)*factorX; + + int lowerX = std::floor(originalX); + int upperX = std::min((float)(origSize.X-1), std::floor(originalX+1.0f)); + int lowerY = std::floor(originalY); + int upperY = std::min((float)(origSize.Y-1), std::floor(originalY+1.0f)); + + unsigned char topRight = origBitmap[(lowerY*origSize.X)+upperX]; + unsigned char topLeft = origBitmap[(lowerY*origSize.X)+lowerX]; + unsigned char bottomRight = origBitmap[(upperY*origSize.X)+upperX]; + unsigned char bottomLeft = origBitmap[(upperY*origSize.X)+lowerX]; + float top = LinearInterpolate<float>(topLeft, topRight, lowerX, upperX, originalX); + float bottom = LinearInterpolate<float>(bottomLeft, bottomRight, lowerX, upperX, originalX); + float mid = LinearInterpolate<float>(top, bottom, lowerY, upperY, originalY); + bitmap[(y*size.X)+x] = mid > 128 ? 255 : 0; + } + } + } + } + } + virtual ~BitmapBrush() + { + if(origBitmap) + delete[] origBitmap; + } +}; + +#endif /* BTIMAPBRUSH_H_ */ diff --git a/src/gui/game/Brush.cpp b/src/gui/game/Brush.cpp new file mode 100644 index 0000000..9f2f2a8 --- /dev/null +++ b/src/gui/game/Brush.cpp @@ -0,0 +1,51 @@ +#include "Brush.h" +#include "graphics/Renderer.h" + +void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) +{ + int width, height, t; + width = position2.X-position1.X; + height = position2.Y-position1.Y; + if(height<0) + { + position1.Y += height; + height *= -1; + } + if(width<0) + { + position1.X += width; + width *= -1; + } + + ren->xor_line(position1.X, position1.Y, position1.X+width, position1.Y); + if(height>0){ + ren->xor_line(position1.X, position1.Y+height, position1.X+width, position1.Y+height); + if(height>1){ + ren->xor_line(position1.X+width, position1.Y+1, position1.X+width, position1.Y+height-1); + if(width>0) + ren->xor_line(position1.X, position1.Y+1, position1.X, position1.Y+height-1); + } + } +} + +void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) +{ + ren->xor_line(position1.X, position1.Y, position2.X, position2.Y); +} + +void Brush::RenderPoint(Renderer * ren, ui::Point position) +{ + if(!outline) + updateOutline(); + if(!outline) + return; + ren->xor_bitmap(outline, position.X-radius.X, position.Y-radius.Y, size.X, size.Y); +} + +void Brush::RenderFill(Renderer * ren, ui::Point position) +{ + ren->xor_line(position.X-5, position.Y, position.X-1, position.Y); + ren->xor_line(position.X+5, position.Y, position.X+1, position.Y); + ren->xor_line(position.X, position.Y-5, position.X, position.Y-1); + ren->xor_line(position.X, position.Y+5, position.X, position.Y+1); +} diff --git a/src/gui/game/Brush.h b/src/gui/game/Brush.h new file mode 100644 index 0000000..a853609 --- /dev/null +++ b/src/gui/game/Brush.h @@ -0,0 +1,108 @@ +#ifndef BRUSH_H_ +#define BRUSH_H_ + +#include <iostream> +#include "gui/interface/Point.h" + +class Renderer; +class Brush +{ +protected: + unsigned char * outline; + unsigned char * bitmap; + ui::Point size; + ui::Point radius; + void updateOutline() + { + if(!bitmap) + GenerateBitmap(); + if(!bitmap) + return; + if(outline) + delete[] outline; + outline = new unsigned char[size.X*size.Y]; + for(int x = 0; x < size.X; x++) + { + for(int y = 0; y < size.Y; y++) + { + if(bitmap[y*size.X+x] && (!y || !x || x == size.X-1 || y == size.Y-1 || !bitmap[y*size.X+(x+1)] || !bitmap[y*size.X+(x-1)] || !bitmap[(y-1)*size.X+x] || !bitmap[(y+1)*size.X+x])) + { + outline[y*size.X+x] = 255; + } + else + outline[y*size.X+x] = 0; + } + } + } +public: + Brush(ui::Point size_): + bitmap(NULL), + outline(NULL), + radius(0, 0), + size(0, 0) + { + SetRadius(size_); + }; + + //Radius of the brush 0x0 - infxinf (Radius of 0x0 would be 1x1, radius of 1x1 would be 3x3) + ui::Point GetRadius() + { + return radius; + } + + //Size of the brush bitmap mask, 1x1 - infxinf + ui::Point GetSize() + { + return size; + } + virtual void SetRadius(ui::Point radius) + { + this->radius = radius; + this->size = radius+radius+ui::Point(1, 1); + + GenerateBitmap(); + updateOutline(); + } + virtual ~Brush() { + if(bitmap) + delete[] bitmap; + if(outline) + delete[] outline; + } + virtual void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2); + virtual void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2); + virtual void RenderPoint(Renderer * ren, ui::Point position); + virtual void RenderFill(Renderer * ren, ui::Point position); + virtual void GenerateBitmap() + { + if(bitmap) + delete[] bitmap; + bitmap = new unsigned char[size.X*size.Y]; + for(int x = 0; x < size.X; x++) + { + for(int y = 0; y < size.Y; y++) + { + bitmap[(y*size.X)+x] = 255; + } + } + } + //Get a bitmap for drawing particles + unsigned char * GetBitmap() + { + if(!bitmap) + GenerateBitmap(); + return bitmap; + } + + unsigned char * GetOutline() + { + if(!outline) + updateOutline(); + if(!outline) + return NULL; + return outline; + } +}; + + +#endif /* BRUSH_H_ */ diff --git a/src/gui/game/DecorationTool.h b/src/gui/game/DecorationTool.h new file mode 100644 index 0000000..679c854 --- /dev/null +++ b/src/gui/game/DecorationTool.h @@ -0,0 +1,43 @@ + +#ifndef DECORATIONTOOL_H_ +#define DECORATIONTOOL_H_ + +#include "Tool.h" + +class DecorationTool: public Tool +{ +public: + enum ToolType { BlendAdd = DECO_ADD, BlendRemove = DECO_SUBTRACT, BlendMultiply = DECO_MULTIPLY, BlendDivide = DECO_DIVIDE, BlendSet = DECO_DRAW, BlendSmudge = DECO_SMUDGE, Remove = DECO_CLEAR }; + + ToolType decoMode; + + unsigned char Red; + unsigned char Green; + unsigned char Blue; + unsigned char Alpha; + + DecorationTool(ToolType decoMode_, string name, string description, int r, int g, int b, std::string identifier): + Tool(0, name, description, r, g, b, identifier), + decoMode(decoMode_), + Red(0), + Green(0), + Blue(0), + Alpha(0) + { + } + virtual ~DecorationTool() {} + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position){ + sim->ApplyDecorationPoint(position.X, position.Y, Red, Green, Blue, Alpha, decoMode, brush); + } + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + sim->ApplyDecorationLine(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, decoMode, brush); + } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + sim->ApplyDecorationBox(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, decoMode); + } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { + + } +}; + +#endif diff --git a/src/gui/game/EllipseBrush.h b/src/gui/game/EllipseBrush.h new file mode 100644 index 0000000..ad28766 --- /dev/null +++ b/src/gui/game/EllipseBrush.h @@ -0,0 +1,56 @@ +#ifndef ELIPSEBRUSH_H_ +#define ELIPSEBRUSH_H_ + +#include <cmath> +#include "Brush.h" + +class EllipseBrush: public Brush +{ +public: + EllipseBrush(ui::Point size_): + Brush(size_) + { + SetRadius(size_); + }; + virtual void GenerateBitmap() + { + if(bitmap) + delete[] bitmap; + bitmap = new unsigned char[size.X*size.Y]; + int rx = radius.X; + int ry = radius.Y; + + if (!rx) + { + for (int j = 0; j <= 2*ry; j++) + { + bitmap[j*(size.X)+rx] = 255; + } + } + else + { + int yTop = ry, yBottom, i, j; + for (i = 0; i <= rx; i++) + { + while (pow(i-rx,2.0f)*pow(ry,2.0f) + pow(yTop-ry,2.0f)*pow(rx,2.0f) <= pow(rx,2.0f)*pow(ry,2.0f)) + yTop++; + yBottom = 2*ry - yTop; + for (int j = 0; j <= ry*2; j++) + { + if (j > yBottom && j < yTop) + { + bitmap[j*(size.X)+i] = 255; + bitmap[j*(size.X)+2*rx-i] = 255; + } + else + { + bitmap[j*(size.X)+i] = 0; + bitmap[j*(size.X)+2*rx-i] = 0; + } + } + } + } + } +}; + +#endif /* ELIPSEBRUSH_H_ */ diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp new file mode 100644 index 0000000..8df5036 --- /dev/null +++ b/src/gui/game/GameController.cpp @@ -0,0 +1,1426 @@ + +#include <iostream> +#include <queue> +#include "Config.h" +#include "Format.h" +#include "GameController.h" +#include "GameModel.h" +#include "client/SaveInfo.h" +#include "client/GameSave.h" +#include "gui/search/SearchController.h" +#include "gui/render/RenderController.h" +#include "gui/login/LoginController.h" +#include "gui/interface/Point.h" +#include "gui/dialogues/ErrorMessage.h" +#include "gui/dialogues/InformationMessage.h" +#include "gui/dialogues/ConfirmPrompt.h" +#include "GameModelException.h" +#include "simulation/Air.h" +#include "gui/elementsearch/ElementSearchActivity.h" +#include "gui/profile/ProfileActivity.h" +#include "gui/colourpicker/ColourPickerActivity.h" +#include "gui/update/UpdateActivity.h" +#include "Notification.h" +#include "gui/filebrowser/FileBrowserActivity.h" +#include "gui/save/LocalSaveActivity.h" +#include "gui/save/ServerSaveActivity.h" +#include "gui/interface/Keys.h" +#include "simulation/Snapshot.h" +#include "debug/DebugInfo.h" +//#include "debug/ElementPopulation.h" + +using namespace std; + +class GameController::SearchCallback: public ControllerCallback +{ + GameController * cc; +public: + SearchCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + if(cc->search->GetLoadedSave()) + { + try + { + cc->gameModel->SetSave(cc->search->GetLoadedSave()); + cc->search->ReleaseLoadedSave(); + } + catch(GameModelException & ex) + { + new ErrorMessage("Cannot open save", ex.what()); + } + } + } +}; + +class GameController::SaveOpenCallback: public ControllerCallback +{ + GameController * cc; +public: + SaveOpenCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + if(cc->activePreview->GetDoOpen() && cc->activePreview->GetSave()) + { + try + { + cc->LoadSave(cc->activePreview->GetSave()); + } + catch(GameModelException & ex) + { + new ErrorMessage("Cannot open save", ex.what()); + } + } + } +}; + + +class GameController::RenderCallback: public ControllerCallback +{ + GameController * cc; +public: + RenderCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + //cc->gameModel->SetUser(cc->loginWindow->GetUser()); + } +}; + +class GameController::OptionsCallback: public ControllerCallback +{ + GameController * cc; +public: + OptionsCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + cc->gameModel->UpdateQuickOptions(); + //cc->gameModel->SetUser(cc->loginWindow->GetUser()); + } +}; + +class GameController::TagsCallback: public ControllerCallback +{ + GameController * cc; +public: + TagsCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + cc->gameView->NotifySaveChanged(cc->gameModel); + } +}; + +class GameController::StampsCallback: public ControllerCallback +{ + GameController * cc; +public: + StampsCallback(GameController * cc_) { cc = cc_; } + virtual void ControllerExit() + { + if(cc->localBrowser->GetSave()) + { + cc->gameModel->SetStamp(cc->localBrowser->GetSave()->GetGameSave()); + if (cc->localBrowser->GetMoveToFront()) + Client::Ref().MoveStampToFront(cc->localBrowser->GetSave()->GetName()); + cc->LoadStamp(); + } + } +}; + +GameController::GameController(): + search(NULL), + renderOptions(NULL), + loginWindow(NULL), + console(NULL), + tagsWindow(NULL), + options(NULL), + activePreview(NULL), + localBrowser(NULL), + HasDone(false), + firstTick(true) +{ + gameView = new GameView(); + gameModel = new GameModel(); + gameModel->BuildQuickOptionMenu(this); + + gameView->AttachController(this); + gameModel->AddObserver(gameView); + + commandInterface = new LuaScriptInterface(this, gameModel);//new TPTScriptInterface(); + ((LuaScriptInterface*)commandInterface)->SetWindow(gameView); + + commandInterface->OnBrushChanged(gameModel->GetBrushID(), gameModel->GetBrush()->GetRadius().X, gameModel->GetBrush()->GetRadius().X); + ActiveToolChanged(0, gameModel->GetActiveTool(0)); + ActiveToolChanged(1, gameModel->GetActiveTool(1)); + ActiveToolChanged(2, gameModel->GetActiveTool(2)); + + //sim = new Simulation(); + Client::Ref().AddListener(this); + + //debugInfo.push_back(new ElementPopulationDebug(gameModel->GetSimulation())); +} + +GameController::~GameController() +{ + if(search) + { + delete search; + } + if(renderOptions) + { + delete renderOptions; + } + if(loginWindow) + { + delete loginWindow; + } + if(tagsWindow) + { + delete tagsWindow; + } + if(console) + { + delete console; + } + if(activePreview) + { + delete activePreview; + } + if(localBrowser) + { + delete localBrowser; + } + if (options) + { + delete options; + } + if(ui::Engine::Ref().GetWindow() == gameView) + { + ui::Engine::Ref().CloseWindow(); + } + //deleted here because it refuses to be deleted when deleted from gameModel even with the same code + std::deque<Snapshot*> history = gameModel->GetHistory(); + for(std::deque<Snapshot*>::iterator iter = history.begin(), end = history.end(); iter != end; ++iter) + { + delete *iter; + } + std::vector<QuickOption*> quickOptions = gameModel->GetQuickOptions(); + for(std::vector<QuickOption*>::iterator iter = quickOptions.begin(), end = quickOptions.end(); iter != end; ++iter) + { + delete *iter; + } + std::vector<Notification*> notifications = gameModel->GetNotifications(); + for(std::vector<Notification*>::iterator iter = notifications.begin(); iter != notifications.end(); ++iter) + { + delete *iter; + } + delete gameModel; + delete gameView; +} + +void GameController::HistoryRestore() +{ + std::deque<Snapshot*> history = gameModel->GetHistory(); + if(history.size()) + { + Snapshot * snap = history.back(); + gameModel->GetSimulation()->Restore(*snap); + if(history.size()>1) + { + history.pop_back(); + delete snap; + gameModel->SetHistory(history); + } + } +} + +void GameController::HistorySnapshot() +{ + std::deque<Snapshot*> history = gameModel->GetHistory(); + Snapshot * newSnap = gameModel->GetSimulation()->CreateSnapshot(); + if(newSnap) + { + if(history.size() >= 1) //History limit is current 1 + { + Snapshot * snap = history.front(); + history.pop_front(); + //snap->Particles.clear(); + delete snap; + } + history.push_back(newSnap); + gameModel->SetHistory(history); + } +} + +GameView * GameController::GetView() +{ + return gameView; +} + +void GameController::PlaceSave(ui::Point position) +{ + if(gameModel->GetPlaceSave()) + { + gameModel->GetSimulation()->Load(position.X, position.Y, gameModel->GetPlaceSave()); + gameModel->SetPaused(gameModel->GetPlaceSave()->paused | gameModel->GetPaused()); + } +} + +void GameController::Install() +{ +#if defined(MACOSX) + new InformationMessage("No Installation necessary", "You don't need to install The Powder Toy on Mac OS X", false); +#elif defined(WIN) || defined(LIN) + class InstallConfirmation: public ConfirmDialogueCallback { + public: + GameController * c; + InstallConfirmation(GameController * c_) { c = c_; } + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + if(Client::Ref().DoInstallation()) + { + new InformationMessage("Install Success", "The installation completed!", false); + } + else + { + new ErrorMessage("Could not install", "The installation did not complete due to an error"); + } + } + } + virtual ~InstallConfirmation() { } + }; + new ConfirmPrompt("Install The Powder Toy", "Do you wish to install The Powder Toy on this computer?\nThis allows you to open save files and saves directly from the website.", new InstallConfirmation(this)); +#else + new ErrorMessage("Cannot install", "You cannot install The Powder Toy on this platform"); +#endif +} + +void GameController::AdjustGridSize(int direction) +{ + if(direction > 0) + gameModel->GetRenderer()->SetGridSize((gameModel->GetRenderer()->GetGridSize()+1)%10); + else + gameModel->GetRenderer()->SetGridSize((gameModel->GetRenderer()->GetGridSize()+9)%10); +} + +void GameController::InvertAirSim() +{ + gameModel->GetSimulation()->air->Invert(); +} + + +void GameController::AdjustBrushSize(int direction, bool logarithmic, bool xAxis, bool yAxis) +{ + if(xAxis && yAxis) + return; + + ui::Point newSize(0, 0); + ui::Point oldSize = gameModel->GetBrush()->GetRadius(); + if(logarithmic) + newSize = gameModel->GetBrush()->GetRadius() + ui::Point(direction * ((gameModel->GetBrush()->GetRadius().X/5)>0?gameModel->GetBrush()->GetRadius().X/5:1), direction * ((gameModel->GetBrush()->GetRadius().Y/5)>0?gameModel->GetBrush()->GetRadius().Y/5:1)); + else + newSize = gameModel->GetBrush()->GetRadius() + ui::Point(direction, direction); + if(newSize.X < 0) + newSize.X = 0; + if(newSize.Y < 0) + newSize.Y = 0; + if(newSize.X > 200) + newSize.X = 200; + if(newSize.Y > 200) + newSize.Y = 200; + + if(xAxis) + gameModel->GetBrush()->SetRadius(ui::Point(newSize.X, oldSize.Y)); + else if(yAxis) + gameModel->GetBrush()->SetRadius(ui::Point(oldSize.X, newSize.Y)); + else + gameModel->GetBrush()->SetRadius(newSize); + + BrushChanged(gameModel->GetBrushID(), gameModel->GetBrush()->GetRadius().X, gameModel->GetBrush()->GetRadius().Y); +} + +void GameController::AdjustZoomSize(int direction, bool logarithmic) +{ + int newSize; + if(logarithmic) + newSize = gameModel->GetZoomSize()+(((gameModel->GetZoomSize()/10)>0?(gameModel->GetZoomSize()/10):1)*direction); + else + newSize = gameModel->GetZoomSize()+direction; + if(newSize<5) + newSize = 5; + if(newSize>64) + newSize = 64; + gameModel->SetZoomSize(newSize); + + int newZoomFactor = 256/newSize; + if(newZoomFactor<3) + newZoomFactor = 3; + gameModel->SetZoomFactor(newZoomFactor); +} + +ui::Point GameController::PointTranslate(ui::Point point) +{ + if(point.X >= XRES) + point.X = XRES-1; + if(point.Y >= YRES) + point.Y = YRES-1; + if(point.Y < 0) + point.Y = 0; + if(point.X < 0) + point.X = 0; + + bool zoomEnabled = gameModel->GetZoomEnabled(); + if(!zoomEnabled) + return point; + //If we try to draw inside the zoom window, normalise the coordinates + int zoomFactor = gameModel->GetZoomFactor(); + ui::Point zoomWindowPosition = gameModel->GetZoomWindowPosition(); + ui::Point zoomWindowSize = ui::Point(gameModel->GetZoomSize()*zoomFactor, gameModel->GetZoomSize()*zoomFactor); + + if(point.X >= zoomWindowPosition.X && point.X >= zoomWindowPosition.Y && point.X <= zoomWindowPosition.X+zoomWindowSize.X && point.Y <= zoomWindowPosition.Y+zoomWindowSize.Y) + return ((point-zoomWindowPosition)/gameModel->GetZoomFactor())+gameModel->GetZoomPosition(); + return point; +} + +ui::Point GameController::NormaliseBlockCoord(ui::Point point) +{ + return (point/CELL)*CELL; +} + +void GameController::DrawRect(int toolSelection, ui::Point point1, ui::Point point2) +{ + Simulation * sim = gameModel->GetSimulation(); + Tool * activeTool = gameModel->GetActiveTool(toolSelection); + gameModel->SetLastTool(activeTool); + Brush * cBrush = gameModel->GetBrush(); + if(!activeTool || !cBrush) + return; + activeTool->SetStrength(gameModel->GetToolStrength()); + activeTool->DrawRect(sim, cBrush, point1, point2); +} + +void GameController::DrawLine(int toolSelection, ui::Point point1, ui::Point point2) +{ + Simulation * sim = gameModel->GetSimulation(); + Tool * activeTool = gameModel->GetActiveTool(toolSelection); + gameModel->SetLastTool(activeTool); + Brush * cBrush = gameModel->GetBrush(); + if(!activeTool || !cBrush) + return; + activeTool->SetStrength(gameModel->GetToolStrength()); + activeTool->DrawLine(sim, cBrush, point1, point2); +} + +void GameController::DrawFill(int toolSelection, ui::Point point) +{ + Simulation * sim = gameModel->GetSimulation(); + Tool * activeTool = gameModel->GetActiveTool(toolSelection); + gameModel->SetLastTool(activeTool); + Brush * cBrush = gameModel->GetBrush(); + if(!activeTool || !cBrush) + return; + activeTool->SetStrength(gameModel->GetToolStrength()); + activeTool->DrawFill(sim, cBrush, point); +} + +void GameController::DrawPoints(int toolSelection, queue<ui::Point> & pointQueue) +{ + Simulation * sim = gameModel->GetSimulation(); + Tool * activeTool = gameModel->GetActiveTool(toolSelection); + gameModel->SetLastTool(activeTool); + Brush * cBrush = gameModel->GetBrush(); + if(!activeTool || !cBrush) + { + if(!pointQueue.empty()) + { + while(!pointQueue.empty()) + { + //delete pointQueue.front(); + pointQueue.pop(); + } + } + return; + } + + activeTool->SetStrength(gameModel->GetToolStrength()); + if(!pointQueue.empty()) + { + ui::Point sPoint(0, 0); + bool first = true; + while(!pointQueue.empty()) + { + ui::Point fPoint = pointQueue.front(); + //delete pointQueue.front(); + pointQueue.pop(); + if(!first) + { + activeTool->DrawLine(sim, cBrush, sPoint, fPoint, true); + } + else + { + first = false; + activeTool->Draw(sim, cBrush, fPoint); + } + sPoint = fPoint; + } + } +} + +void GameController::LoadClipboard() +{ + gameModel->SetPlaceSave(gameModel->GetClipboard()); + if(gameModel->GetPlaceSave() && gameModel->GetPlaceSave()->Collapsed()) + gameModel->GetPlaceSave()->Expand(); +} + +void GameController::LoadStamp() +{ + gameModel->SetPlaceSave(gameModel->GetStamp()); + if(gameModel->GetPlaceSave() && gameModel->GetPlaceSave()->Collapsed()) + gameModel->GetPlaceSave()->Expand(); +} + +void GameController::TranslateSave(ui::Point point) +{ + matrix2d transform = m2d_identity; + vector2d translate = v2d_new(point.X, point.Y); + gameModel->GetPlaceSave()->Transform(transform, translate); + gameModel->SetPlaceSave(gameModel->GetPlaceSave()); +} + +void GameController::TransformSave(matrix2d transform) +{ + vector2d translate = v2d_zero; + gameModel->GetPlaceSave()->Transform(transform, translate); + gameModel->SetPlaceSave(gameModel->GetPlaceSave()); +} + +void GameController::ToolClick(int toolSelection, ui::Point point) +{ + Simulation * sim = gameModel->GetSimulation(); + Tool * activeTool = gameModel->GetActiveTool(toolSelection); + Brush * cBrush = gameModel->GetBrush(); + if(!activeTool || !cBrush) + return; + activeTool->Click(sim, cBrush, point); +} + +void GameController::StampRegion(ui::Point point1, ui::Point point2) +{ + GameSave * newSave; + newSave = gameModel->GetSimulation()->Save(point1.X, point1.Y, point2.X, point2.Y); + if(newSave) + { + newSave->paused = gameModel->GetPaused(); + gameModel->AddStamp(newSave); + } + else + new ErrorMessage("Could not create stamp", "Error generating save file"); +} + +void GameController::CopyRegion(ui::Point point1, ui::Point point2) +{ + GameSave * newSave; + newSave = gameModel->GetSimulation()->Save(point1.X, point1.Y, point2.X, point2.Y); + if(newSave) + { + newSave->paused = gameModel->GetPaused(); + gameModel->SetClipboard(newSave); + } +} + +void GameController::CutRegion(ui::Point point1, ui::Point point2) +{ + CopyRegion(point1, point2); + gameModel->GetSimulation()->clear_area(point1.X, point1.Y, point2.X-point1.X, point2.Y-point1.Y); +} + +bool GameController::MouseMove(int x, int y, int dx, int dy) +{ + return commandInterface->OnMouseMove(x, y, dx, dy); +} + +bool GameController::BrushChanged(int brushType, int rx, int ry) +{ + return commandInterface->OnBrushChanged(brushType, rx, ry); +} + +bool GameController::MouseDown(int x, int y, unsigned button) +{ + return commandInterface->OnMouseDown(x, y, button); +} + +bool GameController::MouseUp(int x, int y, unsigned button) +{ + bool ret = commandInterface->OnMouseUp(x, y, button); + ui::Point point = PointTranslate(ui::Point(x, y)); + x = point.X; + y = point.Y; + if(ret && y<YRES && x<XRES) + { + if (gameModel->GetActiveTool(0)->GetIdentifier() != "DEFAULT_UI_SIGN" || button != BUTTON_LEFT) //If it's not a sign tool or you are right/middle clicking + { + Simulation * sim = gameModel->GetSimulation(); + for (std::vector<sign>::iterator iter = sim->signs.begin(), end = sim->signs.end(); iter != end; ++iter) + { + int signx, signy, signw, signh; + (*iter).pos((*iter).getText(sim), signx, signy, signw, signh); + if (x>=signx && x<=signx+signw && y>=signy && y<=signy+signh) + { + if (sregexp((*iter).text.c_str(), "^{[c|t]:[0-9]*|.*}$")==0) + { + const char * signText = (*iter).text.c_str(); + char buff[256]; + int sldr; + + memset(buff, 0, sizeof(buff)); + + for (sldr=3; signText[sldr] != '|'; sldr++) + buff[sldr-3] = signText[sldr]; + + buff[sldr-3] = '\0'; + + int tempSaveID = format::StringToNumber<int>(std::string(buff)); + if (tempSaveID) + { + if ((*iter).text.c_str()[1] == 'c') + OpenSavePreview(tempSaveID, 0); + else if ((*iter).text.c_str()[1] == 't') + { + char url[256]; + sprintf(url, "http://powdertoy.co.uk/Discussions/Thread/View.html?Thread=%i", tempSaveID); + OpenURI(url); + } + } + break; + } + } + } + } + } + return ret; +} + +bool GameController::MouseWheel(int x, int y, int d) +{ + return commandInterface->OnMouseWheel(x, y, d); +} + +bool GameController::KeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + bool ret = commandInterface->OnKeyPress(key, character, shift, ctrl, alt); + if(ret) + { + Simulation * sim = gameModel->GetSimulation(); + if (key == KEY_RIGHT) + { + sim->player.comm = (int)(sim->player.comm)|0x02; //Go right command + } + if (key == KEY_LEFT) + { + sim->player.comm = (int)(sim->player.comm)|0x01; //Go left command + } + if (key == KEY_DOWN && ((int)(sim->player.comm)&0x08)!=0x08) + { + sim->player.comm = (int)(sim->player.comm)|0x08; //Use element command + } + if (key == KEY_UP && ((int)(sim->player.comm)&0x04)!=0x04) + { + sim->player.comm = (int)(sim->player.comm)|0x04; //Jump command + } + + if (key == KEY_d) + { + sim->player2.comm = (int)(sim->player2.comm)|0x02; //Go right command + } + if (key == KEY_a) + { + sim->player2.comm = (int)(sim->player2.comm)|0x01; //Go left command + } + if (key == KEY_s && ((int)(sim->player2.comm)&0x08)!=0x08) + { + sim->player2.comm = (int)(sim->player2.comm)|0x08; //Use element command + } + if (key == KEY_w && ((int)(sim->player2.comm)&0x04)!=0x04) + { + sim->player2.comm = (int)(sim->player2.comm)|0x04; //Jump command + } + + if((!sim->elementCount[PT_STKM2] || ctrl) && gameView->GetSelectMode() == SelectNone) + { + switch(key) + { + case 'w': + SwitchGravity(); + break; + case 'd': + gameView->ToggleDebug(); + break; + case 's': + gameView->BeginStampSelection(); + break; + } + } + } + return ret; +} + +bool GameController::KeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + bool ret = commandInterface->OnKeyRelease(key, character, shift, ctrl, alt); + if(ret) + { + Simulation * sim = gameModel->GetSimulation(); + if (key == KEY_RIGHT || key == KEY_LEFT) + { + sim->player.pcomm = sim->player.comm; //Saving last movement + sim->player.comm = (int)(sim->player.comm)&12; //Stop command + } + if (key == KEY_UP) + { + sim->player.comm = (int)(sim->player.comm)&11; + } + if (key == KEY_DOWN) + { + sim->player.comm = (int)(sim->player.comm)&7; + } + + if (key == KEY_d || key == KEY_a) + { + sim->player2.pcomm = sim->player2.comm; //Saving last movement + sim->player2.comm = (int)(sim->player2.comm)&12; //Stop command + } + if (key == KEY_w) + { + sim->player2.comm = (int)(sim->player2.comm)&11; + } + if (key == KEY_s) + { + sim->player2.comm = (int)(sim->player2.comm)&7; + } + } + return ret; +} + +void GameController::Tick() +{ + if(firstTick) + { + ((LuaScriptInterface*)commandInterface)->Init(); + if(!Client::Ref().GetPrefBool("InstallCheck", false)) + { + Client::Ref().SetPref("InstallCheck", true); + Install(); + } + firstTick = false; + } + for(std::vector<DebugInfo*>::iterator iter = debugInfo.begin(), end = debugInfo.end(); iter != end; iter++) + { + (*iter)->Draw(ui::Point(10, 10)); + } + commandInterface->OnTick(); +} + +void GameController::Exit() +{ + if(ui::Engine::Ref().GetWindow() == gameView) + ui::Engine::Ref().CloseWindow(); + HasDone = true; +} + +void GameController::ResetAir() +{ + Simulation * sim = gameModel->GetSimulation(); + sim->air->Clear(); + for (int i = 0; i < NPART; i++) + { + if (sim->parts[i].type == PT_QRTZ || sim->parts[i].type == PT_GLAS) + { + sim->parts[i].pavg[0] = sim->parts[i].pavg[1] = 0; + } + } +} + +void GameController::ResetSpark() +{ + Simulation * sim = gameModel->GetSimulation(); + for (int i = 0; i < NPART; i++) + if (sim->parts[i].type == PT_SPRK) + { + if (sim->parts[i].ctype >= 0 && sim->parts[i].ctype < PT_NUM && sim->elements[sim->parts[i].ctype].Enabled) + { + sim->parts[i].type = sim->parts[i].ctype; + sim->parts[i].life = 0; + } + else + sim->kill_part(i); + } +} + +void GameController::SwitchGravity() +{ + gameModel->GetSimulation()->gravityMode = (gameModel->GetSimulation()->gravityMode+1)%3; + + switch (gameModel->GetSimulation()->gravityMode) + { + case 0: + gameModel->SetInfoTip("Gravity: Vertical"); + break; + case 1: + gameModel->SetInfoTip("Gravity: Off"); + break; + case 2: + gameModel->SetInfoTip("Gravity: Radial"); + break; + } +} + +void GameController::SwitchAir() +{ + gameModel->GetSimulation()->air->airMode = (gameModel->GetSimulation()->air->airMode+1)%5; + + switch (gameModel->GetSimulation()->air->airMode) + { + case 0: + gameModel->SetInfoTip("Air: On"); + break; + case 1: + gameModel->SetInfoTip("Air: Pressure Off"); + break; + case 2: + gameModel->SetInfoTip("Air: Velocity Off"); + break; + case 3: + gameModel->SetInfoTip("Air: Off"); + break; + case 4: + gameModel->SetInfoTip("Air: No Update"); + break; + } +} + +void GameController::ToggleAHeat() +{ + gameModel->SetAHeatEnable(!gameModel->GetAHeatEnable()); +} + + +void GameController::LoadRenderPreset(int presetNum) +{ + Renderer * renderer = gameModel->GetRenderer(); + RenderPreset preset = renderer->renderModePresets[presetNum]; + gameModel->SetInfoTip(preset.Name); + renderer->SetRenderMode(preset.RenderModes); + renderer->SetDisplayMode(preset.DisplayModes); + renderer->SetColourMode(preset.ColourMode); +} + +void GameController::Update() +{ + ui::Point pos = gameView->GetMousePosition(); + if(pos.X >= 0 && pos.Y >= 0 && pos.X < XRES && pos.Y < YRES) + { + gameModel->GetRenderer()->mousePosX = pos.X; + gameModel->GetRenderer()->mousePosY = pos.Y; + gameView->SetSample(gameModel->GetSimulation()->Get(pos.X, pos.Y)); + } + + gameModel->GetSimulation()->update_particles(); + if(renderOptions && renderOptions->HasExited) + { + delete renderOptions; + renderOptions = NULL; + } + + if(search && search->HasExited) + { + delete search; + search = NULL; + } + + if(activePreview && activePreview->HasExited) + { + delete activePreview; + activePreview = NULL; + } + + if(loginWindow && loginWindow->HasExited) + { + delete loginWindow; + loginWindow = NULL; + } + + if(localBrowser && localBrowser->HasDone) + { + delete localBrowser; + localBrowser = NULL; + } +} + +void GameController::SetZoomEnabled(bool zoomEnabled) +{ + gameModel->SetZoomEnabled(zoomEnabled); +} + +void GameController::SetToolStrength(float value) +{ + gameModel->SetToolStrength(value); +} + +void GameController::SetZoomPosition(ui::Point position) +{ + ui::Point zoomPosition = position-(gameModel->GetZoomSize()/2); + if(zoomPosition.X < 0) + zoomPosition.X = 0; + if(zoomPosition.Y < 0) + zoomPosition.Y = 0; + if(zoomPosition.X >= XRES-gameModel->GetZoomSize()) + zoomPosition.X = XRES-gameModel->GetZoomSize(); + if(zoomPosition.Y >= YRES-gameModel->GetZoomSize()) + zoomPosition.Y = YRES-gameModel->GetZoomSize(); + + ui::Point zoomWindowPosition = ui::Point(0, 0); + if(position.X < XRES/2) + zoomWindowPosition.X = XRES-(gameModel->GetZoomSize()*gameModel->GetZoomFactor()); + + gameModel->SetZoomPosition(zoomPosition); + gameModel->SetZoomWindowPosition(zoomWindowPosition); +} + +void GameController::SetPaused(bool pauseState) +{ + gameModel->SetPaused(pauseState); +} + +void GameController::SetPaused() +{ + gameModel->SetPaused(!gameModel->GetPaused()); +} + +void GameController::SetDecoration(bool decorationState) +{ + gameModel->SetDecoration(decorationState); +} + +void GameController::SetDecoration() +{ + gameModel->SetDecoration(!gameModel->GetDecoration()); +} + +void GameController::ShowGravityGrid() +{ + gameModel->ShowGravityGrid(!gameModel->GetGravityGrid()); + gameModel->UpdateQuickOptions(); +} + +void GameController::SetHudEnable(bool hudState) +{ + gameView->SetHudEnable(hudState); +} + +void GameController::SetActiveColourPreset(int preset) +{ + gameModel->SetActiveColourPreset(preset); +} + +void GameController::SetColour(ui::Colour colour) +{ + gameModel->SetColourSelectorColour(colour); + gameModel->SetPresetColour(colour); +} + +void GameController::SetActiveMenu(Menu * menu) +{ + gameModel->SetActiveMenu(menu); + vector<Menu*> menuList = gameModel->GetMenuList(); + bool set = false; + for(int i = 0; i < menuList.size(); i++) + { + if(menuList[i]==menu && i == SC_DECO) + { + gameModel->SetColourSelectorVisibility(true); + set = true; + } + } + if(!set) + gameModel->SetColourSelectorVisibility(false); +} + +std::vector<Menu*> GameController::GetMenuList() +{ + return gameModel->GetMenuList(); +} + +void GameController::ActiveToolChanged(int toolSelection, Tool *tool) +{ + commandInterface->OnActiveToolChanged(toolSelection, tool); +} + +void GameController::SetActiveTool(int toolSelection, Tool * tool) +{ + gameModel->SetActiveTool(toolSelection, tool); + gameModel->GetRenderer()->gravityZonesEnabled = false; + gameModel->SetLastTool(tool); + for(int i = 0; i < 3; i++) + { + if(gameModel->GetActiveTool(i) == gameModel->GetMenuList().at(SC_WALL)->GetToolList().at(WL_GRAV)) + { + gameModel->GetRenderer()->gravityZonesEnabled = true; + } + } +} + +void GameController::OpenSearch() +{ + if(!search) + search = new SearchController(new SearchCallback(this)); + ui::Engine::Ref().ShowWindow(search->GetView()); +} + +void GameController::OpenLocalSaveWindow(bool asCurrent) +{ + Simulation * sim = gameModel->GetSimulation(); + GameSave * gameSave = sim->Save(); + gameSave->paused = gameModel->GetPaused(); + gameSave->gravityMode = sim->gravityMode; + gameSave->airMode = sim->air->airMode; + gameSave->legacyEnable = sim->legacy_enable; + gameSave->waterEEnabled = sim->water_equal_test; + gameSave->gravityEnable = sim->grav->ngrav_enable; + if(!gameSave) + { + new ErrorMessage("Error", "Unable to build save."); + } + else + { + std::string filename = ""; + if (gameModel->GetSaveFile()) + filename = gameModel->GetSaveFile()->GetDisplayName(); + SaveFile tempSave(filename); + tempSave.SetGameSave(gameSave); + + if (!asCurrent || !gameModel->GetSaveFile()) + { + class LocalSaveCallback: public FileSavedCallback + { + GameController * c; + public: + LocalSaveCallback(GameController * _c): c(_c) {} + virtual ~LocalSaveCallback() {}; + virtual void FileSaved(SaveFile* file) + { + c->gameModel->SetSaveFile(file); + } + }; + + new LocalSaveActivity(tempSave, new LocalSaveCallback(this)); + } + else if (gameModel->GetSaveFile()) + { + Client::Ref().MakeDirectory(LOCAL_SAVE_DIR); + Client::Ref().WriteFile(gameSave->Serialise(), gameModel->GetSaveFile()->GetName()); + } + } +} + +void GameController::LoadSaveFile(SaveFile * file) +{ + gameModel->SetSaveFile(file); +} + + +void GameController::LoadSave(SaveInfo * save) +{ + gameModel->SetSave(save); +} + +void GameController::OpenSavePreview(int saveID, int saveDate) +{ + activePreview = new PreviewController(saveID, new SaveOpenCallback(this)); + ui::Engine::Ref().ShowWindow(activePreview->GetView()); +} + +void GameController::OpenSavePreview() +{ + if(gameModel->GetSave()) + { + activePreview = new PreviewController(gameModel->GetSave()->GetID(), new SaveOpenCallback(this)); + ui::Engine::Ref().ShowWindow(activePreview->GetView()); + } +} + +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); + delete file; + } + }; + new FileBrowserActivity(LOCAL_SAVE_DIR PATH_SEP, new LocalSaveOpenCallback(this)); +} + +void GameController::OpenLogin() +{ + if(Client::Ref().GetAuthUser().ID) + { + new ProfileActivity(Client::Ref().GetAuthUser().Username); + } + else + { + loginWindow = new LoginController(); + ui::Engine::Ref().ShowWindow(loginWindow->GetView()); + } +} + +void GameController::OpenElementSearch() +{ + vector<Tool*> toolList; + vector<Menu*> menuList = gameModel->GetMenuList(); + for(std::vector<Menu*>::iterator iter = menuList.begin(), end = menuList.end(); iter!=end; ++iter) { + if(!(*iter)) + continue; + vector<Tool*> menuToolList = (*iter)->GetToolList(); + if(!menuToolList.size()) + continue; + toolList.insert(toolList.end(), menuToolList.begin(), menuToolList.end()); + } + vector<Tool*> hiddenTools = gameModel->GetUnlistedTools(); + toolList.insert(toolList.end(), hiddenTools.begin(), hiddenTools.end()); + new ElementSearchActivity(gameModel, toolList); +} + +void GameController::OpenColourPicker() +{ + class ColourPickerCallback: public ColourPickedCallback + { + GameController * c; + public: + ColourPickerCallback(GameController * _c): c(_c) {} + virtual ~ColourPickerCallback() {}; + virtual void ColourPicked(ui::Colour colour) + { + c->SetColour(colour); + } + }; + new ColourPickerActivity(gameModel->GetColourSelectorColour(), new ColourPickerCallback(this)); +} + +void GameController::OpenTags() +{ + if(gameModel->GetUser().ID) + { + if(gameModel->GetSave() && gameModel->GetSave()->GetID()) + { + tagsWindow = new TagsController(new TagsCallback(this), gameModel->GetSave()); + ui::Engine::Ref().ShowWindow(tagsWindow->GetView()); + } + else + { + new ErrorMessage("Error", "No save open"); + } + } + else + { + new ErrorMessage("Error", "You need to login to edit tags."); + } +} + +void GameController::OpenStamps() +{ + localBrowser = new LocalBrowserController(new StampsCallback(this)); + ui::Engine::Ref().ShowWindow(localBrowser->GetView()); +} + +void GameController::OpenOptions() +{ + options = new OptionsController(gameModel, new OptionsCallback(this)); + ui::Engine::Ref().ShowWindow(options->GetView()); + +} + +void GameController::ShowConsole() +{ + if(!console) + console = new ConsoleController(NULL, commandInterface); + if (console->GetView() != ui::Engine::Ref().GetWindow()) + ui::Engine::Ref().ShowWindow(console->GetView()); +} + +void GameController::HideConsole() +{ + if(!console) + return; + if (console->GetView() == ui::Engine::Ref().GetWindow()) + ui::Engine::Ref().CloseWindow(); +} + +void GameController::OpenRenderOptions() +{ + renderOptions = new RenderController(gameModel->GetRenderer(), new RenderCallback(this)); + ui::Engine::Ref().ShowWindow(renderOptions->GetView()); +} + +void GameController::OpenSaveWindow() +{ + class SaveUploadedCallback: public ServerSaveActivity::SaveUploadedCallback + { + GameController * c; + public: + SaveUploadedCallback(GameController * _c): c(_c) {} + virtual ~SaveUploadedCallback() {}; + virtual void SaveUploaded(SaveInfo save) + { + c->LoadSave(&save); + } + }; + if(gameModel->GetUser().ID) + { + Simulation * sim = gameModel->GetSimulation(); + GameSave * gameSave = sim->Save(); + gameSave->paused = gameModel->GetPaused(); + gameSave->gravityMode = sim->gravityMode; + gameSave->airMode = sim->air->airMode; + gameSave->legacyEnable = sim->legacy_enable; + gameSave->waterEEnabled = sim->water_equal_test; + gameSave->gravityEnable = sim->grav->ngrav_enable; + if(!gameSave) + { + new ErrorMessage("Error", "Unable to build save."); + } + else + { + if(gameModel->GetSave()) + { + SaveInfo tempSave(*gameModel->GetSave()); + tempSave.SetGameSave(gameSave); + new ServerSaveActivity(tempSave, new SaveUploadedCallback(this)); + } + else + { + SaveInfo tempSave(0, 0, 0, 0, gameModel->GetUser().Username, ""); + tempSave.SetGameSave(gameSave); + new ServerSaveActivity(tempSave, new SaveUploadedCallback(this)); + } + } + } + else + { + new ErrorMessage("Error", "You need to login to upload saves."); + } +} + +void GameController::SaveAsCurrent() +{ + + class SaveUploadedCallback: public ServerSaveActivity::SaveUploadedCallback + { + GameController * c; + public: + SaveUploadedCallback(GameController * _c): c(_c) {} + virtual ~SaveUploadedCallback() {}; + virtual void SaveUploaded(SaveInfo save) + { + c->LoadSave(&save); + } + }; + + if(gameModel->GetSave() && gameModel->GetUser().ID && gameModel->GetUser().Username == gameModel->GetSave()->GetUserName()) + { + Simulation * sim = gameModel->GetSimulation(); + GameSave * gameSave = sim->Save(); + gameSave->paused = gameModel->GetPaused(); + gameSave->gravityMode = sim->gravityMode; + gameSave->airMode = sim->air->airMode; + gameSave->legacyEnable = sim->legacy_enable; + gameSave->waterEEnabled = sim->water_equal_test; + gameSave->gravityEnable = sim->grav->ngrav_enable; + if(!gameSave) + { + new ErrorMessage("Error", "Unable to build save."); + } + else + { + if(gameModel->GetSave()) + { + SaveInfo tempSave(*gameModel->GetSave()); + tempSave.SetGameSave(gameSave); + new ServerSaveActivity(tempSave, true, new SaveUploadedCallback(this)); + } + else + { + SaveInfo tempSave(0, 0, 0, 0, gameModel->GetUser().Username, ""); + tempSave.SetGameSave(gameSave); + new ServerSaveActivity(tempSave, true, new SaveUploadedCallback(this)); + } + } + } + else if(gameModel->GetUser().ID) + { + OpenSaveWindow(); + } + else + { + new ErrorMessage("Error", "You need to login to upload saves."); + } +} + +void GameController::FrameStep() +{ + gameModel->FrameStep(1); + gameModel->SetPaused(true); +} + +void GameController::Vote(int direction) +{ + if(gameModel->GetSave() && gameModel->GetUser().ID && gameModel->GetSave()->GetID() && gameModel->GetSave()->GetVote()==0) + { + try + { + gameModel->SetVote(direction); + } + catch(GameModelException & ex) + { + new ErrorMessage("Error while voting", ex.what()); + } + } +} + +void GameController::ChangeBrush() +{ + gameModel->SetBrush(gameModel->GetBrushID()+1); + BrushChanged(gameModel->GetBrushID(), gameModel->GetBrush()->GetRadius().X, gameModel->GetBrush()->GetRadius().Y); +} + +void GameController::ClearSim() +{ + gameModel->SetSave(NULL); + gameModel->ClearSimulation(); +} + +void GameController::ReloadSim() +{ + if(gameModel->GetSave() && gameModel->GetSave()->GetGameSave()) + { + gameModel->SetSave(gameModel->GetSave()); + } + else if(gameModel->GetSaveFile() && gameModel->GetSaveFile()->GetGameSave()) + { + gameModel->SetSaveFile(gameModel->GetSaveFile()); + } +} + +std::string GameController::ElementResolve(int type) +{ + if(gameModel && gameModel->GetSimulation() && gameModel->GetSimulation()->elements && type >= 0 && type < PT_NUM) + return std::string(gameModel->GetSimulation()->elements[type].Name); + else + return ""; +} + +std::string GameController::WallName(int type) +{ + if(gameModel && gameModel->GetSimulation() && gameModel->GetSimulation()->wtypes && type >= 0 && type < UI_WALLCOUNT) + return std::string(gameModel->GetSimulation()->wtypes[type].name); + else + return ""; +} + +void GameController::NotifyAuthUserChanged(Client * sender) +{ + User newUser = sender->GetAuthUser(); + gameModel->SetUser(newUser); +} + +void GameController::NotifyNewNotification(Client * sender, std::pair<std::string, std::string> notification) +{ + class LinkNotification : public Notification + { + std::string link; + public: + LinkNotification(std::string link_, std::string message) : link(link_), Notification(message) {} + virtual ~LinkNotification() {} + + virtual void Action() + { + OpenURI(link); + } + }; + gameModel->AddNotification(new LinkNotification(notification.second, notification.first)); +} + +void GameController::NotifyUpdateAvailable(Client * sender) +{ + class UpdateConfirmation: public ConfirmDialogueCallback { + public: + GameController * c; + UpdateConfirmation(GameController * c_) { c = c_; } + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + c->RunUpdater(); + } + } + virtual ~UpdateConfirmation() { } + }; + + class UpdateNotification : public Notification + { + GameController * c; + public: + UpdateNotification(GameController * c, std::string message) : c(c), Notification(message) {} + virtual ~UpdateNotification() {} + + virtual void Action() + { + std::string currentVersion, newVersion; +#ifdef BETA + currentVersion = MTOS(SAVE_VERSION) "." MTOS(MINOR_VERSION) " Beta, Build " MTOS(BUILD_NUM); +#elif defined(SNAPSHOT) + currentVersion = "Snapshot " MTOS(SNAPSHOT_ID); +#else + currentVersion = MTOS(SAVE_VERSION) "." MTOS(MINOR_VERSION) " Stable, Build " MTOS(BUILD_NUM); +#endif + + UpdateInfo info = Client::Ref().GetUpdateInfo(); + if(info.Type == UpdateInfo::Beta) + newVersion = format::NumberToString<int>(info.Major) + " " + format::NumberToString<int>(info.Minor) + " Beta, Build " + format::NumberToString<int>(info.Build); + else if(info.Type == UpdateInfo::Snapshot) + newVersion = "Snapshot " + format::NumberToString<int>(info.Time); + else if(info.Type == UpdateInfo::Stable) + newVersion = format::NumberToString<int>(info.Major) + " " + format::NumberToString<int>(info.Minor) + " Stable, Build " + format::NumberToString<int>(info.Build); + + new ConfirmPrompt("Run Updater", "Are you sure you want to run the updater, please save any changes before updating.\n\nCurrent version:\n " + currentVersion + "\nNew version:\n " + newVersion, new UpdateConfirmation(c)); + } + }; + + switch(sender->GetUpdateInfo().Type) + { + case UpdateInfo::Snapshot: + gameModel->AddNotification(new UpdateNotification(this, std::string("A new snapshot is available - click here to update"))); + break; + case UpdateInfo::Stable: + gameModel->AddNotification(new UpdateNotification(this, std::string("A new version is available - click here to update"))); + break; + case UpdateInfo::Beta: + gameModel->AddNotification(new UpdateNotification(this, std::string("A new beta is available - click here to update"))); + break; + } +} + +void GameController::RemoveNotification(Notification * notification) +{ + gameModel->RemoveNotification(notification); +} + +void GameController::RunUpdater() +{ + Exit(); + new UpdateActivity(); +} diff --git a/src/gui/game/GameController.h b/src/gui/game/GameController.h new file mode 100644 index 0000000..644d25c --- /dev/null +++ b/src/gui/game/GameController.h @@ -0,0 +1,155 @@ + #ifndef GAMECONTROLLER_H +#define GAMECONTROLLER_H + +#include <queue> +#include "GameView.h" +#include "GameModel.h" +#include "simulation/Simulation.h" +#include "gui/interface/Point.h" +#include "gui/search/SearchController.h" +#include "gui/render/RenderController.h" +#include "gui/preview/PreviewController.h" +#include "gui/login/LoginController.h" +#include "gui/tags/TagsController.h" +#include "gui/console/ConsoleController.h" +#include "gui/localbrowser/LocalBrowserController.h" +#include "gui/options/OptionsController.h" +//#include "cat/TPTScriptInterface.h" +#include "cat/LuaScriptInterface.h" +#include "client/ClientListener.h" +#include "RenderPreset.h" +#include "Menu.h" + +using namespace std; + +class DebugInfo; +class Notification; +class GameModel; +class GameView; +class CommandInterface; +class ConsoleController; +class GameController: public ClientListener +{ +private: + //Simulation * sim; + bool firstTick; + int screenshotIndex; + PreviewController * activePreview; + GameView * gameView; + GameModel * gameModel; + SearchController * search; + RenderController * renderOptions; + LoginController * loginWindow; + ConsoleController * console; + TagsController * tagsWindow; + LocalBrowserController * localBrowser; + OptionsController * options; + CommandInterface * commandInterface; + vector<DebugInfo*> debugInfo; +public: + bool HasDone; + class SearchCallback; + class RenderCallback; + class SSaveCallback; + class TagsCallback; + class StampsCallback; + class OptionsCallback; + class SaveOpenCallback; + friend class SaveOpenCallback; + GameController(); + ~GameController(); + GameView * GetView(); + + bool BrushChanged(int brushType, int rx, int ry); + bool MouseMove(int x, int y, int dx, int dy); + bool MouseDown(int x, int y, unsigned button); + bool MouseUp(int x, int y, unsigned button); + bool MouseWheel(int x, int y, int d); + bool KeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + bool KeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + void Tick(); + void Exit(); + + void Install(); + + void HistoryRestore(); + void HistorySnapshot(); + + void AdjustGridSize(int direction); + void InvertAirSim(); + void LoadRenderPreset(int presetNum); + void SetZoomEnabled(bool zoomEnable); + void SetZoomPosition(ui::Point position); + void AdjustBrushSize(int direction, bool logarithmic = false, bool xAxis = false, bool yAxis = false); + void AdjustZoomSize(int direction, bool logarithmic = false); + void ToolClick(int toolSelection, ui::Point point); + void DrawPoints(int toolSelection, queue<ui::Point> & pointQueue); + void DrawRect(int toolSelection, ui::Point point1, ui::Point point2); + void DrawLine(int toolSelection, ui::Point point1, ui::Point point2); + void DrawFill(int toolSelection, ui::Point point); + void StampRegion(ui::Point point1, ui::Point point2); + void CopyRegion(ui::Point point1, ui::Point point2); + void CutRegion(ui::Point point1, ui::Point point2); + void Update(); + void SetPaused(bool pauseState); + void SetPaused(); + void SetDecoration(bool decorationState); + void SetDecoration(); + void ShowGravityGrid(); + void SetHudEnable(bool hudState); + void SetActiveMenu(Menu * menu); + std::vector<Menu*> GetMenuList(); + void SetActiveTool(int toolSelection, Tool * tool); + void ActiveToolChanged(int toolSelection, Tool *tool); + void SetActiveColourPreset(int preset); + void SetColour(ui::Colour colour); + void SetToolStrength(float value); + void LoadSaveFile(SaveFile * file); + void LoadSave(SaveInfo * save); + void OpenSearch(); + void OpenLogin(); + void OpenTags(); + void OpenSavePreview(int saveID, int saveDate); + void OpenSavePreview(); + void OpenLocalSaveWindow(bool asCurrent); + void OpenLocalBrowse(); + void OpenOptions(); + void OpenRenderOptions(); + void OpenSaveWindow(); + void SaveAsCurrent(); + void OpenStamps(); + void OpenElementSearch(); + void OpenColourPicker(); + void PlaceSave(ui::Point position); + void ClearSim(); + void ReloadSim(); + void Vote(int direction); + void ChangeBrush(); + void ShowConsole(); + void HideConsole(); + void FrameStep(); + void TranslateSave(ui::Point point); + void TransformSave(matrix2d transform); + ui::Point PointTranslate(ui::Point point); + ui::Point NormaliseBlockCoord(ui::Point point); + std::string ElementResolve(int type); + std::string WallName(int type); + + void ResetAir(); + void ResetSpark(); + void SwitchGravity(); + void SwitchAir(); + void ToggleAHeat(); + + void LoadClipboard(); + void LoadStamp(); + + void RemoveNotification(Notification * notification); + + virtual void NotifyUpdateAvailable(Client * sender); + virtual void NotifyAuthUserChanged(Client * sender); + virtual void NotifyNewNotification(Client * sender, std::pair<std::string, std::string> notification); + void RunUpdater(); +}; + +#endif // GAMECONTROLLER_H diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp new file mode 100644 index 0000000..37194a5 --- /dev/null +++ b/src/gui/game/GameModel.cpp @@ -0,0 +1,1151 @@ +#include "gui/interface/Engine.h" +#include "GameModel.h" +#include "GameView.h" +#include "simulation/Simulation.h" +#include "simulation/Air.h" +#include "simulation/Tools.h" +#include "graphics/Renderer.h" +#include "gui/interface/Point.h" +#include "Brush.h" +#include "EllipseBrush.h" +#include "TriangleBrush.h" +#include "BitmapBrush.h" +#include "client/Client.h" +#include "client/GameSave.h" +#include "gui/game/DecorationTool.h" +#include "GameModelException.h" +#include "QuickOptions.h" +#include "Format.h" + +GameModel::GameModel(): + sim(NULL), + ren(NULL), + currentBrush(0), + currentUser(0, ""), + currentSave(NULL), + currentFile(NULL), + colourSelector(false), + clipboard(NULL), + stamp(NULL), + placeSave(NULL), + colour(255, 0, 0, 255), + toolStrength(1.0f), + activeColourPreset(-1), + activeMenu(NULL), + edgeMode(0) +{ + sim = new Simulation(); + ren = new Renderer(ui::Engine::Ref().g, sim); + + activeTools = regularToolset; + + std::fill(decoToolset, decoToolset+3, (Tool*)NULL); + std::fill(regularToolset, regularToolset+3, (Tool*)NULL); + + //Default render prefs + std::vector<unsigned int> tempArray; + tempArray.push_back(RENDER_FIRE); + tempArray.push_back(RENDER_EFFE); + tempArray.push_back(RENDER_BASC); + ren->SetRenderMode(tempArray); + tempArray.clear(); + + ren->SetDisplayMode(tempArray); + + ren->SetColourMode(0); + + //Load config into renderer + try + { + ren->SetColourMode(Client::Ref().GetPrefUInteger("Renderer.ColourMode", 0)); + + vector<unsigned int> tempArray = Client::Ref().GetPrefUIntegerArray("Renderer.DisplayModes"); + if(tempArray.size()) + { + std::vector<unsigned int> displayModes(tempArray.begin(), tempArray.end()); + ren->SetDisplayMode(displayModes); + } + + tempArray = Client::Ref().GetPrefUIntegerArray("Renderer.RenderModes"); + if(tempArray.size()) + { + std::vector<unsigned int> renderModes(tempArray.begin(), tempArray.end()); + ren->SetRenderMode(renderModes); + } + + ren->gravityFieldEnabled = Client::Ref().GetPrefBool("Renderer.GravityField", false); + ren->decorations_enable = Client::Ref().GetPrefBool("Renderer.Decorations", true); + } + catch(json::Exception & e) + { + } + + //Load config into simulation + edgeMode = Client::Ref().GetPrefInteger("Simulation.EdgeMode", 0); + sim->SetEdgeMode(edgeMode); + + //Load last user + if(Client::Ref().GetAuthUser().ID) + { + currentUser = Client::Ref().GetAuthUser(); + } + + //Set stamp to first stamp in list + vector<string> stamps = Client::Ref().GetStamps(0, 1); + if(stamps.size()>0) + { + SaveFile * stampFile = Client::Ref().GetStamp(stamps[0]); + if(stampFile && stampFile->GetGameSave()) + stamp = stampFile->GetGameSave(); + } + + BuildMenus(); + + //Set default brush palette + brushList.push_back(new EllipseBrush(ui::Point(4, 4))); + brushList.push_back(new Brush(ui::Point(4, 4))); + brushList.push_back(new TriangleBrush(ui::Point(4, 4))); + + //Load more from brushes folder + std::vector<string> brushFiles = Client::Ref().DirectorySearch(BRUSH_DIR, "", ".ptb"); + for(int i = 0; i < brushFiles.size(); i++) + { + std::vector<unsigned char> brushData = Client::Ref().ReadFile(brushFiles[i]); + if(!brushData.size()) + { + std::cout << "Brushes: Skipping " << brushFiles[i] << ". Could not open" << std::endl; + continue; + } + int dimension = std::sqrt((float)brushData.size()); + if(dimension * dimension != brushData.size()) + { + std::cout << "Brushes: Skipping " << brushFiles[i] << ". Invalid bitmap size" << std::endl; + continue; + } + brushList.push_back(new BitmapBrush(brushData, ui::Point(dimension, dimension))); + } + + //Set default decoration colour + unsigned char colourR = min(Client::Ref().GetPrefInteger("Decoration.Red", 200), 255); + unsigned char colourG = min(Client::Ref().GetPrefInteger("Decoration.Green", 100), 255); + unsigned char colourB = min(Client::Ref().GetPrefInteger("Decoration.Blue", 50), 255); + unsigned char colourA = min(Client::Ref().GetPrefInteger("Decoration.Alpha", 255), 255); + + SetColourSelectorColour(ui::Colour(colourR, colourG, colourB, colourA)); + + colourPresets.push_back(ui::Colour(255, 255, 255)); + colourPresets.push_back(ui::Colour(0, 255, 255)); + colourPresets.push_back(ui::Colour(255, 0, 255)); + colourPresets.push_back(ui::Colour(255, 255, 0)); + colourPresets.push_back(ui::Colour(255, 0, 0)); + colourPresets.push_back(ui::Colour(0, 255, 0)); + colourPresets.push_back(ui::Colour(0, 0, 255)); +} + +GameModel::~GameModel() +{ + //Save to config: + Client::Ref().SetPref("Renderer.ColourMode", ren->GetColourMode()); + + std::vector<unsigned int> displayModes = ren->GetDisplayMode(); + Client::Ref().SetPref("Renderer.DisplayModes", std::vector<unsigned int>(displayModes.begin(), displayModes.end())); + + std::vector<unsigned int> renderModes = ren->GetRenderMode(); + Client::Ref().SetPref("Renderer.RenderModes", std::vector<unsigned int>(renderModes.begin(), renderModes.end())); + + Client::Ref().SetPref("Renderer.GravityField", (bool)ren->gravityFieldEnabled); + Client::Ref().SetPref("Renderer.Decorations", (bool)ren->decorations_enable); + + Client::Ref().SetPref("Simulation.EdgeMode", sim->edgeMode); + + Client::Ref().SetPref("Decoration.Red", (int)colour.Red); + Client::Ref().SetPref("Decoration.Green", (int)colour.Green); + Client::Ref().SetPref("Decoration.Blue", (int)colour.Blue); + Client::Ref().SetPref("Decoration.Alpha", (int)colour.Alpha); + + for(int i = 0; i < menuList.size(); i++) + { + delete menuList[i]; + } + for(std::vector<Tool*>::iterator iter = extraElementTools.begin(), end = extraElementTools.end(); iter != end; ++iter) + { + delete *iter; + } + for(int i = 0; i < brushList.size(); i++) + { + delete brushList[i]; + } + delete sim; + delete ren; + if(placeSave) + delete placeSave; + if(clipboard) + delete clipboard; + if(stamp) + delete stamp; + if(currentSave) + delete currentSave; + if(currentFile) + delete currentFile; + //if(activeTools) + // delete[] activeTools; +} + +void GameModel::UpdateQuickOptions() +{ + for(std::vector<QuickOption*>::iterator iter = quickOptions.begin(), end = quickOptions.end(); iter != end; ++iter) + { + QuickOption * option = *iter; + option->Update(); + } +} + +void GameModel::BuildQuickOptionMenu(GameController * controller) +{ + for(std::vector<QuickOption*>::iterator iter = quickOptions.begin(), end = quickOptions.end(); iter != end; ++iter) + { + delete *iter; + } + quickOptions.clear(); + + quickOptions.push_back(new SandEffectOption(this)); + quickOptions.push_back(new DrawGravOption(this)); + quickOptions.push_back(new DecorationsOption(this)); + quickOptions.push_back(new NGravityOption(this)); + quickOptions.push_back(new AHeatOption(this)); + quickOptions.push_back(new ConsoleShowOption(this, controller)); + + notifyQuickOptionsChanged(); + UpdateQuickOptions(); +} + +void GameModel::BuildMenus() +{ + char lastMenu = 0; + if(activeMenu) + lastMenu = activeMenu->GetIcon(); + + std::string activeToolIdentifiers[3]; + if(regularToolset[0]) + activeToolIdentifiers[0] = regularToolset[0]->GetIdentifier(); + if(regularToolset[1]) + activeToolIdentifiers[1] = regularToolset[1]->GetIdentifier(); + if(regularToolset[2]) + activeToolIdentifiers[2] = regularToolset[2]->GetIdentifier(); + + //Empty current menus + for(std::vector<Menu*>::iterator iter = menuList.begin(), end = menuList.end(); iter != end; ++iter) + { + delete *iter; + } + menuList.clear(); + toolList.clear(); + + for(std::vector<Tool*>::iterator iter = extraElementTools.begin(), end = extraElementTools.end(); iter != end; ++iter) + { + delete *iter; + } + extraElementTools.clear(); + elementTools.clear(); + + //Create menus + for(int i = 0; i < SC_TOTAL; i++) + { + menuList.push_back(new Menu((const char)sim->msections[i].icon[0], sim->msections[i].name)); + } + + //Build menus from Simulation elements + for(int i = 0; i < PT_NUM; i++) + { + if(sim->elements[i].Enabled) + { + Tool * tempTool; + if(i == PT_LIGH) + { + tempTool = new Element_LIGH_Tool(i, sim->elements[i].Name, sim->elements[i].Description, PIXR(sim->elements[i].Colour), PIXG(sim->elements[i].Colour), PIXB(sim->elements[i].Colour), sim->elements[i].Identifier, sim->elements[i].IconGenerator); + } + else if(i == PT_TESC) + { + tempTool = new Element_TESC_Tool(i, sim->elements[i].Name, sim->elements[i].Description, PIXR(sim->elements[i].Colour), PIXG(sim->elements[i].Colour), PIXB(sim->elements[i].Colour), sim->elements[i].Identifier, sim->elements[i].IconGenerator); + } + else if(i == PT_STKM || i == PT_FIGH || i == PT_STKM2) + { + tempTool = new PlopTool(i, sim->elements[i].Name, sim->elements[i].Description, PIXR(sim->elements[i].Colour), PIXG(sim->elements[i].Colour), PIXB(sim->elements[i].Colour), sim->elements[i].Identifier, sim->elements[i].IconGenerator); + } + else + { + tempTool = new ElementTool(i, sim->elements[i].Name, sim->elements[i].Description, PIXR(sim->elements[i].Colour), PIXG(sim->elements[i].Colour), PIXB(sim->elements[i].Colour), sim->elements[i].Identifier, sim->elements[i].IconGenerator); + } + + if(sim->elements[i].MenuSection < SC_TOTAL && sim->elements[i].MenuVisible) + { + menuList[sim->elements[i].MenuSection]->AddTool(tempTool); + } + else + { + extraElementTools.push_back(tempTool); + } + elementTools.push_back(tempTool); + } + } + + //Build menu for GOL types + for(int i = 0; i < NGOL; i++) + { + Tool * tempTool = new GolTool(i, sim->gmenu[i].name, std::string(sim->gmenu[i].description), PIXR(sim->gmenu[i].colour), PIXG(sim->gmenu[i].colour), PIXB(sim->gmenu[i].colour), "DEFAULT_PT_LIFE_"+std::string(sim->gmenu[i].name)); + menuList[SC_LIFE]->AddTool(tempTool); + } + + //Build other menus from wall data + for(int i = 0; i < UI_WALLCOUNT; i++) + { + Tool * tempTool = new WallTool(i, "", std::string(sim->wtypes[i].descs), PIXR(sim->wtypes[i].colour), PIXG(sim->wtypes[i].colour), PIXB(sim->wtypes[i].colour), "DEFAULT_WL_"+format::NumberToString<int>(i), sim->wtypes[i].textureGen); + menuList[SC_WALL]->AddTool(tempTool); + //sim->wtypes[i] + } + + //Add special sign and prop tools + menuList[SC_TOOL]->AddTool(new SampleTool(this)); + menuList[SC_TOOL]->AddTool(new SignTool()); + menuList[SC_TOOL]->AddTool(new PropertyTool()); + menuList[SC_TOOL]->AddTool(new WindTool(0, "WIND", "Create air movement", 64, 64, 64, "DEFAULT_UI_WIND")); + + //Build menu for simtools + for(int i = 0; i < sim->tools.size(); i++) + { + Tool * tempTool; + tempTool = new Tool(i, sim->tools[i]->Name, sim->tools[i]->Description, PIXR(sim->tools[i]->Colour), PIXG(sim->tools[i]->Colour), PIXB(sim->tools[i]->Colour), sim->tools[i]->Identifier); + menuList[SC_TOOL]->AddTool(tempTool); + } + + //Add decoration tools to menu + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendAdd, "ADD", "Colour blending: Add", 0, 0, 0, "DEFAULT_DECOR_ADD")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendRemove, "SUB", "Colour blending: Subtract", 0, 0, 0, "DEFAULT_DECOR_SUB")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendMultiply, "MUL", "Colour blending: Multiply", 0, 0, 0, "DEFAULT_DECOR_MUL")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendDivide, "DIV", "Colour blending: Divide" , 0, 0, 0, "DEFAULT_DECOR_DIV")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendSmudge, "SMDG", "Smudge colour", 0, 0, 0, "DEFAULT_DECOR_SMDG")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::BlendSet, "SET", "Set colour (No blending)", 0, 0, 0, "DEFAULT_DECOR_SET")); + menuList[SC_DECO]->AddTool(new DecorationTool(DecorationTool::Remove, "CLR", "Clear any set decoration", 0, 0, 0, "DEFAULT_DECOR_CLR")); + decoToolset[0] = GetToolFromIdentifier("DEFAULT_DECOR_SET"); + decoToolset[1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR"); + decoToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE"); + + //Set default tools + regularToolset[0] = GetToolFromIdentifier("DEFAULT_PT_DUST"); + regularToolset[1] = GetToolFromIdentifier("DEFAULT_PT_NONE"); + regularToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE"); + + + if(activeToolIdentifiers[0].length()) + regularToolset[0] = GetToolFromIdentifier(activeToolIdentifiers[0]); + if(activeToolIdentifiers[1].length()) + regularToolset[1] = GetToolFromIdentifier(activeToolIdentifiers[1]); + if(activeToolIdentifiers[2].length()) + regularToolset[2] = GetToolFromIdentifier(activeToolIdentifiers[2]); + + lastTool = activeTools[0]; + + //Set default menu + activeMenu = menuList[SC_POWDERS]; + + if(lastMenu) + { + for(std::vector<Menu*>::iterator iter = menuList.begin(), end = menuList.end(); iter != end; ++iter) + { + if((*iter)->GetIcon() == lastMenu) + activeMenu = *iter; + } + } + + if(activeMenu) + toolList = activeMenu->GetToolList(); + else + toolList = std::vector<Tool*>(); + + notifyMenuListChanged(); + notifyToolListChanged(); + notifyActiveToolsChanged(); + notifyLastToolChanged(); +} + +Tool * GameModel::GetToolFromIdentifier(std::string identifier) +{ + for(std::vector<Menu*>::iterator iter = menuList.begin(), end = menuList.end(); iter != end; ++iter) + { + std::vector<Tool*> menuTools = (*iter)->GetToolList(); + for(std::vector<Tool*>::iterator titer = menuTools.begin(), tend = menuTools.end(); titer != tend; ++titer) + { + if(identifier == (*titer)->GetIdentifier()) + return *titer; + } + } + return NULL; +} + +void GameModel::SetEdgeMode(int edgeMode) +{ + this->edgeMode = edgeMode; + sim->SetEdgeMode(edgeMode); +} + +int GameModel::GetEdgeMode() +{ + return this->edgeMode; +} + +std::deque<Snapshot*> GameModel::GetHistory() +{ + return history; +} +void GameModel::SetHistory(std::deque<Snapshot*> newHistory) +{ + history = newHistory; +} + +void GameModel::SetVote(int direction) +{ + if(currentSave) + { + RequestStatus status = Client::Ref().ExecVote(currentSave->GetID(), direction); + if(status == RequestOkay) + { + currentSave->vote = direction; + notifySaveChanged(); + } + else + { + throw GameModelException("Could not vote: "+Client::Ref().GetLastError()); + } + } +} + +Brush * GameModel::GetBrush() +{ + return brushList[currentBrush]; +} + +int GameModel::GetBrushID() +{ + return currentBrush; +} + +void GameModel::SetBrush(int i) +{ + currentBrush = i%brushList.size(); + notifyBrushChanged(); +} + +void GameModel::AddObserver(GameView * observer){ + observers.push_back(observer); + + observer->NotifySimulationChanged(this); + observer->NotifyRendererChanged(this); + observer->NotifyPausedChanged(this); + observer->NotifySaveChanged(this); + observer->NotifyBrushChanged(this); + observer->NotifyMenuListChanged(this); + observer->NotifyToolListChanged(this); + observer->NotifyUserChanged(this); + observer->NotifyZoomChanged(this); + observer->NotifyColourSelectorVisibilityChanged(this); + observer->NotifyColourSelectorColourChanged(this); + observer->NotifyColourPresetsChanged(this); + observer->NotifyColourActivePresetChanged(this); + observer->NotifyQuickOptionsChanged(this); + observer->NotifyLastToolChanged(this); + UpdateQuickOptions(); +} + +void GameModel::SetToolStrength(float value) +{ + toolStrength = value; +} + +float GameModel::GetToolStrength() +{ + return toolStrength; +} + +void GameModel::SetActiveMenu(Menu * menu) +{ + for(int i = 0; i < menuList.size(); i++) + { + if(menuList[i]==menu) + { + activeMenu = menu; + toolList = menu->GetToolList(); + notifyToolListChanged(); + + if(menu == menuList[SC_DECO]) + { + if(activeTools != decoToolset) + { + activeTools = decoToolset; + notifyActiveToolsChanged(); + } + } + else + { + if(activeTools != regularToolset) + { + activeTools = regularToolset; + notifyActiveToolsChanged(); + } + } + } + } +} + +vector<Tool*> GameModel::GetUnlistedTools() +{ + return extraElementTools; +} + +vector<Tool*> GameModel::GetToolList() +{ + return toolList; +} + +Menu * GameModel::GetActiveMenu() +{ + return activeMenu; +} + +Tool * GameModel::GetElementTool(int elementID) +{ + std::cout << elementID << std::endl; + for(std::vector<Tool*>::iterator iter = elementTools.begin(), end = elementTools.end(); iter != end; ++iter) + { + if((*iter)->GetToolID() == elementID) + return *iter; + } + return NULL; +} + +Tool * GameModel::GetActiveTool(int selection) +{ + return activeTools[selection]; +} + +void GameModel::SetActiveTool(int selection, Tool * tool) +{ + activeTools[selection] = tool; + notifyActiveToolsChanged(); +} + +vector<QuickOption*> GameModel::GetQuickOptions() +{ + return quickOptions; +} + +vector<Menu*> GameModel::GetMenuList() +{ + return menuList; +} + +SaveInfo * GameModel::GetSave() +{ + return currentSave; +} + +void GameModel::SetSave(SaveInfo * newSave) +{ + if(currentSave != newSave) + { + if(currentSave) + delete currentSave; + if(newSave == NULL) + currentSave = NULL; + else + currentSave = new SaveInfo(*newSave); + } + if(currentFile) + delete currentFile; + currentFile = NULL; + + if(currentSave && currentSave->GetGameSave()) + { + GameSave * saveData = currentSave->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->start_grav_async(); + else + sim->grav->stop_grav_async(); + sim->SetEdgeMode(0); + sim->clear_sim(); + ren->ClearAccumulation(); + sim->Load(saveData); + } + notifySaveChanged(); + UpdateQuickOptions(); +} + +SaveFile * GameModel::GetSaveFile() +{ + return currentFile; +} + +void GameModel::SetSaveFile(SaveFile * newSave) +{ + if(currentFile != newSave) + { + if(currentFile) + delete currentFile; + if(newSave == NULL) + currentFile = NULL; + else + currentFile = new SaveFile(*newSave); + } + if (currentSave) + delete currentSave; + currentSave = 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->SetEdgeMode(0); + sim->clear_sim(); + ren->ClearAccumulation(); + sim->Load(saveData); + } + + notifySaveChanged(); + UpdateQuickOptions(); +} + +Simulation * GameModel::GetSimulation() +{ + return sim; +} + +Renderer * GameModel::GetRenderer() +{ + return ren; +} + +User GameModel::GetUser() +{ + return currentUser; +} + +Tool * GameModel::GetLastTool() +{ + return lastTool; +} + +void GameModel::SetLastTool(Tool * newTool) +{ + if(lastTool != newTool) + { + lastTool = newTool; + notifyLastToolChanged(); + } +} + +void GameModel::SetZoomEnabled(bool enabled) +{ + ren->zoomEnabled = enabled; + notifyZoomChanged(); +} + +bool GameModel::GetZoomEnabled() +{ + return ren->zoomEnabled; +} + +void GameModel::SetZoomPosition(ui::Point position) +{ + ren->zoomScopePosition = position; + notifyZoomChanged(); +} + +ui::Point GameModel::GetZoomPosition() +{ + return ren->zoomScopePosition; +} + +void GameModel::SetZoomWindowPosition(ui::Point position) +{ + ren->zoomWindowPosition = position; + notifyZoomChanged(); +} + +ui::Point GameModel::GetZoomWindowPosition() +{ + return ren->zoomWindowPosition; +} + +void GameModel::SetZoomSize(int size) +{ + ren->zoomScopeSize = size; + notifyZoomChanged(); +} + +int GameModel::GetZoomSize() +{ + return ren->zoomScopeSize; +} + +void GameModel::SetZoomFactor(int factor) +{ + ren->ZFACTOR = factor; + notifyZoomChanged(); +} + +int GameModel::GetZoomFactor() +{ + return ren->ZFACTOR; +} + +void GameModel::SetActiveColourPreset(int preset) +{ + activeColourPreset = preset; + notifyColourActivePresetChanged(); +} + +int GameModel::GetActiveColourPreset() +{ + return activeColourPreset; +} + +void GameModel::SetPresetColour(ui::Colour colour) +{ + if(activeColourPreset >= 0 && activeColourPreset < colourPresets.size()) + { + colourPresets[activeColourPreset] = colour; + notifyColourPresetsChanged(); + } +} + +std::vector<ui::Colour> GameModel::GetColourPresets() +{ + return colourPresets; +} + +void GameModel::SetColourSelectorVisibility(bool visibility) +{ + if(colourSelector != visibility) + { + colourSelector = visibility; + notifyColourSelectorVisibilityChanged(); + } +} + +bool GameModel::GetColourSelectorVisibility() +{ + return colourSelector; +} + +void GameModel::SetColourSelectorColour(ui::Colour colour_) +{ + colour = colour_; + notifyColourSelectorColourChanged(); + + vector<Tool*> tools = GetMenuList()[SC_DECO]->GetToolList(); + for(int i = 0; i < tools.size(); i++) + { + ((DecorationTool*)tools[i])->Red = colour.Red; + ((DecorationTool*)tools[i])->Green = colour.Green; + ((DecorationTool*)tools[i])->Blue = colour.Blue; + ((DecorationTool*)tools[i])->Alpha = colour.Alpha; + } +} + +ui::Colour GameModel::GetColourSelectorColour() +{ + return colour; +} + +void GameModel::SetUser(User user) +{ + currentUser = user; + //Client::Ref().SetAuthUser(user); + notifyUserChanged(); +} + +void GameModel::SetPaused(bool pauseState) +{ + sim->sys_pause = pauseState?1:0; + notifyPausedChanged(); +} + +bool GameModel::GetPaused() +{ + return sim->sys_pause?true:false; +} + +void GameModel::SetDecoration(bool decorationState) +{ + ren->decorations_enable = decorationState?1:0; + notifyDecorationChanged(); + UpdateQuickOptions(); + if (decorationState) + SetInfoTip("Decorations Layer: On"); + else + SetInfoTip("Decorations Layer: Off"); +} + +bool GameModel::GetDecoration() +{ + return ren->decorations_enable?true:false; +} + +void GameModel::SetAHeatEnable(bool aHeat) +{ + sim->aheat_enable = aHeat; + UpdateQuickOptions(); + if (aHeat) + SetInfoTip("Ambient Heat: On"); + else + SetInfoTip("Ambient Heat: Off"); +} + +bool GameModel::GetAHeatEnable() +{ + return sim->aheat_enable; +} + +void GameModel::ShowGravityGrid(bool showGrid) +{ + ren->gravityFieldEnabled = showGrid; + if (showGrid) + SetInfoTip("Gravity Grid: On"); + else + SetInfoTip("Gravity Grid: Off"); +} + +bool GameModel::GetGravityGrid() +{ + return ren->gravityFieldEnabled; +} + +void GameModel::FrameStep(int frames) +{ + sim->framerender += frames; +} + +void GameModel::ClearSimulation() +{ + //Load defaults + sim->gravityMode = 0; + sim->air->airMode = 0; + sim->legacy_enable = false; + sim->water_equal_test = false; + sim->SetEdgeMode(edgeMode); + + sim->clear_sim(); + ren->ClearAccumulation(); + + notifySaveChanged(); + UpdateQuickOptions(); +} + +void GameModel::SetStamp(GameSave * save) +{ + if(stamp != save) + { + if(stamp) + delete stamp; + if(save) + stamp = new GameSave(*save); + else + stamp = NULL; + } +} + +void GameModel::SetPlaceSave(GameSave * save) +{ + if(save != placeSave) + { + if(placeSave) + delete placeSave; + if(save) + placeSave = new GameSave(*save); + else + placeSave = NULL; + } + notifyPlaceSaveChanged(); +} + +void GameModel::AddStamp(GameSave * save) +{ + if(stamp) + delete stamp; + stamp = save; + Client::Ref().AddStamp(save); +} + +void GameModel::SetClipboard(GameSave * save) +{ + if(clipboard) + delete clipboard; + clipboard = save; +} + +GameSave * GameModel::GetClipboard() +{ + return clipboard; +} + +GameSave * GameModel::GetPlaceSave() +{ + return placeSave; +} + +GameSave * GameModel::GetStamp() +{ + return stamp; +} + +void GameModel::Log(string message) +{ + consoleLog.push_front(message); + if(consoleLog.size()>100) + consoleLog.pop_back(); + notifyLogChanged(message); +} + +deque<string> GameModel::GetLog() +{ + return consoleLog; +} + +std::vector<Notification*> GameModel::GetNotifications() +{ + return notifications; +} + +void GameModel::AddNotification(Notification * notification) +{ + notifications.push_back(notification); + notifyNotificationsChanged(); +} + +void GameModel::RemoveNotification(Notification * notification) +{ + for(std::vector<Notification*>::iterator iter = notifications.begin(); iter != notifications.end(); ++iter) + { + if(*iter == notification) + { + delete *iter; + notifications.erase(iter); + break; + } + } + notifyNotificationsChanged(); +} + +void GameModel::SetToolTip(std::string text) +{ + toolTip = text; + notifyToolTipChanged(); +} + +void GameModel::SetInfoTip(std::string text) +{ + infoTip = text; + notifyInfoTipChanged(); +} + +std::string GameModel::GetToolTip() +{ + return toolTip; +} + +std::string GameModel::GetInfoTip() +{ + return infoTip; +} + +void GameModel::notifyNotificationsChanged() +{ + for(std::vector<GameView*>::iterator iter = observers.begin(); iter != observers.end(); ++iter) + { + (*iter)->NotifyNotificationsChanged(this); + } +} + +void GameModel::notifyColourPresetsChanged() +{ + for(std::vector<GameView*>::iterator iter = observers.begin(); iter != observers.end(); ++iter) + { + (*iter)->NotifyColourPresetsChanged(this); + } +} + +void GameModel::notifyColourActivePresetChanged() +{ + for(std::vector<GameView*>::iterator iter = observers.begin(); iter != observers.end(); ++iter) + { + (*iter)->NotifyColourActivePresetChanged(this); + } +} + +void GameModel::notifyColourSelectorColourChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyColourSelectorColourChanged(this); + } +} + +void GameModel::notifyColourSelectorVisibilityChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyColourSelectorVisibilityChanged(this); + } +} + +void GameModel::notifyRendererChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyRendererChanged(this); + } +} + +void GameModel::notifySaveChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifySaveChanged(this); + } +} + +void GameModel::notifySimulationChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifySimulationChanged(this); + } +} + +void GameModel::notifyPausedChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyPausedChanged(this); + } +} + +void GameModel::notifyDecorationChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + //observers[i]->NotifyPausedChanged(this); + } +} + +void GameModel::notifyBrushChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyBrushChanged(this); + } +} + +void GameModel::notifyMenuListChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyMenuListChanged(this); + } +} + +void GameModel::notifyToolListChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyToolListChanged(this); + } +} + +void GameModel::notifyActiveToolsChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyActiveToolsChanged(this); + } +} + +void GameModel::notifyUserChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyUserChanged(this); + } +} + +void GameModel::notifyZoomChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyZoomChanged(this); + } +} + +void GameModel::notifyPlaceSaveChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyPlaceSaveChanged(this); + } +} + +void GameModel::notifyLogChanged(string entry) +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyLogChanged(this, entry); + } +} + +void GameModel::notifyInfoTipChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyInfoTipChanged(this); + } +} + +void GameModel::notifyToolTipChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyToolTipChanged(this); + } +} + +void GameModel::notifyQuickOptionsChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyQuickOptionsChanged(this); + } +} + +void GameModel::notifyLastToolChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyLastToolChanged(this); + } +} diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h new file mode 100644 index 0000000..0ade162 --- /dev/null +++ b/src/gui/game/GameModel.h @@ -0,0 +1,206 @@ +#ifndef GAMEMODEL_H +#define GAMEMODEL_H + +#include <vector> +#include <deque> +#include "client/SaveInfo.h" +#include "simulation/Simulation.h" +#include "gui/interface/Colour.h" +#include "graphics/Renderer.h" +#include "GameView.h" +#include "GameController.h" +#include "Brush.h" +#include "client/User.h" +#include "Notification.h" + +#include "Tool.h" +#include "Menu.h" + +using namespace std; + +class GameView; +class GameController; +class Simulation; +class Renderer; + +class QuickOption; +class ToolSelection +{ +public: + enum + { + ToolPrimary, ToolSecondary, ToolTertiary + }; +}; + +class GameModel +{ +private: + vector<Notification*> notifications; + //int clipboardSize; + //unsigned char * clipboardData; + GameSave * stamp; + GameSave * clipboard; + GameSave * placeSave; + deque<string> consoleLog; + vector<GameView*> observers; + vector<Tool*> toolList; + + //All tools that are associated with elements + vector<Tool*> elementTools; + //Tools that are present in elementTools, but don't have an associated menu and need to be freed manually + vector<Tool*> extraElementTools; + + vector<Menu*> menuList; + vector<QuickOption*> quickOptions; + Menu * activeMenu; + int currentBrush; + vector<Brush *> brushList; + SaveInfo * currentSave; + SaveFile * currentFile; + Simulation * sim; + Renderer * ren; + Tool * lastTool; + Tool ** activeTools; + Tool * decoToolset[3]; + Tool * regularToolset[3]; + User currentUser; + float toolStrength; + std::deque<Snapshot*> history; + + int activeColourPreset; + std::vector<ui::Colour> colourPresets; + bool colourSelector; + ui::Colour colour; + + int edgeMode; + + std::string infoTip; + std::string toolTip; + //bool zoomEnabled; + void notifyRendererChanged(); + void notifySimulationChanged(); + void notifyPausedChanged(); + void notifyDecorationChanged(); + void notifySaveChanged(); + void notifyBrushChanged(); + void notifyMenuListChanged(); + void notifyToolListChanged(); + void notifyActiveToolsChanged(); + void notifyUserChanged(); + void notifyZoomChanged(); + void notifyClipboardChanged(); + void notifyPlaceSaveChanged(); + void notifyColourSelectorColourChanged(); + void notifyColourSelectorVisibilityChanged(); + void notifyColourPresetsChanged(); + void notifyColourActivePresetChanged(); + void notifyNotificationsChanged(); + void notifyLogChanged(string entry); + void notifyInfoTipChanged(); + void notifyToolTipChanged(); + void notifyQuickOptionsChanged(); + void notifyLastToolChanged(); +public: + GameModel(); + ~GameModel(); + + Tool * GetToolFromIdentifier(std::string identifier); + + void SetEdgeMode(int edgeMode); + int GetEdgeMode(); + + void SetActiveColourPreset(int preset); + int GetActiveColourPreset(); + + void SetPresetColour(ui::Colour colour); + + std::vector<ui::Colour> GetColourPresets(); + + void SetColourSelectorVisibility(bool visibility); + bool GetColourSelectorVisibility(); + + void SetColourSelectorColour(ui::Colour colour); + ui::Colour GetColourSelectorColour(); + + void SetToolTip(std::string text); + void SetInfoTip(std::string text); + std::string GetToolTip(); + std::string GetInfoTip(); + + void BuildMenus(); + void BuildQuickOptionMenu(GameController * controller); + + std::deque<Snapshot*> GetHistory(); + void SetHistory(std::deque<Snapshot*> newHistory); + + void UpdateQuickOptions(); + + void SetToolStrength(float value); + float GetToolStrength(); + + Tool * GetLastTool(); + void SetLastTool(Tool * newTool); + + void SetVote(int direction); + SaveInfo * GetSave(); + SaveFile * GetSaveFile(); + Brush * GetBrush(); + void SetSave(SaveInfo * newSave); + void SetSaveFile(SaveFile * newSave); + void AddObserver(GameView * observer); + + //Get an element tool from an element ID + Tool * GetElementTool(int elementID); + + Tool * GetActiveTool(int selection); + void SetActiveTool(int selection, Tool * tool); + + bool GetPaused(); + void SetPaused(bool pauseState); + bool GetDecoration(); + void SetDecoration(bool decorationState); + bool GetAHeatEnable(); + void SetAHeatEnable(bool aHeat); + bool GetGravityGrid(); + void ShowGravityGrid(bool showGrid); + void ClearSimulation(); + vector<Menu*> GetMenuList(); + vector<Tool*> GetUnlistedTools(); + vector<Tool*> GetToolList(); + vector<QuickOption*> GetQuickOptions(); + void SetActiveMenu(Menu * menu); + Menu * GetActiveMenu(); + void FrameStep(int frames); + User GetUser(); + void SetUser(User user); + void SetBrush(int i); + int GetBrushID(); + Simulation * GetSimulation(); + Renderer * GetRenderer(); + void SetZoomEnabled(bool enabled); + bool GetZoomEnabled(); + void SetZoomSize(int size); + int GetZoomSize(); + void SetZoomFactor(int factor); + int GetZoomFactor(); + void SetZoomPosition(ui::Point position); + ui::Point GetZoomPosition(); + void SetZoomWindowPosition(ui::Point position); + ui::Point GetZoomWindowPosition(); + void SetStamp(GameSave * newStamp); + void AddStamp(GameSave * save); + void SetClipboard(GameSave * save); + void SetPlaceSave(GameSave * save); + void Log(string message); + deque<string> GetLog(); + GameSave * GetClipboard(); + GameSave * GetStamp(); + GameSave * GetPlaceSave(); + + std::vector<Notification*> GetNotifications(); + void AddNotification(Notification * notification); + void RemoveNotification(Notification * notification); +}; + +#endif // GAMEMODEL_H diff --git a/src/gui/game/GameModelException.h b/src/gui/game/GameModelException.h new file mode 100644 index 0000000..c95f7e6 --- /dev/null +++ b/src/gui/game/GameModelException.h @@ -0,0 +1,19 @@ +#ifndef GAMEMODELEXCEPTION_H_ +#define GAMEMODELEXCEPTION_H_ + +#include <string> +#include <exception> +using namespace std; + +struct GameModelException: public exception { + string message; +public: + GameModelException(string message_): message(message_) {} + const char * what() const throw() + { + return message.c_str(); + } + ~GameModelException() throw() {}; +}; + +#endif /* GAMEMODELEXCEPTION_H_ */ diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp new file mode 100644 index 0000000..c11a59d --- /dev/null +++ b/src/gui/game/GameView.cpp @@ -0,0 +1,2140 @@ +#include <sstream> +#include <iomanip> + +#include "Config.h" +#include "gui/Style.h" +#include "GameView.h" +#include "graphics/Graphics.h" +#include "gui/interface/Window.h" +#include "gui/interface/Button.h" +#include "gui/interface/Colour.h" +#include "gui/interface/Keys.h" +#include "gui/interface/Slider.h" +#include "gui/search/Thumbnail.h" +#include "simulation/SaveRenderer.h" +#include "simulation/SimulationData.h" +#include "gui/dialogues/ConfirmPrompt.h" +#include "Format.h" +#include "QuickOption.h" +#include "IntroText.h" + + +class SplitButton; +class SplitButtonAction +{ +public: + virtual void ActionCallbackLeft(ui::Button * sender) {} + virtual void ActionCallbackRight(ui::Button * sender) {} + virtual ~SplitButtonAction() {} +}; +class SplitButton : public ui::Button +{ +private: + bool rightDown; + bool leftDown; + bool showSplit; + int splitPosition; + std::string toolTip2; + SplitButtonAction * splitActionCallback; +public: + SplitButton(ui::Point position, ui::Point size, std::string buttonText, std::string toolTip, std::string toolTip2, int split) : + Button(position, size, buttonText, toolTip), + toolTip2(toolTip2), + splitPosition(split), + splitActionCallback(NULL), + showSplit(true) + { + + } + bool GetShowSplit() { return showSplit; } + void SetShowSplit(bool split) { showSplit = split; } + SplitButtonAction * GetSplitActionCallback() { return splitActionCallback; } + void SetSplitActionCallback(SplitButtonAction * newAction) { splitActionCallback = newAction; } + virtual void OnMouseUnclick(int x, int y, unsigned int button) + { + if(isButtonDown) + { + if(leftDown) + DoLeftAction(); + else if(rightDown) + DoRightAction(); + } + ui::Button::OnMouseUnclick(x, y, button); + + } + virtual void OnMouseMovedInside(int x, int y, int dx, int dy) + { + if(x >= splitPosition || !showSplit) + { + if(toolTip.length()>0 && GetParentWindow()) + { + GetParentWindow()->ToolTip(this, ui::Point(x, y), toolTip2); + } + } + else if(x < splitPosition) + { + if(toolTip2.length()>0 && GetParentWindow()) + { + GetParentWindow()->ToolTip(this, ui::Point(x, y), toolTip); + } + } + } + virtual void OnMouseEnter(int x, int y) + { + isMouseInside = true; + if(!Enabled) + return; + if(x >= splitPosition || !showSplit) + { + if(toolTip.length()>0 && GetParentWindow()) + { + GetParentWindow()->ToolTip(this, ui::Point(x, y), toolTip2); + } + } + else if(x < splitPosition) + { + if(toolTip2.length()>0 && GetParentWindow()) + { + GetParentWindow()->ToolTip(this, ui::Point(x, y), toolTip); + } + } + } + virtual void TextPosition() + { + ui::Button::TextPosition(); + textPosition.X += 3; + } + virtual void OnMouseClick(int x, int y, unsigned int button) + { + ui::Button::OnMouseClick(x, y, button); + rightDown = false; + leftDown = false; + if(x >= splitPosition) + rightDown = true; + else if(x < splitPosition) + leftDown = true; + } + void DoRightAction() + { + if(!Enabled) + return; + if(splitActionCallback) + splitActionCallback->ActionCallbackRight(this); + } + void DoLeftAction() + { + if(!Enabled) + return; + if(splitActionCallback) + splitActionCallback->ActionCallbackLeft(this); + } + void Draw(const ui::Point& screenPos) + { + ui::Button::Draw(screenPos); + Graphics * g = ui::Engine::Ref().g; + drawn = true; + + if(showSplit) + g->draw_line(splitPosition+screenPos.X, screenPos.Y+1, splitPosition+screenPos.X, screenPos.Y+Size.Y-2, 180, 180, 180, 255); + } + virtual ~SplitButton() + { + if(splitActionCallback) + delete splitActionCallback; + } +}; + + +GameView::GameView(): + ui::Window(ui::Point(0, 0), ui::Point(XRES+BARSIZE, YRES+MENUSIZE)), + pointQueue(queue<ui::Point>()), + isMouseDown(false), + ren(NULL), + activeBrush(NULL), + currentMouse(0, 0), + toolIndex(0), + zoomEnabled(false), + zoomCursorFixed(false), + drawPoint1(0, 0), + drawPoint2(0, 0), + drawMode(DrawPoints), + drawModeReset(false), + selectMode(SelectNone), + selectPoint1(0, 0), + selectPoint2(0, 0), + placeSaveThumb(NULL), + mousePosition(0, 0), + lastOffset(0), + drawSnap(false), + toolTip(""), + infoTip(""), + infoTipPresence(0), + buttonTipShow(0), + toolTipPosition(-1, -1), + shiftBehaviour(false), + ctrlBehaviour(false), + altBehaviour(false), + showHud(true), + showDebug(false), + introText(2048), + introTextMessage(introTextData), + wallBrush(false), + doScreenshot(false), + recording(false), + screenshotIndex(0), + recordingIndex(0), + toolTipPresence(0), + currentSaveType(0), + lastLogEntry(0.0f), + lastMenu(NULL) +{ + + int currentX = 1; + //Set up UI + class SearchAction : public ui::ButtonAction + { + GameView * v; + public: + SearchAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalBrowse(); + else + v->c->OpenSearch(); + } + }; + + scrollBar = new ui::Button(ui::Point(0,YRES+21), ui::Point(XRES, 2), ""); + scrollBar->Appearance.BackgroundInactive = ui::Colour(255, 255, 255); + scrollBar->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + scrollBar->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(scrollBar); + + searchButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(17, 15), "", "Find & open a simulation"); //Open + searchButton->SetIcon(IconOpen); + currentX+=18; + searchButton->SetTogglable(false); + searchButton->SetActionCallback(new SearchAction(this)); + AddComponent(searchButton); + + class ReloadAction : public ui::ButtonAction + { + GameView * v; + public: + ReloadAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->ReloadSim(); + } + void AltActionCallback(ui::Button * sender) + { + v->c->OpenSavePreview(); + } + }; + reloadButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(17, 15), "", "Reload the simulation"); + reloadButton->SetIcon(IconReload); + reloadButton->Appearance.Margin.Left+=2; + currentX+=18; + reloadButton->SetActionCallback(new ReloadAction(this)); + AddComponent(reloadButton); + + class SaveSimulationAction : public SplitButtonAction + { + GameView * v; + public: + SaveSimulationAction(GameView * _v) { v = _v; } + void ActionCallbackRight(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalSaveWindow(false); + else + v->c->OpenSaveWindow(); + } + void ActionCallbackLeft(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalSaveWindow(true); + else + v->c->SaveAsCurrent(); + } + }; + saveSimulationButton = new SplitButton(ui::Point(currentX, Size.Y-16), ui::Point(150, 15), "[untitled simulation]", "Save game as current name", "Save game as new name", 19); + saveSimulationButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + saveSimulationButton->SetIcon(IconSave); + currentX+=151; + ((SplitButton*)saveSimulationButton)->SetSplitActionCallback(new SaveSimulationAction(this)); + AddComponent(saveSimulationButton); + + class UpVoteAction : public ui::ButtonAction + { + GameView * v; + public: + UpVoteAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->Vote(1); + } + }; + upVoteButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(15, 15), "", "Like this save"); + upVoteButton->SetIcon(IconVoteUp); + upVoteButton->Appearance.Margin.Top+=2; + upVoteButton->Appearance.Margin.Left+=2; + currentX+=14; + upVoteButton->SetActionCallback(new UpVoteAction(this)); + AddComponent(upVoteButton); + + class DownVoteAction : public ui::ButtonAction + { + GameView * v; + public: + DownVoteAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->Vote(-1); + } + }; + downVoteButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(15, 15), "", "Dislike this save"); + downVoteButton->SetIcon(IconVoteDown); + downVoteButton->Appearance.Margin.Bottom+=2; + downVoteButton->Appearance.Margin.Left+=2; + currentX+=16; + downVoteButton->SetActionCallback(new DownVoteAction(this)); + AddComponent(downVoteButton); + + class TagSimulationAction : public ui::ButtonAction + { + GameView * v; + public: + TagSimulationAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenTags(); + } + }; + tagSimulationButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(251, 15), "[no tags set]", "Add simulation tags"); + tagSimulationButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tagSimulationButton->SetIcon(IconTag); + currentX+=252; + tagSimulationButton->SetActionCallback(new TagSimulationAction(this)); + AddComponent(tagSimulationButton); + + class ClearSimAction : public ui::ButtonAction + { + GameView * v; + public: + ClearSimAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->ClearSim(); + } + }; + clearSimButton = new ui::Button(ui::Point(Size.X-159, Size.Y-16), ui::Point(17, 15), "", "Erase everything"); + clearSimButton->SetIcon(IconNew); + clearSimButton->Appearance.Margin.Left+=2; + clearSimButton->SetActionCallback(new ClearSimAction(this)); + AddComponent(clearSimButton); + + class LoginAction : public ui::ButtonAction + { + GameView * v; + public: + LoginAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenLogin(); + } + }; + loginButton = new ui::Button(ui::Point(Size.X-141, Size.Y-16), ui::Point(92, 15), "[sign in]", "Sign into simulation server"); + loginButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + loginButton->SetIcon(IconLogin); + loginButton->SetActionCallback(new LoginAction(this)); + AddComponent(loginButton); + + class SimulationOptionAction : public ui::ButtonAction + { + GameView * v; + public: + SimulationOptionAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenOptions(); + } + }; + simulationOptionButton = new ui::Button(ui::Point(Size.X-48, Size.Y-16), ui::Point(15, 15), "", "Simulation options"); + simulationOptionButton->SetIcon(IconSimulationSettings); + simulationOptionButton->Appearance.Margin.Left+=2; + simulationOptionButton->SetActionCallback(new SimulationOptionAction(this)); + AddComponent(simulationOptionButton); + + class DisplayModeAction : public ui::ButtonAction + { + GameView * v; + public: + DisplayModeAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenRenderOptions(); + } + }; + displayModeButton = new ui::Button(ui::Point(Size.X-32, Size.Y-16), ui::Point(15, 15), "", "Renderer options"); + displayModeButton->SetIcon(IconRenderSettings); + displayModeButton->Appearance.Margin.Left+=2; + displayModeButton->SetActionCallback(new DisplayModeAction(this)); + AddComponent(displayModeButton); + + class PauseAction : public ui::ButtonAction + { + GameView * v; + public: + PauseAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->SetPaused(sender->GetToggleState()); + } + }; + pauseButton = new ui::Button(ui::Point(Size.X-16, Size.Y-16), ui::Point(15, 15), "", "Pause/Resume the simulation"); //Pause + pauseButton->SetIcon(IconPause); + pauseButton->SetTogglable(true); + pauseButton->SetActionCallback(new PauseAction(this)); + AddComponent(pauseButton); + + class ElementSearchAction : public ui::ButtonAction + { + GameView * v; + public: + ElementSearchAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenElementSearch(); + } + }; + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, YRES+MENUSIZE-32), ui::Point(15, 15), "\xE5", "Search for elements"); + tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetActionCallback(new ElementSearchAction(this)); + AddComponent(tempButton); + + class ColourPickerAction : public ui::ButtonAction + { + GameView * v; + public: + ColourPickerAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenColourPicker(); + } + }; + colourPicker = new ui::Button(ui::Point((XRES/2)-8, YRES+1), ui::Point(16, 16), "", "Pick Colour"); + colourPicker->SetActionCallback(new ColourPickerAction(this)); +} + +GameView::~GameView() +{ + if(!colourPicker->GetParentWindow()) + delete colourPicker; + + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + if(!button->GetParentWindow()) + { + delete button; + } + + } + + if(placeSaveThumb) + delete placeSaveThumb; +} + +class GameView::MenuAction: public ui::ButtonAction +{ + GameView * v; +public: + Menu * menu; + bool needsClick; + MenuAction(GameView * _v, Menu * menu_) + { + v = _v; + menu = menu_; + if (v->c->GetMenuList()[SC_DECO] == menu) + needsClick = true; + else + needsClick = false; + } + void MouseEnterCallback(ui::Button * sender) + { + if(!needsClick && !ui::Engine::Ref().GetMouseButton()) + v->c->SetActiveMenu(menu); + } + void ActionCallback(ui::Button * sender) + { + if (needsClick) + v->c->SetActiveMenu(menu); + else + MouseEnterCallback(sender); + } +}; + +class GameView::OptionAction: public ui::ButtonAction +{ + QuickOption * option; +public: + OptionAction(QuickOption * _option) { option = _option; } + void ActionCallback(ui::Button * sender) + { + option->Perform(); + } +}; + +class GameView::OptionListener: public QuickOptionListener +{ + ui::Button * button; +public: + OptionListener(ui::Button * _button) { button = _button; } + virtual void OnValueChanged(QuickOption * option) + { + switch(option->GetType()) + { + case QuickOption::Toggle: + button->SetTogglable(true); + button->SetToggleState(option->GetToggle()); + } + } +}; + +class GameView::ToolAction: public ui::ButtonAction +{ + GameView * v; +public: + Tool * tool; + ToolAction(GameView * _v, Tool * tool_) { v = _v; tool = tool_; } + void ActionCallback(ui::Button * sender_) + { + ToolButton *sender = (ToolButton*)sender_; + if(sender->GetSelectionState() >= 0 && sender->GetSelectionState() <= 2) + v->c->SetActiveTool(sender->GetSelectionState(), tool); + } +}; + +void GameView::NotifyQuickOptionsChanged(GameModel * sender) +{ + for(int i = 0; i < quickOptionButtons.size(); i++) + { + RemoveComponent(quickOptionButtons[i]); + delete quickOptionButtons[i]; + } + + int currentY = 1; + vector<QuickOption*> optionList = sender->GetQuickOptions(); + for(vector<QuickOption*>::iterator iter = optionList.begin(), end = optionList.end(); iter != end; ++iter) + { + QuickOption * option = *iter; + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, currentY), ui::Point(15, 15), option->GetIcon(), option->GetDescription()); + //tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetTogglable(true); + tempButton->SetActionCallback(new OptionAction(option)); + option->AddListener(new OptionListener(tempButton)); + AddComponent(tempButton); + + quickOptionButtons.push_back(tempButton); + currentY += 16; + } +} + +void GameView::NotifyMenuListChanged(GameModel * sender) +{ + int currentY = YRES+MENUSIZE-48;//-(sender->GetMenuList().size()*16); + for(int i = 0; i < menuButtons.size(); i++) + { + RemoveComponent(menuButtons[i]); + delete menuButtons[i]; + } + menuButtons.clear(); + for(int i = 0; i < toolButtons.size(); i++) + { + RemoveComponent(toolButtons[i]); + delete toolButtons[i]; + } + toolButtons.clear(); + vector<Menu*> menuList = sender->GetMenuList(); + for(vector<Menu*>::reverse_iterator iter = menuList.rbegin(), end = menuList.rend(); iter != end; ++iter) + { + std::string tempString = ""; + Menu * item = *iter; + tempString += item->GetIcon(); + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, currentY), ui::Point(15, 15), tempString, item->GetDescription()); + tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetTogglable(true); + tempButton->SetActionCallback(new MenuAction(this, item)); + currentY-=16; + AddComponent(tempButton); + menuButtons.push_back(tempButton); + } +} + +void GameView::SetSample(SimulationSample sample) +{ + this->sample = sample; +} + +void GameView::SetHudEnable(bool hudState) +{ + showHud = hudState; +} + +ui::Point GameView::GetMousePosition() +{ + return mousePosition; +} + +void GameView::NotifyActiveToolsChanged(GameModel * sender) +{ + for(int i = 0; i < toolButtons.size(); i++) + { + Tool * tool = ((ToolAction*)toolButtons[i]->GetActionCallback())->tool; + if(sender->GetActiveTool(0) == tool) + { + toolButtons[i]->SetSelectionState(0); //Primary + c->ActiveToolChanged(0, tool); + } + else if(sender->GetActiveTool(1) == tool) + { + toolButtons[i]->SetSelectionState(1); //Secondary + c->ActiveToolChanged(1, tool); + } + else if(sender->GetActiveTool(2) == tool) + { + toolButtons[i]->SetSelectionState(2); //Tertiary + c->ActiveToolChanged(2, tool); + } + else + { + toolButtons[i]->SetSelectionState(-1); + } + } +} + +void GameView::NotifyLastToolChanged(GameModel * sender) +{ + if(sender->GetLastTool() && sender->GetLastTool()->GetResolution() == CELL) + { + wallBrush = true; + } + else + { + wallBrush = false; + } +} + +void GameView::NotifyToolListChanged(GameModel * sender) +{ + //int currentY = YRES+MENUSIZE-36; + lastOffset = 0; + int currentX = XRES+BARSIZE-56; + int totalColour; + for(int i = 0; i < menuButtons.size(); i++) + { + if(((MenuAction*)menuButtons[i]->GetActionCallback())->menu==sender->GetActiveMenu()) + { + menuButtons[i]->SetToggleState(true); + } + else + { + menuButtons[i]->SetToggleState(false); + } + } + for(int i = 0; i < toolButtons.size(); i++) + { + RemoveComponent(toolButtons[i]); + delete toolButtons[i]; + } + toolButtons.clear(); + vector<Tool*> toolList = sender->GetToolList(); + for(int i = 0; i < toolList.size(); i++) + { + //ToolButton * tempButton = new ToolButton(ui::Point(XRES+1, currentY), ui::Point(28, 15), toolList[i]->GetName()); + VideoBuffer * tempTexture = toolList[i]->GetTexture(26, 14); + ToolButton * tempButton; + + if(tempTexture) + tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), "", toolList[i]->GetDescription()); + else + tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), toolList[i]->GetName(), toolList[i]->GetDescription()); + + //currentY -= 17; + currentX -= 31; + tempButton->SetActionCallback(new ToolAction(this, toolList[i])); + + tempButton->Appearance.SetTexture(tempTexture); + if(tempTexture) + delete tempTexture; + + tempButton->Appearance.BackgroundInactive = ui::Colour(toolList[i]->colRed, toolList[i]->colGreen, toolList[i]->colBlue); + + if(sender->GetActiveTool(0) == toolList[i]) + { + tempButton->SetSelectionState(0); //Primary + } + else if(sender->GetActiveTool(1) == toolList[i]) + { + tempButton->SetSelectionState(1); //Secondary + } + else if(sender->GetActiveTool(2) == toolList[i]) + { + tempButton->SetSelectionState(2); //Tertiary + } + + tempButton->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + tempButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(tempButton); + toolButtons.push_back(tempButton); + } + if (sender->GetActiveMenu() != sender->GetMenuList()[SC_DECO]) + lastMenu = sender->GetActiveMenu(); +} + +void GameView::NotifyColourSelectorVisibilityChanged(GameModel * sender) +{ + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + RemoveComponent(button); + button->SetParentWindow(NULL); + } + + RemoveComponent(colourPicker); + colourPicker->SetParentWindow(NULL); + + if(sender->GetColourSelectorVisibility()) + { + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + AddComponent(button); + } + AddComponent(colourPicker); + } +} + +void GameView::NotifyColourPresetsChanged(GameModel * sender) +{ + class ColourPresetAction: public ui::ButtonAction + { + GameView * v; + public: + int preset; + ColourPresetAction(GameView * _v, int preset) : preset(preset) { v = _v; } + void ActionCallback(ui::Button * sender_) + { + ToolButton *sender = (ToolButton*)sender_; + if(sender->GetSelectionState() == 0) + { + v->c->SetActiveColourPreset(preset); + v->c->SetColour(sender->Appearance.BackgroundInactive); + } + else + sender->SetSelectionState(0); + } + }; + + + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + RemoveComponent(button); + delete button; + } + colourPresets.clear(); + + int currentX = 5; + std::vector<ui::Colour> colours = sender->GetColourPresets(); + int i = 0; + for(std::vector<ui::Colour>::iterator iter = colours.begin(), end = colours.end(); iter != end; ++iter) + { + ToolButton * tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), ""); + tempButton->Appearance.BackgroundInactive = *iter; + tempButton->SetActionCallback(new ColourPresetAction(this, i)); + + currentX += 31; + + if(sender->GetColourSelectorVisibility()) + AddComponent(tempButton); + colourPresets.push_back(tempButton); + + i++; + } + NotifyColourActivePresetChanged(sender); +} + +void GameView::NotifyColourActivePresetChanged(GameModel * sender) +{ + for(int i = 0; i < colourPresets.size(); i++) + { + if(sender->GetActiveColourPreset() == i) + { + colourPresets[i]->SetSelectionState(0); //Primary + } + else + { + colourPresets[i]->SetSelectionState(-1); + } + } +} + +void GameView::NotifyColourSelectorColourChanged(GameModel * sender) +{ + colourPicker->Appearance.BackgroundInactive = sender->GetColourSelectorColour(); + colourPicker->Appearance.BackgroundHover = sender->GetColourSelectorColour(); +} + +void GameView::NotifyRendererChanged(GameModel * sender) +{ + ren = sender->GetRenderer(); +} + +void GameView::NotifySimulationChanged(GameModel * sender) +{ + +} +void GameView::NotifyUserChanged(GameModel * sender) +{ + if(!sender->GetUser().ID) + { + loginButton->SetText("[sign in]"); + } + else + { + loginButton->SetText(sender->GetUser().Username); + } + NotifySaveChanged(sender); +} + + +void GameView::NotifyPausedChanged(GameModel * sender) +{ + pauseButton->SetToggleState(sender->GetPaused()); +} + +void GameView::NotifyToolTipChanged(GameModel * sender) +{ + toolTip = sender->GetToolTip(); +} + +void GameView::NotifyInfoTipChanged(GameModel * sender) +{ + infoTip = sender->GetInfoTip(); + infoTipPresence = 120; +} + +void GameView::NotifySaveChanged(GameModel * sender) +{ + if(sender->GetSave()) + { + if(introText > 50) + introText = 50; + + saveSimulationButton->SetText(sender->GetSave()->GetName()); + if(sender->GetSave()->GetUserName() == sender->GetUser().Username) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + else + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + reloadButton->Enabled = true; + upVoteButton->Enabled = (sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==0); + if(sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==1) + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 108, 10, 255)); + else + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + + downVoteButton->Enabled = upVoteButton->Enabled; + if(sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==-1) + downVoteButton->Appearance.BackgroundDisabled = (ui::Colour(108, 0, 10, 255)); + else + downVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + + if (sender->GetUser().ID) + { + upVoteButton->Appearance.BorderDisabled = upVoteButton->Appearance.BorderInactive; + downVoteButton->Appearance.BorderDisabled = downVoteButton->Appearance.BorderInactive; + } + else + { + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + } + + tagSimulationButton->Enabled = (sender->GetSave()->GetID() && sender->GetUser().ID); + if(sender->GetSave()->GetID()) + { + std::stringstream tagsStream; + std::vector<string> tags = sender->GetSave()->GetTags(); + if(tags.size()) + { + for(int i = 0; i < tags.size(); i++) + { + tagsStream << sender->GetSave()->GetTags()[i]; + if(i < tags.size()-1) + tagsStream << " "; + } + tagSimulationButton->SetText(tagsStream.str()); + } + else + { + tagSimulationButton->SetText("[no tags set]"); + } + } + else + { + tagSimulationButton->SetText("[no tags set]"); + } + currentSaveType = 1; + } + else if (sender->GetSaveFile()) + { + if (ctrlBehaviour) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + else + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + saveSimulationButton->SetText(sender->GetSaveFile()->GetDisplayName()); + reloadButton->Enabled = true; + upVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + downVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + tagSimulationButton->Enabled = false; + tagSimulationButton->SetText("[no tags set]"); + currentSaveType = 2; + } + else + { + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + saveSimulationButton->SetText("[untitled simulation]"); + reloadButton->Enabled = false; + upVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100), + downVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100), + tagSimulationButton->Enabled = false; + tagSimulationButton->SetText("[no tags set]"); + currentSaveType = 0; + } +} + +void GameView::NotifyBrushChanged(GameModel * sender) +{ + activeBrush = sender->GetBrush(); +} + +void GameView::screenshot() +{ + doScreenshot = true; +} + +void GameView::record() +{ + if(recording) + { + recording = false; + } + else + { + class RecordingConfirmation: public ConfirmDialogueCallback { + public: + GameView * v; + RecordingConfirmation(GameView * v): v(v) {} + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + v->recording = true; + } + } + virtual ~RecordingConfirmation() { } + }; + new ConfirmPrompt("Recording", "You're about to start recording all drawn frames. This may use a load of hard disk space.", new RecordingConfirmation(this)); + } +} + +void GameView::setToolButtonOffset(int offset) +{ + int offset_ = offset; + offset = offset-lastOffset; + lastOffset = offset_; + + for(vector<ToolButton*>::iterator iter = toolButtons.begin(), end = toolButtons.end(); iter!=end; ++iter) + { + ToolButton * button = *iter; + button->Position.X -= offset; + if(button->Position.X <= 0 || (button->Position.X+button->Size.X) > XRES-2) { + button->Visible = false; + } else { + button->Visible = true; + } + } +} + +void GameView::OnMouseMove(int x, int y, int dx, int dy) +{ + mousePosition = c->PointTranslate(ui::Point(x, y)); + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + selectPoint1 = c->PointTranslate(ui::Point(x, y)); + if(selectPoint1.X!=-1) + selectPoint2 = c->PointTranslate(ui::Point(x, y)); + return; + } + currentMouse = ui::Point(x, y); + if(isMouseDown && drawMode == DrawPoints) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x-dx, y-dy)))); + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } +} + +void GameView::OnMouseDown(int x, int y, unsigned button) +{ + if(altBehaviour && !shiftBehaviour && !ctrlBehaviour) + button = BUTTON_MIDDLE; + if(selectMode!=SelectNone) + { + if(button==BUTTON_LEFT) + { + selectPoint1 = c->PointTranslate(ui::Point(x, y)); + selectPoint2 = selectPoint1; + } + return; + } + if(currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES && !(zoomEnabled && !zoomCursorFixed)) + { + if(button == BUTTON_LEFT) + toolIndex = 0; + if(button == BUTTON_RIGHT) + toolIndex = 1; + if(button == BUTTON_MIDDLE) + toolIndex = 2; + isMouseDown = true; + if(!pointQueue.size()) + c->HistorySnapshot(); + if(drawMode == DrawRect || drawMode == DrawLine) + { + drawPoint1 = c->PointTranslate(ui::Point(x, y)); + } + if(drawMode == DrawPoints) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } + } +} + +void GameView::OnMouseUp(int x, int y, unsigned button) +{ + if(selectMode!=SelectNone) + { + if(button==BUTTON_LEFT) + { + if(selectMode==PlaceSave) + { + if(placeSaveThumb) + { + int thumbX = selectPoint2.X - (placeSaveThumb->Width/2); + int thumbY = selectPoint2.Y - (placeSaveThumb->Height/2); + + if(thumbX<0) + thumbX = 0; + if(thumbX+(placeSaveThumb->Width)>=XRES) + thumbX = XRES-placeSaveThumb->Width; + + if(thumbY<0) + thumbY = 0; + if(thumbY+(placeSaveThumb->Height)>=YRES) + thumbY = YRES-placeSaveThumb->Height; + + c->PlaceSave(ui::Point(thumbX, thumbY)); + } + } + else + { + int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X; + int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y; + int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X; + int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y; + if(selectMode==SelectCopy) + c->CopyRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + else if(selectMode==SelectCut) + c->CutRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + else if(selectMode==SelectStamp) + c->StampRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + } + } + currentMouse = ui::Point(x, y); + selectMode = SelectNone; + return; + } + + if(zoomEnabled && !zoomCursorFixed) + zoomCursorFixed = true; + else + { + if(isMouseDown) + { + isMouseDown = false; + if(drawMode == DrawRect || drawMode == DrawLine) + { + ui::Point finalDrawPoint2(0, 0); + drawPoint2 = c->PointTranslate(ui::Point(x, y)); + finalDrawPoint2 = drawPoint2; + + if(drawSnap && drawMode == DrawLine) + { + finalDrawPoint2 = lineSnapCoords(c->PointTranslate(drawPoint1), drawPoint2); + } + + if(drawSnap && drawMode == DrawRect) + { + finalDrawPoint2 = rectSnapCoords(c->PointTranslate(drawPoint1), drawPoint2); + } + + if(drawMode == DrawRect) + { + c->DrawRect(toolIndex, c->PointTranslate(drawPoint1), finalDrawPoint2); + } + if(drawMode == DrawLine) + { + c->DrawLine(toolIndex, c->PointTranslate(drawPoint1), finalDrawPoint2); + } + } + if(drawMode == DrawPoints) + { + c->ToolClick(toolIndex, c->PointTranslate(ui::Point(x, y))); + //pointQueue.push(ui::Point(x, y)); + } + if(drawModeReset) + { + drawModeReset = false; + drawMode = DrawPoints; + } + } + } +} + +void GameView::ExitPrompt() +{ + class ExitConfirmation: public ConfirmDialogueCallback { + public: + ExitConfirmation() {} + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + ui::Engine::Ref().Exit(); + } + } + virtual ~ExitConfirmation() { } + }; + new ConfirmPrompt("You are about to quit", "Are you sure you want to exit the game?", new ExitConfirmation()); +} + +void GameView::ToolTip(ui::Component * sender, ui::Point mousePosition, std::string toolTip) +{ + if(sender->Position.Y > Size.Y-17) + { + buttonTip = toolTip; + buttonTipShow = 120; + } + else if(sender->Position.X > Size.X-BARSIZE)// < Size.Y-(quickOptionButtons.size()+1)*16) + { + this->toolTip = toolTip; + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), sender->Position.Y+3); + if(toolTipPosition.Y+10 > Size.Y-MENUSIZE) + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), Size.Y-MENUSIZE-10); + toolTipPresence = 120; + } + else + { + this->toolTip = toolTip; + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), Size.Y-MENUSIZE-10); + toolTipPresence = 160; + } +} + +void GameView::OnMouseWheel(int x, int y, int d) +{ + if(!d) + return; + if(selectMode!=SelectNone) + { + return; + } + if(zoomEnabled && !zoomCursorFixed) + { + c->AdjustZoomSize(d); + } + else + { + c->AdjustBrushSize(d, false, shiftBehaviour, ctrlBehaviour); + if(isMouseDown) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } + } +} + +void GameView::ToggleDebug() +{ + showDebug = !showDebug; + if (ren) + ren->debugLines = showDebug; +} + +void GameView::BeginStampSelection() +{ + selectMode = SelectStamp; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to create a stamp"; + infoTipPresence = 120; +} + +void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(introText > 50) + { + introText = 50; + } + + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + { + switch(key) + { + case KEY_RIGHT: + case 'd': + c->TranslateSave(ui::Point(1, 0)); + break; + case KEY_LEFT: + case 'a': + c->TranslateSave(ui::Point(-1, 0)); + break; + case KEY_UP: + case 'w': + c->TranslateSave(ui::Point(0, -1)); + break; + case KEY_DOWN: + case 's': + c->TranslateSave(ui::Point(0, 1)); + break; + case 'r': + if(shift) + { + //Flip + c->TransformSave(m2d_new(-1,0,0,1)); + } + else + { + //Rotate 90deg + c->TransformSave(m2d_new(0,1,-1,0)); + } + break; + } + } + if(key != ' ') + return; + } + switch(key) + { + case KEY_ALT: + drawSnap = true; + enableAltBehaviour(); + break; + case KEY_CTRL: + if(!isMouseDown) + { + if(drawModeReset) + drawModeReset = false; + else + drawPoint1 = currentMouse; + if(shift) + drawMode = DrawFill; + else + drawMode = DrawRect; + } + enableCtrlBehaviour(); + break; + case KEY_SHIFT: + if(!isMouseDown) + { + if(drawModeReset) + drawModeReset = false; + else + drawPoint1 = currentMouse; + if(ctrl) + drawMode = DrawFill; + else + drawMode = DrawLine; + } + enableShiftBehaviour(); + break; + case ' ': //Space + c->SetPaused(); + break; + case KEY_TAB: //Tab + c->ChangeBrush(); + break; + case 'z': + if(ctrl) + { + c->HistoryRestore(); + } + else + { + if (drawMode != DrawLine) + isMouseDown = false; + zoomCursorFixed = false; + c->SetZoomEnabled(true); + } + break; + case '`': + c->ShowConsole(); + break; + case 'p': + screenshot(); + break; + case 'r': + record(); + break; + case 'e': + c->OpenElementSearch(); + break; + case 'f': + c->FrameStep(); + break; + case 'g': + if (ctrl) + c->ShowGravityGrid(); + else if(shift) + c->AdjustGridSize(-1); + else + c->AdjustGridSize(1); + break; + case KEY_F1: + if(!introText) + introText = 8047; + else + introText = 0; + break; + case 'h': + if(ctrl) + { + if(!introText) + introText = 8047; + else + introText = 0; + } + else + showHud = !showHud; + break; + case 'b': + if(ctrl) + c->SetDecoration(); + else + if (colourPicker->GetParentWindow()) + c->SetActiveMenu(lastMenu); + else + { + c->SetDecoration(true); + c->SetPaused(true); + c->SetActiveMenu(c->GetMenuList()[SC_DECO]); + } + break; + case 'y': + c->SwitchAir(); + break; + case KEY_ESCAPE: + case 'q': + ExitPrompt(); + break; + case 'u': + c->ToggleAHeat(); + break; + case '=': + if(ctrl) + c->ResetSpark(); + else + c->ResetAir(); + break; + case 'c': + if(ctrl) + { + selectMode = SelectCopy; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to copy"; + infoTipPresence = 120; + } + break; + case 'x': + if(ctrl) + { + selectMode = SelectCut; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to cut"; + infoTipPresence = 120; + } + break; + case 'v': + if(ctrl) + { + c->LoadClipboard(); + selectPoint2 = mousePosition; + selectPoint1 = selectPoint2; + } + break; + case 'l': + c->LoadStamp(); + selectPoint2 = mousePosition; + selectPoint1 = selectPoint2; + isMouseDown = false; + drawMode = DrawPoints; + break; + case 'k': + selectPoint2 = ui::Point(-1, -1); + selectPoint1 = selectPoint2; + c->OpenStamps(); + break; + case ']': + if(zoomEnabled && !zoomCursorFixed) + c->AdjustZoomSize(1, !alt); + else + c->AdjustBrushSize(1, !alt, shiftBehaviour, ctrlBehaviour); + break; + case '[': + if(zoomEnabled && !zoomCursorFixed) + c->AdjustZoomSize(-1, !alt); + else + c->AdjustBrushSize(-1, !alt, shiftBehaviour, ctrlBehaviour); + break; + case 'i': + if(ctrl) + c->Install(); + else + c->InvertAirSim(); + break; + } + + if (shift && showDebug && key == '1') + c->LoadRenderPreset(10); + else if(key >= '0' && key <= '9') + { + c->LoadRenderPreset(key-'0'); + } +} + +void GameView::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(ctrl && shift) + drawMode = DrawFill; + else if (ctrl) + drawMode = DrawRect; + else if (shift) + drawMode = DrawLine; + else if(!isMouseDown) + drawMode = DrawPoints; + else + drawModeReset = true; + switch(key) + { + case KEY_ALT: + drawSnap = false; + disableAltBehaviour(); + break; + case KEY_CTRL: + disableCtrlBehaviour(); + break; + case KEY_SHIFT: + disableShiftBehaviour(); + break; + case 'z': + if(!ctrl) + { + if(!zoomCursorFixed && !alt) + c->SetZoomEnabled(false); + } + break; + } +} + +void GameView::OnBlur() +{ + disableAltBehaviour(); + disableCtrlBehaviour(); + disableShiftBehaviour(); + isMouseDown = false; + drawMode = DrawPoints; +} + +void GameView::OnTick(float dt) +{ + if(selectMode==PlaceSave && !placeSaveThumb) + selectMode = SelectNone; + if(zoomEnabled && !zoomCursorFixed) + c->SetZoomPosition(currentMouse); + if(drawMode == DrawPoints) + { + if(isMouseDown) + { + pointQueue.push(ui::Point(c->PointTranslate(currentMouse))); + } + if(!pointQueue.empty()) + { + c->DrawPoints(toolIndex, pointQueue); + } + } + if(drawMode == DrawFill && isMouseDown) + { + c->DrawFill(toolIndex, c->PointTranslate(currentMouse)); + } + if(introText) + { + introText -= int(dt)>0?((int)dt < 5? dt:5):1; + if(introText < 0) + introText = 0; + } + if(infoTipPresence>0) + { + infoTipPresence -= int(dt)>0?int(dt):1; + if(infoTipPresence<0) + infoTipPresence = 0; + } + if(buttonTipShow>0) + { + buttonTipShow -= int(dt)>0?int(dt):1; + if(buttonTipShow<0) + buttonTipShow = 0; + } + if(toolTipPresence>0) + { + toolTipPresence -= int(dt)>0?int(dt):1; + if(toolTipPresence<0) + toolTipPresence = 0; + } + c->Update(); + if(lastLogEntry > -0.1f) + lastLogEntry -= 0.16*dt; +} + + +void GameView::DoMouseMove(int x, int y, int dx, int dy) +{ + if(c->MouseMove(x, y, dx, dy)) + Window::DoMouseMove(x, y, dx, dy); + + if(toolButtons.size()) + { + int totalWidth = (toolButtons[0]->Size.X+1)*toolButtons.size(); + int scrollSize = (int)(((float)(XRES-15))/((float)totalWidth) * ((float)XRES-15)); + if (scrollSize>XRES) + scrollSize = XRES; + if(totalWidth > XRES-15) + { + int mouseX = x; + if(mouseX > XRES) + mouseX = XRES; + + scrollBar->Position.X = (int)(((float)mouseX/((float)XRES-15))*(float)(XRES-scrollSize)); + + float overflow = totalWidth-(XRES-15), mouseLocation = float(XRES)/float(mouseX-(XRES)); + setToolButtonOffset(overflow/mouseLocation); + + //Ensure that mouseLeave events are make their way to the buttons should they move from underneith the mouse pointer + if(toolButtons[0]->Position.Y < y && toolButtons[0]->Position.Y+toolButtons[0]->Size.Y > y) + { + for(vector<ToolButton*>::iterator iter = toolButtons.begin(), end = toolButtons.end(); iter!=end; ++iter) + { + ToolButton * button = *iter; + if(button->Position.X < x && button->Position.X+button->Size.X > x) + button->OnMouseEnter(x, y); + else + button->OnMouseLeave(x, y); + } + } + } + else + { + scrollBar->Position.X = 0; + } + scrollBar->Size.X=scrollSize; + } +} + +void GameView::DoMouseDown(int x, int y, unsigned button) +{ + if(introText > 50) + introText = 50; + if(c->MouseDown(x, y, button)) + Window::DoMouseDown(x, y, button); +} + +void GameView::DoMouseUp(int x, int y, unsigned button) +{ + if(c->MouseUp(x, y, button)) + Window::DoMouseUp(x, y, button); +} + +void GameView::DoMouseWheel(int x, int y, int d) +{ + if(c->MouseWheel(x, y, d)) + Window::DoMouseWheel(x, y, d); +} + +void GameView::DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(c->KeyPress(key, character, shift, ctrl, alt)) + Window::DoKeyPress(key, character, shift, ctrl, alt); +} + +void GameView::DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(c->KeyRelease(key, character, shift, ctrl, alt)) + Window::DoKeyRelease(key, character, shift, ctrl, alt); +} + +void GameView::DoDraw() +{ + Window::DoDraw(); + c->Tick(); +} + +void GameView::NotifyNotificationsChanged(GameModel * sender) +{ + class NotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + NotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + notification->Action(); + //v->c->RemoveNotification(notification); + } + }; + class CloseNotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + CloseNotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + v->c->RemoveNotification(notification); + } + void AltActionCallback(ui::Button * sender) + { + v->c->RemoveNotification(notification); + } + }; + + for(std::vector<ui::Component*>::const_iterator iter = notificationComponents.begin(), end = notificationComponents.end(); iter != end; ++iter) { + ui::Component * cNotification = *iter; + RemoveComponent(cNotification); + delete cNotification; + } + notificationComponents.clear(); + + std::vector<Notification*> notifications = sender->GetNotifications(); + + int currentY = YRES-23; + for(std::vector<Notification*>::iterator iter = notifications.begin(), end = notifications.end(); iter != end; ++iter) + { + int width = (Graphics::textwidth((*iter)->Message.c_str()))+8; + ui::Button * tempButton = new ui::Button(ui::Point(XRES-width-22, currentY), ui::Point(width, 15), (*iter)->Message); + tempButton->SetActionCallback(new NotificationButtonAction(this, *iter)); + tempButton->Appearance.BorderInactive = style::Colour::WarningTitle; + tempButton->Appearance.TextInactive = style::Colour::WarningTitle; + tempButton->Appearance.BorderHover = ui::Colour(255, 175, 0); + tempButton->Appearance.TextHover = ui::Colour(255, 175, 0); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + tempButton = new ui::Button(ui::Point(XRES-20, currentY), ui::Point(15, 15)); + tempButton->SetIcon(IconClose); + tempButton->SetActionCallback(new CloseNotificationButtonAction(this, *iter)); + tempButton->Appearance.Margin.Left+=2; + tempButton->Appearance.Margin.Top+=2; + tempButton->Appearance.BorderInactive = style::Colour::WarningTitle; + tempButton->Appearance.TextInactive = style::Colour::WarningTitle; + tempButton->Appearance.BorderHover = ui::Colour(255, 175, 0); + tempButton->Appearance.TextHover = ui::Colour(255, 175, 0); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + currentY -= 17; + } +} + +void GameView::NotifyZoomChanged(GameModel * sender) +{ + zoomEnabled = sender->GetZoomEnabled(); +} + +void GameView::NotifyLogChanged(GameModel * sender, string entry) +{ + logEntries.push_front(entry); + lastLogEntry = 100.0f; + if(logEntries.size()>20) + logEntries.pop_back(); +} + +void GameView::NotifyPlaceSaveChanged(GameModel * sender) +{ + if(placeSaveThumb) + delete placeSaveThumb; + if(sender->GetPlaceSave()) + { + placeSaveThumb = SaveRenderer::Ref().Render(sender->GetPlaceSave()); + selectMode = PlaceSave; + selectPoint2 = mousePosition; + } + else + { + placeSaveThumb = NULL; + selectMode = SelectNone; + } +} + +void GameView::enableShiftBehaviour() +{ + if(!shiftBehaviour) + { + shiftBehaviour = true; + if(isMouseDown) + { + c->SetToolStrength(10.0f); + } + } +} + +void GameView::disableShiftBehaviour() +{ + if(shiftBehaviour) + { + shiftBehaviour = false; + if(!ctrlBehaviour) + c->SetToolStrength(1.0f); + else + c->SetToolStrength(.1f); + } +} + +void GameView::enableAltBehaviour() +{ + if(!altBehaviour) + { + altBehaviour = true; + } +} + +void GameView::disableAltBehaviour() +{ + if(altBehaviour) + { + altBehaviour = false; + } +} + +void GameView::enableCtrlBehaviour() +{ + if(!ctrlBehaviour) + { + ctrlBehaviour = true; + + //Show HDD save & load buttons + saveSimulationButton->Appearance.BackgroundInactive = saveSimulationButton->Appearance.BackgroundHover = ui::Colour(255, 255, 255); + saveSimulationButton->Appearance.TextInactive = saveSimulationButton->Appearance.TextHover = ui::Colour(0, 0, 0); + searchButton->Appearance.BackgroundInactive = searchButton->Appearance.BackgroundHover = ui::Colour(255, 255, 255); + searchButton->Appearance.TextInactive = searchButton->Appearance.TextHover = ui::Colour(0, 0, 0); + if (currentSaveType == 2) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + if(isMouseDown) + { + if(!shiftBehaviour) + c->SetToolStrength(.1f); + else + c->SetToolStrength(10.0f); + } + } +} + +void GameView::disableCtrlBehaviour() +{ + if(ctrlBehaviour) + { + ctrlBehaviour = false; + + //Hide HDD save & load buttons + saveSimulationButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + saveSimulationButton->Appearance.BackgroundHover = ui::Colour(20, 20, 20); + saveSimulationButton->Appearance.TextInactive = saveSimulationButton->Appearance.TextHover = ui::Colour(255, 255, 255); + searchButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + searchButton->Appearance.BackgroundHover = ui::Colour(20, 20, 20); + searchButton->Appearance.TextInactive = searchButton->Appearance.TextHover = ui::Colour(255, 255, 255); + if (currentSaveType == 2) + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + if(!shiftBehaviour) + c->SetToolStrength(1.0f); + else + c->SetToolStrength(10.0f); + } +} + +void GameView::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + if(ren) + { + ren->clearScreen(1.0f); + ren->RenderBegin(); + ren->SetSample(c->PointTranslate(currentMouse).X, c->PointTranslate(currentMouse).Y); + if(selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES) + { + ui::Point finalCurrentMouse = c->PointTranslate(currentMouse); + ui::Point initialDrawPoint = drawPoint1; + + if(wallBrush) + { + finalCurrentMouse = c->NormaliseBlockCoord(finalCurrentMouse); + initialDrawPoint = c->NormaliseBlockCoord(initialDrawPoint); + } + + if(drawMode==DrawRect && isMouseDown) + { + if(drawSnap) + { + finalCurrentMouse = rectSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + activeBrush->RenderRect(ren, c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + else if(drawMode==DrawLine && isMouseDown) + { + if(drawSnap) + { + finalCurrentMouse = lineSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + activeBrush->RenderLine(ren, c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + else if(drawMode==DrawFill)// || altBehaviour) + { + activeBrush->RenderFill(ren, finalCurrentMouse); + } + if(drawMode == DrawPoints || drawMode==DrawLine || (drawMode == DrawRect && !isMouseDown)) + { + if(wallBrush) + { + ui::Point finalBrushRadius = c->NormaliseBlockCoord(activeBrush->GetRadius()); + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y-finalBrushRadius.Y, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y-finalBrushRadius.Y); + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-1, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-1); + + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y-finalBrushRadius.Y+1, finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-2); + ren->xor_line(finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y-finalBrushRadius.Y+1, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-2); + } + else + { + activeBrush->RenderPoint(ren, finalCurrentMouse); + } + } + } + + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + { + if(placeSaveThumb && selectPoint2.X!=-1) + { + int thumbX = selectPoint2.X - (placeSaveThumb->Width/2); + int thumbY = selectPoint2.Y - (placeSaveThumb->Height/2); + + ui::Point thumbPos = c->NormaliseBlockCoord(ui::Point(thumbX, thumbY)); + + if(thumbPos.X<0) + thumbPos.X = 0; + if(thumbPos.X+(placeSaveThumb->Width)>=XRES) + thumbPos.X = XRES-placeSaveThumb->Width; + + if(thumbPos.Y<0) + thumbPos.Y = 0; + if(thumbPos.Y+(placeSaveThumb->Height)>=YRES) + thumbPos.Y = YRES-placeSaveThumb->Height; + + ren->draw_image(placeSaveThumb, thumbPos.X, thumbPos.Y, 128); + + ren->xor_rect(thumbPos.X, thumbPos.Y, placeSaveThumb->Width, placeSaveThumb->Width); + } + } + else + { + if(selectPoint1.X==-1) + { + ren->fillrect(0, 0, XRES, YRES, 0, 0, 0, 100); + } + else + { + int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X; + int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y; + int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X; + int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y; + + if(x2>XRES-1) + x2 = XRES-1; + if(y2>YRES-1) + y2 = YRES-1; + + ren->fillrect(0, 0, XRES, y1, 0, 0, 0, 100); + ren->fillrect(0, y2+1, XRES, YRES-y2-1, 0, 0, 0, 100); + + ren->fillrect(0, y1, x1, (y2-y1)+1, 0, 0, 0, 100); + ren->fillrect(x2+1, y1, XRES-x2-1, (y2-y1)+1, 0, 0, 0, 100); + + ren->xor_rect(x1, y1, (x2-x1)+1, (y2-y1)+1); + } + } + } + + ren->RenderEnd(); + + if(doScreenshot) + { + VideoBuffer screenshot(ren->DumpFrame()); + std::vector<char> data = format::VideoBufferToPNG(screenshot); + + std::stringstream filename; + filename << "screenshot_"; + filename << std::setfill('0') << std::setw(6) << (screenshotIndex++); + filename << ".png"; + + Client::Ref().WriteFile(data, filename.str()); + doScreenshot = false; + } + + if(recording) + { + VideoBuffer screenshot(ren->DumpFrame()); + std::vector<char> data = format::VideoBufferToPPM(screenshot); + + std::stringstream filename; + filename << "frame_"; + filename << std::setfill('0') << std::setw(6) << (recordingIndex++); + filename << ".ppm"; + + Client::Ref().WriteFile(data, filename.str()); + } + + int startX = 20; + int startY = YRES-20; + int startAlpha; + if(lastLogEntry>0.1f && logEntries.size()) + { + startAlpha = 2.55f*lastLogEntry; + deque<string>::iterator iter; + for(iter = logEntries.begin(); iter != logEntries.end() && startAlpha>0; iter++) + { + string message = (*iter); + startY -= 13; + g->fillrect(startX-3, startY-3, Graphics::textwidth((char*)message.c_str())+6, 14, 0, 0, 0, 100); + g->drawtext(startX, startY, message.c_str(), 255, 255, 255, startAlpha); + startAlpha-=14; + } + } + } + + if(recording) + { + std::stringstream sampleInfo; + sampleInfo << recordingIndex; + sampleInfo << ". \x8E REC"; + + int textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 16, (const char*)sampleInfo.str().c_str(), 255, 50, 20, 255); + } + else if(showHud && !introText) + { + //Draw info about simulation under cursor + int wavelengthGfx = 0; + std::stringstream sampleInfo; + sampleInfo.precision(2); + if(sample.particle.type) + { + if(showDebug) + { + int ctype = sample.particle.ctype; + if (sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) + ctype = sample.particle.tmp; + + if (sample.particle.type == PT_LAVA && ctype > 0 && ctype < PT_NUM) + sampleInfo << "Molten " << c->ElementResolve(ctype); + else if((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && ctype > 0 && ctype < PT_NUM) + sampleInfo << c->ElementResolve(sample.particle.type) << " with " << c->ElementResolve(ctype); + else + { + sampleInfo << c->ElementResolve(sample.particle.type); + if(ctype > 0 && ctype < PT_NUM) + sampleInfo << " (" << c->ElementResolve(ctype) << ")"; + else + sampleInfo << " ()"; + } + sampleInfo << ", Temp: " << std::fixed << sample.particle.temp -273.15f; + sampleInfo << ", Life: " << sample.particle.life; + sampleInfo << ", Tmp: " << sample.particle.tmp; + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + else + { + if (sample.particle.type == PT_LAVA && sample.particle.ctype > 0 && sample.particle.ctype < PT_NUM) + sampleInfo << "Molten " << c->ElementResolve(sample.particle.ctype); + else if((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && sample.particle.tmp > 0 && sample.particle.tmp < PT_NUM) + sampleInfo << c->ElementResolve(sample.particle.type) << " with " << c->ElementResolve(sample.particle.tmp); + else + sampleInfo << c->ElementResolve(sample.particle.type); + sampleInfo << ", Temp: " << std::fixed << sample.particle.temp -273.15f; + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + if(sample.particle.type == PT_PHOT) + wavelengthGfx = sample.particle.ctype; + } + else if (sample.WallType) + { + sampleInfo << c->WallName(sample.WallType); + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + else + { + sampleInfo << "Empty, Pressure: " << std::fixed << sample.AirPressure; + } + + int textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 16, (const char*)sampleInfo.str().c_str(), 255, 255, 255, 255*0.75); + +#ifndef OGLI + if(wavelengthGfx) + { + int i, cr, cg, cb, j, h = 3, x = XRES-19-textWidth, y = 10; + int tmp; + g->fillrect(x, y, 30, h, 64, 64, 64, 255); // coords -1 size +1 to work around bug in fillrect - TODO: fix fillrect + for (i = 0; i < 30; i++) + { + if ((wavelengthGfx >> i)&1) + { + // Need a spread of wavelengths to get a smooth spectrum, 5 bits seems to work reasonably well + if (i>2) tmp = 0x1F << (i-2); + else tmp = 0x1F >> (2-i); + + cg = 0; + cb = 0; + cr = 0; + + for (j=0; j<12; j++) + { + cr += (tmp >> (j+18)) & 1; + cb += (tmp >> j) & 1; + } + for (j=0; j<13; j++) + cg += (tmp >> (j+9)) & 1; + + tmp = 624/(cr+cg+cb+1); + cr *= tmp; + cg *= tmp; + cb *= tmp; + for (j=0; j<h; j++) + g->blendpixel(x+29-i,y+j,cr>255?255:cr,cg>255?255:cg,cb>255?255:cb,255); + } + } + } +#endif + + if(showDebug) + { + sampleInfo.str(std::string()); + + if(sample.particle.type) + { + sampleInfo << "#" << sample.ParticleID << ", "; + } + sampleInfo << "X:" << sample.PositionX << " Y:" << sample.PositionY; + if (sample.Gravity) + sampleInfo << " GX: " << sample.GravityVelocityX << " GY: " << sample.GravityVelocityY; + + textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 26, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 30, (const char*)sampleInfo.str().c_str(), 255, 255, 255, 255*0.75); + } + + + //FPS and some version info +#ifndef DEBUG //In debug mode, the Engine will draw FPS and other info instead + std::stringstream fpsInfo; + fpsInfo.precision(2); +#ifdef SNAPSHOT + fpsInfo << "Snapshot " << SNAPSHOT_ID << ", "; +#elif defined(BETA) + fpsInfo << "Beta " << SAVE_VERSION << "." << MINOR_VERSION << "." << BUILD_NUM << ", "; +#endif + fpsInfo << "FPS: " << std::fixed << ui::Engine::Ref().GetFps(); + + if (showDebug) + fpsInfo << " Parts: " << sample.NumParts; + if (ren->GetGridSize()) + fpsInfo << " [GRID: " << ren->GetGridSize() << "]"; + + textWidth = Graphics::textwidth((char*)fpsInfo.str().c_str()); + g->fillrect(12, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(16, 16, (const char*)fpsInfo.str().c_str(), 32, 216, 255, 255*0.75); +#endif + } + + //Tooltips + if(infoTipPresence) + { + int infoTipAlpha = (infoTipPresence>50?50:infoTipPresence)*5; + g->drawtext((XRES-Graphics::textwidth((char*)infoTip.c_str()))/2, (YRES/2)-2, (char*)infoTip.c_str(), 255, 255, 255, infoTipAlpha); + } + + if(toolTipPresence && toolTipPosition.X!=-1 && toolTipPosition.Y!=-1 && toolTip.length()) + { + g->drawtext(toolTipPosition.X, toolTipPosition.Y, (char*)toolTip.c_str(), 255, 255, 255, toolTipPresence>51?255:toolTipPresence*5); + } + + if(buttonTipShow > 0) + { + g->drawtext(6, Size.Y-MENUSIZE-10, (char*)buttonTip.c_str(), 255, 255, 255, buttonTipShow>51?255:buttonTipShow*5); + } + + //Introduction text + if(introText) + { + g->fillrect(0, 0, XRES+BARSIZE, YRES+MENUSIZE, 0, 0, 0, introText>51?102:introText*2); + g->drawtext(16, 20, (char*)introTextMessage.c_str(), 255, 255, 255, introText>51?255:introText*5); + } +} + +ui::Point GameView::lineSnapCoords(ui::Point point1, ui::Point point2) +{ + ui::Point newPoint(0, 0); + float snapAngle = floor(atan2((float)point2.Y-point1.Y, point2.X-point1.X)/(M_PI*0.25)+0.5)*M_PI*0.25; + float lineMag = sqrtf(pow((float)(point2.X-point1.X),2)+pow((float)(point2.Y-point1.Y),2)); + newPoint.X = (int)(lineMag*cos(snapAngle)+point1.X+0.5f); + newPoint.Y = (int)(lineMag*sin(snapAngle)+point1.Y+0.5f); + return newPoint; +} + +ui::Point GameView::rectSnapCoords(ui::Point point1, ui::Point point2) +{ + ui::Point newPoint(0, 0); + float snapAngle = floor((atan2((float)point2.Y-point1.Y, point2.X-point1.X)+M_PI*0.25)/(M_PI*0.5)+0.5)*M_PI*0.5 - M_PI*0.25; + float lineMag = sqrtf(pow((float)(point2.X-point1.X),2)+pow((float)(point2.Y-point1.Y),2)); + newPoint.X = (int)(lineMag*cos(snapAngle)+point1.X+0.5f); + newPoint.Y = (int)(lineMag*sin(snapAngle)+point1.Y+0.5f); + return newPoint; +} diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h new file mode 100644 index 0000000..093d80b --- /dev/null +++ b/src/gui/game/GameView.h @@ -0,0 +1,189 @@ +#ifndef GAMEVIEW_H +#define GAMEVIEW_H + +#include <vector> +#include <queue> +#include <deque> +#include <string> +#include "GameController.h" +#include "GameModel.h" +#include "gui/interface/Window.h" +#include "gui/interface/Point.h" +#include "gui/interface/Button.h" +#include "gui/interface/Slider.h" +#include "gui/interface/Textbox.h" +#include "ToolButton.h" +#include "Brush.h" +#include "simulation/Sample.h" + +using namespace std; + +enum DrawMode +{ + DrawPoints, DrawLine, DrawRect, DrawFill +}; + +enum SelectMode +{ + SelectNone, SelectStamp, SelectCopy, SelectCut, PlaceSave +}; + +class GameController; +class GameModel; +class GameView: public ui::Window +{ +private: + DrawMode drawMode; + + bool doScreenshot; + bool recording; + int screenshotIndex; + int recordingIndex; + + bool isMouseDown; + bool zoomEnabled; + bool zoomCursorFixed; + bool drawSnap; + bool shiftBehaviour; + bool ctrlBehaviour; + bool altBehaviour; + bool showHud; + bool showDebug; + bool wallBrush; + int introText; + int buttonTipShow; + std::string buttonTip; + std::string introTextMessage; + int toolIndex; + int currentSaveType; + Menu * lastMenu; + + int infoTipPresence; + std::string toolTip; + ui::Point toolTipPosition; + std::string infoTip; + int toolTipPresence; + + queue<ui::Point> pointQueue; + GameController * c; + Renderer * ren; + Brush * activeBrush; + //UI Elements + vector<ui::Button*> quickOptionButtons; + vector<ui::Button*> menuButtons; + vector<ToolButton*> toolButtons; + vector<ui::Component*> notificationComponents; + deque<string> logEntries; + float lastLogEntry; + ui::Button * scrollBar; + ui::Button * searchButton; + ui::Button * reloadButton; + ui::Button * saveSimulationButton; + ui::Button * downVoteButton; + ui::Button * upVoteButton; + ui::Button * tagSimulationButton; + ui::Button * clearSimButton; + ui::Button * loginButton; + ui::Button * simulationOptionButton; + ui::Button * displayModeButton; + ui::Button * pauseButton; + ui::Point currentMouse; + + ui::Button * colourPicker; + vector<ToolButton*> colourPresets; + + bool drawModeReset; + ui::Point drawPoint1; + ui::Point drawPoint2; + + SelectMode selectMode; + ui::Point selectPoint1; + ui::Point selectPoint2; + + ui::Point mousePosition; + + VideoBuffer * placeSaveThumb; + + SimulationSample sample; + + int lastOffset; + void setToolButtonOffset(int offset); + virtual ui::Point lineSnapCoords(ui::Point point1, ui::Point point2); + virtual ui::Point rectSnapCoords(ui::Point point1, ui::Point point2); + + void screenshot(); + void record(); + + void enableShiftBehaviour(); + void disableShiftBehaviour(); + void enableCtrlBehaviour(); + void disableCtrlBehaviour(); + void enableAltBehaviour(); + void disableAltBehaviour(); +public: + GameView(); + virtual ~GameView(); + + //Breaks MVC, but any other way is going to be more of a mess. + ui::Point GetMousePosition(); + void SetSample(SimulationSample sample); + void SetHudEnable(bool hudState); + bool CtrlBehaviour(){ return ctrlBehaviour; } + bool ShiftBehaviour(){ return shiftBehaviour; } + void ExitPrompt(); + void ToggleDebug(); + SelectMode GetSelectMode() { return selectMode; } + void BeginStampSelection(); + + void AttachController(GameController * _c){ c = _c; } + void NotifyRendererChanged(GameModel * sender); + void NotifySimulationChanged(GameModel * sender); + void NotifyPausedChanged(GameModel * sender); + void NotifySaveChanged(GameModel * sender); + void NotifyBrushChanged(GameModel * sender); + void NotifyMenuListChanged(GameModel * sender); + void NotifyToolListChanged(GameModel * sender); + void NotifyActiveToolsChanged(GameModel * sender); + void NotifyUserChanged(GameModel * sender); + void NotifyZoomChanged(GameModel * sender); + void NotifyColourSelectorVisibilityChanged(GameModel * sender); + void NotifyColourSelectorColourChanged(GameModel * sender); + void NotifyColourPresetsChanged(GameModel * sender); + void NotifyColourActivePresetChanged(GameModel * sender); + void NotifyPlaceSaveChanged(GameModel * sender); + void NotifyNotificationsChanged(GameModel * sender); + void NotifyLogChanged(GameModel * sender, string entry); + void NotifyToolTipChanged(GameModel * sender); + void NotifyInfoTipChanged(GameModel * sender); + void NotifyQuickOptionsChanged(GameModel * sender); + void NotifyLastToolChanged(GameModel * sender); + + + virtual void ToolTip(ui::Component * sender, ui::Point mousePosition, std::string toolTip); + + virtual void OnMouseMove(int x, int y, int dx, int dy); + virtual void OnMouseDown(int x, int y, unsigned button); + virtual void OnMouseUp(int x, int y, unsigned button); + virtual void OnMouseWheel(int x, int y, int d); + virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual void OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual void OnTick(float dt); + virtual void OnDraw(); + virtual void OnBlur(); + + //Top-level handlers, for Lua interface + virtual void DoDraw(); + virtual void DoMouseMove(int x, int y, int dx, int dy); + virtual void DoMouseDown(int x, int y, unsigned button); + virtual void DoMouseUp(int x, int y, unsigned button); + virtual void DoMouseWheel(int x, int y, int d); + virtual void DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual void DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + + class MenuAction; + class ToolAction; + class OptionAction; + class OptionListener; +}; + +#endif // GAMEVIEW_H diff --git a/src/gui/game/Menu.h b/src/gui/game/Menu.h new file mode 100644 index 0000000..3f955e1 --- /dev/null +++ b/src/gui/game/Menu.h @@ -0,0 +1,51 @@ +#ifndef MENU_H_ +#define MENU_H_ + +#include "Tool.h" + +class Menu +{ + char icon; + string description; + vector<Tool*> tools; +public: + Menu(char icon_, string description_): + icon(icon_), + description(description_), + tools(vector<Tool*>()) + { + + } + + virtual ~Menu() + { + for(int i = 0; i < tools.size(); i++) + { + delete tools[i]; + } + tools.clear(); + } + + vector<Tool*> GetToolList() + { + return tools; + } + + char GetIcon() + { + return icon; + } + + string GetDescription() + { + return description; + } + + void AddTool(Tool * tool_) + { + tools.push_back(tool_); + } +}; + + +#endif /* MENU_H_ */ diff --git a/src/gui/game/Notification.h b/src/gui/game/Notification.h new file mode 100644 index 0000000..b2bf6f8 --- /dev/null +++ b/src/gui/game/Notification.h @@ -0,0 +1,16 @@ +#ifndef NOTIFICATION_H_ +#define NOTIFICATION_H_ + +#include <string> + +class Notification +{ +public: + Notification(std::string message) : Message(message) {} + virtual ~Notification() {}; + std::string Message; + + virtual void Action() { } +}; + +#endif /* NOTIFICATION_H_ */ diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp new file mode 100644 index 0000000..05726d3 --- /dev/null +++ b/src/gui/game/PropertyTool.cpp @@ -0,0 +1,235 @@ +#include <iostream> +#include <sstream> +#include "gui/Style.h" +#include "simulation/Simulation.h" +#include "Tool.h" +#include "gui/interface/Window.h" +#include "gui/interface/Button.h" +#include "gui/interface/Label.h" +#include "gui/interface/Textbox.h" +#include "gui/interface/DropDown.h" +#include "gui/interface/Keys.h" +#include "gui/dialogues/ErrorMessage.h" + +class PropertyWindow: public ui::Window +{ +public: + ui::DropDown * property; + ui::Textbox * textField; + SignTool * tool; + Simulation * sim; + int signID; + ui::Point position; + std::vector<StructProperty> properties; + PropertyWindow(PropertyTool * tool_, Simulation * sim_, ui::Point position_); + void SetProperty(); + virtual void OnDraw(); + virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual void OnTryExit(ExitMethod method); + virtual ~PropertyWindow() {} + class OkayAction: public ui::ButtonAction + { + public: + PropertyWindow * prompt; + OkayAction(PropertyWindow * prompt_) { prompt = prompt_; } + void ActionCallback(ui::Button * sender) + { + ui::Engine::Ref().CloseWindow(); + if(prompt->textField->GetText().length()) + prompt->SetProperty(); + prompt->SelfDestruct(); + return; + } + }; +}; + +PropertyWindow::PropertyWindow(PropertyTool * tool_, Simulation * sim_, ui::Point position_): +ui::Window(ui::Point(-1, -1), ui::Point(200, 87)), +sim(sim_), +position(position_) +{ + properties = Particle::GetProperties(); + + ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 14), "Edit property"); + messageLabel->SetTextColour(style::Colour::InformationTitle); + messageLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + messageLabel->Appearance.VerticalAlign = ui::Appearance::AlignTop; + AddComponent(messageLabel); + + ui::Button * okayButton = new ui::Button(ui::Point(0, Size.Y-17), ui::Point(Size.X, 17), "OK"); + okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200); + okayButton->SetActionCallback(new OkayAction(this)); + AddComponent(okayButton); + SetOkayButton(okayButton); + + class PropertyChanged: public ui::DropDownAction + { + PropertyWindow * w; + public: + PropertyChanged(PropertyWindow * w): w(w) { } + virtual void OptionChanged(ui::DropDown * sender, std::pair<std::string, int> option) + { + w->FocusComponent(w->textField); + } + }; + property = new ui::DropDown(ui::Point(8, 25), ui::Point(Size.X-16, 17)); + property->SetActionCallback(new PropertyChanged(this)); + AddComponent(property); + for(int i = 0; i < properties.size(); i++) + { + property->AddOption(std::pair<std::string, int>(properties[i].Name, i)); + } + property->SetOption(0); + + textField = new ui::Textbox(ui::Point(8, 46), ui::Point(Size.X-16, 16), "", "[value]"); + textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(textField); + FocusComponent(textField); + + ui::Engine::Ref().ShowWindow(this); +} +void PropertyWindow::SetProperty() +{ + if(property->GetOption().second!=-1 && textField->GetText().length() > 0) + { + void * propValue; + int tempInt; + unsigned int tempUInt; + float tempFloat; + std::string value = textField->GetText(); + try { + switch(properties[property->GetOption().second].Type) + { + case StructProperty::Integer: + case StructProperty::ParticleType: + if(value.length() > 2 && value.substr(0, 2) == "0x") + { + //0xC0FFEE + std::stringstream buffer; + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer << std::hex << value.substr(2); + buffer >> tempInt; + } + else if(value.length() > 1 && value[0] == '#') + { + //#C0FFEE + std::stringstream buffer; + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer << std::hex << value.substr(1); + buffer >> tempInt; + } + else + { + if(properties[property->GetOption().second].Type == StructProperty::ParticleType) + { + int type = sim->GetParticleType(value); + if(type != -1) + { +#ifdef DEBUG + std::cout << "Got type from particle name" << std::endl; +#endif + tempInt = type; + } + else + { + std::stringstream buffer(value); + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer >> tempInt; + } + } + else + { + std::stringstream buffer(value); + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer >> tempInt; + } + } +#ifdef DEBUG + std::cout << "Got int value " << tempInt << std::endl; +#endif + propValue = &tempInt; + break; + case StructProperty::UInteger: + if(value.length() > 2 && value.substr(0, 2) == "0x") + { + //0xC0FFEE + std::stringstream buffer; + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer << std::hex << value.substr(2); + buffer >> tempUInt; + } + else if(value.length() > 1 && value[0] == '#') + { + //#C0FFEE + std::stringstream buffer; + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer << std::hex << value.substr(1); + buffer >> tempUInt; + } + else + { + std::stringstream buffer(value); + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer >> tempUInt; + } +#ifdef DEBUG + std::cout << "Got uint value " << tempUInt << std::endl; +#endif + propValue = &tempUInt; + break; + case StructProperty::Float: + { + std::stringstream buffer(value); + buffer.exceptions(std::stringstream::failbit | std::stringstream::badbit); + buffer >> tempFloat; +#ifdef DEBUG + std::cout << "Got float value " << tempFloat << std::endl; +#endif + propValue = &tempFloat; + } + break; + default: + new ErrorMessage("Could not set property", "Invalid property"); + } + sim->flood_prop( + position.X, + position.Y, + properties[property->GetOption().second].Offset, + propValue, + properties[property->GetOption().second].Type + ); + } catch (const std::exception& ex) { + new ErrorMessage("Could not set property", "Invalid value provided"); + } + } +} + +void PropertyWindow::OnTryExit(ExitMethod method) +{ + ui::Engine::Ref().CloseWindow(); + SelfDestruct(); +} + +void PropertyWindow::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + + g->clearrect(Position.X-2, Position.Y-2, Size.X+3, Size.Y+3); + g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 200, 200, 200, 255); +} + +void PropertyWindow::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if (key == KEY_UP) + property->SetOption(property->GetOption().second-1); + else if (key == KEY_DOWN) + property->SetOption(property->GetOption().second+1); +} + +void PropertyTool::Click(Simulation * sim, Brush * brush, ui::Point position) +{ + new PropertyWindow(this, sim, position); +}
\ No newline at end of file diff --git a/src/gui/game/QuickOption.h b/src/gui/game/QuickOption.h new file mode 100644 index 0000000..4bf27ff --- /dev/null +++ b/src/gui/game/QuickOption.h @@ -0,0 +1,76 @@ +#pragma once + +#include <string> +#include <vector> + +class GameModel; +class QuickOption; +class QuickOptionListener +{ +protected: + QuickOptionListener() {} +public: + virtual ~QuickOptionListener() {} + virtual void OnValueChanged(QuickOption * sender) {} +}; +class QuickOption +{ +public: + enum Type { + Toggle, Multi + }; +protected: + std::vector<QuickOptionListener*> listeners; + GameModel * m; + Type type; + std::string icon; + std::string description; + QuickOption(std::string icon, std::string description, GameModel * m, Type type) : + icon(icon), + description(description), + m(m), + type(type) + { + + } + virtual void perform() {} +public: + virtual ~QuickOption() + { + //for(std::vector<QuickOptionListener*>::iterator iter = listeners.begin(), end = listeners.end(); iter != end; ++iter) + // delete *iter; + } + + std::vector<QuickOptionListener*> GetListeners() + { + return listeners; + } + + void AddListener(QuickOptionListener * listener) + { + listeners.push_back(listener); + } + + Type GetType() { return type; } + + virtual bool GetToggle() { return true;} + virtual int GetMutli() { return 0;} + virtual int GetMultiCount() { return 0;} + + std::string GetIcon() { return icon; } + void SetIcon(std::string icon) { this->icon = icon; } + std::string GetDescription() { return description; } + void SetDescription(std::string description) { this->description = description; } + void Perform() + { + perform(); + for(std::vector<QuickOptionListener*>::iterator iter = listeners.begin(), end = listeners.end(); iter != end; ++iter) + (*iter)->OnValueChanged(this); + } + void Update() + { + for(std::vector<QuickOptionListener*>::iterator iter = listeners.begin(), end = listeners.end(); iter != end; ++iter) + (*iter)->OnValueChanged(this); + } +}; + diff --git a/src/gui/game/QuickOptions.h b/src/gui/game/QuickOptions.h new file mode 100644 index 0000000..7c31f9c --- /dev/null +++ b/src/gui/game/QuickOptions.h @@ -0,0 +1,120 @@ +#include "QuickOption.h" +#include "GameModel.h" + +class SandEffectOption: public QuickOption +{ +public: + SandEffectOption(GameModel * m): + QuickOption("P", "Sand effect", m, Toggle) + { + + } + virtual bool GetToggle() + { + return m->GetSimulation()->pretty_powder; + } + virtual void perform() + { + m->GetSimulation()->pretty_powder = !m->GetSimulation()->pretty_powder; + } +}; + +class DrawGravOption: public QuickOption +{ +public: + DrawGravOption(GameModel * m): + QuickOption("G", "Draw gravity field", m, Toggle) + { + + } + virtual bool GetToggle() + { + return m->GetGravityGrid(); + } + virtual void perform() + { + m->ShowGravityGrid(!m->GetGravityGrid()); + } +}; + +class DecorationsOption: public QuickOption +{ +public: + DecorationsOption(GameModel * m): + QuickOption("D", "Draw decorations", m, Toggle) + { + + } + virtual bool GetToggle() + { + return m->GetDecoration(); + } + virtual void perform() + { + m->SetDecoration(!m->GetDecoration()); + } +}; + +class NGravityOption: public QuickOption +{ +public: + NGravityOption(GameModel * m): + QuickOption("N", "Newtonian Gravity", m, Toggle) + { + + } + virtual bool GetToggle() + { + return m->GetSimulation()->grav->ngrav_enable; + } + virtual void perform() + { + if(m->GetSimulation()->grav->ngrav_enable) + { + m->GetSimulation()->grav->stop_grav_async(); + m->SetInfoTip("Newtonian Gravity: Off"); + } + else + { + m->GetSimulation()->grav->start_grav_async(); + m->SetInfoTip("Newtonian Gravity: On"); + } + } +}; + +class AHeatOption: public QuickOption +{ +public: + AHeatOption(GameModel * m): + QuickOption("A", "Ambient heat", m, Toggle) + { + + } + virtual bool GetToggle() + { + return m->GetAHeatEnable(); + } + virtual void perform() + { + m->SetAHeatEnable(!m->GetAHeatEnable()); + } +}; + +class ConsoleShowOption: public QuickOption +{ + GameController * c; +public: + ConsoleShowOption(GameModel * m, GameController * c_): + QuickOption("C", "Show Console", m, Toggle) + { + c = c_; + } + virtual bool GetToggle() + { + return 0; + } + virtual void perform() + { + c->ShowConsole(); + } +}; diff --git a/src/gui/game/RenderPreset.h b/src/gui/game/RenderPreset.h new file mode 100644 index 0000000..9cc9f4c --- /dev/null +++ b/src/gui/game/RenderPreset.h @@ -0,0 +1,19 @@ +#ifndef RENDER_PRESET_H +#define RENDER_PRESET_H +class RenderPreset +{ +public: + std::string Name; + std::vector<unsigned int> RenderModes; + std::vector<unsigned int> DisplayModes; + unsigned int ColourMode; + + RenderPreset(): Name(""), ColourMode(0) {} + RenderPreset(std::string name, std::vector<unsigned int> renderModes, std::vector<unsigned int> displayModes, unsigned int colourMode): + Name(name), + RenderModes(renderModes), + DisplayModes(displayModes), + ColourMode(colourMode) + {} +}; +#endif
\ No newline at end of file diff --git a/src/gui/game/SampleTool.cpp b/src/gui/game/SampleTool.cpp new file mode 100644 index 0000000..b914b1c --- /dev/null +++ b/src/gui/game/SampleTool.cpp @@ -0,0 +1,67 @@ +#include <iostream> +#include "graphics/Graphics.h" +#include "Tool.h" +#include "GameModel.h" +#include "gui/interface/Colour.h" + +VideoBuffer * SampleTool::GetIcon(int toolID, int width, int height) +{ + VideoBuffer * newTexture = new VideoBuffer(width, height); + for (int y=0; y<height; y++) + { + for (int x=0; x<width; x++) + { + pixel pc = x==0||x==width-1||y==0||y==height-1 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); + newTexture->SetPixel(x, y, PIXR(pc), PIXG(pc), PIXB(pc), 255); + } + } + newTexture->SetCharacter((width/2)-5, (height/2)-5, 0xE6, 255, 255, 255, 255); + newTexture->BlendCharacter((width/2)-5, (height/2)-5, 0xE7, 100, 180, 255, 255); + return newTexture; +} + +void SampleTool::Draw(Simulation * sim, Brush * brush, ui::Point position) +{ + if(gameModel->GetColourSelectorVisibility()) + { + pixel colour = gameModel->GetRenderer()->sampleColor; + gameModel->SetColourSelectorColour(ui::Colour(PIXR(colour), PIXG(colour), PIXB(colour), 255)); + } + else + { + int particleType = 0; + int particleCtype = 0; + if (sim->photons[position.Y][position.X]) + { + particleType = sim->parts[sim->photons[position.Y][position.X]>>8].type; + particleCtype = sim->parts[sim->pmap[position.Y][position.X]>>8].ctype; + } + else if (sim->pmap[position.Y][position.X]) + { + particleType = sim->parts[sim->pmap[position.Y][position.X]>>8].type; + particleCtype = sim->parts[sim->pmap[position.Y][position.X]>>8].ctype; + } + + if(particleType) + { + if(particleType == PT_LIFE) + { + Menu * lifeMenu = gameModel->GetMenuList()[SC_LIFE]; + std::vector<Tool*> elementTools = lifeMenu->GetToolList(); + + for(std::vector<Tool*>::iterator iter = elementTools.begin(), end = elementTools.end(); iter != end; ++iter) + { + Tool * elementTool = *iter; + if(elementTool && elementTool->GetToolID() == particleCtype) + gameModel->SetActiveTool(0, elementTool); + } + } + else + { + Tool * elementTool = gameModel->GetElementTool(particleType); + if(elementTool) + gameModel->SetActiveTool(0, elementTool); + } + } + } +} diff --git a/src/gui/game/SignTool.cpp b/src/gui/game/SignTool.cpp new file mode 100644 index 0000000..a4042b1 --- /dev/null +++ b/src/gui/game/SignTool.cpp @@ -0,0 +1,278 @@ +#include <iostream> +#include "gui/Style.h" +#include "simulation/Simulation.h" +#include "Tool.h" +#include "gui/interface/Window.h" +#include "gui/interface/Button.h" +#include "gui/interface/Label.h" +#include "gui/interface/Textbox.h" +#include "gui/interface/DropDown.h" + +class SignWindow: public ui::Window +{ +public: + ui::DropDown * justification; + ui::Textbox * textField; + SignTool * tool; + sign * movingSign; + bool signMoving; + Simulation * sim; + int signID; + ui::Point signPosition; + SignWindow(SignTool * tool_, Simulation * sim_, int signID_, ui::Point position_); + virtual void OnDraw(); + virtual void DoDraw(); + virtual void DoMouseMove(int x, int y, int dx, int dy); + virtual void DoMouseDown(int x, int y, unsigned button); + virtual void DoMouseUp(int x, int y, unsigned button) { if(!signMoving) ui::Window::DoMouseUp(x, y, button); } + virtual void DoMouseWheel(int x, int y, int d) { if(!signMoving) ui::Window::DoMouseWheel(x, y, d); } + virtual void DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) { if(!signMoving) ui::Window::DoKeyPress(key, character, shift, ctrl, alt); }; + virtual void DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) { if(!signMoving) ui::Window::DoKeyRelease(key, character, shift, ctrl, alt); }; + virtual ~SignWindow() {} + virtual void OnTryExit(ui::Window::ExitMethod method); + class OkayAction: public ui::ButtonAction + { + public: + SignWindow * prompt; + OkayAction(SignWindow * prompt_) { prompt = prompt_; } + void ActionCallback(ui::Button * sender) + { + ui::Engine::Ref().CloseWindow(); + if(prompt->signID==-1 && prompt->textField->GetText().length()) + { + prompt->sim->signs.push_back(sign(prompt->textField->GetText(), prompt->signPosition.X, prompt->signPosition.Y, (sign::Justification)prompt->justification->GetOption().second)); + } + else if(prompt->signID!=-1 && prompt->textField->GetText().length()) + { + prompt->sim->signs[prompt->signID] = sign(sign(prompt->textField->GetText(), prompt->signPosition.X, prompt->signPosition.Y, (sign::Justification)prompt->justification->GetOption().second)); + } + prompt->SelfDestruct(); + } + }; + class DeleteAction: public ui::ButtonAction + { + public: + SignWindow * prompt; + DeleteAction(SignWindow * prompt_) { prompt = prompt_; } + void ActionCallback(ui::Button * sender) + { + ui::Engine::Ref().CloseWindow(); + if(prompt->signID!=-1) + { + prompt->sim->signs.erase(prompt->sim->signs.begin()+prompt->signID); + } + prompt->SelfDestruct(); + } + }; + + class SignTextAction: public ui::TextboxAction + { + public: + SignWindow * prompt; + SignTextAction(SignWindow * prompt_) { prompt = prompt_; } + virtual void TextChangedCallback(ui::Textbox * sender) + { + if(prompt->signID!=-1) + { + prompt->sim->signs[prompt->signID].text = sender->GetText(); + prompt->sim->signs[prompt->signID].ju = (sign::Justification)prompt->justification->GetOption().second; + } + } + }; + + class MoveAction: public ui::ButtonAction + { + public: + SignWindow * prompt; + MoveAction(SignWindow * prompt_) { prompt = prompt_; } + void ActionCallback(ui::Button * sender) + { + if(prompt->signID!=-1) + { + prompt->movingSign = &prompt->sim->signs[prompt->signID]; + prompt->sim->signs[prompt->signID].ju = (sign::Justification)prompt->justification->GetOption().second; + prompt->signMoving = true; + } + } + }; +}; + +SignWindow::SignWindow(SignTool * tool_, Simulation * sim_, int signID_, ui::Point position_): + ui::Window(ui::Point(-1, -1), ui::Point(200, 87)), + tool(tool_), + signID(signID_), + sim(sim_), + signPosition(position_), + movingSign(NULL), + signMoving(false) +{ + ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 15), "New sign"); + messageLabel->SetTextColour(style::Colour::InformationTitle); + messageLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + messageLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(messageLabel); + + ui::Button * okayButton = new ui::Button(ui::Point(0, Size.Y-16), ui::Point(Size.X, 16), "OK"); + okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + okayButton->Appearance.BorderInactive = (ui::Colour(200, 200, 200)); + okayButton->SetActionCallback(new OkayAction(this)); + AddComponent(okayButton); + SetOkayButton(okayButton); + + ui::Label * tempLabel = new ui::Label(ui::Point(8, 48), ui::Point(40, 15), "Justify:"); + okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(tempLabel); + + justification = new ui::DropDown(ui::Point(52, 48), ui::Point(50, 16)); + AddComponent(justification); + justification->AddOption(std::pair<std::string, int>("\x9D Left", (int)sign::Left)); + justification->AddOption(std::pair<std::string, int>("\x9E Centre", (int)sign::Centre)); + justification->AddOption(std::pair<std::string, int>("\x9F Right", (int)sign::Right)); + justification->SetOption(1); + justification->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + + textField = new ui::Textbox(ui::Point(8, 25), ui::Point(Size.X-16, 17), "", "[message]"); + textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + textField->SetActionCallback(new SignTextAction(this)); + AddComponent(textField); + FocusComponent(textField); + + if(signID!=-1) + { + messageLabel->SetText("Edit sign"); + + textField->SetText(sim->signs[signID].text); + justification->SetOption(sim->signs[signID].ju); + + ui::Point position = ui::Point(justification->Position.X+justification->Size.X+3, 48); + ui::Button * moveButton = new ui::Button(position, ui::Point(((Size.X-position.X-8)/2)-2, 16), "Move"); + moveButton->SetActionCallback(new MoveAction(this)); + AddComponent(moveButton); + + position = ui::Point(justification->Position.X+justification->Size.X+3, 48)+ui::Point(moveButton->Size.X+3, 0); + ui::Button * deleteButton = new ui::Button(position, ui::Point((Size.X-position.X-8)-1, 16), "Delete"); + //deleteButton->SetIcon(IconDelete); + deleteButton->SetActionCallback(new DeleteAction(this)); + + signPosition.X = sim->signs[signID].x; + signPosition.Y = sim->signs[signID].y; + + AddComponent(deleteButton); + } + + ui::Engine::Ref().ShowWindow(this); +} + +void SignWindow::OnTryExit(ui::Window::ExitMethod method) +{ + ui::Engine::Ref().CloseWindow(); + SelfDestruct(); +} + +void SignWindow::DoDraw() +{ + for(std::vector<sign>::iterator iter = sim->signs.begin(), end = sim->signs.end(); iter != end; ++iter) + { + sign & currentSign = *iter; + int x, y, w, h, dx, dy; + Graphics * g = ui::Engine::Ref().g; + std::string text = currentSign.getText(sim); + currentSign.pos(text, x, y, w, h); + g->clearrect(x, y, w+1, h); + g->drawrect(x, y, w+1, h, 192, 192, 192, 255); + if (sregexp(currentSign.text.c_str(), "^{[c|t]:[0-9]*|.*}$")) + g->drawtext(x+3, y+3, text, 255, 255, 255, 255); + else + g->drawtext(x+3, y+3, text, 0, 191, 255, 255); + + x = currentSign.x; + y = currentSign.y; + dx = 1 - currentSign.ju; + dy = (currentSign.y > 18) ? -1 : 1; +#ifdef OGLR + glBegin(GL_LINES); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glVertex2i(x, y); + glVertex2i(x+(dx*4), y+(dy*4)); + glEnd(); +#else + for (int j=0; j<4; j++) + { + g->blendpixel(x, y, 192, 192, 192, 255); + x+=dx; + y+=dy; + } +#endif + } + if(!signMoving) + { + ui::Window::DoDraw(); + } +} + +void SignWindow::DoMouseMove(int x, int y, int dx, int dy) { + if(!signMoving) + ui::Window::DoMouseMove(x, y, dx, dy); + else + { + if(x < XRES && y < YRES) + { + movingSign->x = x; + movingSign->y = y; + signPosition.X = x; + signPosition.Y = y; + } + } +} + +void SignWindow::DoMouseDown(int x, int y, unsigned button) +{ + if(!signMoving) + ui::Window::DoMouseDown(x, y, button); + else + { + signMoving = false; + } +} + +void SignWindow::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + + g->clearrect(Position.X-2, Position.Y-2, Size.X+3, Size.Y+3); + g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 200, 200, 200, 255); +} + +VideoBuffer * SignTool::GetIcon(int toolID, int width, int height) +{ + VideoBuffer * newTexture = new VideoBuffer(width, height); + for (int y=0; y<height; y++) + { + for (int x=0; x<width; x++) + { + pixel pc = x==0||x==width-1||y==0||y==height-1 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); + newTexture->SetPixel(x, y, PIXR(pc), PIXG(pc), PIXB(pc), 255); + } + } + newTexture->SetCharacter((width/2)-5, (height/2)-5, 0xA1, 32, 64, 128, 255); + newTexture->BlendCharacter((width/2)-5, (height/2)-5, 0xA0, 255, 255, 255, 255); + return newTexture; +} + +void SignTool::Click(Simulation * sim, Brush * brush, ui::Point position) +{ + int signX, signY, signW, signH, signIndex = -1; + for(int i = 0; i < sim->signs.size(); i++){ + sim->signs[i].pos(sim->signs[i].getText(sim), signX, signY, signW, signH); + if(position.X > signX && position.X < signX+signW && position.Y > signY && position.Y < signY+signH) + { + signIndex = i; + break; + } + } + if (signIndex != -1 || sim->signs.size() < MAXSIGNS) + new SignWindow(this, sim, signIndex, position); +} diff --git a/src/gui/game/Tool.cpp b/src/gui/game/Tool.cpp new file mode 100644 index 0000000..def6e46 --- /dev/null +++ b/src/gui/game/Tool.cpp @@ -0,0 +1,215 @@ +#include <string> +#include "Tool.h" +#include "gui/game/Brush.h" + +#include "simulation/Simulation.h" + +using namespace std; + +Tool::Tool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): + toolID(id), + toolName(name), + toolDescription(description), + colRed(r), + colGreen(g), + colBlue(b), + textureGen(textureGen), + strength(1.0f), + resolution(1), + identifier(identifier) +{ +} + +VideoBuffer * Tool::GetTexture(int width, int height) +{ + if(textureGen) + { + return textureGen(toolID, width, height); + } + return NULL; +} +void Tool::SetTextureGen(VideoBuffer * (*textureGen)(int, int, int)) +{ + this->textureGen = textureGen; +} +std::string Tool::GetIdentifier() { return identifier; } +string Tool::GetName() { return toolName; } +string Tool::GetDescription() { return toolDescription; } +Tool::~Tool() {} + +void Tool::Click(Simulation * sim, Brush * brush, ui::Point position) { } +void Tool::Draw(Simulation * sim, Brush * brush, ui::Point position) { + sim->ToolBrush(position.X, position.Y, toolID, brush, strength); +} +void Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + sim->ToolLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush, strength); +} +void Tool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + sim->ToolBox(position1.X, position1.Y, position2.X, position2.Y, toolID, brush, strength); +} +void Tool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {}; + + +ElementTool::ElementTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): + Tool(id, name, description, r, g, b, identifier, textureGen) +{ +} +ElementTool::~ElementTool() {} +void ElementTool::Draw(Simulation * sim, Brush * brush, ui::Point position){ + sim->CreateParts(position.X, position.Y, toolID, brush); +} +void ElementTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush); +} +void ElementTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID, 0); +} +void ElementTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { + sim->FloodParts(position.X, position.Y, toolID, -1, -1, 0); +} + + +WallTool::WallTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): +Tool(id, name, description, r, g, b, identifier, textureGen) +{ + resolution = CELL; +} +WallTool::~WallTool() {} +void WallTool::Draw(Simulation * sim, Brush * brush, ui::Point position){ + sim->CreateWalls(position.X, position.Y, 1, 1, toolID, 0, brush); +} +void WallTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + int wallX = position1.X/CELL; + int wallY = position1.Y/CELL; + if(dragging == false && toolID == WL_FAN && sim->bmap[wallY][wallX]==WL_FAN) + { + float newFanVelX = (position2.X-position1.X)*0.005f; + newFanVelX *= strength; + float newFanVelY = (position2.Y-position1.Y)*0.005f; + newFanVelY *= strength; + sim->FloodWalls(position1.X, position1.Y, WL_FLOODHELPER, -1, WL_FAN, 0); + for (int j = 0; j < YRES/CELL; j++) + for (int i = 0; i < XRES/CELL; i++) + if (sim->bmap[j][i] == WL_FLOODHELPER) + { + sim->fvx[j][i] = newFanVelX; + sim->fvy[j][i] = newFanVelY; + sim->bmap[j][i] = WL_FAN; + } + } + else + { + sim->CreateWallLine(position1.X, position1.Y, position2.X, position2.Y, 1, 1, toolID, 0, brush); + } +} +void WallTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + sim->CreateWallBox(position1.X, position1.Y, position2.X, position2.Y, toolID, 0); +} +void WallTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { + if (toolID != WL_STREAM) + sim->FloodWalls(position.X, position.Y, toolID, -1, -1, 0); +} + + +GolTool::GolTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): + Tool(id, name, description, r, g, b, identifier, textureGen) +{ +} +GolTool::~GolTool() {} +void GolTool::Draw(Simulation * sim, Brush * brush, ui::Point position){ + sim->CreateParts(position.X, position.Y, PT_LIFE|(toolID<<8), brush); +} +void GolTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, PT_LIFE|(toolID<<8), brush); +} +void GolTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, PT_LIFE|(toolID<<8), 0); +} +void GolTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { + sim->FloodParts(position.X, position.Y, PT_LIFE|(toolID<<8), -1, -1, 0); +} + + +WindTool::WindTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): + Tool(id, name, description, r, g, b, identifier, textureGen) +{ +} +WindTool::~WindTool() {} +void WindTool::Draw(Simulation * sim, Brush * brush, ui::Point position) +{ + +} +void WindTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) +{ + int radiusX, radiusY, sizeX, sizeY; + + float strength = dragging?0.01f:0.002f; + strength *= this->strength; + + radiusX = brush->GetRadius().X; + radiusY = brush->GetRadius().Y; + + sizeX = brush->GetSize().X; + sizeY = brush->GetSize().Y; + + unsigned char *bitmap = brush->GetBitmap(); + + for(int y = 0; y < sizeY; y++) + { + for(int x = 0; x < sizeX; x++) + { + if(bitmap[(y*sizeX)+x] && (position1.X+(x-radiusX) >= 0 && position1.Y+(y-radiusY) >= 0 && position1.X+(x-radiusX) < XRES && position1.Y+(y-radiusY) < YRES)) + { + sim->vx[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.X-position1.X)*strength; + sim->vy[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.Y-position1.Y)*strength; + } + } + } +} +void WindTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) {} +void WindTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {} + + +void Element_LIGH_Tool::Draw(Simulation * sim, Brush * brush, ui::Point position) +{ + if(sim->currentTick >= nextUse) + { + int p = sim->create_part(-2, position.X, position.Y, toolID); + if (p != -1) + { + sim->parts[p].life = brush->GetRadius().X+brush->GetRadius().Y; + if (sim->parts[p].life > 55) + sim->parts[p].life = 55; + sim->parts[p].temp = sim->parts[p].life*150; // temperature of the lighting shows the power of the lighting + nextUse = sim->currentTick+sim->parts[p].life/4; + } + } +} + + +Element_TESC_Tool::Element_TESC_Tool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int)): + ElementTool(id, name, description, r, g, b, identifier, textureGen) + { + } +void Element_TESC_Tool::Draw(Simulation * sim, Brush * brush, ui::Point position){ + int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; + sim->CreateParts(position.X, position.Y, toolID | (radiusInfo << 8), brush); +} +void Element_TESC_Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { + int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; + sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, toolID | (radiusInfo << 8), brush); +} +void Element_TESC_Tool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { + int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; + sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID | (radiusInfo << 8), 0); +} +void Element_TESC_Tool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { + int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; + sim->FloodParts(position.X, position.Y, toolID | (radiusInfo << 8), -1, -1, 0); +} + + +void PlopTool::Click(Simulation * sim, Brush * brush, ui::Point position) +{ + sim->create_part(-1, position.X, position.Y, toolID); +}
\ No newline at end of file diff --git a/src/gui/game/Tool.h b/src/gui/game/Tool.h new file mode 100644 index 0000000..ea38fbc --- /dev/null +++ b/src/gui/game/Tool.h @@ -0,0 +1,183 @@ +#ifndef TOOL_H_ +#define TOOL_H_ + +#include <iostream> + +using namespace std; + +#include "gui/interface/Point.h" + +class Simulation; +class Brush; +class VideoBuffer; + +class Tool +{ +protected: + VideoBuffer * (*textureGen)(int, int, int); + int toolID; + string toolName; + string toolDescription; + float strength; + int resolution; + std::string identifier; +public: + Tool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + int GetToolID() { return toolID; } + string GetName(); + string GetDescription(); + std::string GetIdentifier(); + int GetResolution() { return resolution; } + void SetStrength(float value) { strength = value; } + float GetStrength() { return strength; } + VideoBuffer * GetTexture(int width, int height); + void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int)); + virtual ~Tool(); + virtual void Click(Simulation * sim, Brush * brush, ui::Point position); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); + int colRed, colBlue, colGreen; +}; + +class SignTool: public Tool +{ +public: + SignTool(): + Tool(0, "SIGN", "Sign. Click a sign to edit or anywhere else to create a new one", 0, 0, 0, "DEFAULT_UI_SIGN", SignTool::GetIcon) + { + } + static VideoBuffer * GetIcon(int toolID, int width, int height); + virtual ~SignTool() {} + virtual void Click(Simulation * sim, Brush * brush, ui::Point position); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position) { } + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) { } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } +}; + +class GameModel; + +class SampleTool: public Tool +{ + GameModel * gameModel; +public: + SampleTool(GameModel * model): + Tool(0, "SMPL", "Sample an element on the screen", 0, 0, 0, "DEFAULT_UI_SAMPLE", SampleTool::GetIcon), + gameModel(model) + { + } + static VideoBuffer * GetIcon(int toolID, int width, int height); + virtual ~SampleTool() {} + virtual void Click(Simulation * sim, Brush * brush, ui::Point position) { } + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) { } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } +}; + +class PropertyTool: public Tool +{ +public: + PropertyTool(): + Tool(0, "PROP", "Property Edit. Click to alter the properties of elements in the field", 0xfe, 0xa9, 0x00, "DEFAULT_UI_PROPERTY", NULL) + { + } + virtual ~PropertyTool() {} + virtual void Click(Simulation * sim, Brush * brush, ui::Point position); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position) {}; + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) { } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } +}; + +class Element_LIGH_Tool: public Tool +{ + int nextUse; +public: + Element_LIGH_Tool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL): + Tool(id, name, description, r, g, b, identifier, textureGen), + nextUse(0) + { + } + virtual ~Element_LIGH_Tool() {} + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void Click(Simulation * sim, Brush * brush, ui::Point position) { } + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) { } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } +}; + + +class ElementTool: public Tool +{ +public: + ElementTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + virtual ~ElementTool(); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); +}; + +class Element_TESC_Tool: public ElementTool +{ +public: + Element_TESC_Tool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + virtual ~Element_TESC_Tool() {} + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); +}; + +class PlopTool: public ElementTool +{ +public: + PlopTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL): + ElementTool(id, name, description, r, g, b, identifier, textureGen) + { + } + virtual ~PlopTool() {} + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position) {} + virtual void Click(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) { } + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { } + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } +}; + +class WallTool: public Tool +{ +public: + WallTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + virtual ~WallTool(); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); +}; + +class GolTool: public Tool +{ +public: + GolTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + virtual ~GolTool(); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); +}; + +class WindTool: public Tool +{ +public: + WindTool(int id, string name, string description, int r, int g, int b, std::string identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); + virtual ~WindTool(); + virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); + virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); + virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); + virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); +}; + +#endif /* TOOL_H_ */ diff --git a/src/gui/game/ToolButton.cpp b/src/gui/game/ToolButton.cpp new file mode 100644 index 0000000..8539ac7 --- /dev/null +++ b/src/gui/game/ToolButton.cpp @@ -0,0 +1,91 @@ +#include "ToolButton.h" +#include "gui/interface/Keys.h" + +ToolButton::ToolButton(ui::Point position, ui::Point size, std::string text_, std::string toolTip): + ui::Button(position, size, text_, toolTip) +{ + SetSelectionState(-1); + Appearance.BorderActive = ui::Colour(255, 0, 0); +} + +void ToolButton::OnMouseClick(int x, int y, unsigned int button) +{ + isButtonDown = true; +} + +void ToolButton::OnMouseUnclick(int x, int y, unsigned int button) +{ + if(isButtonDown) + { + isButtonDown = false; + if(button == BUTTON_LEFT) + SetSelectionState(0); + if(button == BUTTON_RIGHT) + SetSelectionState(1); + if(button == BUTTON_MIDDLE) + SetSelectionState(2); + DoAction(); + } +} + +void ToolButton::Draw(const ui::Point& screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + int totalColour = Appearance.BackgroundInactive.Blue + (3*Appearance.BackgroundInactive.Green) + (2*Appearance.BackgroundInactive.Red); + + if(Appearance.GetTexture()) + { + g->draw_image(Appearance.GetTexture(), screenPos.X+2, screenPos.Y+2, 255); + } + else + { + g->fillrect(screenPos.X+2, screenPos.Y+2, Size.X-4, Size.Y-4, Appearance.BackgroundInactive.Red, Appearance.BackgroundInactive.Green, Appearance.BackgroundInactive.Blue, Appearance.BackgroundInactive.Alpha); + } + + if(isMouseInside && currentSelection == -1) + { + g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, Appearance.BorderActive.Red, Appearance.BorderActive.Green, Appearance.BorderActive.Blue, Appearance.BorderActive.Alpha); + } + else + { + g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, Appearance.BorderInactive.Red, Appearance.BorderInactive.Green, Appearance.BorderInactive.Blue, Appearance.BorderInactive.Alpha); + } + + if (totalColour<544) + { + g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, buttonDisplayText.c_str(), 255, 255, 255, 255); + } + else + { + g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, buttonDisplayText.c_str(), 0, 0, 0, 255); + } +} + +void ToolButton::SetSelectionState(int state) +{ + currentSelection = state; + switch(state) + { + case 0: + Appearance.BorderInactive = ui::Colour(255, 0, 0); + break; + case 1: + Appearance.BorderInactive = ui::Colour(0, 0, 255); + break; + case 2: + Appearance.BorderInactive = ui::Colour(0, 255, 0); + break; + default: + Appearance.BorderInactive = ui::Colour(0, 0, 0); + break; + } +} + +int ToolButton::GetSelectionState() +{ + return currentSelection; +} + +ToolButton::~ToolButton() { +} + diff --git a/src/gui/game/ToolButton.h b/src/gui/game/ToolButton.h new file mode 100644 index 0000000..86c8970 --- /dev/null +++ b/src/gui/game/ToolButton.h @@ -0,0 +1,18 @@ +#ifndef TOOLBUTTON_H_ +#define TOOLBUTTON_H_ + +#include "gui/interface/Button.h" + +class ToolButton: public ui::Button { + int currentSelection; +public: + ToolButton(ui::Point position, ui::Point size, std::string text_, std::string toolTip = ""); + virtual void OnMouseUnclick(int x, int y, unsigned int button); + virtual void OnMouseClick(int x, int y, unsigned int button); + virtual void Draw(const ui::Point& screenPos); + void SetSelectionState(int state); + int GetSelectionState(); + virtual ~ToolButton(); +}; + +#endif /* TOOLBUTTON_H_ */ diff --git a/src/gui/game/TriangleBrush.h b/src/gui/game/TriangleBrush.h new file mode 100644 index 0000000..7d537bd --- /dev/null +++ b/src/gui/game/TriangleBrush.h @@ -0,0 +1,46 @@ +/* + * TriangleBrush.h + * + * Created on: Jan 26, 2012 + * Author: Savely Skresanov + */ + +#ifndef TRIANGLEBRUSH_H_ +#define TRIANGLEBRUSH_H_ + +#include <cmath> +#include "Brush.h" + +class TriangleBrush: public Brush +{ +public: + TriangleBrush(ui::Point size_): + Brush(size_) + { + SetRadius(size_); + }; + virtual void GenerateBitmap() + { + if(bitmap) + delete[] bitmap; + bitmap = new unsigned char[size.X*size.Y]; + int rx = radius.X; + int ry = radius.Y; + for(int x = -rx; x <= rx; x++) + { + for(int y = -ry; y <= ry; y++) + { + if ((abs((rx+2*x)*ry+rx*y) + abs(2*rx*(y-ry)) + abs((rx-2*x)*ry+rx*y))<=(4*rx*ry)) + { + bitmap[(y+ry)*(size.X)+x+rx] = 255; + } + else + { + bitmap[(y+ry)*(size.X)+x+rx] = 0; + } + } + } + } +}; + +#endif /* TRIANGLEBRUSH_H_ */ |
