Hello and welcome to scripting for artist.
My name is Simon and in this episode I will show you how to create your own operator.
So far we only created snippets of code.
You can use them but they're not the most you have friendly.
Many people have asked for ways to create
menus and buttons and custom panels and stuff.
In this episode we will not look at that yet but we will
look at it necessary first step which is creating your first operator.
Yeah.
Mm
First we'll look at what an operator is exactly.
Then we will see how to create your own operator and
how to make it more flexible by passing parameters to it.
And then we conclude by limiting the operator to specific context.
An operator is to glue between menus,
buttons and hot keys and the code that should
be executed by them in the first episode,
we already worked with operators by copy pasting
them from menus and buttons into our own script
operators can be implemented in blender itself in the C
programming language or they can of course be written in python
and no matter how they're made, they all have the same ingredients
first is an identifier. So this is what you would put after the beep idol.
Ops So in this operator example, um it's far from complete but we're building it up.
So in this example it would be be private ob start S F a dot example.
Um These are always in the form of some category dot name.
I usually it's best to pick a category that already exists like object
or mesh or sculpt or whatever is suitable for your your operator.
Um but as you can see you can also create your own then we have a label,
this is what appears on the menu items and buttons
and a description that is shown as a tool tip.
Then everything is combined into a class and this
is something that we will look at in a minute
for now just think of it as some pot in
which we gather all the ingredients of our operator.
You can see that the class is named after the operator.
So we have the category in capitals then ot for
the operator type and then the rest of the identify where
So far we've seen description but not actual code yet.
And this can be added in different ways for different purposes.
So here are the possibilities from simple to complex you execute.
This is where you put the main functionality of the code.
If you want to create 600 monkeys, then this is place to do it.
Um the execute function is also what gets called from python directly.
So if you call an operator like be pilot opposite something that's something
this is the function that gets called,
then we have invoked.
This function is called when the operator is called for a menu or a button.
If you want to do something extra in
that case you want to have slightly different behavior
then you can do that in invoke and you can then call your execute function from there.
And now we get to the most complex that model one.
The motor function is for special operators that need
to run for a longer period of time.
This receives all kinds of events from blender from when you move your mouth.
You click on button. She used the keyword that kind of stuff.
Things like the blend of cloud texture browser or C. D. Cookies.
Right open floor implemented like this.
If after all of this, you're in doubt about which function to use. Keep it simple.
Just use the executed function.
If that turns out not to be able to do what you want to do,
then you have a concrete reason to look at something more complex.
But before that just keep things simple.
Now let's turn this into an actual operator that we can use.
Let's create some more monkeys.
Let's start by removing what we don't need. Let's keep it simple.
Just execute function.
If you look at the
mesh operators,
you can see that they start with Bp Ops mesh
primitive monkey AD for example or uh beep I.
Ops mesh primitive ecos. Fear add so all the operators that creating a mesh object.
They start with mesh. So let's keep doing that.
So the idea and becomes mesh and we're going to create a monkey grid. So
monkey grid uh label monkey grid. The tool tip will be let's spread some joy.
And then the class name we have to change
that becomes category and score all t underscore.
Mhm.
Okay grid.
The execute function has to do something but it also
has to tell blender whether everything succeeded or not.
So everything was all right.
You return finished and that tells blender that the code actually performed well.
But maybe your operator cannot work.
Maybe it is for extruding a mesh and the mesh doesn't have any vertex is.
Um So in that case
do return council.
There are a few other options and they are all described in the manual to go.
There you go. To help.
And then python api reference and then to the section about be part of ops.
So let's assume that everything will work correctly.
We will return finished.
And now all we have to do is put the code here that creates our monkey grid.
So let's copy the code from Chapter three of scripting for artists. And put it here.
So this creates are 600 monkeys and rows of 25.
Um having one unit like blender unit between them.
The operators almost done already. So we have all the ingredients here.
The only thing that we need to do now is to tell blender that this operator exists.
And this is called registration
fortunately this is rather simple.
We just call be pie dot you tails dot registered class. And then the name of the class.
In our case mesh. Ot monkey grid. Um for symmetry.
There should also be a unregistered function.
So that looks like this instead of
calling registered closet called unregistered class.
So basically and does what the register function was doing.
And then we're almost there.
It's just that as you know, when you have a function like this,
it's not automatically cold when you run the script.
And there's a little trick for this
if you add some magic like this in here.
And it looks a bit weird.
But basically what this means is that if this script
is run then it should call the register function.
There's multiple ways in which blender can access your script. It can execute it.
But it can also be imported from something else. Just like we import bP.
Other code can import this file as well.
So there's a distinction between being imported from somewhere else and being run
and only when it's being run. Should it called the register function.
And that is what this code does.
So now what we can do, let's just name this
monkey. Great dot pie. For good measure.
And then let's click play
and nothing happens. Which is kind of a good thing. We didn't see any error message.
Our code doesn't show any message. So silence is kind of good here.
So
let's see what happens now.
The pie boss.
Yeah,
nash,
there we go. We can create a monkey grid. The operator is there that spread some joy.
Let's not call it here. Let's see if we can find our new operator here in the F.
Three menu
Monkey and there's a monkey grid so that's really cool. Press enter to execute it.
And as you can see blend enough freezes one is creating the 600 monkeys.
And this is what happens when you do
something that takes time in the execute function.
And that is okay. The code is part of this Bland file.
So let's see what happens when we create a new blend file.
Yeah
and as you can see the operator is still
there it's been loaded into memory of blender.
It's been registered
and it just keeps taking around.
Now let's see what happens if we restart blender.
Yeah.
Uh huh.
Okay.
And now the monkey. Great operators no longer there.
And this is because blender doesn't just execute all the
scripts that they can find in a blend file.
You have to tell it to do that.
First you have to make sure that the name of the tax file ends in dot py
and then here in the text menu you can check the registered check box.
Now let's save restart blender.
Mhm.
And now it's there.
So let's have some fun and add some parameters when you add a cube.
What you see here on the left is called the redo panel
when you open it you see different parameters that you can set.
So what happens is that when you change the parameters value,
blender pushes the undo button automatically and then re executes the operator
and that is why it's called the redo panel because it's redoing things all the time.
So let's add support for the redo panel to our operator.
We start by declaring the properties that we want to have and
this will be the number of monkeys in the X direction,
number of monkeys in the Y direction and monkey size.
Just like operators live in B pilot ups the properties live in b pilot props.
So again if you want to have more information just go to help python,
api reference and then click on the bp dot props section,
I'll show you what it looks like.
Let's call it count X b pie props.
Yeah,
okay.
In property
instance for integer which means a whole number
because we cannot have all of monkeys.
So count X has to be either one or two or three but can never be like 2.5 or something.
So it's whole numbers only.
And this declares that we want to have that property.
There was a big difference between the Colin that we have here
and the equal sign that we have there.
This sets a name to a value and this is for things that just have to be set.
We have to set Bill I. D. Name too much monkey grid to make it work.
But here we don't really said anything. We just declare to blender.
This is an in property. Please act accordingly.
You can add some parameters here to change behavior.
First of all, we should set a name.
We can call it accent maybe a bit cryptic but for now it will do
and we can add a description
number of monkeys in the X direction. So let's copy this.
Okay
to the why
my name is why a number of monkeys in the Y direction.
And with a size which is another be part corrupts dot
float property
float stands for floating point. It's a technical term for just decimal numbers
name. The size description is size of age, monkey.
So this gives us our properties but they're not used yet.
So let's take a look at the execute function where we're supposed to use them.
This comment, it has to go because we no longer creating 600 monkeys in rows of 25
but it's all flexible. So let's remove that for now.
Now we have to access the properties.
So we declare them and this self gives us access to the actual value,
self is appointed thing and I won't go into detail here about what it represents.
Just know that if you declare property here as count X,
then you can access it here as self dot count X.
So the total number of monkeys.
This number of monkeys in the accent in the Y direction.
Uh This 25 here was the number of monkeys in the X direction.
And then all that is left is to set a size
and that's it. Let's give it a try.
Let's see what happens in the console first.
Yeah.
And there you can see our properties, count X,
count y size and they're all equal to zero because we haven't said any default yet.
And there we have our three monkeys
before we go to actually call it from the view part,
let's have some sensible defaults.
Mhm,
default is three
for the wine default is too I choose different values there on purpose,
this is the default.
So when somebody clicks on the monkey red button or select it from the three list.
This will be what they say because they see a three by two grid,
they immediately know what they need to change.
If they want to change the 3 to 4,
they just changed it 3 to 4 without having to
think about whether it's the X or the Y direction.
So if we were to give them the same default, then they wouldn't be able to see it.
And then they would have to think like which direction is X, which direction is why,
which value do I want to change?
And this is why I give them distinct values.
Finally default for the size run again,
delete everything.
Mhm.
Okay.
And there you can see your defaults and when we execute without any values,
it just uses those defaults.
Mhm.
And the same for the three menu,
there's one more step left and that is to get the redo panel,
we have the properties so blender knows what should hypothetically go in there.
It just doesn't know yet that we support that redo panel.
So let's tell blender that we do.
This is done through bill options. The default value is
register and we have to add undue to it. This will give us the final ingredient.
There you go.
Now we can make them big and small and give them even invalid values.
So to make it pleasant to use for people,
we should really set limits to the sliders so that
it's all sensible values that you can select their.
Fortunately this is again quite simple.
We can set a minimum,
let's set it to one because creating zero monkeys doesn't make sense
and creating negative monkeys even less. So let's start at one.
Let's set the maximum to 10 for now. We can do the same for the count. Why?
And we can set the size zero to minimum and the maximum that set it to one
and now we can drag and things are still nice and sane.
You can see that already gets a little bit slower when these numbers increase
And we still can't get to the 600 we had before.
Even when I type 100 year, it is cut off to the maximum.
So this is why blender has a soft limit.
The hard limit is what we said.
Now that's the absolute limit of the value of the property.
Whereas the soft limit is what the slider will do when you drag around.
So if you want to allow maximum values that are
bigger than 10 or sizes that are bigger than one.
But still want these limits as the limit for the slider.
You can change the maximum into soft maximum,
the minimum that we have now really as
minimum because creating zero monkeys doesn't make sense.
Negative monkeys is impossible.
Also creating a negatively sized monkey is impossible.
So let's change the maximum. Too soft.
Now the dragon is still the same.
What we can set it to create much more monkeys than you would get with dragon.
Now let's get back to that class declaration.
I will explain a little bit more about how classes work in an intuitive way.
I hope without going too much into technical details.
Classes use a system called inheritance. Just like with people.
Uh it's like a parent child structure.
So in this case be pie dot types of operator is the parent and mesh.
Ot monkey grid access to the child.
If you ask a child a question that it knows the answer to say,
do you want to have a cookie?
The child will say yes immediately without asking the parent of course.
But if you ask about taxes, then mom,
please help me out here because I don't know anything.
And then the child differs that question to the parent
and this is the same way that classes work in python,
roughly
we could do without the be all options are child didn't know anything about it.
So python asked the parent
and when we want to have something different,
we can add bill options to our child to our class
and then that is asked first to that takes precedence over whatever the parent ones.
So we always have lucky Children who gets all the cookies they want.
So before I end this video, I have two more things that I wanted to tell you one.
Again, we look at the execute function.
You see that it gets a context parameter and this
is pretty much like the context we've seen before.
It gives us context, object context dot seen, context to the dot selected objects.
All these things you've seen before in the private context.
It gets here as well, but then localized specifically for this operator.
So as a general rule of thumb, if you have a function that gets the context,
use that context and don't use be pie dot context.
So if you want to do something with
all the selected postpones in this execute function,
you would use context dot
selected postpones
another function. And that is the second thing that I wanted to show you.
Another function that gets a context is the whole
function and it's written in a bit weird way.
Uh just take it from me, it works like that.
Yeah,
again,
you get a context in this function but instead
of doing something like instead of performing an action,
this function is meant to check whether that action will be possible.
So this poor function is called by blender every time this operator is supposed
to show up in a menu or as a button on the panel,
I can show you how this works right now.
It returns through which means that it is always allowed just
as it was before and just as it was before,
It shows up here in the F three Menu,
what are the chances of false?
It will never show up anywhere which is kind of useless.
Let's tweak this to make a bit more useful.
You can see here in the console
we have Outer complete, which makes sense. In a python console.
But that same operator does not work
in the three D view part because the context is wrong.
This is also something we can do ourselves right now. When I change this to True.
Again,
the monkey grid operator also shows up in the context of the python console
and it will show up anywhere in blender which is not exactly the right way to go.
Let's take another look at a variable inside that context
context.
That area gives you the area that is currently active in blenders user interface.
So in this case it will be the console but if the mouse is here and we pull up the three
menu then all of a sudden three D view port
that is active and here it would be the outline er
so every area in blender has its own area type and we can use that in our poll
function to make sure that it's only working in the area that we wanted to work in.
One thing I don't really like is guesswork.
So we know now that the area type of the console is console but
is it in three D view port is a three D
view three D underscore view is a three D view port.
I don't know. So let's make our script tell us. Instead,
I can just say print my area is context, the area type
and let's see what happens on the terminal where all these kind of prints are sent to
here. You see the console
and immediately you see it being called.
My area is if you're three D but when I do it here in the outline, er
my areas outline er if I do it here in the properties panel,
my Areas properties.
So that way you can just use these print statements to
know what you have to put, where we know,
we know which value to use for the three D view port.
So let's just do that
If context area, that type equals view 3D then return true.
Otherwise we can return false. Let's see how this works.
Yeah,
here it still shows up,
but here is no longer there and of course here and
there now it only shows up where we wanted to show up
one final thing.
These kind of constructs.
I see them a lot also from experienced programmers,
it's more complex than necessary actually
because this guy is already an expression that is true or false.
So basically what the code is saying is that if the value of this thing,
this selected expression,
if the value of that thing is true, return true and if the value of that thing is false,
return false.
So that basically means
return the value of this thing which you can of course right as
this.
So that was it for this episode of scripting for artists.
If you have any questions or remarks,
please leave a comment down below and I will see you soon.