Buli Brush Switch

Ok great!
I already encountered weird things with resources database, I think there’s currently still bugs on which developers are working on…
Deleting it often solve problems, I hope this will be more stable when final Krita 5 release will be deployed :crossed_fingers:

Really hard to understand what happened here :frowning:

If you’ve kept the database backup file, is it possible to provide it?
You can use https://www.file.io/ for sharing (once file is downloaded it’s automatically deleted, and I don’t think there’s sensible information in database file)

I would like to test it on my side if possible, to understand from where the problem you encountered came

Grum999

1 Like

The file is too big for file.io, so here’s a OneDrive link: resourcecache.sqlite_B

1 Like

Ok thanks!

I’ve downloaded it
You can delete it from onedrive if you want

Grum999

1 Like

Hi,

The plugin seems to be working (I can add brushes and such), but a couple of seconds after I close Krita, this error pops up:

TypeError
Python 3.8.1: C:\Program Files\Krita (x64)\bin\krita.exe
Fri Dec 10 15:17:23 2021

A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.

C:\Users\Gremr\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py in __kritaIsClosing(self=<bulibrushswitch.bulibrushswitch.BuliBrushSwitch object>)
119 “”“Save configuration before closing”“”
120 if BBSSettings.modified():
121 BBSSettings.saveConfig()
122
123 def setup(self):
global BBSSettings = <class ‘bulibrushswitch.bbs.bbssettings.BBSSettings’>
BBSSettings.saveConfig =
TypeError: saveConfig() missing 1 required positional argument: ‘self’
cause = None
class = <class ‘TypeError’>
context = None
delattr = <method-wrapper ‘delattr’ of TypeError object>
dict = {}
dir =
doc = ‘Inappropriate argument type.’
eq = <method-wrapper ‘eq’ of TypeError object>
format =
ge = <method-wrapper ‘ge’ of TypeError object>
getattribute = <method-wrapper ‘getattribute’ of TypeError object>
gt = <method-wrapper ‘gt’ of TypeError object>
hash = <method-wrapper ‘hash’ of TypeError object>
init = <method-wrapper ‘init’ of TypeError object>
init_subclass =
le = <method-wrapper ‘le’ of TypeError object>
lt = <method-wrapper ‘lt’ of TypeError object>
ne = <method-wrapper ‘ne’ of TypeError object>
new =
reduce =
reduce_ex =
repr = <method-wrapper ‘repr’ of TypeError object>
setattr = <method-wrapper ‘setattr’ of TypeError object>
setstate =
sizeof =
str = <method-wrapper ‘str’ of TypeError object>
subclasshook =
suppress_context = False
traceback =
args = (“saveConfig() missing 1 required positional argument: ‘self’”,)
with_traceback =

The above is a description of an error in a Python program. Here is
the original traceback:

Traceback (most recent call last):
File “C:\Users\Gremr\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py”, line 121, in __kritaIsClosing
BBSSettings.saveConfig()
TypeError: saveConfig() missing 1 required positional argument: ‘self’

1 Like

yes this one is known and already been fixed for next version :wink:

Grum999

1 Like

Ah, ok. Nevermind then :slight_smile:

1 Like

You’re welcome; I prefer to be informed twice of a bug than having no feedback :relaxed:

Grum999

2 Likes

I’ve implemented both rules

There will be an option at plugin level (means that choosen rule is applied for all brushes, not at brush level)

I don’t really like it but if users have different usage than me :sweat_smile:

I’m not sure options are easy to understand.

Here are the tooltips:

  • Title “Behavior for brushes with specific values”:
    For brushes with specific paint tool and/or color, define what to do when exit plugin’s brush

  • Option “Ignore modified state”:
    For brushes with specific paint tool and/or color, exiting plugin’s brush will always restore initial paint tool and/or color

  • Option “Keep modified state”:
    For brushes with specific paint tool and/or color, exiting plugin’s brush will:
    – If paint tool and/or color has been modified, keep last selected paint tool and/or color
    – If paint tool and/or color has NOT been modified, restore initial paint tool and/or color

If anyone have better tooltip and/or title for options…

Grum999

4 Likes

Thank you very much! Coding a new option seems like a lot of work for me because I have no knowledge of coding :sweat_smile:

the sources for a brush:


if you click the 'mix" in the color box, you can mix plain color (foreground/background) or gradient.

here is a use case of my grass brush.


with a gradient option, you can choose specific colors to make the blending more “beautiful” but the foreground/background option can work too.

I think it will take longer for me to change foreground/background color or choose a new gradient color everytime I want to use my grass brush because i use other brushes with “mix” option too. but please take a rest and consider this on another day :smiley: .

1 Like

