Commit Graph

252 Commits

Author SHA1 Message Date
Alx Sa e678a20951 core: Initial non-destructive editing implementation
This patch implements an initial form of
non-destructive editing. Filters now stay active
instead of being immediately merged down.
A new column is added to the layer tree view, which
can be clicked to show a pop-over menu.
Filters can currently be hidden/shown, edited, reordered,
deleted, and merged down from this pop-over menu.

Currently, this works on layers and layer selections only.
Plenty of room for improvement!
2024-01-23 15:39:09 +00:00
Jehan 4776b092bd app: action names set in GimpToolControl don't need the group name appended.
Not with the new GAction-based actions.
2023-04-12 22:07:08 +02:00
Jehan 622d0da43e app, libgimpwidgets: allowing changing a dockable settings value while…
… blinking it.

This will be necessary to demo new features available only in some
situations. E.g. a new option in line art detection mode of bucket fill
would require said mode to be enabled.
2022-03-06 19:30:31 +01:00
Jehan 60a9c90074 app: create a concept of "blink scenario" to blink several widget in…
… a given order, not at the same time.

This will be used for the release item notifications to show people
where new or changed features are, but in an ordered blink scenario. For
instance: select a tool first, then blink some tool icon, open the tool
options and finally blink the specific new/changed option. I am hoping
it would help awareness of changes (just words on a web news may make
some features a bit foreign when not used to look in details in advanced
options).
2022-03-05 17:42:54 +01:00
Jehan 5dcc833398 app: move gimp_tools_blink_widget() as gimp_blink_dockable() in…
… gimpwidgets-utils.h.

It just makes more sense, even in terms of #include-s which we'd need to
make.
2022-03-05 17:42:54 +01:00
Jehan e1c3e7d85b app: use new gimp_tools_blink_widget() to blink source scrolldown.
When the bucket fill can't work because the line art source is not
right, let's blink the associated settings for people to know where to
look at.
2022-03-04 15:41:53 +01:00
Jehan d3686fdb9c app: make the "Automatic closure" a settings of its own.
This is the same thing as setting the max gap length to 0, except that
it would mean constantly having to play with the gap length and possibly
losing settings you carefully tweaked. Instead with this additional
settings, we hide the gap length settings when automatic closure is
disabled.

Also it makes kind of a nice parallel with the "Manual closure" settings
which can also be enabled/disabled similarly.
2022-03-03 20:05:14 +01:00
Jehan 46d2d19724 app: new manual closure option can't work with pattern fill. 2022-03-03 18:44:03 +01:00
Jehan ab8e7b6358 app: allowing to choose the paint tool used for stroking. 2022-03-03 18:44:03 +01:00
Jehan 76699e89ac app: add a new feature to stroke the line art fill borders.
Currently the option is quite simple. What should happen to make it more
usable:

* Right now, it uses the last stroke options (e.g. as used in a
  previously run "Stroke Selection" or "Stroke Path"). We should have
  some dedicated GUI in the bucket fill options.
* The bucket fill options GUI should really be redesigned. The more we
  add options, the less understandable it is.
* There is a question whether we want to just use whatever brush size is
  being set or if we want to have it vary and follow the line art width
  (since we have proper distance map, we could use this to tweak the
  stroke per-coords).

As usual, this feature was suggested by Aryeom who was still very
saddened that despite all the fancy features in this tool, it is not
able to produce nice rendering. So she proposed that the tool could
stroke the fill region borders.
2022-03-03 18:44:03 +01:00
Jehan e72f5614da app: properly blink the right locked layer when pixels are locked.
In particular, if painting on a layer whose parent's pixels are locked,
we were blinking an empty lock spot, which is confusing. Now
gimp_item_is_content_locked() will also return the proper item (when
relevant, i.e. when returning TRUE) which is locked. It may or may not
the same item as passed in (it may also be a parent item in particular).
2022-02-15 22:08:23 +01:00
Jehan 35cef54899 app: fix handling multi-drawables selected in bucket fill tool.
We were getting a critical when selecting multiple drawables (either
changing layer selection while the tool is ON, or starting with multiple
selection). We should not have assert code here, just handle the case
gracefully with a normal error message when trying to fill on several
layers at once.
2022-02-09 00:27:04 +01:00
Jehan e7668c03bd app: add some new feature to close line arts manually.
The line art algorithm is useful but not always accurate enough and
sometimes it can even be counter-productive to fast painters.

