Blender’s Python API lets you manipulate data like objects, materials, etc. in a blend file. But, have you ever wondered what would happen if you called the add operator
+ on two objects? Or when you multiply
* an object by a number?
Of course, Blender would throw an error saying unsupported operand types. 🙂
But, if you think about it, whenever you call an operator like the
+ operator, Python is calling the respective double underscore method.
Blender throws an error because the
bpy.types.Object, doesn’t implement multiplication or addition. But, this doesn’t mean Blender forbids us from adding this functionality to objects.
Just think about for a second what multiplying an object with an integer would mean in Blender’s context? 🤔
Of course, the closest thing we can relate to is duplicating an object. Multiplying an object by an integer should duplicate it that many times.
Lets try it out!
Duplicate objects using multiply operator
Have a look at this code snippet.
Here, the function
duplicate_ntimes duplicates a given object,
self, n times based on the second argument,
other. But, if you notice the last line, you can see that we are assigning this function as the
__mul__ method to
__mul__ method using setattr adds it to the bpy.types.Object class so that next time when we multiply an object with an integer, this method will be invoked.
Now you can simply duplicate an object n times like this:
By the way, don’t forget to add these imports. Otherwise this code snippet will raise an error.
import bpy from bpy import context
Contextual behaviour using context managers
Okay, implementing multiplication was pretty easy. Now, lets park that for a moment and shift our focus to addition. Think about what addition could mean in Blender’s context.
The Join operation right? 😃
But, wait. What about booleans? Addition could also mean Boolean Union. Does that mean we have to choose one over the other? 🤔 Is there a way to have both?
There is a mechanism built into Python to handle issues like this. It’s called a context manager (different from Blender’s
bpy.context) and you have definitely seen or used it before.
Anytime you read a file using the
with statement, you are using a context manager. Context managers enable us to set something up, yield the execution to other statements, and eventually tear down the initial setup.
When reading a file using the with statement, the setup is opening the file. Then you do something else, and finally, the file is closed for you. This setup and teardown is handled using
__exit__ methods respectively.
But, implementing something using these methods means writing a class and I am personally not fond of classes. 🙂
Python has yet another mechanism to solve this. It’s called
contextlib – a standard library module to make the process of implementing context managers as simple as writing a function.
contextlib and try the following snippet:
In the above snippet, you can see we are defining a function called
zbool which in turn defines the
__iadd__ method and adds it to
__iadd__ method is responsible for the
If you notice, after we use
setattr, we are yielding control back to the user to do something. In this case, it is to use the
And once the user is done, we delete the
__iadd__ attribute from the
bpy.types.Object class. This way, the
+= operator performs a Boolean Union only inside this
zbool context manager.
And we make this function as context manager using the decorator
@contextlib.contextmanager from the
Now, you perform Boolean Union operations simply like this:
By the way, those cubes were produced by the previous multiply operation. 🙂
This way we can implement contextual behaviours for our operators.
And, that’s it for now.
A few things you can try:
- Try implementing the join operation when
+=is called outside the context manager.
- Think of what operators like
/, etc. could mean in Blender.
Read more about Python’s double underscore methods in the Python documentation.
Learn more about Python’s advanced features from this talk by James Powell.
Subscribe to my newsletter
Join other Technical Artists, Developers and CG enthusiasts who receive my latest posts on Blender, Python, scripting, computer graphics and more directly to their inbox.