Let’s see, I can give it a try, maybe something along the lines of:

  • Title “Behaviour of brush preset overrides”:
    Define whether Bulli-Brush switch is able to override brush specific settings (such as color, size and opacity) or that the plugin should default to the presets as defined by Krita.

*Note that no brush presets are altered by the plugin. Any changes are stored locally.

  • Option “Ignore modified state”
    When enabled, any modifications to a brush or tool setting (color, size, opacity, etc.) will be discarded upon exiting the plugin - or upon switching tools?- subsequent uses will revert back to the default brush presets as defined by Krita.

  • Option “Keep modified state”:
    When enabled, brush and tool settings specified with Bulli-brush switch active are retained when exiting the plugin or switching tools. They are enabled next time a tool is activated.
    – If paint tool and/or color settings were modified, these settings are restored
    – If paint tool and/or color were NOT modified, it will default to Krita’s presets

I hope that I understood things right :sweat_smile::wink:

1 Like

Thanks for your feedback!

No :upside_down_face:
But your english is better than mine, what you wrote is clear to read :slight_smile:

But it clearly means my explanations are not really understandable :sweat_smile:


The brush properties (such as size and opacity) are always restored to their previous values when exiting plugin selected brush (go back to “normal”)

The option Behavior for brushes with specific values is only used in a very specific case:

  • Act on paint tool and color only (not size, opacity, …)
  • Is taken in account only when a specific paint tool or color value is defined for brush
  • Is taken in account only when user modify paint tool or color while painting

Here some examples, that gives a better overview of the situation.
I’ve “highlighted” difference for specific case with some +++

Basic case (the option Behavior for brushes with specific values is ignored here)

Actions Plugin brush settings
→ Color is not fixed
Plugin brush settings
→ Color is fixed (Green)
Krita’s current brush color Red Red
Select brush plugin
→ Applied brush color
Red (unchanged) Green (from settings)
Exit brush plugin state Red (keep color) Red (restore original color)

Specific case (the option Behavior for brushes with specific values is taken in account - “Ignore modified state” is checked)

Actions Plugin brush settings
→ Color is not fixed
Plugin brush settings
→ Color is fixed (Green)
Krita’s current brush color Red Red
Select brush plugin
→ Applied brush color
Red (unchanged) Green (from settings)
Change Krita’s brush color Blue Blue
Exit brush plugin state Blue (keep color) Red +++(restore initial color)+++

Specific case (the option Behavior for brushes with specific values is taken in account - “Keep modified state” is checked)

Actions Plugin brush settings
→ Color is not fixed
Plugin brush settings
→ Color is fixed (Green)
Krita’s current brush color Red Red
Select brush plugin
→ Applied brush color
Red (unchanged) Green (from settings)
Change Krita’s brush color Blue Blue
Exit brush plugin state Blue (keep color) Blue +++(keep color)+++

Grum999

2 Likes

Oops haha :sweat_smile:
For these sorts of scheme’s I find it much easier to just try things out in the plugin though.

@Grum999 Could you post an update to the thread when the reported bugs in this thread are fixed? Then I will download it myself :yum:

1 Like

Yes don’t worry :wink:

I’m currently preparing the release, it should be published in few hours :slight_smile:

I’ve kept my not understandable tooltips and also use them for the documentation :upside_down_face:
They’ll be changed for a next version.

Grum999

4 Likes

Release v0.2.0b published
Main topic has been updated!
(don’t know if modifying the main topic is really visible or not… :thinking:)

Grum999

1 Like

I get a script error when I launch Krita.

KeyError
Python 3.8.1: C:\Program Files\Krita 5\bin\krita.exe
Sat Dec 11 13:07:23 2021

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 C:\Users\Sammy\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py in createActions(self=<bulibrushswitch.bulibrushswitch.BuliBrushSwitch object>, window=<PyKrita.krita.Window object>)
  147                 action=BBSSettings.brushAction(brushNfo[BBSBrush.KEY_UUID], brushNfo[BBSBrush.KEY_NAME], brushNfo[BBSBrush.KEY_COMMENTS], True, window)
  148 
  149                 if brushNfo[BBSBrush.KEY_SHORTCUT]:
  150                     # action will be loaded with defaul shortcut
  151                     # force "dedicated" shortcut to be the same than default one to