A technique of advanced painters which Aryeom uses and teaches when she
wants to close an area without actually closing the line art (i.e. the
non-closed line is a stylistic choice) is to close with a brush the area
on the color layer. It has also a great advantage over the line art
"smart" closing algorithm: you control the brush style and the exact
shape of the closure (therefore something you'd usually have to redo
with a closure made by an algorithm as you would likely not find it
pretty enough).
This new feature takes this technique into account. Basically rather
than relying on the closure algorithm, you would close yourself and the
tool is able to recognize closure pixels by the color proximity with the
fill color.

Final point is that this additional step is made after line art
computation i.e. in particular the target drawable is not added to the
sources for line art logics. This allows to stay fast otherwise the line
art would have to recompute itself after each fill.

This also shows why the previous commit of moving the line art object
was necessary, because a painter would likely want to move regularly
from bucket fill to a brush tool to create area closures and we want to
avoid recomputation every time.
2022-02-08 23:45:22 +01:00
Jehan 0db35973c8 app: temporarily move GimpLineArt ownership to context when bucket…
… fill tool finalizes.

The idea is that you may want to quickly switch tool to do something and
back to the bucket fill for line art selection. If the input drawable(s)
did not change, the previously computed data is still valid, so let's
hang on the line art object a little longer.
Since we are resetting the input when we get back, we would still
recompute anyway *if needed*, and the line art object does follow
changes on the input pickable so we would not get any deprecated data
anyway. Still we move around ownership a tiny bit to optimize for
common case of tool switching.

In order not to keep forever this data (buffer and distmap in
particular) forever just because one tried the line art once, I add a
timer to free it after a few minutes.

Moreover it will be useful for other cases, such as being able to share
the same line art object with the fuzzy select tool (if we end up adding
the line art option there). In a coming commit, the usage will be even
more obvious for use case where you want to edit the filled area with
other paint tools, then back to bucket fill while not touching the line
art source layer.
2022-02-08 23:45:22 +01:00
Jehan c7b3c3c629 app: free leaking drawable list (as reported by Massimo). 2021-08-14 13:35:48 +02:00
Jehan 03af9da83b app: GimpTool multi-drawable aware.
Right now I don't change the logics of any of the tools, except that the
GimpTool class now stores a list of drawables instead of a single
drawable. This can be later used on a case-by-case basis to make various
tools actually work on multiple drawables.
2020-05-26 14:15:17 +02:00
Jehan bcacf6e2ae app: "active item" concept => "selected items".
After much thought, tests and discussions with Aryeom, we decided adding
back an active item concept additionally to the selected items ones is a
bad idea as it makes only usage unecessarily complex.
We will just have selected layers. Some kind of operations will work
when more than one item (layers, channels, vectors) are selected while
others will require exacty one item.

In particular, let's replace instances of gimp_image_(s|g)et_active_*()
by corresponding gimp_image_(s|g)et_selected_*(). Also replace single
item in various undo classes by GList of items.
Also "active-*-changed" GimpImage signals are no more, fully replaced by
"selected-*s-changed".

This is still work-in-progress.
2020-05-17 18:32:16 +02:00
Jehan f7b86c9062 app: fix selection after a drag'n drop move.
Though it's not finished yet, I am changing "active layer" into
"selected layers" logics. Probably the "active layer" concept will be
back eventually (i.e. even in a multi-selection a specific layer could
be said "active", highlighted in the list a bit differently, hence one
could edit this specific layer only). But for simplicity, for now, it's
better to first get rid of it, otherwise it's just messy.
2020-05-17 18:32:15 +02:00
Ell 43a1c33ecf app: add "show all" support to the Bucket Fill tool in line-art mode
In the Bucket Fill tool, when using line-art mode, use a
GimpImageProxy as input for the GimpLineArt object, instead of
using the image direclty, when the line-art source is "all visible
layers".  Set the proxy's show-all mode according to the active
shell, so that the line-art uses the full image projection,
including out-of-canvas regions, when in show-all mode.
2019-11-04 13:27:04 +02:00
Jehan 16d9c1f00d Issue #4049: Colour fill on Line Art Detection misaligned when…
… different layer size/location used.

