﻿WEBVTT

00:00:00.240 --> 00:00:03.000
Hello and welcome to Scripting for Artists. My name is Sybren.

00:00:03.000 --> 00:00:06.000
And in this episode, we'll visit a topic that many of you

00:00:06.000 --> 00:00:09.960
have asked for, User Interface. In the previous videos,

00:00:09.960 --> 00:00:13.720
we created our own operator, and then turned it into an Addon .

00:00:13.720 --> 00:00:16.840
The basics of creating your own User Interface in Blender

00:00:16.840 --> 00:00:19.600
is pretty much the same you create a class,

00:00:19.600 --> 00:00:22.720
you add some properties to it, you add a function to it,

00:00:22.720 --> 00:00:25.120
then you register the thing. So in this video, we'll look at

00:00:25.120 --> 00:00:28.120
the following, will be finding existing UI code. So if you're wondering,

00:00:28.120 --> 00:00:31.000
how did they do it? After this, you'll know where to find it.

00:00:31.000 --> 00:00:34.080
We'll look at the ingredients of panel

00:00:34.080 --> 00:00:37.120
before making our own monkey grid panel. What else?

00:00:37.120 --> 00:00:40.000
Will be adding operator buttons to the panel, and then,

00:00:40.000 --> 00:00:42.360
tweaking the layout a little bit. Then, we'll add seeing an object properties

00:00:42.360 --> 00:00:44.960
to it, and we'll also look at conditional drawing.

00:00:44.960 --> 00:00:48.000
Because sometimes there is no active object,

00:00:48.000 --> 00:00:50.000
so you won't be able to draw properties from the active object.

00:00:50.000 --> 00:00:52.480
And finally, we will look at adding your own operators

00:00:52.480 --> 00:00:56.120
to existing menus in Blender. Before we make your own,

00:00:56.120 --> 00:00:59.600
let's take a look at existing panels in Blender. In the 3D Viewport,

00:00:59.600 --> 00:01:02.840
press N to show the panels. And then

00:01:02.840 --> 00:01:05.840
let's look at the 3D cursor panel, right-click and choose Edit Source.

00:01:05.840 --> 00:01:08.480
If you don't see the Edit Source option,

00:01:08.480 --> 00:01:11.360
go to Preferences, Interface, and enable Developer Extras

00:01:11.360 --> 00:01:14.120
in Python Tool Tips, and then it should show up.

00:01:14.120 --> 00:01:17.000
Let's see what happens if we click it. Blender now tells us here in the corner,

00:01:17.000 --> 00:01:21.120
but it's a bit far away because of my scaling.

00:01:21.120 --> 00:01:23.960
Basically it tells us to go to a Text Editor, and there

00:01:23.960 --> 00:01:26.120
 we should find the file with the Source. But there is an easier way.

00:01:26.120 --> 00:01:30.240
If you split this window, and make sure that

00:01:30.240 --> 00:01:34.480
there is a Text Editor right here, you can click Edit Source,

00:01:34.480 --> 00:01:37.080
and there, you have the file. It will be opened for you

00:01:37.080 --> 00:01:38.360
and even scrolls to the right line.

00:01:39.960 --> 00:01:43.120
Let's scroll through this and see what we can find. As we've seen,

00:01:43.120 --> 00:01:46.480
with operators as a class, it has the same kind of naming.

00:01:46.480 --> 00:01:50.240
It has the category in capitals and then PT for Panel Type

00:01:50.240 --> 00:01:53.720
instead of Operator Type. And then in lower case, the rest of the identifier.

00:01:53.720 --> 00:01:57.080
And here, you have the Panel class.

00:01:57.080 --> 00:01:59.720
In this case, it's Panel, and not Operator. You would expect

00:01:59.720 --> 00:02:03.000
"bpy.type.panel" here instead of just "panel".

00:02:03.000 --> 00:02:06.720
We'll see why this is in a bit. Let's look for other commonalities.

00:02:06.720 --> 00:02:09.960
First, "bl label", which is the panel's name, the User Interface,

00:02:09.960 --> 00:02:13.240
and then we've a Category, a Region type, and a Space Type.

00:02:13.240 --> 00:02:17.840
The Space Type and Region Type define

00:02:17.840 --> 00:02:20.720
where in the User Interface it will show up. In this case, we're looking at

