Skip to content

Conversation

MrStevns
Copy link
Member

@MrStevns MrStevns commented Sep 30, 2021

  • Filling on layer below when reference layer was all layers, would not allow stroke filling when applying on non transparent color
  • Filling with overlay would result in multiple undo operations for one paint operation...
  • Click fill with tablet would result in two fill events. (reported as fixed by Jose)

- Filling on layer below when reference layer was all layers, would not allow stroke filling
- Filling with overlay would result in multiple undo operations for one paint operation...
- Click fill with tablet would result in two fill events.
@MrStevns MrStevns changed the title Fix a few cases where fill drag behaviour didn't work as expected Fix a few cases where click fill and fill drag behaviour didn't work as expected Sep 30, 2021
Copy link
Member

@scribblemaniac scribblemaniac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to review this, but I need to understand the intent of this a little bit more first. Also I am unable to replicate either the multiple tablet event issues so @Jose-Moreno will have to test those parts at least.

This is a question for the team: How do you expect the fill drag behavior to work? To me, when you first press down, the color of the pixel at that location on the reference image (let's call this the origin color) is the only color filled for the duration of the fill drag. Each time the pointer moves it checks if the pixel color at the current location of the reference image, and if it matches the origin pixel (or perhaps matches within the color tolerance if that is enabled), then it does a flood fill using the reference layer to determine the fill region, and writing to the target layer using the specified blend mode. Based on the code, it doesn't look like it was doing that, and it is definitely not do that now. Not only is it filling all transparent areas, its behavior is tied to the the contents of the target layer which I just don't understand why that would be desirable.

When it comes to undoing and fill drag, the behavior I have observed (both on master and in this PR) is one undo event per region filled while dragging. Is this what we want? I think it's nice this way, but if you're filling a lot of smaller regions it could quickly fill up the undo/redo stack.

@MrStevns
Copy link
Member Author

Thanks for reviewing Scribble 🙏

I tried to review this, but I need to understand the intent of this a little bit more first. Also I am unable to replicate either the multiple tablet event issues so @Jose-Moreno will have to test those parts at least.

I tested the implementation with Jose and we both concluded that it seems to work as expected now. My understanding is that it's an Windows only issue but I'm not sure why it happens... presumably a Qt bug. I haven't experienced it on my macbook or virtual linux machine either.

This is a question for the team: How do you expect the fill drag behavior to work? To me, when you first press down, the color of the pixel at that location on the reference image (let's call this the origin color) is the only color filled for the duration of the fill drag. Each time the pointer moves it checks if the pixel color at the current location of the reference image, and if it matches the origin pixel (or perhaps matches within the color tolerance if that is enabled), then it does a flood fill using the reference layer to determine the fill region, and writing to the target layer using the specified blend mode. Based on the code, it doesn't look like it was doing that, and it is definitely not do that now. Not only is it filling all transparent areas, its behavior is tied to the the contents of the target layer which I just don't understand why that would be desirable.

The way I envisioned it is also based on the way that the behavior works in Clip Studio Paint (from my own testing and comparison), where even if the the reference mode doesn't look at all layers, you should never fill multiple times on the same color, even if that color ends up on a different layer.

In practice it should mean that there's no difference between the reference mode when it's about determining whether it should fill while dragging, which imo. improves the user experience.

When it comes to undoing and fill drag, the behavior I have observed (both on master and in this PR) is one undo event per region filled while dragging. Is this what we want? I think it's nice this way, but if you're filling a lot of smaller regions it could quickly fill up the undo/redo stack.

I too think this is a nice behavior, however we could merge the undo elements based on whether they are created within a given timespan, like if you move quickly and it fills 10 regions within 1 second or so, then it will count as one undo action, otherwise a new one is created. This might be out of scope for the current undo implementation but it's possible with the undo/redo rework PR.

- Use compareColor instead of raw pixel comparison for the ability to fill when the pixel is in average the same.
@MrStevns MrStevns force-pushed the BitmapBucket-fill-behaviour-bugs branch 3 times, most recently from b818f6c to 895fae0 Compare October 17, 2021 15:15
@MrStevns MrStevns force-pushed the BitmapBucket-fill-behaviour-bugs branch from 895fae0 to a197d52 Compare October 17, 2021 15:32
@MrStevns MrStevns force-pushed the BitmapBucket-fill-behaviour-bugs branch 2 times, most recently from a46e3b7 to e278c1e Compare May 12, 2022 18:49
@MrStevns MrStevns force-pushed the BitmapBucket-fill-behaviour-bugs branch from e278c1e to 27d73c0 Compare May 12, 2022 19:08
@MrStevns
Copy link
Member Author

MrStevns commented Aug 17, 2022

It would be nice to have this merged as it's also contains some fixes related to tablet behavior. I still believe that the implementation works as intended and there's tests to back it up but of course we should agree on the changes nevertheless

@chchwy
Copy link
Member

chchwy commented Aug 17, 2022

Will be looking at this PR soon.

@chchwy
Copy link
Member

chchwy commented Sep 14, 2022

I would suggest making another PR for the mouse/table event things next time. Let's focus on one thing at a time.

@MrStevns
Copy link
Member Author

Noted 👍 . At the time it made sense for me because the tablet bug was reproducible and somewhat related to the drag behavior but yes in hindsight I should have done that

@MrStevns
Copy link
Member Author

Any news regarding this PR, would it make it easier to review if I moved the double click event logic out?

@J5lx
Copy link
Member

J5lx commented Oct 30, 2022

I’ll take a look in a moment.

@J5lx J5lx self-assigned this Oct 30, 2022
Copy link
Member

@J5lx J5lx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the wait, I needed to do something else for a while because thinking about all the different cases to handle made my head spin. Like I said earlier, I’ve been able to reproduce the last two issues and can verify that they’re fixed, but not the first one. Thanks for helping me with that!

Right now there are still some cases that don’t seem quite right to me. I’ve also made some cosmetic changes which I’ll push in a moment. Other than that the changes look good to me all in all.

The real problem causing this has been fixed via pencil2d#1729
Layer setup:
Bitmap Layer Stroke
Bitmap Layer Fill

1. draw a circle on the stroke layer and slice it up with lines, so you can fill individual parts
2. set fillTo mode to "layer below" and reference to "all layers"
3. fill and drag a color, eg. red.. across the slices
4. Change fillTo mode to "current layer"
5. repeat step 3 with a different color
@MrStevns
Copy link
Member Author

MrStevns commented Nov 1, 2022

PR should be ready for review again

Copy link
Member

@J5lx J5lx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh, the way the effect of the fill tool varies based on the target layer setting doesn’t seem quite right. Either that or I just have a different concept of how target and reference layer should affect the fill behaviour. Anyway, I’m starting to develop a strong distaste of the fill tool… there’s just so many combinations of parameters to take into account… I feel like at some point we should add some human-readable documentation (and not just tests) on how the tool is supposed to behave (though not necessarily in this PR).

Code looks fine all in all… but I’m at a point where I’d like a (non-code) review of the functionality from at least one other person before we proceed with this PR. For now, thanks for all your hard work!

@davidlamhauge
Copy link
Contributor

Basically, I like the fill tool. I like the expand fill, and I also like the possibility to fill on the layer below.
On the other hand, I must side with Jakob, that there are many combinations, and it can be confusing.
A week ago I myself ruined a background for a project, because I accidently made a fill on the layer below, and when I realised what I'd done, the background was beyond repair. It was 100% my fault, but I'd wish there was some warning or indication, that I was about to fill on another layer. I will probably not be the only one making that mistake.
Besides this bad experience, I am very pleased with the fill tool.

J5lx pushed a commit that referenced this pull request Nov 8, 2022
)

* Fix mouse press event could be fired after a tablet release event

* Fix typo
@J5lx
Copy link
Member

J5lx commented Nov 8, 2022

I’ve cherry-picked the tablet event fix onto master.

@davidlamhauge Have you tried the fill behaviour changes from this PR?

@davidlamhauge
Copy link
Contributor

@J5lx No, I was commenting on your worries about too many combinations, and the possibility to make mistakes.
I have time to test it tomorrow. Anything I should test in particular?

@MrStevns
Copy link
Member Author

MrStevns commented Nov 8, 2022

Thanks for reviewing again Jakob and for the comments David 😃

However, I feel like talking about how the feature should behave is a little too late or not relevant as far as this PR goes.. the functionality is already there, this PR was only meant to fix bugs regarding existing functionality, not reinvent or remove the existing implementation. Can't we take this discussion in some other way that doesn't involve stalling the PR or derailing its purpose?

@J5lx
As far as the tool goes, you don't have to use all its features, just like blending modes, each feature is a something that can be used for a certain task or workflow. Of course if you feel like you're developing a distaste for the tool because it's getting too complex, then we should look into that.

@MrStevns
Copy link
Member Author

MrStevns commented Nov 9, 2022

I will try to write up how I envisioned the feature, with some examples, so we can all get a clear understanding of the logic. I should have some time later today.

@J5lx
Copy link
Member

J5lx commented Nov 9, 2022

Can't we take this discussion in some other way that doesn't involve stalling the PR or derailing its purpose?

I’m very sorry. I didn’t want to make you feel like your work was being artificially held up or sidetracked. I need to be more careful with my words.

The entire remark about the complexity of the fill tool has nothing to do with the changes introduced by this PR and is just an expression of my frustration at the unique challenges of reviewing them. Not because these particular changes are especially complex or anything, but because the fill tool in general, with its various parameters and the many possible combinations of them, is complex per se (in regard to its inner workings, not so much in regard to its usefulness in various workflows). And I’m not even sure if there’s much that can be done about it. That is, I don’t necessarily think it’s too complex, I just think it’s complex.

The reason I was still talking about intended functionality is not because I want to change it or turn this PR into something else, but because I feel that I should understand the intended functionality in order to properly assess whether this code implements it and I’m unsure if my current understanding of it is correct. More specifically, the current behaviour (of this PR) didn’t feel right for me and I wasn’t sure if that was because there’s actually something wrong with it or just because I misunderstood the intention behind it. The behaviour has changed throughout this PR in response to feedback and I wanted to make sure that all of it is still part of the fixes.

Maybe I’m being too fastidious. Or maybe this stuff is just too much for me and I should have left the review for someone more competent on this matter. Either way, I’m sorry I came off the wrong way. I’ll try to be more careful in the future and I’ll see if I can work on my approach to be more targeted. I’m looking forward to your write-up.

@MrStevns
Copy link
Member Author

MrStevns commented Nov 10, 2022

I’m very sorry. I didn’t want to make you feel like your work was being artificially held up or sidetracked. I need to be more careful with my words.

It's hard to convey emotions through text, and depending on what time of the day one reads and answers something, intend and understanding may differ. No need to apologize 😅

The entire remark about the complexity of the fill tool has nothing to do with the changes introduced by this PR and is just an expression of my frustration at the unique challenges of reviewing them. Not because these particular changes are especially complex or anything, but because the fill tool in general, with its various parameters and the many possible combinations of them, is complex per se (in regard to its inner workings, not so much in regard to its usefulness in various workflows). And I’m not even sure if there’s much that can be done about it. That is, I don’t necessarily think it’s too complex, I just think it’s complex.

That one is mostly on me, I should have written down the functionality the first time I made this proposal, so it would be clear how I intended it to work and so that in the future we would be to read up on its functionality. Hopefully the following write up makes it clearer 😄

The reason I was still talking about intended functionality is not because I want to change it or turn this PR into something else, but because I feel that I should understand the intended functionality in order to properly assess whether this code implements it and I’m unsure if my current understanding of it is correct. More specifically, the current behavior (of this PR) didn’t feel right for me and I wasn’t sure if that was because there’s actually something wrong with it or just because I misunderstood the intention behind it. The behavior has changed throughout this PR in response to feedback and I wanted to make sure that all of it is still part of the fixes.

That also makes sense, it's difficult to review something if it's too complex to understand from code alone or simply has too many combinations to understand the intend.
It's true that the behavior has changed a few times during the lifecycle of the PR, either to address a bug or me realizing an odd behavior.. so it's a good thing to have this clarified once a for all and not basing it on loose assumptions or what I say and don't say, is right.

Understanding the feature

The idea behind the drag to fill behavior is that you should be able to apply several fills in an easy and less error prone manner than manually clicking on a pixel several times, and we can do that because we know where you started.
To keep things simpler, we should be able to apply the following rules in all cases:

  1. You should be able to drag across and not fill any other pixel than transparent when the start drag position is a transparent pixel.
  2. When the start drag position is a colored pixel, only a pixel of similar (based on tolerance) color or an area which is transparent will be filled.

Also, the rules assume that the pixel to be compared against is found on the reference layer, ie. either the current or all layers based on the reference setting. This was how I envisioned it anyway...

How I tested:

Original image:
image
project: fill-drag-pr.pclx.zip

Bucket settings:

Blend mode: replace
Reference mode: current layer

Filling on the same layer

Rule Master PR Functionality Conclusion
You should be able to drag across and not fill any other pixel than transparent when the start drag position is a transparent pixel. master1 pr1 same Works as intended
When the start drag position is a colored pixel, only a pixel of similar (based on tolerance) color or an area which is transparent will be filled.: master2 pr2 same Works as intended

Filling on layer below

Rule Master PR Functionality Conclusion
You should be able to drag across and not fill any other pixel than transparent when the start drag position is a transparent pixel. master3 pr3 Differ, on master the target layer avoids filling where the reference color is, even though it's a different layer. On the PR branch, we don't take this into account anymore. PR algorithm is more loose about where to fill, is this better or worse? I'd say worse.. I think the master implementation is better.
When the start drag position is a colored pixel, only a pixel of similar (based on tolerance) color or an area which is transparent will be filled.: master4 pr4 Differs, on master the start pixel is filled and all other colors that are not the same or transparent are ignored. In the PR, the white background is kept, and filling happens on all reference points, because the fill to layer is blank. PR algorithm doesn't work entirely, the white pixels should have been filled and as with the Rule1, we should try to be smarter about where we paint, even if we're working on a different layer.

In other words... if we consider the initial implementation the best outcome, then there's still code to be written in order to make sure the rules apply, when painting on the layer below.

@MrStevns
Copy link
Member Author

MrStevns commented Nov 11, 2022

After having tried a few things, I'm pretty sure i have the algorithm sorted out now... now the only problem is that I don't like the fillTo feature anymore 😆

The reason is that when it's correctly implemented (ie. not the result of master...) then it's only usable when the reference is all layers, at least if you consider the rules I wrote down in the previous post and the test project.

For example:
filldrag-fillTo-stuff

I start by filling the layer below with a green color, at this point the reference is set to 'all layers', and both reference and target pixel is transparent, thus it works. Next I change the color to Purple and fill again, as I try it out with reference: 'all layers', it continues to work fine because we're scanning all layers, because both the reference and target color is found. This however doesn't work when I afterwards change to reference: 'current layer', because in this case the reference pixel is still transparent, only the target pixel is green and therefore it doesn't fill.

I thought it was a pretty cool feature in the beginning, because you would be able to both draw the lines of your animation and do the filling efficiently after, without having to jump between layers but the additional complexity it adds to the drag algorithm, makes me think otherwise.

Copy link
Member

@J5lx J5lx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally got around to taking a good look at this again (it’s taken me far too long, sorry!). Unfortunately it seems the bug with the multiple undo operations seems to have crept back in, and occurs irrespective of the blend mode now. But for a mercy, at least with the current version, I think fixing it might be relatively simple unless I’m overlooking something, so I’ll just make a PR. Other than that, the code seems to be fundamentally quite sound now in the sense that it seems to work as intended and there is no other unintended behaviour left.

However, I also agree with your verdict on the fill-to feature. I think you summed it up pretty accurately, and I don’t have much to add there. That said, keeping your previous comment about (not) derailing the PR in mind, if my PR finds your approval, I’d say it’s fine to merge this once those changes are in, since the current version is quite coherent. Then the fill-to feature can potentially be discussed separately. Does that sound alright to you?

@MrStevns
Copy link
Member Author

MrStevns commented Jan 8, 2023

Thanks for reviewing again Jacob, I've made a few smaller changes to make up for the more limited functionality of the fillTo layer mechanism now and fixed a bunch of typos. I have also merged your PR, so I'd say it's ready to be reviewed again

@MrStevns MrStevns force-pushed the BitmapBucket-fill-behaviour-bugs branch from 3b14075 to 343dfe9 Compare January 8, 2023 09:15
Copy link
Member

@J5lx J5lx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, seems like a sensible UI change. Will merge once checks have completed.

@J5lx J5lx merged commit 2ea34f3 into pencil2d:master Jan 8, 2023
@MrStevns MrStevns added this to the v0.6.7 milestone Jul 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

5 participants