We need to use the source coordinate space when generating the first
fill buffer, then transform to the target layer coordinate space when
applying the drawable filter.
2019-10-12 13:12:11 +02:00
Ell 17f8cff6f6 app: add "show all" support to the bucket-fill tool in "fill similar colors" mode
In the bucket-fill tool, allow using the tool outside the canvas
bounds with "sample merged" active in "fill similar colors" mode,
when the current display is in "show all" mode.  Additionally,
ignore "sample merged" in "fill whole selection" mode, on which it
has no effect.
2019-09-05 18:04:12 +03:00
Ell cf3638391d app: add support for color picking in "show all" mode
Add a show_all parameter to gimp_image_pick_color(), which, when
TRUE, allows picking colors outside the canvas bounds in sample-
merged mode.  Forward the display's "show all" mode through this
parameter where applicable (in particular, in the color-picker tool
and the pointer dockable).
2019-09-04 20:51:43 +03:00
Jehan 6391b2bcff Issue #3263: fix critical error on bucket fill tool.
Fixes the error:
> Critical error: gimp_line_art_thaw: assertion 'line_art->priv->frozen'

This may happen in cases when we didn't actually freeze the line art at
pointer click, because we were in an invalid case (for instance,
clicking out of selection), hence we must not thaw the line art either
at button release.
2019-08-27 12:41:49 +02:00
Michael Natterer e47936182e app: some formatting in the edit non-visible layers code 2019-06-24 15:57:21 +02:00
woob 39c71c6fb3 app: Add initial support for configurable editing of non-visible layers (Issue #2713)
Add a "edit-non-visible" configuration option, found under
Edit->Preferences->Tool Options as "Allow editing on non-visible layers"
2019-06-23 16:15:59 +03:00
Jehan d821b088e2 app: change antialias feature in fill by line art into Feather Edges.
This was actually more of a feathering feature I added earlier, and we
already have a function for that: gimp_gegl_apply_feather(). This is
using a gaussian blur, just as what I was doing anyway. This commit also
adds the "Feather Radius" scale, similar to other tools with the
"Feather Edges". So that makes it consistent (and more useful as you can
adapt to your needs).
2019-03-28 14:06:17 +01:00
Jehan c0996241f6 app: avoid useless line art closure recomputation.
On various property changes, only recompute the line art when the
property actually changed. Also add a gimp_line_art_bind_gap_length() to
avoid computing twice the line art when changing both type of closure
(splines and segments) together, as is currently the case.
2019-03-04 16:43:19 +01:00
Jehan bc187cc5cc app: add a GimpBusyBox near the "Line Art Detection" label in…
… Bucket Fill tool options.
This will provide feedback when the line art closure is being computed,
which may be useful on big images where it may take some time. Otherwise
painter may be left hanging without knowing what takes time.
2019-03-04 16:06:59 +01:00
Jehan 74cfd4fd95 app: error messages should happen on button press, not initialization.
The initialization is sometimes done when switching tools (for instance
when selecting the active tool by command), not always on button press.
So the error output behavior was inconsistent, and worse, the tool was
sometimes not forbidden to run when it should have been.
Just run all the checks (layer groups, locks and whatnot) on button
press.
2019-02-09 22:33:36 +01:00
Jehan 9c13058d54 app: allow more motion events with line art bucket fill.
When a fill zone was a bit too segmented, you'd want to just stroke
across it. But it was leaving some pieces uncolored, even though the
pointer dragged through it! The exact motion mode allows more events.

Note: I don't set it in the similar color filling (where it could have
been useful too) mostly because it is harder to remove events then (even
if a point was already filled, it could still serve as a seed for more
filling if threshold > 0), thus implied too much processing. Anyway in
all my tests, it was more a problem for line art filling anyway.
2019-01-23 16:59:45 +01:00
Jehan 0a952a3429 app: fix a crash in bucket fill tool.
In commit c71b4916af, I forgot to disconnect signals on the bucket fill
options at finalization, leading the software to crash on an
non-existing tool.
2019-01-17 13:48:40 +01:00
Jehan c71b4916af app: add the concept of line art source to Bucket Fill tool.
Additionally to sample merge and active layer, now we can only use the
layer above or below the active layer as line art source.

