Godot Version:
4.7.1
Problem:
I have a drag and drop system. The thing is that I have an auto-scroll feature that makes the scroll move with a certain speed. I noticed that if I have some high speed, my data is dropped into another node, not the one that was dropped, and it is in the opposite direction of the movement (nodes that I leave behind when I move).
I am guessing that the node is dropped before the scroll is calculated (although when I debug, it looks fine) and it targets another node.
I have thought that the only solution would be to wait and draw the frame before _drop_data() is called, but even then I do not know if the values it receives would be correct.
I have already thought about “guessing” the data. I could stop _drop_data() and manually call it with the drag data once I have drawn, but I do not like this solution and maybe it would not be possible.
Waiting (await get_tree().process_frame) when the scroll is drawn does not solve this.
The application is Taskesy 2 on Steam and it happens when I move boxes or columns through the scroll at a high speed.
A _drop_data just gets a position relative to the control, so I’m not really sure what waiting a frame would achieve.
What is your control hierarchy and where on it are you testing for the drop data?
My guess is you’ve got it on something to do with the scroll itself rather that what is being scrolled? I’d suggest you might need to place _drop_data’s etc onto the components you’re wanting to get the data rather than trying to calculate which component the drop should refer to? As I haven’t seen what you’ve done, it’s just a (very) wild guess which may be completely off the mark.
To simplify things, basically my boxes can be dropped to other boxes. The thing is that I have made an auto-scroll system so when you move a box in the direction where you want to move to another box, if the scroll is big you will be moving at a high speed.
If I drag and drop while I have a lot of speed, the box where I dropped the dragging box does not receive the dropping box; it is another one.
Let’s see an example. Imagine that there are from 0 (top of the scroll) to N (bottom of the scroll) boxes in a vertical scroll, and I am dragging the box at index N-2. There are a lot of boxes between 0 and N, so I want to move the box upwards in the scroll. When I get a lot of speed when moving to the top due to the auto-scroll system. If I were to drop the dragging box (N-2) to box 0, although I drop it at box 0, another box will receive the dropping box (N-2), for example, box 6.
That is my problem, it should have been dropped to box 0, but box 6 receives the dragging box and its _drop_data() function is called, not the one of box 0.
My approach to waiting frames was to see if at the moment when I drop the dragging box, the scroll may not have been calculated properly so the position is the one of another box.
The boxes have a script with the _drop_data() function, I do not guess anything, that was just a possible (unwanted) solution.
Here you have a real example of my problem. In the first part, you see that I drag and drop the box to box “0”, but the box appears elsewhere. This only happens at a high speed and then I showcase the normal behaviour in two different boxes.
Maybe this example showcases that waiting frames might not be a solution either, because the scroll looks good at the moment of dropping the box and the receiving node is very far from the intended box 0.
If the speed is not this fast, then the auto-scroll system always works fine.
Well I said it was a wild guess as to what your code might be doing and that I could be completely off the mark…
Anyway, looking at your video, it would appear that your auto scroll routine is doing something with testing that you’re on the first item of the scroll area? You probably need to be looking at that code rather than on the drop side of things. The thing is that you’re not really in control of what the server will say is the box you dropped it on, so I’m drawing a blank on what you can do to fix it.
However mulling it over you may be able to get around the issue…
I notice you can’t drop between the boxes. It might make sense if you could anyway so perhaps you need to implement it in one of the ways I was guessing you might have been trying to implement it.
You could just do this when the screen is scrolling rather than all the time. To do that just say that you can’t drop on a box if your auto-scrolling is scrolling. That should pass the drop mechanism onto the next drop mechanism.
Then add drop code to the container inside the scroller. This should then run when over the gaps between the boxes and when the boxes aren’t accepting drops (e.g. when auto-scrolling). If your boxes are all the same size as in the video then you should be able to calculate the box via the position / (box size + gap size). I suspect the boxes aren’t going to all be the same size outside your demo scenario. Not sure how you could calculate which box it was then. It may turn out the position is still incorrect anyway and would give you the wrong coordinate, so it might be worth experimenting by implementing this just to see if you get a value near 0 for the y position or say 1000 or more which would be about where row 13 would be. Knowing both get it wrong might tell you something (although not sure what).
If the issue is just when you drop at the top you could also use the above mechanism and then only use the drop if the y position is less than the size of the first box, therefore presuming any larger number is one of the gaps and therefore not supported? In that respect it could be a work around.