00:02:20.720 --> 00:02:24.840
3D Viewport and Region Type is UI, which means it's right in the 3D Viewport

00:02:24.840 --> 00:00:02.650
and not in a header or footer. Then the category is View

00:02:28.120 --> 00:02:31.720
which is the name of the tab here. And then, we get to be a label

00:02:31.720 --> 00:02:35.600
which is the name of the panel. Where operators had

00:02:35.600 --> 00:02:38.600
an Execute function that performs the task of the operators,

00:02:38.600 --> 00:02:42.080
here, we have a Draw function that draws the panel.

00:02:42.080 --> 00:02:44.600
The drawing itself is done through "self.layout"

00:02:44.600 --> 00:02:48.840
which is a UI Layout instance. And you can find this with Help,

00:02:48.840 --> 00:02:52.600
and then Python API Reference, and search for UILayout,

00:02:52.600 --> 00:02:54.600
one word. There, you'll find the class definition with everything

00:02:54.600 --> 00:02:57.360
that is possible. In this video, I will show you the basics still,

00:02:57.360 --> 00:03:00.240
and that will get you quite far already.

00:03:00.240 --> 00:03:03.600
Now, let's go back to the class definition, because we saw

00:03:03.600 --> 00:03:06.600
that panel here and this is a little bit different than we've seen before.

00:03:06.600 --> 00:03:09.960
As I said, you would have expected something

00:03:09.960 --> 00:03:13.360
like "bpy.type.panel" and not just "panel".

00:03:13.360 --> 00:03:16.840
This is because, in this file, is imported in the different way.

00:03:16.840 --> 00:03:20.720
Let's scroll to the top and here you can see from "bpy.type import"

00:03:20.720 --> 00:03:24.960
Header, Menu, and Panel". Because of this,

00:03:24.960 --> 00:03:28.000
you can just type "panel" instead of "bpy.type.panel",

00:03:28.000 --> 00:03:30.720
and it would refer to the same thing. Personally, I would say,

00:03:30.720 --> 00:03:33.840
be very careful with inputs like this. It can save you some typing

00:03:33.840 --> 00:03:37.000
and that may sound like a good thing, but you will read code

00:03:37.000 --> 00:03:40.120
way more often than you write it. I would always optimize

00:03:40.120 --> 00:03:44.000
for code readability and understandability

00:03:44.000 --> 00:03:47.360
rather than saving a few seconds of keystrokes.

00:03:47.480 --> 00:03:50.480
The only time where I would use an import like this
is where it is very clear

00:03:50.480 --> 00:03:53.240
what's going on. In this case, it's Blender's User Interface definition,

00:03:53.240 --> 00:03:56.360
and there is only one header, there's only one menu,

00:03:56.360 --> 00:03:59.360
there's only one panel and they always come from "bpy.types".

00:03:59.360 --> 00:04:03.360
So in this case, I would find it acceptable.

00:04:03.360 --> 00:04:06.360
In general though, I would avoid this and always use the full name of the thing

00:04:06.360 --> 00:04:09.600
so that once you see it, is clear where it come from.

00:04:09.600 --> 00:04:12.960
Now that is out of the way. Let's just jump in

00:04:12.960 --> 00:04:16.080
and make your own panel for the monkey grid.
Let's take a look at our Addon code

00:04:16.080 --> 00:04:19.000
where we left off last time. So here,

00:04:19.000 --> 00:04:20.240
we have the "monkey grid.py",

00:04:21.360 --> 00:04:25.600
with the monkey grid operator class and the Register

00:04:25.600 --> 00:04:30.240
and Unregister functions. Now, to do this, we can add a monkey grid panel.

00:04:30.240 --> 00:04:34.480
So, just like before, we create our class, we name it properly.

00:04:34.480 --> 00:04:38.120
I kept the category "view 3D" because it's a View 3D panel anyway.

00:04:38.120 --> 00:04:42.720
PT, I called it "monkey grid",

00:04:42.720 --> 00:04:46.720
and we extend "bpy.type.panel". I just copy these values

00:04:46.720 --> 00:04:50.000
from the 3D Cursor panel and into category "monkeys"

00:04:50.000 --> 00:04:54.600
so we get our own little tab there. And I labeled it "grid".

00:04:54.600 --> 00:04:56.720
And then the only thing that you really need to have is a Draw function.