The line art fill is meant to work on drawing lines. Though sample merge
still is ok in many cases, the more you fill with colors, the more the
line art computation becomes unecessarily complex. Also when you use a
lot of layers with some of them already filled with colors, it makes it
impossible to colorize some line art zones with the tool. Moreover you
just don't want to have to hide every layers out there to colorize one
layer (especially background layers and such as you may want to see the
result with your background).
Thus we want to be able to set the source as a unique layer, while it
not being necessarily the active one (because you want lines and colors
on different layers). In this case, I am assuming that the color and the
line layers are next to each other (most common organization).
2019-01-15 16:06:50 +01:00
Ell 4b4fffbd0e app: in bucket fill tool, don't calculate line art of layer groups
... since they can't be used with the fill tool.
2019-01-07 04:27:24 -05:00
Ell 823d4a0d24 app: in bucket-fill tool, avoid calculating line art when not in line-art mode
In the bucket-fill tool, don't pre-calculate the line art when not
using a line-art fill area.  Also, misc. cleanup.
2019-01-06 16:30:41 -05:00
Michael Natterer 292903b78d app: wrap some overly long lines in gimpbucketfilltool.c
and some other pedantic style fixes.
2019-01-02 16:34:20 +01:00
Jehan 503775a5a0 app: rename and merge the spline and segment length properties...
... in GimpBucketFillOptions for the line art algorithm.

Inside GimpLineArt, there are still 2 properties, but we don't show them
anymore in the Bucket Fill tool options. One of the main reason is
probably that it's hard to differentiate their usage. One is to close
with curved lines, the other with straight segments. Yet we don't
actually have any control on one or the other. All one knows is that you
can have "holes" in your drawing of a given size and you want them
close-like for filling. Only reason I can see to have 2 types of closure
is whether you'd want to totally disable one type of closure (then you
set it to 0). But this is a very limited reason for making the options
less understandable overall, IMO.
So for the time being, let's show up only a single option which sets
both properties in GimpLineArt. As patdavid says "it makes sense as a
first pass".

Also rename the option to shorter/simpler "Maximum gap length". Thanks
to patdavid and pippin for helping on figuring out this better label!

Finally I am bumping the default for the gaps to 100px. The original
values were ok for the basic small images used in demos, but not for
real life image where it was always too short (even 100px may still be
too short actually, but much better than the 20 and 60px from before!).
2018-12-24 13:33:58 +01:00
Jehan cd924f453a app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!

This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.

I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 15:27:48 +01:00
Jehan 5a157bf1ba app: allow switching fill type with Alt even when Pattern fill selected.
Currently in bucket fill tool, the modifier was only switching fg to bg
and bg to fg, and was doing nothing when pattern was set. I make it
switch to fg as well (and remember which was the original value).
2018-12-10 16:47:47 +01:00
Ell 637105b962 app: in all tools, blink lock box when the current item is locked
In all tools, when the current item can't be edited due to its lock
mask, use gimp_tools_blink_lock_box(), added in the previous
commit,to blink the lock box of the corresponding dockable, in
addition to showing an error message in the status bar, to hint at
the source of the error.
2018-12-10 08:55:17 -05:00
Jehan db18c679f3 app: reorganize the line art code inside a GimpLineArt object.
The code was too much spread out, in core and tool code, and also it was
made too specific to fill. I'll want to reuse this code at least in the
fuzzy select tool. This will avoid code duplication, and also make this
new process more self-contained and simpler to review later (the
algorithm also has a lot of settings and it is much cleaner to have them
as properties rather than passing these as parameters through many
functions).

The refactoring may not be finished; that's at least a first step.
2018-12-07 22:18:06 +01:00
Ell 6103f0e5d0 app: use gimp_async_add_callback_for_object() in the bucket-fill tool
... for the same reason as commit
7c00cf498a.
2018-11-30 04:14:59 -05:00
Jehan d71efdec20 app: add the segment and spline max length options for line art.
We can't just hardcode this. On huge images in particular, you'll want
to increase this value.
2018-11-29 17:29:42 +01:00
Jehan 5d4281944f app: make GimpBucketFillTool a GimpColorTool.
In particular, it allows to easily color pick. This just makes sense as
the bucket fill is definitely what one could call a "color tool", and
being able to easily change color without having to constantly switch to
color picker tool nor open a color chooser dialog is a must.

