diff --git a/src/gui/game/ConfigTool.cpp b/src/gui/game/ConfigTool.cpp new file mode 100644 index 0000000000..faf23161b4 --- /dev/null +++ b/src/gui/game/ConfigTool.cpp @@ -0,0 +1,448 @@ +#include "GameModel.h" +#include "Tool.h" + +class FiltConfigWindow: public ui::Window +{ +public: + ConfigTool *tool; + Simulation *sim; + FiltConfigWindow(ConfigTool *tool_, Simulation *sim); + void OnSelect(int result); + virtual void OnTryExit(ExitMethod method); + virtual ~FiltConfigWindow() {} + class SelectAction: public ui::ButtonAction + { + public: + FiltConfigWindow *prompt; + int result; + SelectAction(FiltConfigWindow *prompt_, int result_): + prompt(prompt_), + result(result_) + { } + void ActionCallback(ui::Button *sender) + { + prompt->OnSelect(result); + return; + } + }; +}; + +FiltConfigWindow::FiltConfigWindow(ConfigTool * tool_, Simulation *sim_): +ui::Window(ui::Point(-1, -1), ui::Point(150, 200)), +tool(tool_), +sim(sim_) +{ + int maxTextWidth = 0; + for (int i = 0; i <= Element_FILT::NUM_MODES; i++) + { + String buttonText = (i == Element_FILT::NUM_MODES) ? + String::Build("Cancel") : Element_FILT::MODES[i]; + int textWidth = Graphics::textwidth(buttonText); + if (textWidth > maxTextWidth) + maxTextWidth = textWidth; + } + int buttonWidth = maxTextWidth + 15; + int buttonHeight = 17; + int buttonLeft = Size.X/2 - buttonWidth/2; + int buttonTop = Size.Y/2 - ((buttonHeight-1) * (Element_FILT::NUM_MODES))/2; + for (int i = 0; i < Element_FILT::NUM_MODES; i++) + { + String buttonText = Element_FILT::MODES[i]; + ui::Button * b = new ui::Button(ui::Point(buttonLeft, i * (buttonHeight-1) + buttonTop), ui::Point(buttonWidth, buttonHeight), buttonText); + b->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + b->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + b->SetActionCallback(new SelectAction(this, i)); + AddComponent(b); + } + MakeActiveWindow(); +} + +void FiltConfigWindow::OnSelect(int result) +{ + tool->OnSelectFiltTmp(sim, result); + CloseActiveWindow(); + SelfDestruct(); +} + +void FiltConfigWindow::OnTryExit(ExitMethod method) +{ + CloseActiveWindow(); + SelfDestruct(); +} + +int ConfigTool::getIdAt(Simulation *sim, ui::Point position) +{ + if (position.X<0 || position.X>=XRES || position.Y<0 || position.Y>=YRES) + return -1; + int p = sim->photons[position.Y][position.X]; + if (!p) + { + p = sim->pmap[position.Y][position.X]; + if (!p) + return -1; + } + return ID(p); +} + +Particle ConfigTool::getPartAt(Simulation *sim, ui::Point position) +{ + int id = getIdAt(sim, position); + Particle nullPart; + nullPart.type = PT_NONE; + return (id == -1) ? nullPart : sim->parts[id]; +} + +bool ConfigTool::isSamePart(Particle p1, Particle p2) +{ + return p1.type == p2.type && + int(p1.x+0.5f) == int(p2.x+0.5f) && + int(p1.y+0.5f) == int(p2.y+0.5f); +} + +ui::Point ConfigTool::projectPoint(Particle part, int sampleX, int sampleY, bool allowDiag) +{ + int partX = int(part.x + 0.5f), partY = int(part.y + 0.5f); + int relX = sampleX - partX, relY = sampleY - partY; + int absX = (relX > 0) ? relX : -relX, absY = (relY > 0) ? relY : -relY; + int projX = 0, projY = 0, diagProjX, diagProjY; + if (absX > absY) + projX = relX; + else + projY = relY; + if ((relX > 0) == (relY > 0)) + { + diagProjX = (relX + relY) / 2; + diagProjY = diagProjX; + } + else + { + diagProjX = (relX - relY) / 2; + diagProjY = -diagProjX; + } + int relProjX = relX - projX, relProjY = relY - projY; + int relDiagProjX = relX - diagProjX, relDiagProjY = relY - diagProjY; + int distProj = relProjX*relProjX + relProjY*relProjY; + int distDiagProj = relDiagProjX*relDiagProjX + relDiagProjY*relDiagProjY; + if (distProj < distDiagProj || !allowDiag) + return ui::Point(projX, projY); + else + return ui::Point(diagProjX, diagProjY); +} + +int ConfigTool::getDist(ui::Point relPos, int offset) +{ + int signedDist = relPos.X ? relPos.X : relPos.Y; + int dist = ((signedDist > 0) ? signedDist : -signedDist) - offset; + return (dist < 0) ? 0 : dist; +} + +int ConfigTool::getDist(Particle part, int sampleX, int sampleY, int offset, bool allowDiag) +{ + ui::Point proj = projectPoint(part, sampleX, sampleY, allowDiag); + return getDist(proj, offset); +} + +void ConfigTool::OnSelectFiltTmp(Simulation *sim, int tmp) +{ + if (!isSamePart(sim->parts[currId], configPart)) + { + Reset(); + return; + } + sim->parts[currId].tmp = tmp; +} + +void ConfigTool::CalculatePreview(int x, int y, Particle samplePart) +{ + cursorPos = ui::Point(x, y); + bool allowDiag = !(configState == ConfigState::dtecTmp2); + ui::Point proj = projectPoint(configPart, x, y, allowDiag); + dirx = (proj.X == 0) ? 0 : ((proj.X > 0) ? 1 : -1); + diry = (proj.Y == 0) ? 0 : ((proj.Y > 0) ? 1 : -1); + switch (configState) + { + case ConfigState::ready: + configPart = samplePart; + break; + case ConfigState::drayTmp: + configPart.tmp = getDist(proj); + break; + case ConfigState::drayTmp2: + configPart.tmp2 = getDist(proj, configPart.tmp); + break; + case ConfigState::crayTmp2: + configPart.tmp2 = getDist(proj); + break; + case ConfigState::crayTmp: + configPart.tmp = getDist(proj, configPart.tmp2); + break; + case ConfigState::ldtcLife: + configPart.life = getDist(proj); + break; + case ConfigState::ldtcTmp: + configPart.tmp = getDist(proj, configPart.life); + break; + case ConfigState::dtecTmp2: + configPart.tmp2 = getDist(proj); + break; + case ConfigState::convTmp: + configPart.tmp = samplePart.type; + break; + default: + break; + } +} + +void ConfigTool::Click(Simulation *sim, Brush *brush, ui::Point position) +{ + if (configState != ConfigState::ready && + !isSamePart(sim->parts[currId], configPart)) + { + Reset(); + } + CalculatePreview(position.X, position.Y, getPartAt(sim, position)); + switch (configState) + { + case ConfigState::ready: + currId = getIdAt(sim, position); + if (currId == -1) + break; + configPart = sim->parts[currId]; + switch (configPart.type) + { + case PT_DRAY: + configState = ConfigState::drayTmp; + break; + case PT_CRAY: + configState = ConfigState::crayTmp2; + break; + case PT_LDTC: + configState = ConfigState::ldtcLife; + break; + case PT_DTEC: + configState = ConfigState::dtecTmp2; + break; + case PT_CONV: + configState = ConfigState::convTmp; + break; + case PT_FILT: + new FiltConfigWindow(this, sim); + break; + default: + break; + } + break; + case ConfigState::drayTmp: + sim->parts[currId].tmp = configPart.tmp; + configState = ConfigState::drayTmp2; + break; + case ConfigState::drayTmp2: + sim->parts[currId].tmp2 = configPart.tmp2; + configState = ConfigState::ready; + break; + case ConfigState::crayTmp2: + sim->parts[currId].tmp2 = configPart.tmp2; + configState = ConfigState::crayTmp; + break; + case ConfigState::crayTmp: + sim->parts[currId].tmp = configPart.tmp; + configState = ConfigState::ready; + break; + case ConfigState::ldtcLife: + sim->parts[currId].life = configPart.life; + configState = ConfigState::ldtcTmp; + break; + case ConfigState::ldtcTmp: + sim->parts[currId].tmp = configPart.tmp; + configState = ConfigState::ready; + break; + case ConfigState::dtecTmp2: + sim->parts[currId].tmp2 = configPart.tmp2; + configState = ConfigState::ready; + break; + case ConfigState::convTmp: + sim->parts[currId].tmp = configPart.tmp; + configState = ConfigState::ready; + break; + default: + break; + } +} + +void ConfigTool::Reset() +{ + configState = ConfigState::ready; +} + +Particle ConfigTool::GetPart() +{ + return configPart; +} + +bool ConfigTool::IsConfigurableType(int type) +{ + return type == PT_DRAY || type == PT_CRAY || type == PT_LDTC || + type == PT_DTEC || type == PT_CONV || type == PT_FILT; +} + +bool ConfigTool::IsConfiguring() +{ + return configState != ConfigState::ready; +} + +bool ConfigTool::IsConfiguringTemp() +{ + return false; +} + +bool ConfigTool::IsConfiguringLife() +{ + return configState == ConfigState::ldtcLife; +} + +bool ConfigTool::IsConfiguringTmp() +{ + return configState == ConfigState::drayTmp || + configState == ConfigState::crayTmp || + configState == ConfigState::ldtcTmp || + configState == ConfigState::convTmp; +} + +bool ConfigTool::IsConfiguringTmp2() +{ + return configState == ConfigState::drayTmp2 || + configState == ConfigState::crayTmp2 || + configState == ConfigState::dtecTmp2; +} + +void ConfigTool::drawRedLine(Renderer *ren, int startx, int starty, int endx, int endy) +{ + ren->draw_line(startx, starty, endx, endy, 255, 0, 0, 200); +} + +void ConfigTool::drawWhiteLine(Renderer *ren, int startx, int starty, int endx, int endy) +{ + ren->draw_line(startx, starty, endx, endy, 255, 200, 200, 220); +} + +void ConfigTool::drawTripleLine(Renderer *ren, int firstLineLen, int midLineLen, bool drawFirstLine, bool drawThirdLine) +{ + int mid1x = configPart.x + dirx * firstLineLen, + mid1y = configPart.y + diry * firstLineLen; + int mid2x = mid1x + dirx * midLineLen, + mid2y = mid1y + diry * midLineLen; + if (drawFirstLine && firstLineLen > 0) + drawWhiteLine(ren, configPart.x + dirx, configPart.y + diry, mid1x, mid1y); + if (midLineLen > 0) + drawRedLine(ren, mid1x + dirx, mid1y + diry, mid2x, mid2y); + if (drawThirdLine && firstLineLen > 0) + drawWhiteLine(ren, mid2x + dirx, mid2y + diry, mid2x + dirx * firstLineLen, mid2y + diry * firstLineLen); +} + +void ConfigTool::drawDtecBox(Renderer *ren) +{ + ren->drawrect(configPart.x - configPart.tmp2, configPart.y - configPart.tmp2, configPart.tmp2 * 2 + 1, configPart.tmp2 * 2 + 1, 200, 200, 200, 220); +} + +void ConfigTool::DrawHUD(Renderer *ren) +{ + switch (configState) + { + case ConfigState::ready: + ren->xor_line(cursorPos.X, cursorPos.Y, cursorPos.X, cursorPos.Y); + switch (configPart.type) + { + case PT_DTEC: + drawDtecBox(ren); + break; + } + break; + case ConfigState::drayTmp: + drawTripleLine(ren, 0, configPart.tmp, false, false); + break; + case ConfigState::drayTmp2: + drawTripleLine(ren, configPart.tmp, configPart.tmp2); + break; + case ConfigState::crayTmp2: + drawTripleLine(ren, 0, configPart.tmp2, false, false); + break; + case ConfigState::crayTmp: + drawTripleLine(ren, configPart.tmp2, configPart.tmp, true, false); + break; + case ConfigState::ldtcLife: + drawTripleLine(ren, 0, configPart.life, false, false); + break; + case ConfigState::ldtcTmp: + drawTripleLine(ren, configPart.life, configPart.tmp, true, false); + break; + case ConfigState::dtecTmp2: + drawDtecBox(ren); + break; + case ConfigState::convTmp: + { + int partX = int(configPart.x+0.5f), partY = int(configPart.y+0.5f); + drawRedLine(ren, partX, partY, partX, partY); + ren->xor_line(cursorPos.X, cursorPos.Y, cursorPos.X, cursorPos.Y); + break; + } + default: + break; + } +} + +void ConfigTool::ReleaseTool::Click(Simulation *sim, Brush *brush, ui::Point position) +{ + if (configTool->IsConfiguring()) + configTool->Reset(); + else + { + ui::Point oldSize = brush->GetRadius(); + brush->SetRadius(ui::Point(0, 0)); + clearTool->Click(sim, brush, position); + brush->SetRadius(oldSize); + } +} + +void ConfigTool::ReleaseTool::Draw(Simulation * sim, Brush * brush, ui::Point position) +{ + if (!configTool->IsConfiguring()) + { + ui::Point oldSize = brush->GetRadius(); + brush->SetRadius(ui::Point(0, 0)); + clearTool->Draw(sim, brush, position); + brush->SetRadius(oldSize); + } +} + +void ConfigTool::ReleaseTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) +{ + if (!configTool->IsConfiguring()) + { + ui::Point oldSize = brush->GetRadius(); + brush->SetRadius(ui::Point(0, 0)); + clearTool->DrawLine(sim, brush, position1, position2, dragging); + brush->SetRadius(oldSize); + } +} + +void ConfigTool::ReleaseTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) +{ + if (!configTool->IsConfiguring()) + { + ui::Point oldSize = brush->GetRadius(); + brush->SetRadius(ui::Point(0, 0)); + clearTool->DrawRect(sim, brush, position1, position2); + brush->SetRadius(oldSize); + } +} + +void ConfigTool::ReleaseTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) +{ + if (!configTool->IsConfiguring()) + { + ui::Point oldSize = brush->GetRadius(); + brush->SetRadius(ui::Point(0, 0)); + clearTool->DrawFill(sim, brush, position); + brush->SetRadius(oldSize); + } +} diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index b52cb40b37..946c57f391 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -1155,6 +1155,14 @@ void GameController::ActiveToolChanged(int toolSelection, Tool *tool) commandInterface->OnActiveToolChanged(toolSelection, tool); } +ConfigTool * GameController::GetActiveConfigTool() +{ + Tool * t = GetActiveTool(0); + if(t->GetIdentifier() == "DEFAULT_UI_CONFIG") + return (ConfigTool*)t; + else return NULL; +} + Tool * GameController::GetActiveTool(int selection) { return gameModel->GetActiveTool(selection); @@ -1162,6 +1170,11 @@ Tool * GameController::GetActiveTool(int selection) void GameController::SetActiveTool(int toolSelection, Tool * tool) { + if(tool->GetIdentifier() == "DEFAULT_UI_CONFIG") + { + ((ConfigTool *)tool)->Reset(); + toolSelection = 0; + } if (gameModel->GetActiveMenu() == SC_DECO && toolSelection == 2) toolSelection = 0; gameModel->SetActiveTool(toolSelection, tool); @@ -1191,6 +1204,14 @@ void GameController::SetLastTool(Tool * tool) gameModel->SetLastTool(tool); } +void GameController::ToggleConfigTool() +{ + if (GetActiveConfigTool()) + gameModel->ResetToolset(); + else + SetActiveTool(0, "DEFAULT_UI_CONFIG"); +} + int GameController::GetReplaceModeFlags() { return gameModel->GetSimulation()->replaceModeFlags; diff --git a/src/gui/game/GameController.h b/src/gui/game/GameController.h index 119aeb4085..243d4d49d2 100644 --- a/src/gui/game/GameController.h +++ b/src/gui/game/GameController.h @@ -107,10 +107,12 @@ class GameController: public ClientListener std::vector GetMenuList(); int GetNumMenus(bool onlyEnabled); void RebuildFavoritesMenu(); + ConfigTool * GetActiveConfigTool(); Tool * GetActiveTool(int selection); void SetActiveTool(int toolSelection, Tool * tool); void SetActiveTool(int toolSelection, ByteString identifier); void SetLastTool(Tool * tool); + void ToggleConfigTool(); int GetReplaceModeFlags(); void SetReplaceModeFlags(int flags); void ActiveToolChanged(int toolSelection, Tool *tool); diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index e5d953cb28..36e53bfe3c 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -46,6 +46,7 @@ GameModel::GameModel(): activeTools = regularToolset; std::fill(decoToolset, decoToolset+4, (Tool*)NULL); + std::fill(configToolset, configToolset+4, (Tool*)NULL); std::fill(regularToolset, regularToolset+4, (Tool*)NULL); //Default render prefs @@ -327,6 +328,7 @@ void GameModel::BuildMenus() //Add special sign and prop tools menuList[SC_TOOL]->AddTool(new WindTool(0, "WIND", "Creates air movement.", 64, 64, 64, "DEFAULT_UI_WIND")); menuList[SC_TOOL]->AddTool(new PropertyTool()); + menuList[SC_TOOL]->AddTool(new ConfigTool(this)); menuList[SC_TOOL]->AddTool(new SignTool(this)); menuList[SC_TOOL]->AddTool(new SampleTool(this)); @@ -343,6 +345,13 @@ void GameModel::BuildMenus() decoToolset[1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR"); decoToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE"); decoToolset[3] = GetToolFromIdentifier("DEFAULT_PT_NONE"); + ConfigTool *configTool = (ConfigTool*)GetToolFromIdentifier("DEFAULT_UI_CONFIG"); + configTool->SetClearTool(GetToolFromIdentifier("DEFAULT_PT_NONE")); + configToolset[0] = configTool; + configToolset[1] = &configTool->releaseTool; + // Reserved for more complex configuration + configToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE"); + configToolset[3] = GetToolFromIdentifier("DEFAULT_PT_NONE"); //Set default tools regularToolset[0] = GetToolFromIdentifier("DEFAULT_PT_DUST"); @@ -557,7 +566,7 @@ void GameModel::SetActiveMenu(int menuID) notifyActiveToolsChanged(); } } - else + else if(activeTools != configToolset) { if(activeTools != regularToolset) { @@ -600,10 +609,20 @@ Tool * GameModel::GetActiveTool(int selection) void GameModel::SetActiveTool(int selection, Tool * tool) { + if (tool->GetIdentifier() == "DEFAULT_UI_CONFIG") + activeTools = configToolset; + else if (activeTools == configToolset) + activeTools = regularToolset; activeTools[selection] = tool; notifyActiveToolsChanged(); } +void GameModel::ResetToolset() +{ + activeTools = regularToolset; + notifyActiveToolsChanged(); +} + vector GameModel::GetQuickOptions() { return quickOptions; diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h index 0e97ed1c2e..428c0b8b8e 100644 --- a/src/gui/game/GameModel.h +++ b/src/gui/game/GameModel.h @@ -63,6 +63,7 @@ class GameModel Tool ** activeTools; Tool * decoToolset[4]; Tool * regularToolset[4]; + Tool * configToolset[4]; User currentUser; float toolStrength; std::deque history; @@ -145,6 +146,7 @@ class GameModel Tool * GetActiveTool(int selection); void SetActiveTool(int selection, Tool * tool); + void ResetToolset(); void SetToolStrength(float value); float GetToolStrength(); Tool * GetLastTool(); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index d9bc533f89..0f794b436e 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -1593,6 +1593,10 @@ void GameView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, buttonTip = "\x0F\xEF\xEF\020Click-and-drag to specify an area to copy (right click = cancel)"; buttonTipShow = 120; } + else + { + c->ToggleConfigTool(); + } break; case 'x': if(ctrl) @@ -2097,6 +2101,9 @@ void GameView::SetSaveButtonTooltips() void GameView::OnDraw() { + ConfigTool * configTool = c->GetActiveConfigTool(); + if(configTool) + configTool->CalculatePreview(sample.PositionX, sample.PositionY, sample.particle); Graphics * g = GetGraphics(); if (ren) { @@ -2158,6 +2165,10 @@ void GameView::OnDraw() 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 if(configTool) + { + configTool->DrawHUD(ren); + } else { activeBrush->RenderPoint(ren, finalCurrentMouse); @@ -2284,65 +2295,107 @@ void GameView::OnDraw() StringBuilder sampleInfo; sampleInfo << Format::Precision(2); - int type = sample.particle.type; + bool isConfiguring = configTool && configTool->IsConfiguring(); + Particle samplePart = isConfiguring ? + configTool->GetPart() : sample.particle; + + int type = samplePart.type; if (type) { - int ctype = sample.particle.ctype; + int ctype = samplePart.ctype; if (type == PT_PHOT || type == PT_BIZR || type == PT_BIZRG || type == PT_BIZRS || type == PT_FILT || type == PT_BRAY || type == PT_C5) wavelengthGfx = (ctype&0x3FFFFFFF); - if (showDebug) + if (showDebug || configTool) { + String lbrace = String::Build("["), + rbrace = String::Build("]"), + noneString = String::Build(""); if (type == PT_LAVA && c->IsValidElement(ctype)) sampleInfo << "Molten " << c->ElementResolve(ctype, -1).FromAscii(); else if ((type == PT_PIPE || type == PT_PPIP) && c->IsValidElement(ctype)) - sampleInfo << c->ElementResolve(type, -1).FromAscii() << " with " << c->ElementResolve(ctype, (int)sample.particle.pavg[1]).FromAscii(); + sampleInfo << c->ElementResolve(type, -1).FromAscii() << " with " << c->ElementResolve(ctype, (int)samplePart.pavg[1]).FromAscii(); else if (type == PT_LIFE) sampleInfo << c->ElementResolve(type, ctype).FromAscii(); - else if (type == PT_FILT) - { - sampleInfo << c->ElementResolve(type, ctype).FromAscii(); - String filtModes[] = {"set colour", "AND", "OR", "subtract colour", "red shift", "blue shift", "no effect", "XOR", "NOT", "old QRTZ scattering", "variable red shift", "variable blue shift"}; - if (sample.particle.tmp>=0 && sample.particle.tmp<=11) - sampleInfo << " (" << filtModes[sample.particle.tmp] << ")"; - else - sampleInfo << " (unknown mode)"; - } else { + bool isConfigurable = configTool && + (configTool->IsConfiguring() || + ConfigTool::IsConfigurableType(type)); + if (isConfigurable) + sampleInfo << lbrace; sampleInfo << c->ElementResolve(type, ctype).FromAscii(); - if (wavelengthGfx) - sampleInfo << " (" << ctype << ")"; - // Some elements store extra LIFE info in upper bits of ctype, instead of tmp/tmp2 - else if (type == PT_CRAY || type == PT_DRAY || type == PT_CONV) - sampleInfo << " (" << c->ElementResolve(TYP(ctype), ID(ctype)).FromAscii() << ")"; - else if (c->IsValidElement(ctype)) - sampleInfo << " (" << c->ElementResolve(ctype, -1).FromAscii() << ")"; + if (type == PT_FILT) + { + if (samplePart.tmp>=0 && samplePart.tmpElementResolve(TYP(ctype), ID(ctype)).FromAscii() << ")"; + else if (c->IsValidElement(ctype)) + sampleInfo << " (" << c->ElementResolve(ctype, -1).FromAscii() << ")"; + else + sampleInfo << " ()"; + } + if (isConfigurable) + sampleInfo << rbrace; } - sampleInfo << ", Temp: " << (sample.particle.temp - 273.15f) << " C"; - sampleInfo << ", Life: " << sample.particle.life; - if (sample.particle.type != PT_RFRG && sample.particle.type != PT_RFGL) + bool isConfiguringTemp = configTool && + configTool->IsConfiguringTemp(); + bool isConfiguringLife = configTool && + configTool->IsConfiguringLife(); + bool isConfiguringTmp = configTool && + configTool->IsConfiguringTmp(); + bool isConfiguringTmp2 = configTool && + configTool->IsConfiguringTmp2(); + sampleInfo << ", " << + (isConfiguringTemp ? lbrace : noneString) << + "Temp" << + (isConfiguringTemp ? rbrace : noneString) << + ": " << (samplePart.temp - 273.15f) << " C"; + sampleInfo << ", " << + (isConfiguringLife ? lbrace : noneString) << + "Life" << + (isConfiguringLife ? rbrace : noneString) << + ": " << samplePart.life; + if (samplePart.type != PT_RFRG && samplePart.type != PT_RFGL) { - if (sample.particle.type == PT_CONV) + sampleInfo << ", " << + (isConfiguringTmp ? lbrace : noneString) << + "Tmp" << + (isConfiguringTmp ? rbrace : noneString) << + ": "; + if (samplePart.type == PT_CONV) { String elemName = c->ElementResolve( - TYP(sample.particle.tmp), - ID(sample.particle.tmp)).FromAscii(); + TYP(samplePart.tmp), + ID(samplePart.tmp)).FromAscii(); if (elemName == "") - sampleInfo << ", Tmp: " << sample.particle.tmp; + sampleInfo << samplePart.tmp; else - sampleInfo << ", Tmp: " << elemName; + sampleInfo << elemName; } else - sampleInfo << ", Tmp: " << sample.particle.tmp; + sampleInfo << samplePart.tmp; } // only elements that use .tmp2 show it in the debug HUD - if (type == PT_CRAY || type == PT_DRAY || type == PT_EXOT || type == PT_LIGH || type == PT_SOAP || type == PT_TRON || type == PT_VIBR || type == PT_VIRS || type == PT_WARP || type == PT_LCRY || type == PT_CBNW || type == PT_TSNS || type == PT_DTEC || type == PT_LSNS || type == PT_PSTN || type == PT_LDTC) - sampleInfo << ", Tmp2: " << sample.particle.tmp2; + if (type == PT_CRAY || type == PT_DRAY || type == PT_EXOT || type == PT_LIGH || type == PT_SOAP || type == PT_TRON || type == PT_VIBR || type == PT_VIRS || type == PT_WARP || type == PT_LCRY || type == PT_CBNW || type == PT_TSNS || type == PT_DTEC || type == PT_LSNS || type == PT_PSTN) + { + sampleInfo << ", " << + (isConfiguringTmp2 ? lbrace : noneString) << + "Tmp2" << + (isConfiguringTmp2 ? rbrace : noneString) << + ": " << samplePart.tmp2; + } sampleInfo << ", Pressure: " << sample.AirPressure; } @@ -2351,12 +2404,12 @@ void GameView::OnDraw() if (type == PT_LAVA && c->IsValidElement(ctype)) sampleInfo << "Molten " << c->ElementResolve(ctype, -1).FromAscii(); else if ((type == PT_PIPE || type == PT_PPIP) && c->IsValidElement(ctype)) - sampleInfo << c->ElementResolve(type, -1).FromAscii() << " with " << c->ElementResolve(ctype, (int)sample.particle.pavg[1]).FromAscii(); + sampleInfo << c->ElementResolve(type, -1).FromAscii() << " with " << c->ElementResolve(ctype, (int)samplePart.pavg[1]).FromAscii(); else if (type == PT_LIFE) sampleInfo << c->ElementResolve(type, ctype).FromAscii(); else sampleInfo << c->ElementResolve(type, ctype).FromAscii(); - sampleInfo << ", Temp: " << sample.particle.temp - 273.15f << " C"; + sampleInfo << ", Temp: " << samplePart.temp - 273.15f << " C"; sampleInfo << ", Pressure: " << sample.AirPressure; } } @@ -2450,6 +2503,8 @@ void GameView::OnDraw() else fpsInfo << " Parts: " << sample.NumParts; } + if (configTool) + fpsInfo << " [CONFIG TOOL]"; if (c->GetReplaceModeFlags()&REPLACE_MODE) fpsInfo << " [REPLACE MODE]"; if (c->GetReplaceModeFlags()&SPECIFIC_DELETE) diff --git a/src/gui/game/Tool.h b/src/gui/game/Tool.h index f0224bf877..daea358873 100644 --- a/src/gui/game/Tool.h +++ b/src/gui/game/Tool.h @@ -6,8 +6,12 @@ #include "common/String.h" #include "gui/interface/Point.h" #include "simulation/StructProperty.h" +#include "simulation/Particle.h" +#include "simulation/Sample.h" class Simulation; +class GameController; +class Renderer; class Brush; class VideoBuffer; @@ -80,6 +84,87 @@ class SampleTool: public Tool virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { } }; +class ConfigTool: public Tool +{ + class ReleaseTool : public Tool + { + ConfigTool * configTool; + Tool * clearTool; + public: + ReleaseTool(ConfigTool *configTool_): + Tool(0, "", "", 0, 0, 0, "DEFAULT_UI_CONFIG_RELEASE", NULL), + configTool(configTool_), + clearTool(NULL) + { + } + virtual ~ReleaseTool() {} + void SetClearTool(Tool *clearTool_) { clearTool = clearTool_; } + 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); + }; + + enum struct ConfigState + { + ready, + drayTmp, + drayTmp2, + crayTmp, + crayTmp2, + dtecTmp2, + convTmp, + ldtcTmp, + ldtcLife + }; + GameModel * gameModel; + int currId; + Particle configPart; + int dirx, diry; + ui::Point cursorPos; + ConfigState configState; +public: + ReleaseTool releaseTool; + ConfigTool(GameModel *model): + Tool(0, "CNFG", "Configurator.", 0xff, 0xcc, 0, "DEFAULT_UI_CONFIG", NULL), + gameModel(model), + cursorPos(0, 0), + configState(ConfigState::ready), + releaseTool(ReleaseTool(this)) + { + } + virtual ~ConfigTool() {} + void SetClearTool(Tool *clearTool) { releaseTool.SetClearTool(clearTool); } + void Reset(); + Particle GetPart(); + static bool IsConfigurableType(int type); + bool IsConfiguring(); + bool IsConfiguringTemp(); + bool IsConfiguringLife(); + bool IsConfiguringTmp(); + bool IsConfiguringTmp2(); + void CalculatePreview(int x, int y, Particle samplePart); + void DrawHUD(Renderer *ren); + void OnSelectFiltTmp(Simulation *sim, int tmp); + 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) { } +private: + int getIdAt(Simulation *sim, ui::Point position); + Particle getPartAt(Simulation *sim, ui::Point position); + bool isSamePart(Particle p1, Particle p2); + ui::Point projectPoint(Particle part, int sampleX, int sampleY, bool allowDiag = true); + int getDist(ui::Point relPos, int offset = 0); + int getDist(Particle part, int sampleX, int sampleY, int offset = 0, bool allowDiag = true); + void drawRedLine(Renderer *ren, int startx, int starty, int endx, int endy); + void drawWhiteLine(Renderer *ren, int startx, int starty, int endx, int endy); + void drawTripleLine(Renderer *ren, int firstLineLen, int midLineLen, bool drawFirstLine = true, bool drawThirdLine = true); + void drawDtecBox(Renderer *ren); +}; + class PropertyTool: public Tool { public: diff --git a/src/simulation/elements/FILT.cpp b/src/simulation/elements/FILT.cpp index 65025da335..d9905ac94c 100644 --- a/src/simulation/elements/FILT.cpp +++ b/src/simulation/elements/FILT.cpp @@ -45,6 +45,11 @@ Element_FILT::Element_FILT() Graphics = &Element_FILT::graphics; } +//#TPT-Directive ElementHeader Element_FILT static int NUM_MODES +int Element_FILT::NUM_MODES = 12; +//#TPT-Directive ElementHeader Element_FILT static String MODES[] +String Element_FILT::MODES[] = {"set colour", "AND", "OR", "subtract colour", "red shift", "blue shift", "no effect", "XOR", "NOT", "old QRTZ scattering", "variable red shift", "variable blue shift"}; + //#TPT-Directive ElementHeader Element_FILT static int graphics(GRAPHICS_FUNC_ARGS) int Element_FILT::graphics(GRAPHICS_FUNC_ARGS) {