00:04:56.720 --> 00:05:00.360
For it to show up as a panel, it needs to have Draw function,

00:05:00.360 --> 00:05:03.600
even if that function does nothing. And because

00:05:03.600 --> 00:05:07.480
the function in Python always have to have something,

00:05:07.480 --> 00:05:11.000
I put "pass" here, which is Python code for don't do anything.

00:05:11.000 --> 00:05:15.240
Every code block after a ":" is indented, and every indent block needs

00:05:15.240 --> 00:05:18.240
a little bit of text there in order to make sure that

00:05:18.240 --> 00:05:21.240
Python understands that it's indented in the first place.

00:05:21.240 --> 00:05:24.080
That's why they have the "pass" key word. Now, the only thing left

00:05:24.080 --> 00:05:26.840
is to tell Blender that this class exists in the first place,

00:05:26.840 --> 00:05:29.720
which means registering it.

00:05:29.720 --> 00:05:33.360
We can copy the Register and Unregister Class function calls

00:05:33.360 --> 00:05:37.000
and put in our new class, and that should be it.  Let's go to Blender,

00:05:37.000 --> 00:05:40.120
see what happens. Now, all we have to do is reload the script.

00:05:40.120 --> 00:05:44.720
Go to System, Reload Script, and you'll see "monkeys"

00:05:44.720 --> 00:05:48.600
pop up here. This route also gives you access to right-click

00:05:48.600 --> 00:05:51.840
and then add to Quick Favorites.

00:05:51.840 --> 00:05:55.000
You could just press Q, and Reload Scripts, will give you a fast  way

00:05:55.000 --> 00:05:58.120
to reload them. When we go to the Monkeys tab, we can see that

00:05:58.120 --> 00:06:01.000
our Grid panel is here. It doesn't contain anything yet.

00:06:01.000 --> 00:06:03.600
Of course, we don't draw anything there, but at least, it shows up.

00:06:03.600 --> 00:06:06.720
Let's put a button there for the operator.

00:06:06.720 --> 00:06:09.240
Let's go back to the code and here in "draw" "self.layout"

00:06:10.960 --> 00:06:14.360
lets us draw things. And to draw operator,

00:06:14.360 --> 00:06:17.960
you type "operator", and then you give the ID name of the operator

00:06:17.960 --> 00:06:22.080
you want to have there. Let's copy paste that in.

00:06:22.080 --> 00:06:25.600
Go to Blender, reload the script. There, you can see, we have

00:06:25.600 --> 00:06:29.840
a monkey grip button in the grid panel, and it actually works.

00:06:29.840 --> 00:06:32.480
To customize this button, there's a few possibilities.

00:06:32.480 --> 00:06:36.000
Let's go take a look at them. First of all, we can change the text

00:06:36.000 --> 00:06:37.480
that is shown on the button.

00:06:39.480 --> 00:06:41.720
So let's call it the "default grid". Because pressing this button,

00:06:41.720 --> 00:06:44.480
will just give us the default properties. Save the file,

00:06:44.480 --> 00:06:48.960
go back to Blender, reload the scripts, and now it's called

00:06:48.960 --> 00:06:51.600
"Default Grid". The nice thing is that, if we search for the "monkey grid",

00:06:51.600 --> 00:06:55.080
it's still called "monkey grid" in the F3 panel,

00:06:55.080 --> 00:06:58.240
because that is the name of the operator.

00:06:58.240 --> 00:07:01.000
It is just that on this particular spot in the User Interface,

00:07:01.000 --> 00:07:04.360
we've a different text on the button. Finally we can add an icon to it.

00:07:07.000 --> 00:07:10.000
Then we have to know the name of that Icon, so you can either

00:07:10.000 --> 00:07:13.360
look at existing code to cheat off of that or you can activate

00:07:13.360 --> 00:07:16.240
the Icon Viewer Addon. It's bundled with Blender,

00:07:16.240 --> 00:07:19.080
but not activated by default. And then, in the Python code,

00:07:19.080 --> 00:07:21.600
you get this button called Icon Viewer. You can click on the icon

00:07:21.600 --> 00:07:24.240
that you want. Say a monkey. This is copied onto the clipboard,

00:07:24.240 --> 00:07:29.120
paste it there, save, go back to Blender, reload the script,

