diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-22 14:14:17 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-22 14:14:17 (GMT) |
| commit | 9abe51526cac2634af0541c3de69834dd30e9f78 (patch) | |
| tree | 6ae4deadfe00a83094b9d288d8c11d8ce823577a /src/gui/game/GameView.cpp | |
| parent | 2c311b9a36a88fadd96f3d39acb1ab2590835d81 (diff) | |
| download | powder-9abe51526cac2634af0541c3de69834dd30e9f78.zip powder-9abe51526cac2634af0541c3de69834dd30e9f78.tar.gz | |
Move all GUI source files into gui/
Diffstat (limited to 'src/gui/game/GameView.cpp')
| -rw-r--r-- | src/gui/game/GameView.cpp | 2140 |
1 files changed, 2140 insertions, 0 deletions
diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp new file mode 100644 index 0000000..b7db87f --- /dev/null +++ b/src/gui/game/GameView.cpp @@ -0,0 +1,2140 @@ +#include <sstream> +#include <iomanip> + +#include "Config.h" +#include "Style.h" +#include "GameView.h" +#include "graphics/Graphics.h" +#include "gui/interface/Window.h" +#include "gui/interface/Button.h" +#include "gui/interface/Colour.h" +#include "gui/interface/Keys.h" +#include "gui/interface/Slider.h" +#include "search/Thumbnail.h" +#include "simulation/SaveRenderer.h" +#include "simulation/SimulationData.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), + buttonTipShow(0), + toolTipPosition(-1, -1), + shiftBehaviour(false), + ctrlBehaviour(false), + altBehaviour(false), + showHud(true), + showDebug(false), + introText(2048), + introTextMessage(introTextData), + wallBrush(false), + doScreenshot(false), + recording(false), + screenshotIndex(0), + recordingIndex(0), + toolTipPresence(0), + currentSaveType(0), + lastLogEntry(0.0f), + lastMenu(NULL) +{ + + int currentX = 1; + //Set up UI + class SearchAction : public ui::ButtonAction + { + GameView * v; + public: + SearchAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalBrowse(); + else + v->c->OpenSearch(); + } + }; + + scrollBar = new ui::Button(ui::Point(0,YRES+21), ui::Point(XRES, 2), ""); + scrollBar->Appearance.BackgroundInactive = ui::Colour(255, 255, 255); + scrollBar->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + scrollBar->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(scrollBar); + + searchButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(17, 15), "", "Find & open a simulation"); //Open + searchButton->SetIcon(IconOpen); + currentX+=18; + searchButton->SetTogglable(false); + searchButton->SetActionCallback(new SearchAction(this)); + AddComponent(searchButton); + + class ReloadAction : public ui::ButtonAction + { + GameView * v; + public: + ReloadAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->ReloadSim(); + } + void AltActionCallback(ui::Button * sender) + { + v->c->OpenSavePreview(); + } + }; + reloadButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(17, 15), "", "Reload the simulation"); + reloadButton->SetIcon(IconReload); + reloadButton->Appearance.Margin.Left+=2; + currentX+=18; + reloadButton->SetActionCallback(new ReloadAction(this)); + AddComponent(reloadButton); + + class SaveSimulationAction : public SplitButtonAction + { + GameView * v; + public: + SaveSimulationAction(GameView * _v) { v = _v; } + void ActionCallbackRight(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalSaveWindow(false); + else + v->c->OpenSaveWindow(); + } + void ActionCallbackLeft(ui::Button * sender) + { + if(v->CtrlBehaviour()) + v->c->OpenLocalSaveWindow(true); + else + v->c->SaveAsCurrent(); + } + }; + saveSimulationButton = new SplitButton(ui::Point(currentX, Size.Y-16), ui::Point(150, 15), "[untitled simulation]", "Save game as current name", "Save game as new name", 19); + saveSimulationButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + saveSimulationButton->SetIcon(IconSave); + currentX+=151; + ((SplitButton*)saveSimulationButton)->SetSplitActionCallback(new SaveSimulationAction(this)); + AddComponent(saveSimulationButton); + + class UpVoteAction : public ui::ButtonAction + { + GameView * v; + public: + UpVoteAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->Vote(1); + } + }; + upVoteButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(15, 15), "", "Like this save"); + upVoteButton->SetIcon(IconVoteUp); + upVoteButton->Appearance.Margin.Top+=2; + upVoteButton->Appearance.Margin.Left+=2; + currentX+=14; + upVoteButton->SetActionCallback(new UpVoteAction(this)); + AddComponent(upVoteButton); + + class DownVoteAction : public ui::ButtonAction + { + GameView * v; + public: + DownVoteAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->Vote(-1); + } + }; + downVoteButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(15, 15), "", "Dislike this save"); + downVoteButton->SetIcon(IconVoteDown); + downVoteButton->Appearance.Margin.Bottom+=2; + downVoteButton->Appearance.Margin.Left+=2; + currentX+=16; + downVoteButton->SetActionCallback(new DownVoteAction(this)); + AddComponent(downVoteButton); + + class TagSimulationAction : public ui::ButtonAction + { + GameView * v; + public: + TagSimulationAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenTags(); + } + }; + tagSimulationButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(251, 15), "[no tags set]", "Add simulation tags"); + tagSimulationButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tagSimulationButton->SetIcon(IconTag); + currentX+=252; + tagSimulationButton->SetActionCallback(new TagSimulationAction(this)); + AddComponent(tagSimulationButton); + + class ClearSimAction : public ui::ButtonAction + { + GameView * v; + public: + ClearSimAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->ClearSim(); + } + }; + clearSimButton = new ui::Button(ui::Point(Size.X-159, Size.Y-16), ui::Point(17, 15), "", "Erase everything"); + clearSimButton->SetIcon(IconNew); + clearSimButton->Appearance.Margin.Left+=2; + clearSimButton->SetActionCallback(new ClearSimAction(this)); + AddComponent(clearSimButton); + + class LoginAction : public ui::ButtonAction + { + GameView * v; + public: + LoginAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenLogin(); + } + }; + loginButton = new ui::Button(ui::Point(Size.X-141, Size.Y-16), ui::Point(92, 15), "[sign in]", "Sign into simulation server"); + loginButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + loginButton->SetIcon(IconLogin); + loginButton->SetActionCallback(new LoginAction(this)); + AddComponent(loginButton); + + class SimulationOptionAction : public ui::ButtonAction + { + GameView * v; + public: + SimulationOptionAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenOptions(); + } + }; + simulationOptionButton = new ui::Button(ui::Point(Size.X-48, Size.Y-16), ui::Point(15, 15), "", "Simulation options"); + simulationOptionButton->SetIcon(IconSimulationSettings); + simulationOptionButton->Appearance.Margin.Left+=2; + simulationOptionButton->SetActionCallback(new SimulationOptionAction(this)); + AddComponent(simulationOptionButton); + + class DisplayModeAction : public ui::ButtonAction + { + GameView * v; + public: + DisplayModeAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenRenderOptions(); + } + }; + displayModeButton = new ui::Button(ui::Point(Size.X-32, Size.Y-16), ui::Point(15, 15), "", "Renderer options"); + displayModeButton->SetIcon(IconRenderSettings); + displayModeButton->Appearance.Margin.Left+=2; + displayModeButton->SetActionCallback(new DisplayModeAction(this)); + AddComponent(displayModeButton); + + class PauseAction : public ui::ButtonAction + { + GameView * v; + public: + PauseAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->SetPaused(sender->GetToggleState()); + } + }; + pauseButton = new ui::Button(ui::Point(Size.X-16, Size.Y-16), ui::Point(15, 15), "", "Pause/Resume the simulation"); //Pause + pauseButton->SetIcon(IconPause); + pauseButton->SetTogglable(true); + pauseButton->SetActionCallback(new PauseAction(this)); + AddComponent(pauseButton); + + class ElementSearchAction : public ui::ButtonAction + { + GameView * v; + public: + ElementSearchAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenElementSearch(); + } + }; + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, YRES+MENUSIZE-32), ui::Point(15, 15), "\xE5", "Search for elements"); + tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetActionCallback(new ElementSearchAction(this)); + AddComponent(tempButton); + + class ColourPickerAction : public ui::ButtonAction + { + GameView * v; + public: + ColourPickerAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenColourPicker(); + } + }; + colourPicker = new ui::Button(ui::Point((XRES/2)-8, YRES+1), ui::Point(16, 16), "", "Pick Colour"); + colourPicker->SetActionCallback(new ColourPickerAction(this)); +} + +GameView::~GameView() +{ + if(!colourPicker->GetParentWindow()) + delete colourPicker; + + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + if(!button->GetParentWindow()) + { + delete button; + } + + } + + if(placeSaveThumb) + delete placeSaveThumb; +} + +class GameView::MenuAction: public ui::ButtonAction +{ + GameView * v; +public: + Menu * menu; + bool needsClick; + MenuAction(GameView * _v, Menu * menu_) + { + v = _v; + menu = menu_; + if (v->c->GetMenuList()[SC_DECO] == menu) + needsClick = true; + else + needsClick = false; + } + void MouseEnterCallback(ui::Button * sender) + { + if(!needsClick && !ui::Engine::Ref().GetMouseButton()) + v->c->SetActiveMenu(menu); + } + void ActionCallback(ui::Button * sender) + { + if (needsClick) + v->c->SetActiveMenu(menu); + else + MouseEnterCallback(sender); + } +}; + +class GameView::OptionAction: public ui::ButtonAction +{ + QuickOption * option; +public: + OptionAction(QuickOption * _option) { option = _option; } + void ActionCallback(ui::Button * sender) + { + option->Perform(); + } +}; + +class GameView::OptionListener: public QuickOptionListener +{ + ui::Button * button; +public: + OptionListener(ui::Button * _button) { button = _button; } + virtual void OnValueChanged(QuickOption * option) + { + switch(option->GetType()) + { + case QuickOption::Toggle: + button->SetTogglable(true); + button->SetToggleState(option->GetToggle()); + } + } +}; + +class GameView::ToolAction: public ui::ButtonAction +{ + GameView * v; +public: + Tool * tool; + ToolAction(GameView * _v, Tool * tool_) { v = _v; tool = tool_; } + void ActionCallback(ui::Button * sender_) + { + ToolButton *sender = (ToolButton*)sender_; + if(sender->GetSelectionState() >= 0 && sender->GetSelectionState() <= 2) + v->c->SetActiveTool(sender->GetSelectionState(), tool); + } +}; + +void GameView::NotifyQuickOptionsChanged(GameModel * sender) +{ + for(int i = 0; i < quickOptionButtons.size(); i++) + { + RemoveComponent(quickOptionButtons[i]); + delete quickOptionButtons[i]; + } + + int currentY = 1; + vector<QuickOption*> optionList = sender->GetQuickOptions(); + for(vector<QuickOption*>::iterator iter = optionList.begin(), end = optionList.end(); iter != end; ++iter) + { + QuickOption * option = *iter; + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, currentY), ui::Point(15, 15), option->GetIcon(), option->GetDescription()); + //tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetTogglable(true); + tempButton->SetActionCallback(new OptionAction(option)); + option->AddListener(new OptionListener(tempButton)); + AddComponent(tempButton); + + quickOptionButtons.push_back(tempButton); + currentY += 16; + } +} + +void GameView::NotifyMenuListChanged(GameModel * sender) +{ + int currentY = YRES+MENUSIZE-48;//-(sender->GetMenuList().size()*16); + for(int i = 0; i < menuButtons.size(); i++) + { + RemoveComponent(menuButtons[i]); + delete menuButtons[i]; + } + menuButtons.clear(); + for(int i = 0; i < toolButtons.size(); i++) + { + RemoveComponent(toolButtons[i]); + delete toolButtons[i]; + } + toolButtons.clear(); + vector<Menu*> menuList = sender->GetMenuList(); + for(vector<Menu*>::reverse_iterator iter = menuList.rbegin(), end = menuList.rend(); iter != end; ++iter) + { + std::string tempString = ""; + Menu * item = *iter; + tempString += item->GetIcon(); + ui::Button * tempButton = new ui::Button(ui::Point(XRES+BARSIZE-16, currentY), ui::Point(15, 15), tempString, item->GetDescription()); + tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); + tempButton->SetTogglable(true); + tempButton->SetActionCallback(new MenuAction(this, item)); + currentY-=16; + AddComponent(tempButton); + menuButtons.push_back(tempButton); + } +} + +void GameView::SetSample(SimulationSample sample) +{ + this->sample = sample; +} + +void GameView::SetHudEnable(bool hudState) +{ + showHud = hudState; +} + +ui::Point GameView::GetMousePosition() +{ + return mousePosition; +} + +void GameView::NotifyActiveToolsChanged(GameModel * sender) +{ + for(int i = 0; i < toolButtons.size(); i++) + { + Tool * tool = ((ToolAction*)toolButtons[i]->GetActionCallback())->tool; + if(sender->GetActiveTool(0) == tool) + { + toolButtons[i]->SetSelectionState(0); //Primary + c->ActiveToolChanged(0, tool); + } + else if(sender->GetActiveTool(1) == tool) + { + toolButtons[i]->SetSelectionState(1); //Secondary + c->ActiveToolChanged(1, tool); + } + else if(sender->GetActiveTool(2) == tool) + { + toolButtons[i]->SetSelectionState(2); //Tertiary + c->ActiveToolChanged(2, tool); + } + else + { + toolButtons[i]->SetSelectionState(-1); + } + } +} + +void GameView::NotifyLastToolChanged(GameModel * sender) +{ + if(sender->GetLastTool() && sender->GetLastTool()->GetResolution() == CELL) + { + wallBrush = true; + } + else + { + wallBrush = false; + } +} + +void GameView::NotifyToolListChanged(GameModel * sender) +{ + //int currentY = YRES+MENUSIZE-36; + lastOffset = 0; + int currentX = XRES+BARSIZE-56; + int totalColour; + for(int i = 0; i < menuButtons.size(); i++) + { + if(((MenuAction*)menuButtons[i]->GetActionCallback())->menu==sender->GetActiveMenu()) + { + menuButtons[i]->SetToggleState(true); + } + else + { + menuButtons[i]->SetToggleState(false); + } + } + for(int i = 0; i < toolButtons.size(); i++) + { + RemoveComponent(toolButtons[i]); + delete toolButtons[i]; + } + toolButtons.clear(); + vector<Tool*> toolList = sender->GetToolList(); + for(int i = 0; i < toolList.size(); i++) + { + //ToolButton * tempButton = new ToolButton(ui::Point(XRES+1, currentY), ui::Point(28, 15), toolList[i]->GetName()); + VideoBuffer * tempTexture = toolList[i]->GetTexture(26, 14); + ToolButton * tempButton; + + if(tempTexture) + tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), "", toolList[i]->GetDescription()); + else + tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), toolList[i]->GetName(), toolList[i]->GetDescription()); + + //currentY -= 17; + currentX -= 31; + tempButton->SetActionCallback(new ToolAction(this, toolList[i])); + + tempButton->Appearance.SetTexture(tempTexture); + if(tempTexture) + delete tempTexture; + + tempButton->Appearance.BackgroundInactive = ui::Colour(toolList[i]->colRed, toolList[i]->colGreen, toolList[i]->colBlue); + + if(sender->GetActiveTool(0) == toolList[i]) + { + tempButton->SetSelectionState(0); //Primary + } + else if(sender->GetActiveTool(1) == toolList[i]) + { + tempButton->SetSelectionState(1); //Secondary + } + else if(sender->GetActiveTool(2) == toolList[i]) + { + tempButton->SetSelectionState(2); //Tertiary + } + + tempButton->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + tempButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(tempButton); + toolButtons.push_back(tempButton); + } + if (sender->GetActiveMenu() != sender->GetMenuList()[SC_DECO]) + lastMenu = sender->GetActiveMenu(); +} + +void GameView::NotifyColourSelectorVisibilityChanged(GameModel * sender) +{ + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + RemoveComponent(button); + button->SetParentWindow(NULL); + } + + RemoveComponent(colourPicker); + colourPicker->SetParentWindow(NULL); + + if(sender->GetColourSelectorVisibility()) + { + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + AddComponent(button); + } + AddComponent(colourPicker); + } +} + +void GameView::NotifyColourPresetsChanged(GameModel * sender) +{ + class ColourPresetAction: public ui::ButtonAction + { + GameView * v; + public: + int preset; + ColourPresetAction(GameView * _v, int preset) : preset(preset) { v = _v; } + void ActionCallback(ui::Button * sender_) + { + ToolButton *sender = (ToolButton*)sender_; + if(sender->GetSelectionState() == 0) + { + v->c->SetActiveColourPreset(preset); + v->c->SetColour(sender->Appearance.BackgroundInactive); + } + else + sender->SetSelectionState(0); + } + }; + + + for(std::vector<ToolButton*>::iterator iter = colourPresets.begin(), end = colourPresets.end(); iter != end; ++iter) + { + ToolButton * button = *iter; + RemoveComponent(button); + delete button; + } + colourPresets.clear(); + + int currentX = 5; + std::vector<ui::Colour> colours = sender->GetColourPresets(); + int i = 0; + for(std::vector<ui::Colour>::iterator iter = colours.begin(), end = colours.end(); iter != end; ++iter) + { + ToolButton * tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), ""); + tempButton->Appearance.BackgroundInactive = *iter; + tempButton->SetActionCallback(new ColourPresetAction(this, i)); + + currentX += 31; + + if(sender->GetColourSelectorVisibility()) + AddComponent(tempButton); + colourPresets.push_back(tempButton); + + i++; + } + NotifyColourActivePresetChanged(sender); +} + +void GameView::NotifyColourActivePresetChanged(GameModel * sender) +{ + for(int i = 0; i < colourPresets.size(); i++) + { + if(sender->GetActiveColourPreset() == i) + { + colourPresets[i]->SetSelectionState(0); //Primary + } + else + { + colourPresets[i]->SetSelectionState(-1); + } + } +} + +void GameView::NotifyColourSelectorColourChanged(GameModel * sender) +{ + colourPicker->Appearance.BackgroundInactive = sender->GetColourSelectorColour(); + colourPicker->Appearance.BackgroundHover = sender->GetColourSelectorColour(); +} + +void GameView::NotifyRendererChanged(GameModel * sender) +{ + ren = sender->GetRenderer(); +} + +void GameView::NotifySimulationChanged(GameModel * sender) +{ + +} +void GameView::NotifyUserChanged(GameModel * sender) +{ + if(!sender->GetUser().ID) + { + loginButton->SetText("[sign in]"); + } + else + { + loginButton->SetText(sender->GetUser().Username); + } + NotifySaveChanged(sender); +} + + +void GameView::NotifyPausedChanged(GameModel * sender) +{ + pauseButton->SetToggleState(sender->GetPaused()); +} + +void GameView::NotifyToolTipChanged(GameModel * sender) +{ + toolTip = sender->GetToolTip(); +} + +void GameView::NotifyInfoTipChanged(GameModel * sender) +{ + infoTip = sender->GetInfoTip(); + infoTipPresence = 120; +} + +void GameView::NotifySaveChanged(GameModel * sender) +{ + if(sender->GetSave()) + { + if(introText > 50) + introText = 50; + + saveSimulationButton->SetText(sender->GetSave()->GetName()); + if(sender->GetSave()->GetUserName() == sender->GetUser().Username) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + else + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + reloadButton->Enabled = true; + upVoteButton->Enabled = (sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==0); + if(sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==1) + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 108, 10, 255)); + else + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + + downVoteButton->Enabled = upVoteButton->Enabled; + if(sender->GetSave()->GetID() && sender->GetUser().ID && sender->GetSave()->GetVote()==-1) + downVoteButton->Appearance.BackgroundDisabled = (ui::Colour(108, 0, 10, 255)); + else + downVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + + if (sender->GetUser().ID) + { + upVoteButton->Appearance.BorderDisabled = upVoteButton->Appearance.BorderInactive; + downVoteButton->Appearance.BorderDisabled = downVoteButton->Appearance.BorderInactive; + } + else + { + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + } + + tagSimulationButton->Enabled = (sender->GetSave()->GetID() && sender->GetUser().ID); + if(sender->GetSave()->GetID()) + { + std::stringstream tagsStream; + std::vector<string> tags = sender->GetSave()->GetTags(); + if(tags.size()) + { + for(int i = 0; i < tags.size(); i++) + { + tagsStream << sender->GetSave()->GetTags()[i]; + if(i < tags.size()-1) + tagsStream << " "; + } + tagSimulationButton->SetText(tagsStream.str()); + } + else + { + tagSimulationButton->SetText("[no tags set]"); + } + } + else + { + tagSimulationButton->SetText("[no tags set]"); + } + currentSaveType = 1; + } + else if (sender->GetSaveFile()) + { + if (ctrlBehaviour) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + else + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + saveSimulationButton->SetText(sender->GetSaveFile()->GetDisplayName()); + reloadButton->Enabled = true; + upVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + downVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100); + tagSimulationButton->Enabled = false; + tagSimulationButton->SetText("[no tags set]"); + currentSaveType = 2; + } + else + { + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + saveSimulationButton->SetText("[untitled simulation]"); + reloadButton->Enabled = false; + upVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + upVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100), + downVoteButton->Enabled = false; + upVoteButton->Appearance.BackgroundDisabled = (ui::Colour(0, 0, 0)); + downVoteButton->Appearance.BorderDisabled = ui::Colour(100, 100, 100), + tagSimulationButton->Enabled = false; + tagSimulationButton->SetText("[no tags set]"); + currentSaveType = 0; + } +} + +void GameView::NotifyBrushChanged(GameModel * sender) +{ + activeBrush = sender->GetBrush(); +} + +void GameView::screenshot() +{ + doScreenshot = true; +} + +void GameView::record() +{ + if(recording) + { + recording = false; + } + else + { + class RecordingConfirmation: public ConfirmDialogueCallback { + public: + GameView * v; + RecordingConfirmation(GameView * v): v(v) {} + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + v->recording = true; + } + } + virtual ~RecordingConfirmation() { } + }; + new ConfirmPrompt("Recording", "You're about to start recording all drawn frames. This may use a load of hard disk space.", new RecordingConfirmation(this)); + } +} + +void GameView::setToolButtonOffset(int offset) +{ + int offset_ = offset; + offset = offset-lastOffset; + lastOffset = offset_; + + for(vector<ToolButton*>::iterator iter = toolButtons.begin(), end = toolButtons.end(); iter!=end; ++iter) + { + ToolButton * button = *iter; + button->Position.X -= offset; + if(button->Position.X <= 0 || (button->Position.X+button->Size.X) > XRES-2) { + button->Visible = false; + } else { + button->Visible = true; + } + } +} + +void GameView::OnMouseMove(int x, int y, int dx, int dy) +{ + mousePosition = c->PointTranslate(ui::Point(x, y)); + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + selectPoint1 = c->PointTranslate(ui::Point(x, y)); + if(selectPoint1.X!=-1) + selectPoint2 = c->PointTranslate(ui::Point(x, y)); + return; + } + currentMouse = ui::Point(x, y); + if(isMouseDown && drawMode == DrawPoints) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x-dx, y-dy)))); + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } +} + +void GameView::OnMouseDown(int x, int y, unsigned button) +{ + if(altBehaviour && !shiftBehaviour && !ctrlBehaviour) + button = BUTTON_MIDDLE; + if(selectMode!=SelectNone) + { + if(button==BUTTON_LEFT) + { + selectPoint1 = c->PointTranslate(ui::Point(x, y)); + selectPoint2 = selectPoint1; + } + return; + } + if(currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES && !(zoomEnabled && !zoomCursorFixed)) + { + if(button == BUTTON_LEFT) + toolIndex = 0; + if(button == BUTTON_RIGHT) + toolIndex = 1; + if(button == BUTTON_MIDDLE) + toolIndex = 2; + isMouseDown = true; + if(!pointQueue.size()) + c->HistorySnapshot(); + if(drawMode == DrawRect || drawMode == DrawLine) + { + drawPoint1 = c->PointTranslate(ui::Point(x, y)); + } + if(drawMode == DrawPoints) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } + } +} + +void GameView::OnMouseUp(int x, int y, unsigned button) +{ + if(selectMode!=SelectNone) + { + if(button==BUTTON_LEFT) + { + if(selectMode==PlaceSave) + { + if(placeSaveThumb) + { + int thumbX = selectPoint2.X - (placeSaveThumb->Width/2); + int thumbY = selectPoint2.Y - (placeSaveThumb->Height/2); + + if(thumbX<0) + thumbX = 0; + if(thumbX+(placeSaveThumb->Width)>=XRES) + thumbX = XRES-placeSaveThumb->Width; + + if(thumbY<0) + thumbY = 0; + if(thumbY+(placeSaveThumb->Height)>=YRES) + thumbY = YRES-placeSaveThumb->Height; + + c->PlaceSave(ui::Point(thumbX, thumbY)); + } + } + else + { + int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X; + int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y; + int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X; + int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y; + if(selectMode==SelectCopy) + c->CopyRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + else if(selectMode==SelectCut) + c->CutRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + else if(selectMode==SelectStamp) + c->StampRegion(ui::Point(x1, y1), ui::Point(x2, y2)); + } + } + currentMouse = ui::Point(x, y); + selectMode = SelectNone; + return; + } + + if(zoomEnabled && !zoomCursorFixed) + zoomCursorFixed = true; + else + { + if(isMouseDown) + { + isMouseDown = false; + if(drawMode == DrawRect || drawMode == DrawLine) + { + ui::Point finalDrawPoint2(0, 0); + drawPoint2 = c->PointTranslate(ui::Point(x, y)); + finalDrawPoint2 = drawPoint2; + + if(drawSnap && drawMode == DrawLine) + { + finalDrawPoint2 = lineSnapCoords(c->PointTranslate(drawPoint1), drawPoint2); + } + + if(drawSnap && drawMode == DrawRect) + { + finalDrawPoint2 = rectSnapCoords(c->PointTranslate(drawPoint1), drawPoint2); + } + + if(drawMode == DrawRect) + { + c->DrawRect(toolIndex, c->PointTranslate(drawPoint1), finalDrawPoint2); + } + if(drawMode == DrawLine) + { + c->DrawLine(toolIndex, c->PointTranslate(drawPoint1), finalDrawPoint2); + } + } + if(drawMode == DrawPoints) + { + c->ToolClick(toolIndex, c->PointTranslate(ui::Point(x, y))); + //pointQueue.push(ui::Point(x, y)); + } + if(drawModeReset) + { + drawModeReset = false; + drawMode = DrawPoints; + } + } + } +} + +void GameView::ExitPrompt() +{ + class ExitConfirmation: public ConfirmDialogueCallback { + public: + ExitConfirmation() {} + virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) { + if (result == ConfirmPrompt::ResultOkay) + { + ui::Engine::Ref().Exit(); + } + } + virtual ~ExitConfirmation() { } + }; + new ConfirmPrompt("You are about to quit", "Are you sure you want to exit the game?", new ExitConfirmation()); +} + +void GameView::ToolTip(ui::Component * sender, ui::Point mousePosition, std::string toolTip) +{ + if(sender->Position.Y > Size.Y-17) + { + buttonTip = toolTip; + buttonTipShow = 120; + } + else if(sender->Position.X > Size.X-BARSIZE)// < Size.Y-(quickOptionButtons.size()+1)*16) + { + this->toolTip = toolTip; + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), sender->Position.Y+3); + if(toolTipPosition.Y+10 > Size.Y-MENUSIZE) + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), Size.Y-MENUSIZE-10); + toolTipPresence = 120; + } + else + { + this->toolTip = toolTip; + toolTipPosition = ui::Point(Size.X-27-Graphics::textwidth((char*)toolTip.c_str()), Size.Y-MENUSIZE-10); + toolTipPresence = 160; + } +} + +void GameView::OnMouseWheel(int x, int y, int d) +{ + if(!d) + return; + if(selectMode!=SelectNone) + { + return; + } + if(zoomEnabled && !zoomCursorFixed) + { + c->AdjustZoomSize(d); + } + else + { + c->AdjustBrushSize(d, false, shiftBehaviour, ctrlBehaviour); + if(isMouseDown) + { + pointQueue.push(ui::Point(c->PointTranslate(ui::Point(x, y)))); + } + } +} + +void GameView::ToggleDebug() +{ + showDebug = !showDebug; + if (ren) + ren->debugLines = showDebug; +} + +void GameView::BeginStampSelection() +{ + selectMode = SelectStamp; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to create a stamp"; + infoTipPresence = 120; +} + +void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(introText > 50) + { + introText = 50; + } + + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + { + switch(key) + { + case KEY_RIGHT: + case 'd': + c->TranslateSave(ui::Point(1, 0)); + break; + case KEY_LEFT: + case 'a': + c->TranslateSave(ui::Point(-1, 0)); + break; + case KEY_UP: + case 'w': + c->TranslateSave(ui::Point(0, -1)); + break; + case KEY_DOWN: + case 's': + c->TranslateSave(ui::Point(0, 1)); + break; + case 'r': + if(shift) + { + //Flip + c->TransformSave(m2d_new(-1,0,0,1)); + } + else + { + //Rotate 90deg + c->TransformSave(m2d_new(0,1,-1,0)); + } + break; + } + } + if(key != ' ') + return; + } + switch(key) + { + case KEY_ALT: + drawSnap = true; + enableAltBehaviour(); + break; + case KEY_CTRL: + if(!isMouseDown) + { + if(drawModeReset) + drawModeReset = false; + else + drawPoint1 = currentMouse; + if(shift) + drawMode = DrawFill; + else + drawMode = DrawRect; + } + enableCtrlBehaviour(); + break; + case KEY_SHIFT: + if(!isMouseDown) + { + if(drawModeReset) + drawModeReset = false; + else + drawPoint1 = currentMouse; + if(ctrl) + drawMode = DrawFill; + else + drawMode = DrawLine; + } + enableShiftBehaviour(); + break; + case ' ': //Space + c->SetPaused(); + break; + case KEY_TAB: //Tab + c->ChangeBrush(); + break; + case 'z': + if(ctrl) + { + c->HistoryRestore(); + } + else + { + if (drawMode != DrawLine) + isMouseDown = false; + zoomCursorFixed = false; + c->SetZoomEnabled(true); + } + break; + case '`': + c->ShowConsole(); + break; + case 'p': + screenshot(); + break; + case 'r': + record(); + break; + case 'e': + c->OpenElementSearch(); + break; + case 'f': + c->FrameStep(); + break; + case 'g': + if (ctrl) + c->ShowGravityGrid(); + else if(shift) + c->AdjustGridSize(-1); + else + c->AdjustGridSize(1); + break; + case KEY_F1: + if(!introText) + introText = 8047; + else + introText = 0; + break; + case 'h': + if(ctrl) + { + if(!introText) + introText = 8047; + else + introText = 0; + } + else + showHud = !showHud; + break; + case 'b': + if(ctrl) + c->SetDecoration(); + else + if (colourPicker->GetParentWindow()) + c->SetActiveMenu(lastMenu); + else + { + c->SetDecoration(true); + c->SetPaused(true); + c->SetActiveMenu(c->GetMenuList()[SC_DECO]); + } + break; + case 'y': + c->SwitchAir(); + break; + case KEY_ESCAPE: + case 'q': + ExitPrompt(); + break; + case 'u': + c->ToggleAHeat(); + break; + case '=': + if(ctrl) + c->ResetSpark(); + else + c->ResetAir(); + break; + case 'c': + if(ctrl) + { + selectMode = SelectCopy; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to copy"; + infoTipPresence = 120; + } + break; + case 'x': + if(ctrl) + { + selectMode = SelectCut; + selectPoint1 = ui::Point(-1, -1); + infoTip = "\x0F\xEF\xEF\x10Select an area to cut"; + infoTipPresence = 120; + } + break; + case 'v': + if(ctrl) + { + c->LoadClipboard(); + selectPoint2 = mousePosition; + selectPoint1 = selectPoint2; + } + break; + case 'l': + c->LoadStamp(); + selectPoint2 = mousePosition; + selectPoint1 = selectPoint2; + isMouseDown = false; + drawMode = DrawPoints; + break; + case 'k': + selectPoint2 = ui::Point(-1, -1); + selectPoint1 = selectPoint2; + c->OpenStamps(); + break; + case ']': + if(zoomEnabled && !zoomCursorFixed) + c->AdjustZoomSize(1, !alt); + else + c->AdjustBrushSize(1, !alt, shiftBehaviour, ctrlBehaviour); + break; + case '[': + if(zoomEnabled && !zoomCursorFixed) + c->AdjustZoomSize(-1, !alt); + else + c->AdjustBrushSize(-1, !alt, shiftBehaviour, ctrlBehaviour); + break; + case 'i': + if(ctrl) + c->Install(); + else + c->InvertAirSim(); + break; + } + + if (shift && showDebug && key == '1') + c->LoadRenderPreset(10); + else if(key >= '0' && key <= '9') + { + c->LoadRenderPreset(key-'0'); + } +} + +void GameView::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(ctrl && shift) + drawMode = DrawFill; + else if (ctrl) + drawMode = DrawRect; + else if (shift) + drawMode = DrawLine; + else if(!isMouseDown) + drawMode = DrawPoints; + else + drawModeReset = true; + switch(key) + { + case KEY_ALT: + drawSnap = false; + disableAltBehaviour(); + break; + case KEY_CTRL: + disableCtrlBehaviour(); + break; + case KEY_SHIFT: + disableShiftBehaviour(); + break; + case 'z': + if(!ctrl) + { + if(!zoomCursorFixed && !alt) + c->SetZoomEnabled(false); + } + break; + } +} + +void GameView::OnBlur() +{ + disableAltBehaviour(); + disableCtrlBehaviour(); + disableShiftBehaviour(); + isMouseDown = false; + drawMode = DrawPoints; +} + +void GameView::OnTick(float dt) +{ + if(selectMode==PlaceSave && !placeSaveThumb) + selectMode = SelectNone; + if(zoomEnabled && !zoomCursorFixed) + c->SetZoomPosition(currentMouse); + if(drawMode == DrawPoints) + { + if(isMouseDown) + { + pointQueue.push(ui::Point(c->PointTranslate(currentMouse))); + } + if(!pointQueue.empty()) + { + c->DrawPoints(toolIndex, pointQueue); + } + } + if(drawMode == DrawFill && isMouseDown) + { + c->DrawFill(toolIndex, c->PointTranslate(currentMouse)); + } + if(introText) + { + introText -= int(dt)>0?((int)dt < 5? dt:5):1; + if(introText < 0) + introText = 0; + } + if(infoTipPresence>0) + { + infoTipPresence -= int(dt)>0?int(dt):1; + if(infoTipPresence<0) + infoTipPresence = 0; + } + if(buttonTipShow>0) + { + buttonTipShow -= int(dt)>0?int(dt):1; + if(buttonTipShow<0) + buttonTipShow = 0; + } + if(toolTipPresence>0) + { + toolTipPresence -= int(dt)>0?int(dt):1; + if(toolTipPresence<0) + toolTipPresence = 0; + } + c->Update(); + if(lastLogEntry > -0.1f) + lastLogEntry -= 0.16*dt; +} + + +void GameView::DoMouseMove(int x, int y, int dx, int dy) +{ + if(c->MouseMove(x, y, dx, dy)) + Window::DoMouseMove(x, y, dx, dy); + + if(toolButtons.size()) + { + int totalWidth = (toolButtons[0]->Size.X+1)*toolButtons.size(); + int scrollSize = (int)(((float)(XRES-15))/((float)totalWidth) * ((float)XRES-15)); + if (scrollSize>XRES) + scrollSize = XRES; + if(totalWidth > XRES-15) + { + int mouseX = x; + if(mouseX > XRES) + mouseX = XRES; + + scrollBar->Position.X = (int)(((float)mouseX/((float)XRES-15))*(float)(XRES-scrollSize)); + + float overflow = totalWidth-(XRES-15), mouseLocation = float(XRES)/float(mouseX-(XRES)); + setToolButtonOffset(overflow/mouseLocation); + + //Ensure that mouseLeave events are make their way to the buttons should they move from underneith the mouse pointer + if(toolButtons[0]->Position.Y < y && toolButtons[0]->Position.Y+toolButtons[0]->Size.Y > y) + { + for(vector<ToolButton*>::iterator iter = toolButtons.begin(), end = toolButtons.end(); iter!=end; ++iter) + { + ToolButton * button = *iter; + if(button->Position.X < x && button->Position.X+button->Size.X > x) + button->OnMouseEnter(x, y); + else + button->OnMouseLeave(x, y); + } + } + } + else + { + scrollBar->Position.X = 0; + } + scrollBar->Size.X=scrollSize; + } +} + +void GameView::DoMouseDown(int x, int y, unsigned button) +{ + if(introText > 50) + introText = 50; + if(c->MouseDown(x, y, button)) + Window::DoMouseDown(x, y, button); +} + +void GameView::DoMouseUp(int x, int y, unsigned button) +{ + if(c->MouseUp(x, y, button)) + Window::DoMouseUp(x, y, button); +} + +void GameView::DoMouseWheel(int x, int y, int d) +{ + if(c->MouseWheel(x, y, d)) + Window::DoMouseWheel(x, y, d); +} + +void GameView::DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(c->KeyPress(key, character, shift, ctrl, alt)) + Window::DoKeyPress(key, character, shift, ctrl, alt); +} + +void GameView::DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(c->KeyRelease(key, character, shift, ctrl, alt)) + Window::DoKeyRelease(key, character, shift, ctrl, alt); +} + +void GameView::DoDraw() +{ + Window::DoDraw(); + c->Tick(); +} + +void GameView::NotifyNotificationsChanged(GameModel * sender) +{ + class NotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + NotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + notification->Action(); + //v->c->RemoveNotification(notification); + } + }; + class CloseNotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + CloseNotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + v->c->RemoveNotification(notification); + } + void AltActionCallback(ui::Button * sender) + { + v->c->RemoveNotification(notification); + } + }; + + for(std::vector<ui::Component*>::const_iterator iter = notificationComponents.begin(), end = notificationComponents.end(); iter != end; ++iter) { + ui::Component * cNotification = *iter; + RemoveComponent(cNotification); + delete cNotification; + } + notificationComponents.clear(); + + std::vector<Notification*> notifications = sender->GetNotifications(); + + int currentY = YRES-23; + for(std::vector<Notification*>::iterator iter = notifications.begin(), end = notifications.end(); iter != end; ++iter) + { + int width = (Graphics::textwidth((*iter)->Message.c_str()))+8; + ui::Button * tempButton = new ui::Button(ui::Point(XRES-width-22, currentY), ui::Point(width, 15), (*iter)->Message); + tempButton->SetActionCallback(new NotificationButtonAction(this, *iter)); + tempButton->Appearance.BorderInactive = style::Colour::WarningTitle; + tempButton->Appearance.TextInactive = style::Colour::WarningTitle; + tempButton->Appearance.BorderHover = ui::Colour(255, 175, 0); + tempButton->Appearance.TextHover = ui::Colour(255, 175, 0); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + tempButton = new ui::Button(ui::Point(XRES-20, currentY), ui::Point(15, 15)); + tempButton->SetIcon(IconClose); + tempButton->SetActionCallback(new CloseNotificationButtonAction(this, *iter)); + tempButton->Appearance.Margin.Left+=2; + tempButton->Appearance.Margin.Top+=2; + tempButton->Appearance.BorderInactive = style::Colour::WarningTitle; + tempButton->Appearance.TextInactive = style::Colour::WarningTitle; + tempButton->Appearance.BorderHover = ui::Colour(255, 175, 0); + tempButton->Appearance.TextHover = ui::Colour(255, 175, 0); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + currentY -= 17; + } +} + +void GameView::NotifyZoomChanged(GameModel * sender) +{ + zoomEnabled = sender->GetZoomEnabled(); +} + +void GameView::NotifyLogChanged(GameModel * sender, string entry) +{ + logEntries.push_front(entry); + lastLogEntry = 100.0f; + if(logEntries.size()>20) + logEntries.pop_back(); +} + +void GameView::NotifyPlaceSaveChanged(GameModel * sender) +{ + if(placeSaveThumb) + delete placeSaveThumb; + if(sender->GetPlaceSave()) + { + placeSaveThumb = SaveRenderer::Ref().Render(sender->GetPlaceSave()); + selectMode = PlaceSave; + selectPoint2 = mousePosition; + } + else + { + placeSaveThumb = NULL; + selectMode = SelectNone; + } +} + +void GameView::enableShiftBehaviour() +{ + if(!shiftBehaviour) + { + shiftBehaviour = true; + if(isMouseDown) + { + c->SetToolStrength(10.0f); + } + } +} + +void GameView::disableShiftBehaviour() +{ + if(shiftBehaviour) + { + shiftBehaviour = false; + if(!ctrlBehaviour) + c->SetToolStrength(1.0f); + else + c->SetToolStrength(.1f); + } +} + +void GameView::enableAltBehaviour() +{ + if(!altBehaviour) + { + altBehaviour = true; + } +} + +void GameView::disableAltBehaviour() +{ + if(altBehaviour) + { + altBehaviour = false; + } +} + +void GameView::enableCtrlBehaviour() +{ + if(!ctrlBehaviour) + { + ctrlBehaviour = true; + + //Show HDD save & load buttons + saveSimulationButton->Appearance.BackgroundInactive = saveSimulationButton->Appearance.BackgroundHover = ui::Colour(255, 255, 255); + saveSimulationButton->Appearance.TextInactive = saveSimulationButton->Appearance.TextHover = ui::Colour(0, 0, 0); + searchButton->Appearance.BackgroundInactive = searchButton->Appearance.BackgroundHover = ui::Colour(255, 255, 255); + searchButton->Appearance.TextInactive = searchButton->Appearance.TextHover = ui::Colour(0, 0, 0); + if (currentSaveType == 2) + ((SplitButton*)saveSimulationButton)->SetShowSplit(true); + if(isMouseDown) + { + if(!shiftBehaviour) + c->SetToolStrength(.1f); + else + c->SetToolStrength(10.0f); + } + } +} + +void GameView::disableCtrlBehaviour() +{ + if(ctrlBehaviour) + { + ctrlBehaviour = false; + + //Hide HDD save & load buttons + saveSimulationButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + saveSimulationButton->Appearance.BackgroundHover = ui::Colour(20, 20, 20); + saveSimulationButton->Appearance.TextInactive = saveSimulationButton->Appearance.TextHover = ui::Colour(255, 255, 255); + searchButton->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + searchButton->Appearance.BackgroundHover = ui::Colour(20, 20, 20); + searchButton->Appearance.TextInactive = searchButton->Appearance.TextHover = ui::Colour(255, 255, 255); + if (currentSaveType == 2) + ((SplitButton*)saveSimulationButton)->SetShowSplit(false); + if(!shiftBehaviour) + c->SetToolStrength(1.0f); + else + c->SetToolStrength(10.0f); + } +} + +void GameView::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + if(ren) + { + ren->clearScreen(1.0f); + ren->RenderBegin(); + ren->SetSample(c->PointTranslate(currentMouse).X, c->PointTranslate(currentMouse).Y); + if(selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES) + { + ui::Point finalCurrentMouse = c->PointTranslate(currentMouse); + ui::Point initialDrawPoint = drawPoint1; + + if(wallBrush) + { + finalCurrentMouse = c->NormaliseBlockCoord(finalCurrentMouse); + initialDrawPoint = c->NormaliseBlockCoord(initialDrawPoint); + } + + if(drawMode==DrawRect && isMouseDown) + { + if(drawSnap) + { + finalCurrentMouse = rectSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + activeBrush->RenderRect(ren, c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + else if(drawMode==DrawLine && isMouseDown) + { + if(drawSnap) + { + finalCurrentMouse = lineSnapCoords(c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + activeBrush->RenderLine(ren, c->PointTranslate(initialDrawPoint), finalCurrentMouse); + } + else if(drawMode==DrawFill)// || altBehaviour) + { + activeBrush->RenderFill(ren, finalCurrentMouse); + } + if(drawMode == DrawPoints || drawMode==DrawLine || (drawMode == DrawRect && !isMouseDown)) + { + if(wallBrush) + { + ui::Point finalBrushRadius = c->NormaliseBlockCoord(activeBrush->GetRadius()); + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y-finalBrushRadius.Y, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y-finalBrushRadius.Y); + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-1, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-1); + + ren->xor_line(finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y-finalBrushRadius.Y+1, finalCurrentMouse.X-finalBrushRadius.X, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-2); + ren->xor_line(finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y-finalBrushRadius.Y+1, finalCurrentMouse.X+finalBrushRadius.X+CELL-1, finalCurrentMouse.Y+finalBrushRadius.Y+CELL-2); + } + else + { + activeBrush->RenderPoint(ren, finalCurrentMouse); + } + } + } + + if(selectMode!=SelectNone) + { + if(selectMode==PlaceSave) + { + if(placeSaveThumb && selectPoint2.X!=-1) + { + int thumbX = selectPoint2.X - (placeSaveThumb->Width/2); + int thumbY = selectPoint2.Y - (placeSaveThumb->Height/2); + + ui::Point thumbPos = c->NormaliseBlockCoord(ui::Point(thumbX, thumbY)); + + if(thumbPos.X<0) + thumbPos.X = 0; + if(thumbPos.X+(placeSaveThumb->Width)>=XRES) + thumbPos.X = XRES-placeSaveThumb->Width; + + if(thumbPos.Y<0) + thumbPos.Y = 0; + if(thumbPos.Y+(placeSaveThumb->Height)>=YRES) + thumbPos.Y = YRES-placeSaveThumb->Height; + + ren->draw_image(placeSaveThumb, thumbPos.X, thumbPos.Y, 128); + + ren->xor_rect(thumbPos.X, thumbPos.Y, placeSaveThumb->Width, placeSaveThumb->Width); + } + } + else + { + if(selectPoint1.X==-1) + { + ren->fillrect(0, 0, XRES, YRES, 0, 0, 0, 100); + } + else + { + int x2 = (selectPoint1.X>selectPoint2.X)?selectPoint1.X:selectPoint2.X; + int y2 = (selectPoint1.Y>selectPoint2.Y)?selectPoint1.Y:selectPoint2.Y; + int x1 = (selectPoint2.X<selectPoint1.X)?selectPoint2.X:selectPoint1.X; + int y1 = (selectPoint2.Y<selectPoint1.Y)?selectPoint2.Y:selectPoint1.Y; + + if(x2>XRES-1) + x2 = XRES-1; + if(y2>YRES-1) + y2 = YRES-1; + + ren->fillrect(0, 0, XRES, y1, 0, 0, 0, 100); + ren->fillrect(0, y2+1, XRES, YRES-y2-1, 0, 0, 0, 100); + + ren->fillrect(0, y1, x1, (y2-y1)+1, 0, 0, 0, 100); + ren->fillrect(x2+1, y1, XRES-x2-1, (y2-y1)+1, 0, 0, 0, 100); + + ren->xor_rect(x1, y1, (x2-x1)+1, (y2-y1)+1); + } + } + } + + ren->RenderEnd(); + + if(doScreenshot) + { + VideoBuffer screenshot(ren->DumpFrame()); + std::vector<char> data = format::VideoBufferToPNG(screenshot); + + std::stringstream filename; + filename << "screenshot_"; + filename << std::setfill('0') << std::setw(6) << (screenshotIndex++); + filename << ".png"; + + Client::Ref().WriteFile(data, filename.str()); + doScreenshot = false; + } + + if(recording) + { + VideoBuffer screenshot(ren->DumpFrame()); + std::vector<char> data = format::VideoBufferToPPM(screenshot); + + std::stringstream filename; + filename << "frame_"; + filename << std::setfill('0') << std::setw(6) << (recordingIndex++); + filename << ".ppm"; + + Client::Ref().WriteFile(data, filename.str()); + } + + int startX = 20; + int startY = YRES-20; + int startAlpha; + if(lastLogEntry>0.1f && logEntries.size()) + { + startAlpha = 2.55f*lastLogEntry; + deque<string>::iterator iter; + for(iter = logEntries.begin(); iter != logEntries.end() && startAlpha>0; iter++) + { + string message = (*iter); + startY -= 13; + g->fillrect(startX-3, startY-3, Graphics::textwidth((char*)message.c_str())+6, 14, 0, 0, 0, 100); + g->drawtext(startX, startY, message.c_str(), 255, 255, 255, startAlpha); + startAlpha-=14; + } + } + } + + if(recording) + { + std::stringstream sampleInfo; + sampleInfo << recordingIndex; + sampleInfo << ". \x8E REC"; + + int textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 16, (const char*)sampleInfo.str().c_str(), 255, 50, 20, 255); + } + else if(showHud && !introText) + { + //Draw info about simulation under cursor + int wavelengthGfx = 0; + std::stringstream sampleInfo; + sampleInfo.precision(2); + if(sample.particle.type) + { + if(showDebug) + { + int ctype = sample.particle.ctype; + if (sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) + ctype = sample.particle.tmp; + + if (sample.particle.type == PT_LAVA && ctype > 0 && ctype < PT_NUM) + sampleInfo << "Molten " << c->ElementResolve(ctype); + else if((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && ctype > 0 && ctype < PT_NUM) + sampleInfo << c->ElementResolve(sample.particle.type) << " with " << c->ElementResolve(ctype); + else + { + sampleInfo << c->ElementResolve(sample.particle.type); + if(ctype > 0 && ctype < PT_NUM) + sampleInfo << " (" << c->ElementResolve(ctype) << ")"; + else + sampleInfo << " ()"; + } + sampleInfo << ", Temp: " << std::fixed << sample.particle.temp -273.15f; + sampleInfo << ", Life: " << sample.particle.life; + sampleInfo << ", Tmp: " << sample.particle.tmp; + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + else + { + if (sample.particle.type == PT_LAVA && sample.particle.ctype > 0 && sample.particle.ctype < PT_NUM) + sampleInfo << "Molten " << c->ElementResolve(sample.particle.ctype); + else if((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && sample.particle.tmp > 0 && sample.particle.tmp < PT_NUM) + sampleInfo << c->ElementResolve(sample.particle.type) << " with " << c->ElementResolve(sample.particle.tmp); + else + sampleInfo << c->ElementResolve(sample.particle.type); + sampleInfo << ", Temp: " << std::fixed << sample.particle.temp -273.15f; + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + if(sample.particle.type == PT_PHOT) + wavelengthGfx = sample.particle.ctype; + } + else if (sample.WallType) + { + sampleInfo << c->WallName(sample.WallType); + sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; + } + else + { + sampleInfo << "Empty, Pressure: " << std::fixed << sample.AirPressure; + } + + int textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 16, (const char*)sampleInfo.str().c_str(), 255, 255, 255, 255*0.75); + +#ifndef OGLI + if(wavelengthGfx) + { + int i, cr, cg, cb, j, h = 3, x = XRES-19-textWidth, y = 10; + int tmp; + g->fillrect(x, y, 30, h, 64, 64, 64, 255); // coords -1 size +1 to work around bug in fillrect - TODO: fix fillrect + for (i = 0; i < 30; i++) + { + if ((wavelengthGfx >> i)&1) + { + // Need a spread of wavelengths to get a smooth spectrum, 5 bits seems to work reasonably well + if (i>2) tmp = 0x1F << (i-2); + else tmp = 0x1F >> (2-i); + + cg = 0; + cb = 0; + cr = 0; + + for (j=0; j<12; j++) + { + cr += (tmp >> (j+18)) & 1; + cb += (tmp >> j) & 1; + } + for (j=0; j<13; j++) + cg += (tmp >> (j+9)) & 1; + + tmp = 624/(cr+cg+cb+1); + cr *= tmp; + cg *= tmp; + cb *= tmp; + for (j=0; j<h; j++) + g->blendpixel(x+29-i,y+j,cr>255?255:cr,cg>255?255:cg,cb>255?255:cb,255); + } + } + } +#endif + + if(showDebug) + { + sampleInfo.str(std::string()); + + if(sample.particle.type) + { + sampleInfo << "#" << sample.ParticleID << ", "; + } + sampleInfo << "X:" << sample.PositionX << " Y:" << sample.PositionY; + if (sample.Gravity) + sampleInfo << " GX: " << sample.GravityVelocityX << " GY: " << sample.GravityVelocityY; + + textWidth = Graphics::textwidth((char*)sampleInfo.str().c_str()); + g->fillrect(XRES-20-textWidth, 26, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(XRES-16-textWidth, 30, (const char*)sampleInfo.str().c_str(), 255, 255, 255, 255*0.75); + } + + + //FPS and some version info +#ifndef DEBUG //In debug mode, the Engine will draw FPS and other info instead + std::stringstream fpsInfo; + fpsInfo.precision(2); +#ifdef SNAPSHOT + fpsInfo << "Snapshot " << SNAPSHOT_ID << ", "; +#elif defined(BETA) + fpsInfo << "Beta " << SAVE_VERSION << "." << MINOR_VERSION << "." << BUILD_NUM << ", "; +#endif + fpsInfo << "FPS: " << std::fixed << ui::Engine::Ref().GetFps(); + + if (showDebug) + fpsInfo << " Parts: " << sample.NumParts; + if (ren->GetGridSize()) + fpsInfo << " [GRID: " << ren->GetGridSize() << "]"; + + textWidth = Graphics::textwidth((char*)fpsInfo.str().c_str()); + g->fillrect(12, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); + g->drawtext(16, 16, (const char*)fpsInfo.str().c_str(), 32, 216, 255, 255*0.75); +#endif + } + + //Tooltips + if(infoTipPresence) + { + int infoTipAlpha = (infoTipPresence>50?50:infoTipPresence)*5; + g->drawtext((XRES-Graphics::textwidth((char*)infoTip.c_str()))/2, (YRES/2)-2, (char*)infoTip.c_str(), 255, 255, 255, infoTipAlpha); + } + + if(toolTipPresence && toolTipPosition.X!=-1 && toolTipPosition.Y!=-1 && toolTip.length()) + { + g->drawtext(toolTipPosition.X, toolTipPosition.Y, (char*)toolTip.c_str(), 255, 255, 255, toolTipPresence>51?255:toolTipPresence*5); + } + + if(buttonTipShow > 0) + { + g->drawtext(6, Size.Y-MENUSIZE-10, (char*)buttonTip.c_str(), 255, 255, 255, buttonTipShow>51?255:buttonTipShow*5); + } + + //Introduction text + if(introText) + { + g->fillrect(0, 0, XRES+BARSIZE, YRES+MENUSIZE, 0, 0, 0, introText>51?102:introText*2); + g->drawtext(16, 20, (char*)introTextMessage.c_str(), 255, 255, 255, introText>51?255:introText*5); + } +} + +ui::Point GameView::lineSnapCoords(ui::Point point1, ui::Point point2) +{ + ui::Point newPoint(0, 0); + float snapAngle = floor(atan2((float)point2.Y-point1.Y, point2.X-point1.X)/(M_PI*0.25)+0.5)*M_PI*0.25; + float lineMag = sqrtf(pow((float)(point2.X-point1.X),2)+pow((float)(point2.Y-point1.Y),2)); + newPoint.X = (int)(lineMag*cos(snapAngle)+point1.X+0.5f); + newPoint.Y = (int)(lineMag*sin(snapAngle)+point1.Y+0.5f); + return newPoint; +} + +ui::Point GameView::rectSnapCoords(ui::Point point1, ui::Point point2) +{ + ui::Point newPoint(0, 0); + float snapAngle = floor((atan2((float)point2.Y-point1.Y, point2.X-point1.X)+M_PI*0.25)/(M_PI*0.5)+0.5)*M_PI*0.5 - M_PI*0.25; + float lineMag = sqrtf(pow((float)(point2.X-point1.X),2)+pow((float)(point2.Y-point1.Y),2)); + newPoint.X = (int)(lineMag*cos(snapAngle)+point1.X+0.5f); + newPoint.Y = (int)(lineMag*sin(snapAngle)+point1.Y+0.5f); + return newPoint; +} |
