Hello and welcome to scripting for artist.
My name is civilian and in this episode we'll visit the topic that
many of you have asked for user interfaces in the previous videos.
We created our own operator and then turned it into an
ad on the basics of creating your own user interface.
In blender is pretty much the same. You create a class, you add some properties to it,
you had a function to it and then you register that thing.
So in this video we will look at the following will be finding existing you Aiko.
So if you're wondering how did they do it after this? You'll know where to find it.
We'll look at the ingredients of panel before making our own monkey grid panel.
Of course,
what else we'll be adding operator buttons to the
panel and then tweaking the layout a little bit.
Then we'll add seeing an object protest to it.
And we'll also look at conditional drawing
because sometimes there is no active objects.
So you won't be able to draw properties from the active object.
And finally we'll look at adding your own operators to existing menus and blender
Before we make your own let's take a look at existing panels and blender
in the three D view port,
press and to show the panels and then let's look at the three d cursor panel,
right click and choose.
Edit Sirs.
If you don't see the edit source option,
go to preferences interface and enable developer extras and
python tool tips and then it should show up.
So let's see what happens if we click it
blend owner tells us here in the corner but
it's a bit far away because of my scaling basically
it tells us to go to a text editor and there we should find the file with the source.
But there's an easier way
if you split this window and make sure that there is a text editor right here,
you can click edit sores and there.
Yes, the file, it will be open for you and even scrolls to the right line.
Now let's scroll through this and see what we can find
as we've seen with operators as a class. It has the same kind of naming.
It has the category in capitals and then pt for panel type instead of operator type
and then in lower case the rest of the identifier.
And here you have the parent class in this case it's
panel and the operator you would expect big pipe type.
Stop panel here instead of a panel and we'll see why this is in a bit.
Let's look for other commonalities.
First will be a label which is the panels naming the user interface
and then we have a category or region type and a space type.
The space type and region type defined where in the user face it will show up.
In this case we're looking at three D view port and region type issue I which
means it's right in the three D view port and not in a header or footer.
And the category is view which is the name of the tab here
and then we get to be a label which is the name of
the panel where operators had an execute function that performs the task of
the operator here we have a draw function that draws the panel.
The drawing itself is done through self dot layout which is a ui layout instance
and you can find this with help and then python api reference and search for you.
I lay out one word there you'll find the class
definition with everything that is possible in this video.
I will show you the basics though and that will get you quite far already.
Now let's go back to the class definition
because we saw that panel here and this is
a little bit different than we've seen before.
As I said,
you would have expected something like bp dot types dot panel and not just panel.
And this is because in this file is imported in a different way
that's cruel to the top
and here you can see from be part of types import heather,
menu and panel and because of this you can just type panel instead of be
part of type stock panel and it would refer to the same thing personally.
I would say be very careful with imports like this,
it can save you some typing and that may sound like a good thing
but you will read code way more often than you write it.
I would always optimise for code readability and understand
ability rather than saving a few seconds of keystrokes.
The only time where I would use an import like
this is where it is very clear what's going on.
In this case it's blenders user interface definition and there is only one header,
there's only one menu,
there's only one panel and they always come from the pilot types.
So in this case I would find it acceptable
in general though I would avoid this and always use
the full name of the thing so that once you see it is clear where it comes from.
Now that is out of the way.
Let's just jump in and make her own panel for the monkey grid.
Let's take a look at our adults code where we left off last time.
So here we have the monkey grip that pie
with the monkey grid operator class
and the registered and unregistered functions.
Now to this
we can add our monkey great panel.
So just like before we create our class
we name it properly. I kept the category few three D. Because it's a view three D.
Panel. Anyway we have to P. T. I called it monkey grid
and we extend be piled up types that panel. I just copy these values from the three D.
Cursor panel
and into category monkeys so that we get our own little tab there
and I labeled it grid
and then the only thing that you really need to have is a draw function
for it to show up as a panel.
It needs to have draw function even if that function is nothing.
And because the function in python always have to have something
I put pass here which is python code for don't do anything.
Every code block after a Colin is indented
and every invented blog needs a little bit of
text there in order to make sure that python
understands that it's invented in the first place.
So that's why they have the past keyword.
Now.
The only thing that's left is to tell blender that this class exists in the first
place which means registering it so we can
just copy the registered and unregistered class function calls
and put in our new class and that should be it. Let's go to blender. See what happens
now, all we have to do is reload the script
so a good system. Reload scripts and you'll see monkeys pop up here.
This route also gives you access to right click and then add to quick favorites.
So if you do that then you can just press Q. And reload scripts
will give you a fast way to reload them. When we go to the monkeys tab.
We can see that our great panel is here. It doesn't contain anything yet.
Of course we don't draw anything there. But at least it shows up.
So let's put a button there for the operator.
Let's go back to the code
and here in draw.
Yeah.
Self taught layout lets us draw things. And to draw an operator,
you type operator and then you give the idea name of the operator.
You want to have their
let's go to paste that in, go to blender.
Rewrote the script
and there you can see we have a monkey
grip button in the grid panel and it actually works
to customise this button. There's a few possibilities.
And let's go take a look at them.
First of all we can change the text that is shown on the button.
So let's call it the default grid because pressing
this button will just give us the default properties.
Save the file, go back to blender.
Reload the scripts and now it's called default grid.
The nice thing is that if we search for the monkey grid then it's still called
monkey grid in the F three panel because that is the name of the operator.
It is just that on this particular spot in the
user interface we have a different text on the button.
Finally we can add an icon to it
and then we have to know the name of the icons.
So you can either look at existing code to cheat
off of that or you can activate the icon,
viewer add on it's bundled with blender but not activated by default.
And then in the python cause all you get this button called icon viewer.
Then you can click on the icon that you want to say a monkey.
This is copied it onto the clipboard,
paste it there, save
go back to blender. Reload the script and there you have the icon
in the tool tip.
You can also see the description and you can see that
it will actually call our operator with all the default parameters.
Let's tweak this and make some buttons that you
specific values for these parameters rather than the default.
So again, we go back to the source,
let's copy this call.
And instead of just having this we can say props equals self layout of the operator,
yada, yada yada.
Let's change this to big grid.
Self to lay out the operator is a function that returns something
and the thing that it returns represented properties of our operator.
So here we can say props dot and let's
take a look. We had
count X. Count y and size.
Okay,
so here we can save props dot
count x equals 10
and count y equals 10
and size equals 0.8.
So let's save. Go back to blender. Reload the script.
We have a new button, big grid and when you have over it,
you can see that it has different values for those parameters to lead the monkeys.
If you click on big grid automatically, it will take those values of course.
To top this off,
we can also make a small grid and then we have a few more buttons to play around with.
So for the small grid
let's set count exceeds one count y is one and keep the size to the default.
So we just don't mention it here.
Save picture blender.
Reload
no word of a small grid as well,
which is of course just one.
But in the redo panel we can extend this however we want.
Now you can also see the value of being able to set the text
on that button because it's all the same operator but with different behaviors.
Now there's one more thing.
I don't like how these buttons are space so far apart
from each other because they're basically doing the same thing.
They're creating a monkey grid and they should really be grouped together.
Fortunately we can do this by laying in the mountain a column and I
can hear you ask but see when they are already in a column.
So what are you on about?
Well,
a function to create a column has some parameters
that we can use to influence the layout.
So let's take a look at our code again.
Right now,
each operator is drawn by calling softer layout operator and we can change it.
We can create a column first.
And then instead of calling operator on self layout, we call operator on call
safety code.
Go back to blender.
Reload the script and you can see they're already squeezed together a
little bit more and we can go a little bit further,
add align equals true here
and then they are exactly as I wanted them to be nicely squeezed together.
So beside the operators,
you can also drop properties on the panel and this
can be pretty much any property that you want.
So you could use it to group together these properties that
are strewn throughout lenders user interface but you use a lot.
So for your specific workflow you can add them to your
own panel and make your life a little bit easier.
So let's take two properties. One property of cycles.
So let's say the number of vieux port samples in cycles and
the other I want to have relative to the currently selected object.
So let's well the view port visibility there.
So one of the properties is this guy here, the number of U port samples.
And the other property that we want to add is this
one here disabling vieux port before we go to the code,
let's see what blender already tells us.
So you hover over the view port property there, it says at the bottom of the tool tip,
be pi data seen seen that cycles of previous samples and this is almost what we want.
But if we were to use this we would hard code the name seen in our script.
So if we ever rename the scene then our scriptures broken already.
And also when you use multiple scenes, it also wouldn't work anymore.
So rather than using this literally as it stands there,
even though for this case it might work
what we use the context again and just get the current scene with context not seen.
So the property that we want to show is
actually context dot scene dot cycles dot preview samples.
Now, let's go to the code, let's add another column
and then we call call dot prop to render the property for us.
It takes a minimum of two parameters.
The first one is the thing that contains the
property and then it's the name of the property.
So the thing that contains the property is context not seen,
but cycles everything up to the last point.
And then the name is preview samples.
Let's save, Go back to blender. Rewrote the script
And there you have it preview samples 10.
So we can change this and you can see that here.
It changes as well, which indicates that we have the right property.
So here you can also add these texts and icon parameters.
They work the same as with the operator call.
So in order to keep this video a bit to the point, I'll leave that for you to toy with.
Now let's take a look at the second property we wanted
to add which is a property of the active object.
I want to be able to control the view port, visibility. So that is this guy over here
and there it says be pi data object. Suzanne dot hide view port.
And again, is with the scene. We don't want to do this specifically for Suzanne only.
We want to do this for the currently
active object which means context dot active object.
So the property we're going for is context active object dot hide view port.
Let's just copy what we had.
Change the thing that contains the property to context active object
and
change the property name to hide view port. And this should render that property.
Let's take a look like a blender. We reload
and there is the property that we wanted to have.
Now let's see if it works
and there you go, it's working. But it's a bit weird because it disappears
and here it doesn't. So what's going on?
It turns out when you hide an object is no longer active.
So that means that context, not active object becomes none. Instead of Suzanne.
None doesn't have a property hide report. So our code is actually causing problems.
Now
let's take a look at the terminal where started blender And here you see rather
cryptic error message here at the bottom is the terminal where is to blend it from
And it's complaining about the monkey great pie file line
82 which is of course the call that we just added
And it says ever with argument one. Data. So apparently this argument is called data
function. That data does not support a non assignment.
It's a bit vague description, but it does match what I just said.
The active object is none and you cannot draw a property of nothing.
So we have to add a little bit of a guard around this code to make it always work.
We know that
we know that contacts the active object can become none. So let's check for it.
And in that case
let's just add a label. Otherwise we'd rather property as we did before.
Let's see how this works. Now. Reload the script
and there you have it. It says no active object instead of
going out and all the code will keep working.
You could argue that this is a bit of a silly
button because it only works once and you will be right.
But I wanted to have this example to show you
how things can go wrong and how to resolve that.
It's also a demonstration of one thing that I find quite
important and that is showing why something is not there.
So rather than not drawing the property at all and just silently skipping over it.
Now we draw the text, no active object which indicates to whoever is using your code,
why the option is gone.
I think that's quite important. So that's why I wanted to have this example here.
Anyway, even though it's rather useless.
You now know how to draw your own properties.
So it's up to you to make it useful for your particular workflow
before we end this video,
I want to show you one more thing which is adding operators to menus,
given what we've seen so far. This is rather easy.
So this is why I kept it as the last step.
Let's add our monkey grid operator to the mesh, add menu.
So here we have add
mesh and it would be nice if underneath monkey there was a monkey. Great.
This means we have to add it to a menu and there's a trick for that.
I will show you but first we have to know which menu it is so you can hover here or
add and it shows view three D Empty AD And
you probably already guessed empty stands for menu type.
Now the thing is sub menus don't show this,
You don't know what the measure is,
but we can look around in the python console and see if we can find it.
Anyway, it is a type. So it is part of be piled up types
dot few three D. Empty. And let's see if we can find something
right.
There you go. Mash add. So this is very likely to be our menu. Calling it here.
We'll just give an error. So let's not do that.
But at least we have the name now few three D Empty.
Mash add in be piled up types, let's copy this and then go to the code
as you would have guessed it.
We have to do something in the register and then the unregistered functions
and this time is quite different than what we've seen so far.
First we have to make our own function that will draw whatever we
want to add to the menu so that looks something like this,
the name that you can think of yourself and again self comma context
for now let's put pass in there to make points and happy.
And this function basically will be called after the draw function of that panel.
So where our own panel has this draw function with self and context.
This function will be called with the same self and the same context.
So self will refer to that menu in our case.
Now let's register and unregistered er this function
this is done by taking that beep.
I types few three D. Yeah really? Era
and saying dot append
at menu draw. The opposite is removed.
So when the unregistered
we remove mesh add menu draw now what to put in here.
Well that's the same as with the panel we can just call self not layout dot operator.
Okay the idea of the operator
and this should work
let's save and go back to blender.
Reload the script,
add mesh and there we have monkey grid, it doesn't have an icon yet
but now you know how to add one. So I'll leave that for you
now.
You've seen how to add your own panel,
how to add your own operators to existing menus,
but most importantly, you've seen how to look at other code.
So when you see something that's interesting, when you're wondering,
how did they do that?
You can just right click edit sores and most of the user interface
elements in blender are written in python and then this just works.
So this is it for this episode of scripting for artists.
If you have any questions or remarks,
please leave them in the comment below and I will see you soon.