00:07:29.120 --> 00:07:31.120
and there you have the icon. In the Tool Tip,

00:07:32.240 --> 00:07:36.000
you can also see the description.

00:07:36.000 --> 00:07:38.840
And you can see that it will actually call our operator

00:07:38.840 --> 00:07:41.960
will all the default parameters. Let's tweak this and make some buttons

00:07:41.960 --> 00:07:44.360
that use specific values for these parameters, rather than the default.

00:07:44.360 --> 00:07:47.120
So again, we go back to the source.

00:07:48.360 --> 00:07:51.840
Let's copy this call, and instead of just having this,

00:07:51.840 --> 00:07:56.120
we can say "props = self.layout.operator......"

00:07:56.120 --> 00:08:01.120
Let's change this to "Big Grid", "self.layout.operator" is a function

00:08:01.120 --> 00:08:03.960
that returns something,

00:08:03.960 --> 00:08:07.120
the thing it returns represented properties over an operator.

00:08:07.120 --> 00:08:12.360
Here we can say "props.", let's take a look.

00:08:12.360 --> 00:08:14.600
We have "count X" "count Y" and "size".

00:08:15.840 --> 00:08:17.720
So here we can say "props.count X=10"

00:08:18.840 --> 00:08:26.600
and "count y=10",  and "size=0.8".

00:08:27.960 --> 00:08:32.240
Let's save, go back to Blender, reload the script, we've a new button

00:08:32.240 --> 00:08:35.480
"Big Grid", and when you hover over it, you can see that

00:08:35.480 --> 00:08:38.360
it has different values for those parameters.  Delete the monkey,

00:08:38.360 --> 00:08:42.000
delete click on "Big Grid", automatically

00:08:42.000 --> 00:08:45.000
it will take those values, of course. To top this off,

00:08:45.000 --> 00:08:48.240
can also make a small grid and then we have a few more buttons
 to play around with.

00:08:50.960 --> 00:08:52.000
So for the small grid,

00:08:54.000 --> 00:08:59.000
let's set count X is 1, count Y is 1, and keep the size to the default.

00:08:59.000 --> 00:09:01.120
So we just don't mention it here.

00:09:02.840 --> 00:09:08.080
Save, back to Blender, Reload, then we have a small grid as well.

00:09:08.080 --> 00:09:12.240
Which is, of course, just 1. But in the Redo panel,

00:09:12.240 --> 00:09:15.840
we can extend this however we want. Now, you can also see,

00:09:15.840 --> 00:09:19.000
the value of being able to set the text on that button,

00:09:19.000 --> 00:09:22.720
because it's all the same operator, but with different behaviors.

00:09:22.720 --> 00:09:25.080
Now, there's one more thing. I don't like how these buttons are spaced

00:09:25.080 --> 00:09:27.960
so far apart from each other, because they're basically

00:09:27.960 --> 00:09:30.600
doing the same thing. They're creating a monkey grid,

00:09:30.600 --> 00:09:33.480
and they should really be grouped together. Fortunately, we can do this

00:09:33.480 --> 00:09:36.360
by laying in multi column. I can hear you ask,

00:09:36.360 --> 00:09:38.960
but Sybren, they are already in a column, what are you talking about?

00:09:38.960 --> 00:09:42.120
Well, a function to create a column has some parameters

00:09:42.120 --> 00:09:44.960
which we can use to influence the layout.

00:09:44.960 --> 00:09:47.960
So let's take a look at the code again. Right now, each operator

00:09:47.960 --> 00:09:51.360
is drawn by calling "self.layout.operator", and we can change it.

00:09:51.360 --> 00:09:53.360
We can create a column first,

00:09:57.080 --> 00:09:59.960
and then, instead of calling operator on "self.layout",

00:09:59.960 --> 00:10:01.360
we call operator on "col",

00:10:03.960 --> 00:10:08.080
save the code, go back to Blender, reload the script,

00:10:08.080 --> 00:10:10.240
and you can see, they're already squeezed together a little bit more.

00:10:10.240 --> 00:10:15.080
And we can go a little bit further. Add "align=true" here,

00:10:16.720 --> 00:10:19.480
and then they are exactly as I wanted them to be,

00:10:19.480 --> 00:10:22.480
nicely squeezed together. So beside the operators, you can also draw properties