brushNfo = {'blendingMode': 'erase', 'color': '', 'colorBg': '', 'comments': '', 'defaultPaintTool': None, 'eraserMode': True, 'flow': 1.0, 'ignoreEraserMode': True, 'keepUserModifications': True, 'name': 'a) Eraser Circle', ...}
global BBSBrush = <class 'bulibrushswitch.bbs.bbswbrushes.BBSBrush'>
BBSBrush.KEY_SHORTCUT = 'shortcut'
KeyError: 'shortcut'
    __cause__ = None
    __class__ = <class 'KeyError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of KeyError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of KeyError object>
    __doc__ = 'Mapping key not found.'
    __eq__ = <method-wrapper '__eq__' of KeyError object>
    __format__ = <built-in method __format__ of KeyError object>
    __ge__ = <method-wrapper '__ge__' of KeyError object>
    __getattribute__ = <method-wrapper '__getattribute__' of KeyError object>
    __gt__ = <method-wrapper '__gt__' of KeyError object>
    __hash__ = <method-wrapper '__hash__' of KeyError object>
    __init__ = <method-wrapper '__init__' of KeyError object>
    __init_subclass__ = <built-in method __init_subclass__ of type object>
    __le__ = <method-wrapper '__le__' of KeyError object>
    __lt__ = <method-wrapper '__lt__' of KeyError object>
    __ne__ = <method-wrapper '__ne__' of KeyError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of KeyError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of KeyError object>
    __repr__ = <method-wrapper '__repr__' of KeyError object>
    __setattr__ = <method-wrapper '__setattr__' of KeyError object>
    __setstate__ = <built-in method __setstate__ of KeyError object>
    __sizeof__ = <built-in method __sizeof__ of KeyError object>
    __str__ = <method-wrapper '__str__' of KeyError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('shortcut',)
    with_traceback = <built-in method with_traceback of KeyError object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "C:\Users\Sammy\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py", line 149, in createActions
    if brushNfo[BBSBrush.KEY_SHORTCUT]:
KeyError: 'shortcut'


2 Likes

Hi

Thanks, didn’t saw this one.
I’m preparing a v0.2.1b to fix this one quickly :slight_smile:

A workaround: even with error message, the plugin is able to start then go in plugin settings, just click OK button.
Restart Krita, and it should be ok, no more error message.

Grum999

2 Likes

Release v0.2.1b published
Main topic has been updated!

Grum999

4 Likes

Error is gone.

The plugin works great. A bit fiddly with all the setting up, but easy enough once you know where everything is. Way more elaborated than what I initially wanted, but it works for my purposes as well. Even better than Photoshop actually. I can now switch to the brush by either hitting “B” or hitting “E” when I’m using the eraser (and vice versa for the brush). I can now use ONE button on my Cintiq remote and don’t even have to move my thumb to another button any more. That’s the proper way of kicking PS’s a$$ :wink:

A few things I noticed during the setup.

*) I was not able to assign “B” and “E” (as they were already used by the default tools). Is there a way to overwrite the original key bindings without having to delete them first. Would make it a bit easier to use for first time users. Maybe a checkbox or a button like “Override default shortscuts” would be a option as well.

*) When I deselect “Ignore eraser mode” in the brush settings of the plugin and click “OK”, it’s still there then next time I open the dialog.

*) Trying to close the brush settings window by clicking the “X” of the dialog, doesn’t work.

Otherwise you killed it, mate. While I myself will not really work in Krita in the near future, this will be appreciated by everybody who does a lot of painting. What a great time saver.

1 Like

One more thing. There seems to be a little discrepancy in the icon display.

image

Here I’m painting right now, yet your icon shows the eraser. Shouldn’t they be the same? Also what’s the purpose of the button of you plugin being blue once I click it?

1 Like

There are a few confusing things still.

When I start Krita, icon configuration is like this.
image

When I start Krita, the brush is active (the one closed Krita with). Now, when I hit “B”, nothing should happen as I’m already using a brush. Instead the brush of the plugin gets selected, which is the originally selected brush (this one should now also hold the last used brush that I closed Krita with). When I hit “B” again, I’m back to the “Krita” brush.

When I hit “E”, it switches to the default eraser of your plugin (Eraser Circle). I then select a different eraser (e.g. a soft one) and hit “B” again. I’m back in the plugin brush (not in the Krita start brush any more). When I know hit “E” again, I’m back in the default plugin eraser (Eraser Circle) and not the soft one, which I chose earlier.

As you can see, this is very confusing and it’s even hard to reconstruct mentally what’s going on.

So here are my suggestions.

*) Have a “trigger” eraser slot and a “trigger” brush slot by default - the ones I could assign my “E” and “B” to by default. They will always hold the last selected brush and eraser, and when I close Krita, the last selected ones will be saved there as well. On the initialization of the plugin those slots need to be filled with either the actual eraser or brush (if the tool is active) or some default brushes that come with Krita.

*) When I hit “E” now and a “non-eraser” is active, the “Trigger Eraser” is selected with whatever eraser is in there right now. When I hit “E” and and eraser is active the “Trigger Brush” is selected - as I mentioned above, I like this flip-shortcut-function.

*) Analogue the brush selecting should work.

*) On top of the two default slots, you can add other slots like you have it now. Basically improving on the Ten Brushes addon, by doing so.

I hope this makes sense.

2 Likes