Bug 485053 - Document.refreshProjection()/.waitForDone() doesn't wait for transform masks to complete
Summary: Document.refreshProjection()/.waitForDone() doesn't wait for transform masks ...
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: Scripting (show other bugs)
Version: 5.2.2
Platform: Homebrew (macOS) macOS
: NOR normal
Target Milestone: ---
Assignee: Krita Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-04 23:29 UTC by code
Modified: 2024-04-08 11:29 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
example repro script (646 bytes, text/x-python-script)
2024-04-04 23:29 UTC, code
Details

Note You need to log in before you can comment on or make changes to this bug.
Description code 2024-04-04 23:29:04 UTC
Created attachment 168159 [details]
example repro script

SUMMARY
When showing/hiding a transform mask or transform masked layer, there is often a significant delay before the mask is fully applied. Until then, a lower quality version is used. From my testing both `Document.refreshProjection()` and `Document.waitForDone()` ignore this and return the moment the low quality is available. If afterward you immediately trigger an export, the exported file will use the low quality version.

STEPS TO REPRODUCE
1. Create a medium-sized document
2. Import a much larger image as a new layer
3. Add a transform mask and scale the layer down to fit/fill the canvas
4. Manually hide the transformed layer
5. Programmatically set the transformed layer to visible, call `.refreshProjection()`, and export the document (example script attached)
  - optionally use `layer.setBlendingMode(layer.blendingMode())` together with `doc.waitForDone()` instead of `.refreshProjection()`

OBSERVED RESULT

The exported file contains the low-quality "preview" output from the transform mask

EXPECTED RESULT

Both `.refreshProjection()` and `.waitForDone()` should wait for the transform mask to fully apply, and the resulting exported file should use the full-quality transform mask output. If the 2-3 second delay includes artificial debouncing, that delay should be skipped.

SOFTWARE/OS VERSIONS
macOS: 13.5.1 (22G90)
Comment 1 code 2024-04-05 23:47:28 UTC
After digging through the source code online, it looks like this could be fixed with a call to `KisLayerUtils::forceAllDelayedNodesUpdate` in `Document::waitForDone()`. I would test this myself, but I'm having difficulty setting up the krita dev environment.
Comment 2 Bug Janitor Service 2024-04-06 18:27:25 UTC
A possibly relevant merge request was started @ https://invent.kde.org/graphics/krita/-/merge_requests/2110
Comment 3 Dmitry Kazakov 2024-04-08 11:29:33 UTC
Git commit d78219863dc37ec7ddd5af6d051bc9cdbf0c78fa by Dmitry Kazakov, on behalf of Agata Cacko.
Committed on 08/04/2024 at 11:29.
Pushed by dkazakov into branch 'master'.

Fix waitForDone() not waiting for transform mask update

Before this commit, if you had a very slow transform mask in an image
and you used a script to enable it, then running waitForDone() wasn't
enough to ensure that the transform mask stopped updating before
running any other code.
This commit ensures that it does wait until all the updates are done.

Test file can be just a simple document with one transform mask attached to
a paint layer with a scribble. The transform mask should heavily use Liquify
transform, since it is the slowest one at the moment.

Steps to reproduce:
1. Create test file
2. Disable the transform mask (so there will be some updates)
3. Run the script

Example test script (use in Scripter):
(comes from the bug report)

'''
from krita import *

doc = Krita.instance().activeDocument()
doc.activeNode().setVisible(True)

 #doc.refreshProjection()
doc.activeNode().setBlendingMode(doc.activeNode().blendingMode())
doc.waitForDone()

try:
    doc.setBatchmode(True)
    exportParameters = InfoObject()
    exportParameters.setProperty("alpha", True)
    exportParameters.setProperty("compression", 6)  # 0-9
    exportParameters.setProperty("indexed", False)
    if not doc.exportImage('/path/to/file/test485053.png', exportParameters):
        dialog = QMessageBox()
        dialog.setText("Error exporting")
        dialog.exec()
finally:
    doc.setBatchmode(False)
'''

M  +1    -0    libs/libkis/Document.cpp

https://invent.kde.org/graphics/krita/-/commit/d78219863dc37ec7ddd5af6d051bc9cdbf0c78fa