00:10:22.480 --> 00:10:26.000
on a panel, and this can be pretty much any property you want.

00:10:26.000 --> 00:10:29.480
So you couldt use it to group together these properties

00:10:29.480 --> 00:10:32.080
that are strewn throughout Blender's User Interface

00:10:32.080 --> 00:10:35.240
but you use a lot. So, for your specific workflow,

00:10:35.240 --> 00:10:37.960
you can add them to your own panel and make your life a bit easier.

00:10:37.960 --> 00:10:41.720
So let's take two properties, one, a property of Cycles.

00:10:41.720 --> 00:10:44.600
Let's say, the number of viewports samples in Cycles.

00:10:44.600 --> 00:10:48.480
And the other, I want to have relative

00:10:48.480 --> 00:10:51.360
to the currently selected object. So let's draw

00:10:51.360 --> 00:10:55.080
the viewport visibility there. So one of the properties is this guy here,

00:10:55.080 --> 00:10:57.480
the number of viewports samples, and the other property

00:10:57.480 --> 00:11:00.240
we want to add is this one here, Disabling Viewport.
Before we go to the code,

00:11:00.240 --> 00:11:03.000
let's see what Blender already tells us.

00:11:03.000 --> 00:11:05.840
You hover over the Viewport Property. There, it says at the bottom

00:11:05.840 --> 00:11:09.720
of the Tool Tip "bpy data scenes.cycle.preview sample"

00:11:09.720 --> 00:11:13.080
This is almost what we want.

00:11:13.080 --> 00:11:15.360
But if we were to use this, we would hard code the name "scene" in our script.

00:11:15.360 --> 00:11:18.080
So if we ever renamed the "scene", then our script is broken already.

00:11:18.080 --> 00:11:21.080
And also when you use multiple scenes,

00:11:21.080 --> 00:11:24.360
it also wouldn't work anymore. So, rather than using this literally

00:11:24.360 --> 00:11:27.480
as it stands there, even though for this case,

00:11:27.480 --> 00:11:31.080
it might work, but we'll use the context again, and just get

00:11:31.080 --> 00:11:34.960
the current scene with "context.scene". So the property

00:11:34.960 --> 00:11:38.720
we want to show is actually "context.scene.cycle.preview sample".

00:11:38.720 --> 00:11:42.240
Now, let's go to the code. Let's add another column.

00:11:50.360 --> 00:11:54.360
And then we call "col.prop" to render the property for us.

00:11:54.360 --> 00:11:57.600
It takes a minimum of two parameters. The first one is

00:11:57.600 --> 00:12:00.480
the thing that contains the property, and then it's the name

00:12:00.480 --> 00:12:03.360
of the property. So the thing that contains the property is

00:12:03.360 --> 00:12:08.080
"context.scene.cycle" everything up to the last point.

00:12:08.080 --> 00:12:09.840
And then the name is "preview samples".

00:12:11.240 --> 00:12:15.360
Let's save, go back to Blender, reload the script and there

00:12:15.360 --> 00:12:18.960
you have it "preview samples 10". So we can change this,

00:12:18.960 --> 00:12:21.360
you can see that here, it changes as well. Which indicates that

00:12:21.360 --> 00:12:24.720
we have the right property. So here, you can also add

00:12:24.720 --> 00:12:27.840
these texts and icon parameters. They work the same as
with the operator "col".

00:12:27.840 --> 00:12:30.720
So in order to keep this video a bit to the point,

00:12:30.720 --> 00:12:34.120
I'll leave that for you to toy with. Now, let's take a look

00:12:34.120 --> 00:12:37.000
at the second property we wanted to add,

00:12:37.000 --> 00:12:40.000
which is a property of the active object.
I want to be able to control

00:12:40.000 --> 00:12:43.960
the viewport visibility. So that is this guy over here,

00:12:43.960 --> 00:12:47.240
there it says "bpy.data object suzanne.pi viewport".

00:12:47.240 --> 00:12:50.080
And again, as with the scene, we don't want to do this

00:12:50.080 --> 00:12:52.720
specifically for Suzanne only. We want to do this

00:12:52.720 --> 00:12:56.080
for the currently active object, which means "context.active object".

00:12:56.080 --> 00:12:59.120
So the property we're going for is "context.active object.hide viewport"

