Did a lot of improvements in the meantime, now it’s more usable with smaller widgets
Awesome work dude, this looks great!
Hope? It’s really awesome
Adding images as references instead as layers would be cool too
Huge thank you! I’m not familiar with the references workflow inside of Krita, so that’s why I didn’t support that
It’s OK. Great timesaver, let’s build some nice legooo landscape ! Haha
Olá @slightlyangrydodo .
I just started testing it a bit and I have noticed some odd behaviors while I am using Krita 5 beta.
Behaviours:
- There seems to be a lack of a manual. The desktop file is missing the entrance that allows the manual to be displayed.
- it creates new layer but it applies the image to the node that is selected. you have to move up the layer stack but I think that is not possible unless the bug to do so was corrected.
- Image scale seems unresponsive also fit to scale, as placing images or their representation are fixed size. If I am using it incorrectly I have no information on the manual to check.
- On the code you seem to have something to center the image to the center of the document but the image locks to (zero, zero) and the document is big enough for it.
- At the last page if it is lasting like 2 images the buttons become unalign. having the buttons inside a grid layout it helps the buttons underneath to become align.
Bugs:
- I played with “image scale” and “fit image” and I got this:
ZeroDivisionError
Python 3.8.1: C:\Users\EyeOd\Desktop\krita-x64-5.0.0-beta1\bin\krita.exe
Sat Sep 25 20:29:43 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\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py in <lambda>()
92 self.imagesButtons[6].clicked.connect(lambda: self.buttonClick(6))
93 self.imagesButtons[7].clicked.connect(lambda: self.buttonClick(7))
94 self.imagesButtons[8].clicked.connect(lambda: self.buttonClick(8))
95
96 mainLayout.addLayout(topLayout)
self = <photobash_images.photobash.PhotobashDocker object>
self.imagesButtons = [<PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>]
].clicked undefined
self.buttonClick = <bound method PhotobashDocker.buttonClick of <photobash_images.photobash.PhotobashDocker object>>
C:\Users\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py in buttonClick(self=<photobash_images.photobash.PhotobashDocker object>, position=8)
191 def buttonClick(self, position):
192 if position < len(self.foundImages) - len(self.imagesButtons) * self.currPage:
193 self.addImageLayer(self.foundImages[position + len(self.imagesButtons) * self.currPage])
194
195 def updateImages(self):
self = <photobash_images.photobash.PhotobashDocker object>
self.addImageLayer = <bound method PhotobashDocker.addImageLayer of <photobash_images.photobash.PhotobashDocker object>>
self.foundImages = ['G:/Frame Cutz/Vtuber/References/0086095a7e64d639e5d32b4c98c7a1b0.jpg', 'G:/Frame Cutz/Vtuber/References/0103e734b16cea22f3f828def3c67c5a.jpg', 'G:/Frame Cutz/Vtuber/References/02448d75e4f2bd0dd96a2e5e8b69f938.jpg', 'G:/Frame Cutz/Vtuber/References/04a70b4c56eef2239f8118f01a3e17f4.jpg', 'G:/Frame Cutz/Vtuber/References/04ccb9cc50203ef3ceaebcdac43494d5.jpg', 'G:/Frame Cutz/Vtuber/References/04f962839250c11c56139f11c879f10c.jpg', 'G:/Frame Cutz/Vtuber/References/06110e7cf8c6a72f3f2ff176970a1bd0.jpg', 'G:/Frame Cutz/Vtuber/References/06148f6ee4dfe71451032ec4dac8742a.jpg', 'G:/Frame Cutz/Vtuber/References/082d0967495d179d96e8664da0c83033.jpg', 'G:/Frame Cutz/Vtuber/References/08c282d90f5187e42441fd9fdb858b32.jpg', 'G:/Frame Cutz/Vtuber/References/098c07d5e484481126a95ea3e46ed533.jpg', 'G:/Frame Cutz/Vtuber/References/09dfac1b1107e0a23b4fb619670b90f2.jpg', 'G:/Frame Cutz/Vtuber/References/0a2f3c59ca4a12984b31f3fadb41f92a.jpg', 'G:/Frame Cutz/Vtuber/References/0a7dffb0fab5957e61553603d4530698.jpg', 'G:/Frame Cutz/Vtuber/References/0b1eeb5af64673a8b150e29aa91aa22b.jpg', 'G:/Frame Cutz/Vtuber/References/0b487d385b899b4afc1df248f476328c.jpg', 'G:/Frame Cutz/Vtuber/References/0d4ee170f6dbbacebe5925a97fa42dc8.jpg', 'G:/Frame Cutz/Vtuber/References/0df386230fac07a62e9f82e6a9094ad0.jpg', 'G:/Frame Cutz/Vtuber/References/0eb5cf46302d9f7e5d668f25e07cd238.jpg', 'G:/Frame Cutz/Vtuber/References/0f1a188d25d3ca32a9dedfc0f8c8ad08.jpg', ...]
position = 8
builtinlen = <built-in function len>
self.imagesButtons = [<PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>, <PyQt5.QtWidgets.QToolButton object>]
self.currPage = 0
C:\Users\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py in addImageLayer(self=<photobash_images.photobash.PhotobashDocker object>, photoPath='G:/Frame Cutz/Vtuber/References/082d0967495d179d96e8664da0c83033.jpg')
255
256 if self.fitCanvasChecked:
257 if activeNode.bounds().width() / activeNode.bounds().height() > doc.bounds().width() / doc.bounds().height():
258 scalingFactor = doc.bounds().width() / activeNode.bounds().width()
259 newWidth = doc.bounds().width() * self.currImageScale / 100
activeNode = <PyKrita.krita.Node object>
activeNode.bounds = <built-in method bounds of Node object>
).width undefined
).height undefined
doc = <PyKrita.krita.Document object>
doc.bounds = <built-in method bounds of Document object>
ZeroDivisionError: division by zero
__cause__ = None
__class__ = <class 'ZeroDivisionError'>
__context__ = None
__delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
__dict__ = {}
__dir__ = <built-in method __dir__ of ZeroDivisionError object>
__doc__ = 'Second argument to a division or modulo operation was zero.'
__eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
__format__ = <built-in method __format__ of ZeroDivisionError object>
__ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
__getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
__gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
__hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
__init__ = <method-wrapper '__init__' of ZeroDivisionError object>
__init_subclass__ = <built-in method __init_subclass__ of type object>
__le__ = <method-wrapper '__le__' of ZeroDivisionError object>
__lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
__ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
__new__ = <built-in method __new__ of type object>
__reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
__reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
__repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
__setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
__setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
__sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
__str__ = <method-wrapper '__str__' of ZeroDivisionError object>
__subclasshook__ = <built-in method __subclasshook__ of type object>
__suppress_context__ = False
__traceback__ = <traceback object>
args = ('division by zero',)
with_traceback = <built-in method with_traceback of ZeroDivisionError 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\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py", line 94, in <lambda>
self.imagesButtons[8].clicked.connect(lambda: self.buttonClick(8))
File "C:\Users\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py", line 193, in buttonClick
self.addImageLayer(self.foundImages[position + len(self.imagesButtons) * self.currPage])
File "C:\Users\EyeOd\Desktop\krita-x64-5.0.0-beta1\share\krita\pykrita\photobash_images\photobash.py", line 257, in addImageLayer
if activeNode.bounds().width() / activeNode.bounds().height() > doc.bounds().width() / doc.bounds().height():
ZeroDivisionError: division by zero
Suggestions
Some ideas you might like or not:
- adding reference images instead of adding layers but I was not finding reference images in Python
- maybe a counter of how many pages there are with images and in which page we are.
- right click to open a menu on the buttons with a Context Menu if you add more options
- Ability to just open a single image for reference within the docker.
- I may be dreaming too much but maybe dragging and dropping a image with the mouse with
event.mimeData().hasImage
and it would be interesting to drop it on the canvas or on other dockers that accept images. Pigmento accepts images like that and it does feel proper to move it in and not use the explorer constantly. - if there is no document open you could open that document with that image also.
Yeah, I had the feeling a lot of things would break for 5.0… I’ll try to get back on the Krita horse soon, thanks for the feedback, and for the troubleshooting!
Okay, so I’m finally reading this more thoroughly, and I’m going to address your post, point by point.
Yup, this is clearly a bug. Fixing shouldn’t be too hard!
I actually think that this behaviour is best, as I could want to photobash an image with other things in front of it to occlude it. However I do see that this could be useful, so I’m thinking of adding a button to allow this.
This seems to be a bug for 5.0, will look into it.
Again, this seems like a 5.0 bug. Will look into it.
Yeah, this one is probably going to be a bit of a pain to do, but I’ll look into it after other more important things are fixed, since it’s relatively low priority.
Yeah, this is probably not going to be done. I could check how to add a reference image, but the point of this plugin is to photobash, and I want them to be regular paint layers so that I can do whatever I want with them, paint over, merge with other images, etc.
This seems relatively harmless and a nice QoL improvement, so I’ll add it in.
This is a great idea. I dislike the idea of having too many buttons cluttering up the UI, but this really could solve a lot of things. I feel this will be a pain to implement, but it’s a great addition, and already solves some design problems I can see.
I’m not sure I understand this one, like hovering to get a larger preview or something like that?
Yeah, this one isn’t goint to the list as of now. I think that a lot more than this needs to be implemented in order to work with good UX. Still, I’ll check some things out, but not for this release.
I have no idea how to do that, and I personally don’t think that this is worth the extra complexity. If I want to create a new artwork, I’ll create the canvas the way I want to first, and then fit the image on to that.
I have no ETA as to when things will be fixed, as I’m working a full-time job now, with other projects on the side (as well as fixing the UI Redesign plugin for 5.0). Still, when there’s news to share, I’ll make sure to tag you!
Thanks once again for this awesome, thorough feedback!
More like hidding the 9 buttons to show just one widget preview.
Well if you feel overwhelmed with time I could help by chip in with some code if you want and you can take a look after and change as you see fit.
Some of my suggestions I have them already made so giving a boost should not be too hard.
I wouldn’t mind reviewing some stuff you made, I could always learn some more! What points did you address?
I mean, made for myself. I just scrap them out because they were of no use for my current project but I have notes on everything new I do.
I never edit anything of other people without having clearance to do so. It is very rude to edit stuff without the ok I think. I will start writing something today. I have to do a fork or something like that if I am not mistaken or is it a pull? I need to check how to do this. Github is still a mystery to me.
No fork needed! I haven’t added the license yet, but it will be MIT, so it’s very permissive. I can give you permissions to create branches, and so you can just create a branch on the repo, push your changes there, and then create a pull request. If you have any doubts, I’m happy to lend a hand!
I never heard about any of that before.
I am checking out how that goes now.
I was just talking about the licenses of plugin in other thread, but I think Krita plugins need to be GPL licensed.
Oh, didn’t know that, that’s nice to know, thanks!
Yeah the whole license discussion is here
To my knowledge, MIT is less restrictive than GPL, and is compatible with GPL
So for me it shouldn’t be a problem
Grum999
I know that it’s less restrictive, but if it’s GPL that forces everything that uses my code to be open-source (or GPL, not sure). I personally prefer MIT, but I can see the use case for GPL.
@slightlyangrydodo
I was taking a look at that and it seems you need to add me as a collaborator or something like that to a branch you create. or something like that. I will make some tweaks and when you have time to adjust that I will put in the files with the changes.
And you should add your license right away. I discovered yesterday I was applying my license incorrectly yesterday and was updating everything.
Yeah, I’ll send you more info in a PM