summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2012-11-17 19:44:09 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2012-11-17 19:44:09 (GMT)
commit058a2edd75debbd0297f92572316daa704bd379f (patch)
treead303f091f9a08b209b91eb34a9fcad996a3de69 /src/game
parente3594aba9e05c6865d396418c028049cda92c2f3 (diff)
parent7a21ae192fe19868539956f3fe28e62b2c7c4429 (diff)
downloadpowder-058a2edd75debbd0297f92572316daa704bd379f.zip
powder-058a2edd75debbd0297f92572316daa704bd379f.tar.gz
Merge branch 'master' of github.com:FacialTurd/PowderToypp
Diffstat (limited to 'src/game')
-rw-r--r--src/game/Brush.cpp48
-rw-r--r--src/game/Brush.h114
-rw-r--r--src/game/DecorationTool.h43
-rw-r--r--src/game/EllipseBrush.h46
-rw-r--r--src/game/GameController.cpp1326
-rw-r--r--src/game/GameController.h147
-rw-r--r--src/game/GameModel.cpp1133
-rw-r--r--src/game/GameModel.h206
-rw-r--r--src/game/GameModelException.h26
-rw-r--r--src/game/GameView.cpp2079
-rw-r--r--src/game/GameView.h187
-rw-r--r--src/game/Menu.h58
-rw-r--r--src/game/Notification.h23
-rw-r--r--src/game/PropertyTool.cpp235
-rw-r--r--src/game/QuickOption.h76
-rw-r--r--src/game/QuickOptions.h120
-rw-r--r--src/game/RenderPreset.h19
-rw-r--r--src/game/SampleTool.cpp67
-rw-r--r--src/game/SignTool.cpp289
-rw-r--r--src/game/Tool.cpp216
-rw-r--r--src/game/Tool.h190
-rw-r--r--src/game/ToolButton.cpp99
-rw-r--r--src/game/ToolButton.h25
-rw-r--r--src/game/TriangleBrush.h46
24 files changed, 6818 insertions, 0 deletions
diff --git a/src/game/Brush.cpp b/src/game/Brush.cpp
new file mode 100644
index 0000000..38dd809
--- /dev/null
+++ b/src/game/Brush.cpp
@@ -0,0 +1,48 @@
+#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)
+{
+
+}
diff --git a/src/game/Brush.h b/src/game/Brush.h
new file mode 100644
index 0000000..068ecf5
--- /dev/null
+++ b/src/game/Brush.h
@@ -0,0 +1,114 @@
+/*
+ * Brush.h
+ *
+ * Created on: Jan 22, 2012
+ * Author: Simon
+ */
+#ifndef BRUSH_H_
+#define BRUSH_H_
+
+#include <iostream>
+#include "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;
+ }
+ 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/game/DecorationTool.h b/src/game/DecorationTool.h
new file mode 100644
index 0000000..679c854
--- /dev/null
+++ b/src/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/game/EllipseBrush.h b/src/game/EllipseBrush.h
new file mode 100644
index 0000000..9a75dfb
--- /dev/null
+++ b/src/game/EllipseBrush.h
@@ -0,0 +1,46 @@
+/*
+ * ElipseBrush.h
+ *
+ * Created on: Jan 26, 2012
+ * Author: Simon
+ */
+
+#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;
+ for(int x = 0; x <= radius.X*2; x++)
+ {
+ for(int y = 0; y <= radius.Y*2; y++)
+ {
+ if((pow(x-radius.X,2.0f)*pow(ry,2.0f)+pow(y-radius.Y,2.0f)*pow(rx,2.0f)<=pow(rx,2.0f)*pow(ry,2.0f)))
+ {
+ bitmap[y*(size.X)+x] = 255;
+ }
+ else
+ {
+ bitmap[y*(size.X)+x] = 0;
+ }
+ }
+ }
+ }
+};
+
+#endif /* ELIPSEBRUSH_H_ */
diff --git a/src/game/GameController.cpp b/src/game/GameController.cpp
new file mode 100644
index 0000000..18b93d6
--- /dev/null
+++ b/src/game/GameController.cpp
@@ -0,0 +1,1326 @@
+
+#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 "search/SearchController.h"
+#include "render/RenderController.h"
+#include "login/LoginController.h"
+#include "interface/Point.h"
+#include "dialogues/ErrorMessage.h"
+#include "dialogues/InformationMessage.h"
+#include "dialogues/ConfirmPrompt.h"
+#include "GameModelException.h"
+#include "simulation/Air.h"
+#include "elementsearch/ElementSearchActivity.h"
+#include "colourpicker/ColourPickerActivity.h"
+#include "update/UpdateActivity.h"
+#include "Notification.h"
+#include "filebrowser/FileBrowserActivity.h"
+#include "save/LocalSaveActivity.h"
+#include "save/ServerSaveActivity.h"
+#include "interface/Keys.h"
+#include "simulation/Snapshot.h"
+
+using namespace std;
+
+class GameController::LoginCallback: public ControllerCallback
+{
+ GameController * cc;
+public:
+ LoginCallback(GameController * cc_) { cc = cc_; }
+ virtual void ControllerExit()
+ {
+ cc->gameModel->SetUser(cc->loginWindow->GetUser());
+ }
+};
+
+
+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());
+ }
+ 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());
+ 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);
+
+ //sim = new Simulation();
+ Client::Ref().AddListener(this);
+}
+
+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(ui::Engine::Ref().GetWindow() == gameView)
+ {
+ ui::Engine::Ref().CloseWindow();
+ }
+ 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");
+#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 without error");
+ }
+ else
+ {
+ new ErrorMessage("Could not install", "The installation did not complete due to an error");
+ }
+ }
+ }
+ virtual ~InstallConfirmation() { }
+ };
+ new ConfirmPrompt("Install The Powder Toy", "You are about to install The Powder Toy onto this computer", 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>128)
+ newSize.X = 128;
+ if(newSize.Y>128)
+ newSize.Y = 128;
+
+ 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(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();
+ firstTick = false;
+ }
+ commandInterface->OnTick();
+}
+
+void GameController::Exit()
+{
+ if(ui::Engine::Ref().GetWindow() == gameView)
+ ui::Engine::Ref().CloseWindow();
+ HasDone = true;
+}
+
+void GameController::ResetAir()
+{
+ gameModel->GetSimulation()->air->Clear();
+}
+
+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::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);
+}
+
+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::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()
+{
+ loginWindow = new LoginController(new LoginCallback(this));
+ 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);
+ ui::Engine::Ref().ShowWindow(console->GetView());
+}
+
+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)
+ return std::string(gameModel->GetSimulation()->wtypes[type].name);
+ else
+ return "";
+}
+
+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/game/GameController.h b/src/game/GameController.h
new file mode 100644
index 0000000..4c7a8c9
--- /dev/null
+++ b/src/game/GameController.h
@@ -0,0 +1,147 @@
+ #ifndef GAMECONTROLLER_H
+#define GAMECONTROLLER_H
+
+#include <queue>
+#include "GameView.h"
+#include "GameModel.h"
+#include "interface/Point.h"
+#include "simulation/Simulation.h"
+#include "search/SearchController.h"
+#include "render/RenderController.h"
+#include "preview/PreviewController.h"
+#include "login/LoginController.h"
+#include "tags/TagsController.h"
+#include "console/ConsoleController.h"
+#include "localbrowser/LocalBrowserController.h"
+//#include "cat/TPTScriptInterface.h"
+#include "cat/LuaScriptInterface.h"
+#include "options/OptionsController.h"
+#include "client/ClientListener.h"
+#include "RenderPreset.h"
+#include "Menu.h"
+
+using namespace std;
+
+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;
+public:
+ bool HasDone;
+ class LoginCallback;
+ 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 SetActiveMenu(Menu * menu);
+ void SetActiveTool(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 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 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);
+ void RunUpdater();
+};
+
+#endif // GAMECONTROLLER_H
diff --git a/src/game/GameModel.cpp b/src/game/GameModel.cpp
new file mode 100644
index 0000000..5c4ee97
--- /dev/null
+++ b/src/game/GameModel.cpp
@@ -0,0 +1,1133 @@
+#include "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 "interface/Point.h"
+#include "Brush.h"
+#include "EllipseBrush.h"
+#include "TriangleBrush.h"
+#include "client/Client.h"
+#include "client/GameSave.h"
+#include "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 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 < 12 && 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 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)));
+
+ //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->grav->stop_grav_async();
+ 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/game/GameModel.h b/src/game/GameModel.h
new file mode 100644
index 0000000..c1d97d6
--- /dev/null
+++ b/src/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 "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/game/GameModelException.h b/src/game/GameModelException.h
new file mode 100644
index 0000000..05138f2
--- /dev/null
+++ b/src/game/GameModelException.h
@@ -0,0 +1,26 @@
+/*
+ * SaveLoadException.h
+ *
+ * Created on: Mar 29, 2012
+ * Author: Simon
+ */
+
+#ifndef SAVELOADEXCEPTION_H_
+#define SAVELOADEXCEPTION_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 /* SAVELOADEXCEPTION_H_ */
diff --git a/src/game/GameView.cpp b/src/game/GameView.cpp
new file mode 100644
index 0000000..0e3f580
--- /dev/null
+++ b/src/game/GameView.cpp
@@ -0,0 +1,2079 @@
+#include <sstream>
+#include <iomanip>
+
+#include "Config.h"
+#include "Style.h"
+#include "GameView.h"
+#include "graphics/Graphics.h"
+#include "interface/Window.h"
+#include "interface/Button.h"
+#include "interface/Colour.h"
+#include "interface/Keys.h"
+#include "interface/Slider.h"
+#include "search/Thumbnail.h"
+#include "simulation/SaveRenderer.h"
+#include "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),
+ 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)
+{
+
+ 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();
+ }
+ };
+ 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;
+ MenuAction(GameView * _v, Menu * menu_) { v = _v; menu = menu_; }
+ void MouseEnterCallback(ui::Button * sender)
+ {
+ if(!ui::Engine::Ref().GetMouseButton())
+ v->c->SetActiveMenu(menu);
+ }
+ void ActionCallback(ui::Button * sender)
+ {
+ 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;
+}
+
+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
+ }
+ else if(sender->GetActiveTool(1) == tool)
+ {
+ toolButtons[i]->SetSelectionState(1); //Secondary
+ }
+ else if(sender->GetActiveTool(2) == tool)
+ {
+ toolButtons[i]->SetSelectionState(2); //Tertiary
+ }
+ 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);
+ }
+
+}
+
+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, 200, 40, 100));
+ 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(200, 40, 40, 100));
+ else
+ downVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0));
+
+ 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.BackgroundInactive = (ui::Colour(0, 0, 0));
+ downVoteButton->Enabled = false;
+ upVoteButton->Appearance.BackgroundInactive = (ui::Colour(0, 0, 0));
+ 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.BackgroundInactive = (ui::Colour(0, 0, 0));
+ downVoteButton->Enabled = false;
+ upVoteButton->Appearance.BackgroundInactive = (ui::Colour(0, 0, 0));
+ 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->NormaliseBlockCoord(c->PointTranslate(ui::Point(x, y)));
+ if(selectPoint1.X!=-1)
+ selectPoint2 = c->NormaliseBlockCoord(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)
+ button = BUTTON_MIDDLE;
+ if(selectMode!=SelectNone)
+ {
+ if(button==BUTTON_LEFT)
+ {
+ selectPoint1 = c->NormaliseBlockCoord(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 = 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)
+ {
+ Thumbnail * tempThumb = placeSaveThumb;
+ if(tempThumb)
+ {
+ int thumbX = selectPoint2.X - (tempThumb->Size.X/2);
+ int thumbY = selectPoint2.Y - (tempThumb->Size.Y/2);
+
+ if(thumbX<0)
+ thumbX = 0;
+ if(thumbX+(tempThumb->Size.X)>=XRES)
+ thumbX = XRES-tempThumb->Size.X;
+
+ if(thumbY<0)
+ thumbY = 0;
+ if(thumbY+(tempThumb->Size.Y)>=YRES)
+ thumbY = YRES-tempThumb->Size.Y;
+
+ 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(x2-x1>0 && y2-y1>0)
+ {
+ 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
+ {
+ 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();
+ 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 = ui::Point(-1, -1);
+ selectPoint1 = selectPoint2;
+ }
+ break;
+ case 'l':
+ c->LoadStamp();
+ selectPoint2 = ui::Point(-1, -1);
+ 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(!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);
+ }
+ };
+
+ 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;
+ }
+ 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();
+ 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)
+ {
+ activeBrush->RenderFill(ren, finalCurrentMouse);
+ }
+ else
+ {
+ 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)
+ {
+ Thumbnail * tempThumb = placeSaveThumb;
+ if(tempThumb && selectPoint2.X!=-1)
+ {
+ int thumbX = selectPoint2.X - (tempThumb->Size.X/2);
+ int thumbY = selectPoint2.Y - (tempThumb->Size.Y/2);
+
+ ui::Point thumbPos = c->NormaliseBlockCoord(ui::Point(thumbX, thumbY));
+
+ if(thumbPos.X<0)
+ thumbPos.X = 0;
+ if(thumbPos.X+(tempThumb->Size.X)>=XRES)
+ thumbPos.X = XRES-tempThumb->Size.X;
+
+ if(thumbPos.Y<0)
+ thumbPos.Y = 0;
+ if(thumbPos.Y+(tempThumb->Size.Y)>=YRES)
+ thumbPos.Y = YRES-tempThumb->Size.Y;
+
+ ren->draw_image(tempThumb->Data, thumbPos.X, thumbPos.Y, tempThumb->Size.X, tempThumb->Size.Y, 128);
+
+ ren->xor_rect(thumbPos.X, thumbPos.Y, tempThumb->Size.X, tempThumb->Size.Y);
+ }
+ }
+ 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, XRES, YRES-y2, 0, 0, 0, 100);
+
+ ren->fillrect(0, y1, x1, (y2-y1), 0, 0, 0, 100);
+ ren->fillrect(x2, y1, XRES-x2, (y2-y1), 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 (std::abs(sample.Gravity) > 0.1f)
+ 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/game/GameView.h b/src/game/GameView.h
new file mode 100644
index 0000000..e17279f
--- /dev/null
+++ b/src/game/GameView.h
@@ -0,0 +1,187 @@
+#ifndef GAMEVIEW_H
+#define GAMEVIEW_H
+
+#include <vector>
+#include <queue>
+#include <deque>
+#include <string>
+#include "GameController.h"
+#include "GameModel.h"
+#include "interface/Window.h"
+#include "interface/Point.h"
+#include "interface/Button.h"
+#include "interface/Slider.h"
+#include "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;
+
+ 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;
+
+ Thumbnail * 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);
+ 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/game/Menu.h b/src/game/Menu.h
new file mode 100644
index 0000000..261193e
--- /dev/null
+++ b/src/game/Menu.h
@@ -0,0 +1,58 @@
+/*
+ * Menu.h
+ *
+ * Created on: Jan 22, 2012
+ * Author: Simon
+ */
+
+#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/game/Notification.h b/src/game/Notification.h
new file mode 100644
index 0000000..4c64dea
--- /dev/null
+++ b/src/game/Notification.h
@@ -0,0 +1,23 @@
+/*
+ * Notification.h
+ *
+ * Created on: Jun 20, 2012
+ * Author: Simon
+ */
+
+#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/game/PropertyTool.cpp b/src/game/PropertyTool.cpp
new file mode 100644
index 0000000..ee9f9eb
--- /dev/null
+++ b/src/game/PropertyTool.cpp
@@ -0,0 +1,235 @@
+#include <iostream>
+#include <sstream>
+#include "Style.h"
+#include "simulation/Simulation.h"
+#include "Tool.h"
+#include "interface/Window.h"
+#include "interface/Button.h"
+#include "interface/Label.h"
+#include "interface/Textbox.h"
+#include "interface/DropDown.h"
+#include "interface/Keys.h"
+#include "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/game/QuickOption.h b/src/game/QuickOption.h
new file mode 100644
index 0000000..4bf27ff
--- /dev/null
+++ b/src/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/game/QuickOptions.h b/src/game/QuickOptions.h
new file mode 100644
index 0000000..7c31f9c
--- /dev/null
+++ b/src/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/game/RenderPreset.h b/src/game/RenderPreset.h
new file mode 100644
index 0000000..9cc9f4c
--- /dev/null
+++ b/src/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/game/SampleTool.cpp b/src/game/SampleTool.cpp
new file mode 100644
index 0000000..296167b
--- /dev/null
+++ b/src/game/SampleTool.cpp
@@ -0,0 +1,67 @@
+#include <iostream>
+#include "graphics/Graphics.h"
+#include "Tool.h"
+#include "GameModel.h"
+#include "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()->GetPixel(position.X, position.Y);
+ gameModel->SetColourSelectorColour(ui::Colour(PIXR(colour), PIXG(colour), PIXB(colour), 255));
+ }
+ else
+ {
+ int particleType = 0;
+ int particleCtype = 0;
+ 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;
+ }
+ else 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;
+ }
+
+ 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/game/SignTool.cpp b/src/game/SignTool.cpp
new file mode 100644
index 0000000..af267af
--- /dev/null
+++ b/src/game/SignTool.cpp
@@ -0,0 +1,289 @@
+#include <iostream>
+#include "Style.h"
+#include "simulation/Simulation.h"
+#include "Tool.h"
+#include "interface/Window.h"
+#include "interface/Button.h"
+#include "interface/Label.h"
+#include "interface/Textbox.h"
+#include "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();
+ }
+ }
+ };
+
+ 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->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;
+ Graphics * g = ui::Engine::Ref().g;
+ char buff[256]; //Buffer
+ currentSign.pos(x, y, w, h);
+ g->clearrect(x, y, w, h);
+ g->drawrect(x, y, w, h, 192, 192, 192, 255);
+
+ //Displaying special information
+ if (currentSign.text == "{p}")
+ {
+ float pressure = 0.0f;
+ if (currentSign.x>=0 && currentSign.x<XRES && currentSign.y>=0 && currentSign.y<YRES)
+ pressure = sim->pv[currentSign.y/CELL][currentSign.x/CELL];
+ sprintf(buff, "Pressure: %3.2f", pressure); //...pressure
+ g->drawtext(x+3, y+3, buff, 255, 255, 255, 255);
+ }
+ else if (currentSign.text == "{t}")
+ {
+ if (currentSign.x>=0 && currentSign.x<XRES && currentSign.y>=0 && currentSign.y<YRES && sim->pmap[currentSign.y][currentSign.x])
+ sprintf(buff, "Temp: %4.2f", sim->parts[sim->pmap[currentSign.y][currentSign.x]>>8].temp-273.15); //...temperature
+ else
+ sprintf(buff, "Temp: 0.00"); //...temperature
+ g->drawtext(x+3, y+3, buff, 255, 255, 255, 255);
+ }
+ else if (sregexp(currentSign.text.c_str(), "^{[c|t]:[0-9]*|.*}$")==0)
+ {
+ int sldr, startm;
+ memset(buff, 0, sizeof(buff));
+ for (sldr=3; currentSign.text[sldr-1] != '|'; sldr++)
+ startm = sldr + 1;
+ sldr = startm;
+ while (currentSign.text[sldr] != '}')
+ {
+ buff[sldr - startm] = currentSign.text[sldr];
+ sldr++;
+ }
+ g->drawtext(x+3, y+3, buff, 0, 191, 255, 255);
+ }
+ else
+ {
+ g->drawtext(x+3, y+3, currentSign.text, 255, 255, 255, 255);
+ }
+ }
+ 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(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/game/Tool.cpp b/src/game/Tool.cpp
new file mode 100644
index 0000000..7fa8e15
--- /dev/null
+++ b/src/game/Tool.cpp
@@ -0,0 +1,216 @@
+/*
+ * Tool.cpp
+ *
+ * Created on: Jun 24, 2012
+ * Author: Simon
+ */
+
+#include <string>
+#include "Tool.h"
+#include "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) {
+ 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/game/Tool.h b/src/game/Tool.h
new file mode 100644
index 0000000..22898c7
--- /dev/null
+++ b/src/game/Tool.h
@@ -0,0 +1,190 @@
+/*
+ * Tool.h
+ *
+ * Created on: Jan 22, 2012
+ * Author: Simon
+ */
+
+#ifndef TOOL_H_
+#define TOOL_H_
+
+#include <iostream>
+
+using namespace std;
+
+#include "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/game/ToolButton.cpp b/src/game/ToolButton.cpp
new file mode 100644
index 0000000..aa31b3d
--- /dev/null
+++ b/src/game/ToolButton.cpp
@@ -0,0 +1,99 @@
+/*
+ * ToolButton.cpp
+ *
+ * Created on: Jan 30, 2012
+ * Author: Simon
+ */
+
+#include "ToolButton.h"
+#include "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)
+ {
+ if(button == BUTTON_LEFT)
+ SetSelectionState(0);
+ if(button == BUTTON_RIGHT)
+ SetSelectionState(1);
+ if(button == BUTTON_MIDDLE)
+ SetSelectionState(2);
+ DoAction();
+ }
+ isButtonDown = false;
+}
+
+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() {
+ // TODO Auto-generated destructor stub
+}
+
diff --git a/src/game/ToolButton.h b/src/game/ToolButton.h
new file mode 100644
index 0000000..b311d0b
--- /dev/null
+++ b/src/game/ToolButton.h
@@ -0,0 +1,25 @@
+/*
+ * ToolButton.h
+ *
+ * Created on: Jan 30, 2012
+ * Author: Simon
+ */
+
+#ifndef TOOLBUTTON_H_
+#define TOOLBUTTON_H_
+
+#include "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/game/TriangleBrush.h b/src/game/TriangleBrush.h
new file mode 100644
index 0000000..7d537bd
--- /dev/null
+++ b/src/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_ */