00:12:59.120 --> 00:13:03.600
Let's just copy what we had.

00:13:05.960 --> 00:13:08.720
Change the thing that contains the property to "context.active object"

00:13:12.720 --> 00:13:15.120
and change the property name to "hide viewport". And this should render

00:13:15.120 --> 00:13:18.600
that property. Let's take a look. At Blender, reload,

00:13:18.600 --> 00:13:22.720
and there is the property we wanted to have.

00:13:22.720 --> 00:13:24.080
Now, let's see if it works.

00:13:25.480 --> 00:13:29.000
There you go. It's working but it's bit weird,

00:13:29.000 --> 00:13:32.600
because it disappears, and here it doesn't. What's going on?

00:13:32.600 --> 00:13:35.960
It turns out when you hide an object, it's no longer active.

00:13:35.960 --> 00:13:39.840
That means that "context.active object" becomes none instead of Suzanne.

00:13:39.840 --> 00:13:43.720
None doesn't have a property hide viewport,

00:13:43.720 --> 00:13:46.480
so our code is actually causing problems now. Let's take a look

00:13:46.480 --> 00:13:49.080
at the terminal where I started Blender. And here, you see,

00:13:49.080 --> 00:13:52.120
rather cryptic error message here at the bottom is

00:13:52.120 --> 00:13:55.600
the terminal where I started Blender from.

00:13:55.600 --> 00:14:00.000
It's complaining about the "monkey grid.py" file, line 82,

00:14:00.000 --> 00:14:04.120
is, of course, the "col" we just added. And it says error

00:14:04.120 --> 00:14:07.960
with argument one data, so apparently, this argument is called "data".

00:14:09.960 --> 00:14:12.840
"Function.data" does not support a none assignment.

00:14:12.840 --> 00:14:16.480
It's a bit vague description, but it doesn't match what I just said.

00:14:16.480 --> 00:14:20.720
The active object is none and you cannot draw a property of nothing.

00:14:20.720 --> 00:14:23.600
So we have to add a little bit of a guard around this code

00:14:23.600 --> 00:14:25.840
to make it always work.

00:14:27.720 --> 00:14:31.360
We know that "context.active object" can become none.

00:14:31.360 --> 00:14:34.840
So let's check for it. And in that case,

00:14:36.000 --> 00:14:37.000
let's just add a label.

00:14:39.480 --> 00:14:43.960
Otherwise, we draw the property as we did before. Let's see

00:14:43.960 --> 00:14:46.960
how this works now. Reload the script,

00:14:49.080 --> 00:14:52.080
and there you have it. It says "no active object" instead of erroring out,

00:14:52.080 --> 00:14:55.840
and all the code will keep working.

00:14:55.840 --> 00:14:58.080
You can argue that this is a bit of a silly button,

00:14:58.080 --> 00:15:01.080
because it only works once and you will be right. But I wanted to have this example

00:15:01.080 --> 00:15:05.480
to show you how things can go wrong and how to resolve that.

00:15:05.480 --> 00:15:08.720
It's also a demonstration of one thing that I find quite important,

00:15:08.720 --> 00:15:12.840
and that is showing why something is not there.

00:15:12.840 --> 00:15:15.120
So, rather than not drawing the property at all

00:15:15.120 --> 00:15:19.840
and just silently skipping over it, now we draw the text,
"no active object",

00:15:19.840 --> 00:15:24.120
which indicates to whoever is using your code, why the option is gone.

00:15:24.120 --> 00:15:27.240
I think that's quite important. So that's why

00:15:27.240 --> 00:15:30.120
I wanted to have this example here anyway,

00:15:30.120 --> 00:15:33.360
even though it's rather useless. You now know how to draw
your own properties,

00:15:33.360 --> 00:15:35.720
so it's up to you to make it useful for your particular workflow.

00:15:35.720 --> 00:15:39.080
Before we end this video, I want to show you one more thing,

00:15:39.080 --> 00:15:42.720
which is adding operators to menus.

00:15:42.720 --> 00:15:45.480
Given what we've seen so far, this is rather easy.

00:15:45.480 --> 00:15:48.840
This is why I kept it as the last step. Let's add
our monkey grid operator

00:15:48.840 --> 00:15:54.080
to the Mesh Add menu. So here, we have Add, Mesh, and would be nice

