From ed4678c9a87a72b1893a8e90bda0830e96b279f4 Mon Sep 17 00:00:00 2001 From: jacob1 Date: Sun, 30 Aug 2015 01:38:32 -0400 Subject: [PATCH] add deco flood fill, flood fills based on color being close enough flood fill brush is hidden when deco tools are selected like this because it gets in the way. Renderer::vid is compared here so there could definitely be issues, but it works fine when used under normal conditions --- src/gui/game/DecorationTool.h | 13 ++++-- src/gui/game/GameModel.cpp | 14 +++---- src/gui/game/GameView.cpp | 29 +++++++++----- src/gui/game/GameView.h | 1 + src/simulation/Simulation.cpp | 75 ++++++++++++++++++++++++++++++++++- src/simulation/Simulation.h | 2 + 6 files changed, 114 insertions(+), 20 deletions(-) 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);