mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-11 09:40:42 +00:00
Added support for 4 and 8 connected pixel fill method in paint bucket
This commit is contained in:
parent
39d229b0e9
commit
a08cfa9e13
@ -46,6 +46,10 @@
|
|||||||
<value id="ACTIVE_LAYER" value="0" />
|
<value id="ACTIVE_LAYER" value="0" />
|
||||||
<value id="ALL_LAYERS" value="1" />
|
<value id="ALL_LAYERS" value="1" />
|
||||||
</enum>
|
</enum>
|
||||||
|
<enum id="PixelConnectivity">
|
||||||
|
<value id="FOUR_CONNECTED" value="0" />
|
||||||
|
<value id="EIGHT_CONNECTED" value="1" />
|
||||||
|
</enum>
|
||||||
<enum id="EyedropperChannel">
|
<enum id="EyedropperChannel">
|
||||||
<value id="COLOR_ALPHA" value="0" />
|
<value id="COLOR_ALPHA" value="0" />
|
||||||
<value id="COLOR" value="1" />
|
<value id="COLOR" value="1" />
|
||||||
@ -358,6 +362,7 @@
|
|||||||
<section id="floodfill">
|
<section id="floodfill">
|
||||||
<option id="stop_at_grid" type="StopAtGrid" default="StopAtGrid::NEVER" />
|
<option id="stop_at_grid" type="StopAtGrid" default="StopAtGrid::NEVER" />
|
||||||
<option id="refer_to" type="FillReferTo" default="FillReferTo::ACTIVE_LAYER" />
|
<option id="refer_to" type="FillReferTo" default="FillReferTo::ACTIVE_LAYER" />
|
||||||
|
<option id="pixel_connectivity" type="PixelConnectivity" default="PixelConnectivity::FOUR_CONNECTED" />
|
||||||
</section>
|
</section>
|
||||||
</tool>
|
</tool>
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ FOR_ENUM(app::gen::HueSaturationMode)
|
|||||||
FOR_ENUM(app::gen::OnionskinType)
|
FOR_ENUM(app::gen::OnionskinType)
|
||||||
FOR_ENUM(app::gen::PaintingCursorType)
|
FOR_ENUM(app::gen::PaintingCursorType)
|
||||||
FOR_ENUM(app::gen::PivotPosition)
|
FOR_ENUM(app::gen::PivotPosition)
|
||||||
|
FOR_ENUM(app::gen::PixelConnectivity)
|
||||||
FOR_ENUM(app::gen::RightClickMode)
|
FOR_ENUM(app::gen::RightClickMode)
|
||||||
FOR_ENUM(app::gen::SelectionMode)
|
FOR_ENUM(app::gen::SelectionMode)
|
||||||
FOR_ENUM(app::gen::StopAtGrid)
|
FOR_ENUM(app::gen::StopAtGrid)
|
||||||
|
@ -103,6 +103,7 @@ public:
|
|||||||
get_pixel(srcImage, pt.x, pt.y),
|
get_pixel(srcImage, pt.x, pt.y),
|
||||||
loop->getTolerance(),
|
loop->getTolerance(),
|
||||||
loop->getContiguous(),
|
loop->getContiguous(),
|
||||||
|
loop->isPixelConnectivityEightConnected(),
|
||||||
loop, (AlgoHLine)doInkHline);
|
loop, (AlgoHLine)doInkHline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +182,7 @@ namespace app {
|
|||||||
virtual bool getSnapToGrid() = 0;
|
virtual bool getSnapToGrid() = 0;
|
||||||
virtual bool getStopAtGrid() = 0; // For floodfill-like tools
|
virtual bool getStopAtGrid() = 0; // For floodfill-like tools
|
||||||
virtual gfx::Rect getGridBounds() = 0;
|
virtual gfx::Rect getGridBounds() = 0;
|
||||||
|
virtual bool isPixelConnectivityEightConnected() = 0;
|
||||||
|
|
||||||
// Returns true if the figure must be filled when we release the
|
// Returns true if the figure must be filled when we release the
|
||||||
// mouse (e.g. a filled rectangle, etc.)
|
// mouse (e.g. a filled rectangle, etc.)
|
||||||
|
@ -383,6 +383,16 @@ protected:
|
|||||||
menu.addChild(&activeLayer);
|
menu.addChild(&activeLayer);
|
||||||
menu.addChild(&allLayers);
|
menu.addChild(&allLayers);
|
||||||
|
|
||||||
|
menu.addChild(new MenuSeparator);
|
||||||
|
menu.addChild(new Label("Pixel Connectivity:"));
|
||||||
|
|
||||||
|
HBox box;
|
||||||
|
ButtonSet buttonset(2);
|
||||||
|
buttonset.addItem("4-Connected");
|
||||||
|
buttonset.addItem("8-connected");
|
||||||
|
box.addChild(&buttonset);
|
||||||
|
menu.addChild(&box);
|
||||||
|
|
||||||
stopAtGrid.setSelected(
|
stopAtGrid.setSelected(
|
||||||
toolPref.floodfill.stopAtGrid() == app::gen::StopAtGrid::IF_VISIBLE);
|
toolPref.floodfill.stopAtGrid() == app::gen::StopAtGrid::IF_VISIBLE);
|
||||||
activeLayer.setSelected(
|
activeLayer.setSelected(
|
||||||
@ -390,6 +400,15 @@ protected:
|
|||||||
allLayers.setSelected(
|
allLayers.setSelected(
|
||||||
toolPref.floodfill.referTo() == app::gen::FillReferTo::ALL_LAYERS);
|
toolPref.floodfill.referTo() == app::gen::FillReferTo::ALL_LAYERS);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
switch (toolPref.floodfill.pixelConnectivity()) {
|
||||||
|
case app::gen::PixelConnectivity::FOUR_CONNECTED: index = 0; break;
|
||||||
|
case app::gen::PixelConnectivity::EIGHT_CONNECTED: index = 1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonset.setSelectedItem(index);
|
||||||
|
|
||||||
stopAtGrid.Click.connect(
|
stopAtGrid.Click.connect(
|
||||||
[&]{
|
[&]{
|
||||||
toolPref.floodfill.stopAtGrid(
|
toolPref.floodfill.stopAtGrid(
|
||||||
@ -405,6 +424,18 @@ protected:
|
|||||||
toolPref.floodfill.referTo(app::gen::FillReferTo::ALL_LAYERS);
|
toolPref.floodfill.referTo(app::gen::FillReferTo::ALL_LAYERS);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
buttonset.ItemChange.connect(
|
||||||
|
[&buttonset, &toolPref](ButtonSet::Item* item){
|
||||||
|
switch (buttonset.selectedItem()) {
|
||||||
|
case 0:
|
||||||
|
toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::FOUR_CONNECTED);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::EIGHT_CONNECTED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
menu.showPopup(gfx::Point(bounds.x, bounds.y+bounds.h));
|
menu.showPopup(gfx::Point(bounds.x, bounds.y+bounds.h));
|
||||||
deselectItems();
|
deselectItems();
|
||||||
}
|
}
|
||||||
|
@ -246,6 +246,12 @@ public:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isPixelConnectivityEightConnected() override {
|
||||||
|
return (m_toolPref.floodfill.pixelConnectivity()
|
||||||
|
== app::gen::PixelConnectivity::EIGHT_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
gfx::Rect getGridBounds() override { return m_docPref.grid.bounds(); }
|
gfx::Rect getGridBounds() override { return m_docPref.grid.bounds(); }
|
||||||
gfx::Point getCelOrigin() override { return m_celOrigin; }
|
gfx::Point getCelOrigin() override { return m_celOrigin; }
|
||||||
void setSpeed(const gfx::Point& speed) override { m_speed = speed; }
|
void setSpeed(const gfx::Point& speed) override { m_speed = speed; }
|
||||||
|
@ -346,6 +346,7 @@ void floodfill(const Image* image,
|
|||||||
const doc::color_t src_color,
|
const doc::color_t src_color,
|
||||||
const int tolerance,
|
const int tolerance,
|
||||||
const bool contiguous,
|
const bool contiguous,
|
||||||
|
const bool isEightConnected,
|
||||||
void* data,
|
void* data,
|
||||||
AlgoHLine proc)
|
AlgoHLine proc)
|
||||||
{
|
{
|
||||||
@ -398,8 +399,39 @@ void floodfill(const Image* image,
|
|||||||
// Check below the segment?
|
// Check below the segment?
|
||||||
if (p->flags & FLOOD_TODO_BELOW) {
|
if (p->flags & FLOOD_TODO_BELOW) {
|
||||||
p->flags &= ~FLOOD_TODO_BELOW;
|
p->flags &= ~FLOOD_TODO_BELOW;
|
||||||
|
|
||||||
|
if (isEightConnected) {
|
||||||
|
if (p->lpos+1 < bounds.x2() &&
|
||||||
|
check_flood_line(image, mask, p->y+1, p->lpos+1, p->rpos, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
p = FLOOD_LINE(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->lpos-1 >= 0 &&
|
||||||
|
check_flood_line(image, mask, p->y+1, p->lpos-1, p->rpos, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
p = FLOOD_LINE(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->rpos+1 < bounds.x2() &&
|
||||||
|
check_flood_line(image, mask, p->y+1, p->lpos, p->rpos+1, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
p = FLOOD_LINE(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->rpos-1 >= 0 &&
|
||||||
|
check_flood_line(image, mask, p->y+1, p->lpos, p->rpos-1, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
p = FLOOD_LINE(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (check_flood_line(image, mask, p->y+1, p->lpos, p->rpos, bounds,
|
if (check_flood_line(image, mask, p->y+1, p->lpos, p->rpos, bounds,
|
||||||
src_color, tolerance, data, proc)) {
|
src_color, tolerance, data, proc)) {
|
||||||
done = false;
|
done = false;
|
||||||
p = FLOOD_LINE(c);
|
p = FLOOD_LINE(c);
|
||||||
}
|
}
|
||||||
@ -408,6 +440,31 @@ void floodfill(const Image* image,
|
|||||||
// Check above the segment?
|
// Check above the segment?
|
||||||
if (p->flags & FLOOD_TODO_ABOVE) {
|
if (p->flags & FLOOD_TODO_ABOVE) {
|
||||||
p->flags &= ~FLOOD_TODO_ABOVE;
|
p->flags &= ~FLOOD_TODO_ABOVE;
|
||||||
|
|
||||||
|
if (isEightConnected) {
|
||||||
|
if (p->lpos+1 < bounds.x2() &&
|
||||||
|
check_flood_line(image, mask, p->y-1, p->lpos+1, p->rpos, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (p->lpos-1 >= 0 &&
|
||||||
|
check_flood_line(image, mask, p->y-1, p->lpos-1, p->rpos, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->rpos+1 < bounds.x2() &&
|
||||||
|
check_flood_line(image, mask, p->y-1, p->lpos, p->rpos+1, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
if (p->rpos-1 >= 0 &&
|
||||||
|
check_flood_line(image, mask, p->y-1, p->lpos, p->rpos-1, bounds,
|
||||||
|
src_color, tolerance, data, proc)) {
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (check_flood_line(image, mask, p->y-1, p->lpos, p->rpos, bounds,
|
if (check_flood_line(image, mask, p->y-1, p->lpos, p->rpos, bounds,
|
||||||
src_color, tolerance, data, proc)) {
|
src_color, tolerance, data, proc)) {
|
||||||
done = false;
|
done = false;
|
||||||
|
@ -26,6 +26,7 @@ namespace doc {
|
|||||||
const doc::color_t srcColor,
|
const doc::color_t srcColor,
|
||||||
const int tolerance,
|
const int tolerance,
|
||||||
const bool contiguous,
|
const bool contiguous,
|
||||||
|
const bool isEightConnected,
|
||||||
void* data,
|
void* data,
|
||||||
AlgoHLine proc);
|
AlgoHLine proc);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user