diff --git a/src/gui/game/DecorationTool.h b/src/gui/game/DecorationTool.h index cd61fe6e8..a7d5fbe2e 100644 --- a/src/gui/game/DecorationTool.h +++ b/src/gui/game/DecorationTool.h @@ -5,6 +5,7 @@ #include "Tool.h" #include "graphics/Graphics.h" +class Renderer; class DecorationTool: public Tool { public: @@ -12,6 +13,7 @@ public: unsigned char Green; unsigned char Blue; unsigned char Alpha; + Renderer *ren; VideoBuffer * GetIcon(int toolID, int width, int height) { @@ -56,12 +58,13 @@ public: return newTexture; } - DecorationTool(int decoMode, string name, string description, int r, int g, int b, std::string identifier): + DecorationTool(Renderer *ren_, int decoMode, string name, string description, int r, int g, int b, std::string identifier): Tool(decoMode, name, description, r, g, b, identifier), Red(0), Green(0), Blue(0), - Alpha(0) + Alpha(0), + ren(ren_) { } virtual ~DecorationTool() {} @@ -75,7 +78,11 @@ public: sim->ApplyDecorationBox(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID); } virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position) { - + pixel loc = ren->vid[position.X+position.Y*WINDOWW]; + if (toolID == DECO_CLEAR) + sim->ApplyDecorationFill(ren, position.X, position.Y, 0, 0, 0, 0, PIXR(loc), PIXG(loc), PIXB(loc)); + else + sim->ApplyDecorationFill(ren, position.X, position.Y, Red, Green, Blue, Alpha, PIXR(loc), PIXG(loc), PIXB(loc)); } }; diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index 4a282290a..a65f8edcc 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -313,13 +313,13 @@ void GameModel::BuildMenus() menuList[SC_TOOL]->AddTool(new SampleTool(this)); //Add decoration tools to menu - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_ADD, "ADD", "Colour blending: Add.", 0, 0, 0, "DEFAULT_DECOR_ADD")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_SUBTRACT, "SUB", "Colour blending: Subtract.", 0, 0, 0, "DEFAULT_DECOR_SUB")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_MULTIPLY, "MUL", "Colour blending: Multiply.", 0, 0, 0, "DEFAULT_DECOR_MUL")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_DIVIDE, "DIV", "Colour blending: Divide." , 0, 0, 0, "DEFAULT_DECOR_DIV")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_SMUDGE, "SMDG", "Smudge tool, blends surrounding deco together.", 0, 0, 0, "DEFAULT_DECOR_SMDG")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_CLEAR, "CLR", "Erase any set decoration.", 0, 0, 0, "DEFAULT_DECOR_CLR")); - menuList[SC_DECO]->AddTool(new DecorationTool(DECO_DRAW, "SET", "Draw decoration (No blending).", 0, 0, 0, "DEFAULT_DECOR_SET")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_ADD, "ADD", "Colour blending: Add.", 0, 0, 0, "DEFAULT_DECOR_ADD")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_SUBTRACT, "SUB", "Colour blending: Subtract.", 0, 0, 0, "DEFAULT_DECOR_SUB")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_MULTIPLY, "MUL", "Colour blending: Multiply.", 0, 0, 0, "DEFAULT_DECOR_MUL")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_DIVIDE, "DIV", "Colour blending: Divide." , 0, 0, 0, "DEFAULT_DECOR_DIV")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_SMUDGE, "SMDG", "Smudge tool, blends surrounding deco together.", 0, 0, 0, "DEFAULT_DECOR_SMDG")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_CLEAR, "CLR", "Erase any set decoration.", 0, 0, 0, "DEFAULT_DECOR_CLR")); + menuList[SC_DECO]->AddTool(new DecorationTool(ren, DECO_DRAW, "SET", "Draw decoration (No blending).", 0, 0, 0, "DEFAULT_DECOR_SET")); decoToolset[0] = GetToolFromIdentifier("DEFAULT_DECOR_SET"); decoToolset[1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR"); decoToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE"); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index da95e9d32..a03d55138 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -161,6 +161,7 @@ GameView::GameView(): showDebug(false), wallBrush(false), toolBrush(false), + decoBrush(false), windTool(false), toolIndex(0), currentSaveType(0), @@ -637,6 +638,7 @@ bool GameView::GetPlacingZoom() void GameView::NotifyActiveToolsChanged(GameModel * sender) { + decoBrush = false; for (size_t i = 0; i < toolButtons.size(); i++) { Tool * tool = ((ToolAction*)toolButtons[i]->GetActionCallback())->tool; @@ -647,10 +649,15 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender) windTool = true; else windTool = false; + + if (sender->GetActiveTool(0)->GetIdentifier().find("DEFAULT_DECOR_") != sender->GetActiveTool(0)->GetIdentifier().npos) + decoBrush = true; } else if(sender->GetActiveTool(1) == tool) { toolButtons[i]->SetSelectionState(1); //Secondary + if (sender->GetActiveTool(1)->GetIdentifier().find("DEFAULT_DECOR_") != sender->GetActiveTool(1)->GetIdentifier().npos) + decoBrush = true; } else if(sender->GetActiveTool(2) == tool) { @@ -674,15 +681,18 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender) void GameView::NotifyLastToolChanged(GameModel * sender) { - if(sender->GetLastTool() && sender->GetLastTool()->GetResolution() == CELL) - wallBrush = true; - else - wallBrush = false; + if (sender->GetLastTool()) + { + if (sender->GetLastTool()->GetResolution() == CELL) + wallBrush = true; + else + wallBrush = false; - if (sender->GetLastTool() && sender->GetLastTool()->GetIdentifier().find("DEFAULT_TOOL_") != sender->GetLastTool()->GetIdentifier().npos) - toolBrush = true; - else - toolBrush = false; + if (sender->GetLastTool()->GetIdentifier().find("DEFAULT_TOOL_") != sender->GetLastTool()->GetIdentifier().npos) + toolBrush = true; + else + toolBrush = false; + } } void GameView::NotifyToolListChanged(GameModel * sender) @@ -2057,7 +2067,8 @@ void GameView::OnDraw() } else if(drawMode==DrawFill)// || altBehaviour) { - activeBrush->RenderFill(ren, finalCurrentMouse); + if (!decoBrush) + activeBrush->RenderFill(ren, finalCurrentMouse); } if(drawMode == DrawPoints || drawMode==DrawLine || (drawMode == DrawRect && !isMouseDown)) { diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h index ce835bd04..0ca9afba8 100644 --- a/src/gui/game/GameView.h +++ b/src/gui/game/GameView.h @@ -45,6 +45,7 @@ private: bool showDebug; bool wallBrush; bool toolBrush; + bool decoBrush; bool windTool; int toolIndex; int currentSaveType; diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index f4c67cf14..a141014a7 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -422,7 +422,6 @@ int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propva { cs.pop(x, y); x1 = x2 = x; - x1 = x2 = x; while (x1>=CELL) { if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1]) @@ -983,6 +982,80 @@ void Simulation::ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, in ApplyDecoration(i, j, colR, colG, colB, colA, mode); } +bool Simulation::ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB) +{ + pixel pix = ren->vid[x+y*WINDOWW]; + int r = PIXR(pix); + int g = PIXG(pix); + int b = PIXB(pix); + int diff = std::abs(replaceR-r) + std::abs(replaceG-g) + std::abs(replaceB-b); + return diff < 15; +} + +void Simulation::ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB) +{ + int x1, x2; + char *bitmap = (char*)malloc(XRES*YRES); //Bitmap for checking + if (!bitmap) + return; + memset(bitmap, 0, XRES*YRES); + + if (!ColorCompare(ren, x, y, replaceR, replaceG, replaceB)) + return; + + try + { + CoordStack cs; + cs.push(x, y); + do + { + cs.pop(x, y); + x1 = x2 = x; + // go left as far as possible + while (x1>0) + { + if (bitmap[(x1-1)+y*XRES] || !ColorCompare(ren, x1-1, y, replaceR, replaceG, replaceB)) + { + break; + } + x1--; + } + // go right as far as possible + while (x2= 1) + for (x=x1; x<=x2; x++) + if (!bitmap[x+(y-1)*XRES] && ColorCompare(ren, x, y-1, replaceR, replaceG, replaceB)) + cs.push(x, y-1); + + if (y < YRES-1) + for (x=x1; x<=x2; x++) + if (!bitmap[x+(y+1)*XRES] && ColorCompare(ren, x, y+1, replaceR, replaceG, replaceB)) + cs.push(x, y+1); + } while (cs.getSize() > 0); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + free(bitmap); + return; + } + free(bitmap); +} + int Simulation::Tool(int x, int y, int tool, float strength) { if(tools[tool]) diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 366e1cc3f..801f76606 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -170,6 +170,8 @@ public: void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL); void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL); void ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode); + bool ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB); + void ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB); //Drawing Tools like HEAT, AIR, and GRAV int Tool(int x, int y, int tool, float strength = 1.0f);