Storeroom of scripts

This topic is a place to freely post little scripts that can be used in Krita.

Do you have a short script that you use on a regular basis, or a script that you wrote on a whim but found it useless?
What may be boring code to you may be a coding tip to someone else. Please post your scripts here that aren’t good enough to be finished as a plugin, and as Krita Scripting’s sample code accumulates, the result will be an important resource. Scripts that can be pasted into the scripter and executed are preferred, but those that do not are acceptable.

Topic Policy

  • Scripts do not have to be advanced
  • Scripts can be useful or not.
  • You do not have to maintain your own scripts. You are not obligated to answer questions or requests from anyone.

A script can be enclosed by writing three grave accents ``` above and below its text.

12 Likes

Script to slightly decrease the transparency of the active layer

def opacityMinus():
    activeDoc=Krita.instance().activeDocument()
    activeNode=activeDoc.activeNode()

    activeOp = activeNode.opacity()
    setOp = activeOp - 5

    activeNode.setOpacity(setOp)

    ###Code to update the screen
    activeNode.setVisible(not activeNode.visible())
    Krita.instance().action('toggle_layer_visibility').trigger()
    ###
opacityMinus()

:
Script to increase transparency

def opacityPlus():
    activeDoc=Krita.instance().activeDocument()
    activeNode=activeDoc.activeNode()

    activeOp = activeNode.opacity()
    setOp = activeOp + 5

    activeNode.setOpacity(setOp)

    activeNode.setVisible(not activeNode.visible())
    Krita.instance().action('toggle_layer_visibility').trigger()
opacityPlus()

The refreshProjection() function is provided to refresh the screen, but it is heavy processing, so I use another method.

6 Likes

Thank you for making this thread

Here’s a script that
Duplicates layers and merges them together With 1 click

Krita.instance().action(‘duplicatelayer’).trigger()
Krita.instance().action(‘merge_layer’).trigger()

Here’s a script to create shortcut to liquify tool

from krita import (
Krita,)
from PyQt5.QtWidgets import (
QApplication,
QDockWidget,
QToolButton)
def call_liquify():
app = Krita.instance()
qwin = app.activeWindow().qwindow()
KisToolTransform = app.action(“KisToolTransform”)
KisToolTransform.trigger()
# give krita some time to process tool change…
QApplication.processEvents()
# now, KisToolTransform should be fully initilized.
liquifyButton = qwin.findChild(QToolButton, “liquifyButton”)
liquifyButton.click()
call_liquify()

6 Likes

Create a clone layer and give it the same name as the clone source layer and a symbol.

def namedClone():
    activeDoc=Krita.instance().activeDocument()
    activeNode=activeDoc.activeNode()

    namex = activeNode.name()
    cloneLayer=activeDoc.createCloneLayer("==" + namex, activeNode)

    # create clone above activeLayer
    activeNode.parentNode().addChildNode(cloneLayer, activeNode)
namedClone()
7 Likes

Collapses all layer groups.

def collapseAll():
    def rec(nodes):
        for node in nodes:
            if node.type() == "grouplayer":
                rec(node.childNodes())
                node.setCollapsed(True)

    doc = Krita.instance().windows()[0].activeView().document()
    nodes = doc.topLevelNodes()
    rec(nodes)
collapseAll()
6 Likes

I think it is in keeping with the spirit of this topic, and it is fine to also link to scripts posted elsewhere on the forum.

@onde_hurlante just posted this one:


Besides, I think this topic is a very good idea @dk8, I hope this “storeroom” develops into a “goldmine of scripts”!

Michelist

1 Like

I have collected all the scripts I have seen (from github and KA forums). Although I marked them with Chinese notes, you can know their usage from the original links:
脚本 (yuque.com)

5 Likes

Fill in foreground color absolutely .

application = Krita.instance()
window = application.activeWindow()
view = window.activeView()

currentBlend = view.currentBlendingMode()
kritaEraserAction = application.action("erase_action")
eraseCheck = kritaEraserAction.isChecked()##TorF

kritaEraserAction.setChecked(False)
view.setCurrentBlendingMode("normal")
application.action('fill_selection_foreground_color').trigger()

# back to pre-setting
kritaEraserAction.setChecked(eraseCheck)
view.setCurrentBlendingMode(currentBlend)

Krita erases the canvas when the (‘fill_selection_foreground_color’) action is performed if the current pen is in erase mode. However, switching pens to perform a fill can be tedious. This script allows you to always fill with foreground color no matter what setting you have your pen set to.

8 Likes

:heart_eyes: What a great idea! I often fill with “erasing” accidentally, which disorientates me when it happens. For a total script noob like me, where should I paste this script to make it auto-loading whenever I start a new Krita session?

The easiest way is to save this code as a text file and register it in ten scripts. The script will then be able to be executed by actions or action shortcuts.
To attach it to Krita as an extension, I would need to create a plugin file, but that is outside the scope of this “feel free to leave code” topic for me to do.

In the meantime, Script School has instructions on how to create a plugin…
https://scripting.krita.org/lessons/plugins-introduction

5 Likes

Oops, correction.
When saving code, use “.py” instead of “.txt” extension.
For example, if you name the file “fillColorAbs.py” and save it, ten scripts will be able to load it.
But it works without Python installed? I’m also just a beginner so I don’t know. :wink:

2 Likes

Activate previous layer (ignore group)

activeDoc=Krita.instance().activeDocument()
node = activeDoc.activeNode()
nodeCon = node.childNodes()
childs = node.parentNode().childNodes()

if nodeCon != []:
    topNode = nodeCon[-1]
    activeDoc.setActiveNode(topNode)
else:
    while node == childs[0]:
        node = node.parentNode()
        childs = node.parentNode().childNodes()

    nodeNum = node.index()
    preNodeNum = nodeNum - 1

    preNode = childs[preNodeNum]
    activeDoc.setActiveNode(preNode)

Krita’s “Activate Previous Layer” action cannot select a layer over two or more “steps” in a group. The layer selection is stopped in the middle of the layer group hierarchy.
This script avoids that and always moves to the layer below in the layer docker.
I feel like it could be cleaner code, but this topic also allows for dirty code… :slightly_smiling_face:

3 Likes

Script to click on the canvas.

from krita import Krita
from PyQt5.QtCore import (
        Qt,
        QPoint,
        QPointF,
        QEvent)
from PyQt5.QtGui import (
        QMouseEvent,
        QCursor)
from PyQt5.QtWidgets import (
        QWidget,
        QApplication)

def find_current_canvas():
    application = Krita.instance()
    q_window = application.activeWindow().qwindow()
    q_stacked_widget = q_window.centralWidget()
    q_mdi_area = q_stacked_widget.currentWidget()
    q_mdi_sub_window = q_mdi_area.currentSubWindow()
    view = q_mdi_sub_window.widget()
    for c in view.children():
        if c.metaObject().className() == 'KisCanvasController':
            viewport = c.viewport()
            canvas = viewport.findChild(QWidget)
            return canvas

def click_canvas(global_pos=None):

    canvas = find_current_canvas()
    if global_pos is None:
        global_pos = QCursor.pos()# cursor position
        global_posF = QPointF(global_pos)
        posF = QPointF(canvas.mapFromGlobal(global_pos))
    else:
        global_pos = QPoint(global_pos)
        global_posF = QPointF(global_pos)
        posF = QPointF(canvas.mapFromGlobal(global_pos))

    button = Qt.LeftButton
    buttons = Qt.LeftButton
    key_state = Qt.NoModifier

    mouse_press = QMouseEvent(
            QEvent.MouseButtonPress,
            posF,
            button,
            buttons,
            key_state)

    mouse_release = QMouseEvent(
            QEvent.MouseButtonRelease,
            posF,
            button,
            buttons,
            key_state)

    if not canvas.isActiveWindow():
        canvas.activateWindow()
    QApplication.sendEvent(canvas, mouse_press)
    QApplication.sendEvent(canvas, mouse_release)

click_canvas()

This is a simplified version of the one taught in this topic.

It can be used to force tools that require manual clicking, such as continuous selection or layer selection, to work programmatically, but it will not be useful in many situations.
Note that if you register this script to a shortcut that includes the Shift key, for example, the result will be a Shift+click situation.

To create new layer under the current layer instead of on top of current layer

from krita import *
def getNextSibling(node):
previousNode=None
for foundNode in node.parentNode().childNodes():
if foundNode==node:
return previousNode
previousNode=foundNode
return previousNode
doc=Krita.instance().activeDocument()
if doc:
currentNode=doc.activeNode()
if currentNode:
newNode=doc.createNode(“New paint layer”, “paintlayer”) >currentNode.parentNode().addChildNode(newNode, getNextSibling(currentNode))

5 Likes

Script to turn off eraser when selecting brush tool:

Way-center-layer-inside-the-selection:

My Super-Duper opacity Destroyer:

import time
application = Krita.instance()

for i in range(16):
    application.action('duplicatelayer').trigger()
    time.sleep(0.1)
    application.action('merge_layer').trigger()
2 Likes

What does it do?

Hehehe… (malicious smile) I’m glad you asked;

This script duplicates the current layer and merges it back again up to 16 times, the square root of 256, the maximum value of alfa, enough to make opaque even a single pixel of 1% of transparency >:)

Is it possible to change the Distance of the Weighted Brush smoothing? Not only that, but check to see what value it has and change to something else accordingly? Each time the script is executed: If X, then change it to Y. If Y, then change it to X.

Script to enlarge or shrink the current selection mask.

def selectionPM(n):
    application = Krita.instance()
    activeDoc = application.activeDocument()

    s = activeDoc.selection()

    if s == None:
        pass

    elif n > 0:
        s.grow(n, n)

        application.action('invert_selection').trigger()
        application.action('invert_selection').trigger()
    
    else:
        s.shrink(abs(n), abs(n), True)

        application.action('invert_selection').trigger()
        application.action('invert_selection').trigger()

selectionPM(-2)# input number to ( )

Entering a positive number in the parentheses of “selectionPM()” will enlarge the selection, and entering a negative number will shrink it.
For example, typing “selectionPM(5)” will enlarge the selection by 5px.

7 Likes