00:15:54.080 --> 00:15:56.600
if underneath "monkey", there was a monkey grid.

00:15:56.600 --> 00:15:59.480
This means, we have to add it to a menu and there's a trick for that,

00:15:59.480 --> 00:16:02.720
I will show you. But first, we have to know which menu it is.

00:16:02.720 --> 00:16:07.480
You can hover here over Add, and it shows "View 3D MT add",

00:16:07.480 --> 00:16:10.720
and you probably already guessed MT stands for Menu Type.

00:16:10.720 --> 00:16:15.000
Now, the thing is, submenus don't show this.

00:16:15.000 --> 00:16:18.960
See, you don't know what the mesh is. But we can look around in Python console

00:16:18.960 --> 00:16:22.000
and see if we can find it anyway. It is a Type,

00:16:22.000 --> 00:16:26.480
so it is part of the "bpy.types.View3D_MT".

00:16:28.360 --> 00:16:33.360
Let's see if we can find something.

00:16:37.240 --> 00:16:41.360
There you go, "mesh add". So this is very likely to be our menu.

00:16:41.360 --> 00:16:44.840
Calling it here will just give an error, so let's not do that.

00:16:44.840 --> 00:16:49.960
But at least, we have the name now, "view 3D MT mesh add"

00:16:49.960 --> 00:16:53.720
in "bpy.types". Let's copy this and then go to "code".

00:16:53.840 --> 00:16:56.000
As you would have guessed it, we have to do something in the Register

00:16:56.000 --> 00:16:59.120
and in the Unregister functions, and this time is quite different

00:16:59.120 --> 00:17:02.360
than what we've seen so far. First, we have to make

00:17:02.360 --> 00:17:05.840
our own function that will draw whatever we want to add to the menu.

00:17:05.840 --> 00:17:08.000
So that looks something like this.

00:17:11.080 --> 00:17:12.840
The name that you can think of yourself,

00:17:14.360 --> 00:17:18.840
and again, "self, context". Now, let's put "pass" in there

00:17:18.840 --> 00:17:22.000
to make Python happy. And this function basically will be called

00:17:22.000 --> 00:17:25.480
after the Draw function of that panel. So our own panel

00:17:25.480 --> 00:17:29.360
has this Draw function with "self" and "context",

00:17:29.360 --> 00:17:31.960
this function will be called with the same "self" and the same "context".

00:17:31.960 --> 00:17:35.600
So "self" will refer to that menu in our case.

00:17:35.600 --> 00:17:39.080
Now, let's register and unregister this function. This is done

00:17:39.080 --> 00:17:44.240
by taking that "bpy.types.view 3D......." and saying
".append(mesh_add_menu_draw)"

00:17:46.960 --> 00:17:51.240
The opposite is "remove". So if unregister,

00:17:54.120 --> 00:17:58.840
will "remove mesh add menu draw". Now, what to put in here?

00:17:58.840 --> 00:18:02.600
That's the same as with a panel. We can just call "self.layout.operator",

00:18:08.840 --> 00:18:12.000
hopefully the idea of the operator, and this should work.

00:18:12.000 --> 00:18:16.600
Let's save and go back to Blender, reload the script, add mesh,

00:18:16.600 --> 00:18:19.600
and there, we have "monkey grid". It doesn't have an icon yet.

00:18:19.600 --> 00:18:23.000
But now, you know how to add one, so I'll leave that for you.

00:18:23.000 --> 00:18:26.000
Now, you've seen how to add your own panel,

00:18:26.000 --> 00:18:29.360
how to add your own operators to existing menus. But most importantly,

00:18:29.360 --> 00:18:32.840
you've seen how to look at other code. So when you see something

00:18:32.840 --> 00:18:35.480
that's interesting, when you're wondering how did they do that,

00:18:35.480 --> 00:18:38.720
you can just right click Edit Source,

00:18:38.720 --> 00:18:41.720
and most of the User Interface elements in Blender are written in Python,

00:18:41.720 --> 00:18:45.120
and then, this just works. So this is it

00:18:45.120 --> 00:18:47.720
for this episode of Scripting for Artists.

00:18:47.720 --> 00:18:50.120
If you have any questions or remarks, please leave them
 in the comment below

00:18:50.120 --> 00:18:51.120
and I will see you soon.