The fill type option (FG/BG/Pattern) was already mapped to the common
toggle behavior key (Ctrl on Linux), which is commonly used for
switching to color picker on paint tools. So I decided to remap the fill
type switch to GDK_MOD1_MASK (Alt on Linux) to keep consistent with
other tools (at the price of a change for anyone used to this modifier,
though I doubt it was that much used).
I also made possible to combine the 2 modifiers (so you could pick the
foreground or background color with ctrl and ctrl-alt).
2018-11-27 17:25:05 +01:00
Jehan 6bec0bc82d app: radius map actually not useful during smart colorization grow step.
The distance map has all the information we need already. Also we will
actually grow up to the max radius pixel (middle pixel of a stroke).
After discussing with Aryeom, we realized it was better to fill a stroke
fully (for cases of overflowing, I already added the "Maximum growing
size" property anyway).
2018-11-27 14:59:35 +01:00
Jehan eb042e6c87 app: add "line-art-max-grow" property to the bucket fill options.
When flooding the line art, we may overflood it in sample merge (which
would use color in the line art computation). And if having all colors
on the same layer, this would go over other colors (making the wrong
impression that the line art leaked).
This new option is mostly to keep some control over the mask growth.
Usually a few pixels is enough for most styles of drawing (though we
could technically allow for very wide strokes).
2018-11-22 18:13:58 +01:00
Jehan 3467acf096 app: replace gegl:watershed-transform with custom algorithm.
We don't really need to flow every line art pixel and this new
implementation is simpler (because we don't actually need over-featured
watershedding), and a lot lot faster, making the line art bucket fill
now very reactive.
For this, I am keeping the computed distance map, as well as local
thickness map around to be used when flooding the line art pixels
(basically I try to flood half the stroke thickness).

Note that there are still some issues with this new implementation as it
doesn't properly flood yet created (i.e. invisible) splines and
segments, and in particular the ones between 2 colored sections. I am
going to fix this next.
2018-11-22 14:24:52 +01:00
Jehan 36c885a6df app: fix a line art leak in bucket fill tool.
Introduced in commit b4e12fbbbb:
gimp_pickable_contiguous_region_prepare_line_art_async() was running
gimp_pickable_flush(), which provokes the "rendered" signal on the
image projection when a change occured. As a result, it was calling
gimp_bucket_fill_compute_line_art() within itself and since
tool->priv->async was not set yet, none of the call were canceled. Hence
the same line art is computed twice, but one is leaked.
Make sure we block this signal handler as a solution.
2018-11-20 17:53:32 +01:00
Ell b4e12fbbbb app: add gimp_pickable_contiguous_region_prepare_line_art_async() ...
... and use in bucket-fill tool

Add gimp_pickable_contiguous_region_prepare_line_art_async(), which
computes a line-art asynchronously, and use it in the bucket-fill
tool, instead of having the tool create the async op.

This allows the async to keep running even after the pickable dies,
since we only need the pickable's buffer, and not the pickable
itself.  Previously, we reffed the pickable for the duration of the
async, but we could still segfault when unreffing it, if the
pickable was a drawable, and its parent image had already died.

Furthermore, let the async work on a copy of the pickable's buffer,
rather than the pickable's buffer directly.  This avoids some race
conditions when the pickable is the image (i.e., when "sample
merged" is active), since then we're using image projection's
buffer, which is generally unsafe to use in different threads
concurrently.

Also, s/! has_alpha/has_alpha/ when looking for transparent pixels,
and quit early, at least during this stage, if the async in
canceled.
2018-11-19 15:06:38 -05:00
Ell 663a6c7011 app: in bucket-fill tool, cancel async on tool destruction
When computing line-art, don't ref the bucket-fill tool in the
async data, and rather cancel any ongoing async upon tool
destruction, so that the async callback doesn't attept to touch the
now-dead tool.  This avoids segfaulting in the async callback when
switching to a different tool, while a line-art async operation is
active.

Additionally, always cancel any previous async operation in
gimp_bucket_fill_compute_line_art(), even if not starting a new
one.
2018-11-19 15:06:38 -05:00
Ell 2e45c4c8c8 app: in bucket-fill tool, fix potential leak when computing line-art
In the line-art async function, pass ownership over the resulting
buffer to the async object, so that the buffer is properly freed in
case the async in canceled after line-art computation is complete,
but before the completion callback is called.

Also, clear the tool's async pointer in the completion callback, to
avoid leaking the last issued async.
2018-11-19 10:54:05 -05:00