 Welcome. Great to see everybody here. Hopefully you're here for getting started with scripting in Python with me, Mike Shaw. So nice to meet you, folks. Yeah, thank you for the applause. Yeah. Yeah. Of course, you've got to make me earn it. So we'll see you at the end. So anyways, we're going to be doing a little bit of a tutorial here in some sense of just getting you started with scripting in Python. This is for an introductory audience for whatever introductory means to you. So maybe you've done a bunch of programming in other languages and just want to hop into Blender. Maybe some of you are expert artists, but have learned a little bit of programming and want to learn just how to get started. So that's kind of the goal. And that's the origin of this talk here. Just by a raise of hands, how many folks have programmed in Python before? I have a little bit of experience. OK, so good number of the audience. And I suppose of those folks who have rose their hands, how many have done Python programming in Blender? OK, so good number of folks. OK, so yeah, keep me honest. Shout out something if there's something interesting and I'll repeat it. But we'll just go ahead and get started with the beginnings here. So anyways, here's the abstract that hopefully brought you to this talk and got you enticed to learn a little bit of scripting or just to see how things are done or how maybe I approached them. And this should be a fun talk. Again, it's for everybody. Again, whether you've programmed the folks who rose their hands or if you haven't, that's great. You're in the right place. So either way, everybody here is welcome. And I found when I started messing around with scripting in Blender, I just keep messing around even more. More time in Blender, which is great. So again, just to give you a little sense of what we're going to be creating. Again, evaluate your skill level. I'm just going to go ahead and show you whether you're watching this now, live with me, or in the future, what we're going to be building here. So we're going to be basically building just a little Python script. And then we'll implement it as a command for creating a bounding box. So again, if you'll see Suzanne here, our mesh, and then the bounding box that surrounds it, that's what we're going to be creating. Now, of course, there are bounding boxes and ways to do this in Blender already. But we're going to see how to do this programmatically and just explore some of the different APIs that we can use, or rather, the Python API and some of the modules within it. So if that keeps you here, that's great. And we'll go ahead and keep moving along here. So the code for the talk is available. You can, of course, just Google my name. The slides are already on the website. If you want to peek and poke around a little bit, and then you can go from there. And a little bit about me. Primarily, I teach at Northeastern University. I'm housed in the computer science department. And I do a lot of computer graphics programming, so OpenGL, Vulkan, that kind of stuff. But every once in a while, I dabble into the art and into Blender. I make all of my students learn a little bit of Blender, even if they aren't more the computer science and programming side, because everybody needs to know how to talk to everybody, right? So that's a little bit just about me and what I do professionally. And a lot of my consulting work has been writing plugins and extensions with 3D tools to get them working with Blender or some sort of data pipeline. Alrighty. So thinking about programming Blender 3D here, again, the origin of this talk is born out of a computational geometry class. So something that tends to be more proves and algorithms improving things. And I try to make it as applied as possible. So having students implement things in C++ and SDL and doing graphics and interesting algorithms to do in 2D, computing convex holes and typical geometry things that you might think of. But when it comes to the 3D part, I can't assume that folks have OpenGL or Vulkan or Metal Knowledge in this course. But what I also think that opens a door is even if you are somebody who does a lot of 3D programming, is Blender is a great program for using as a playground to play around with different ideas. So again, wherever you are in your journey here, whether you're an expert 3D programmer, consider Blender is a tool you can play around with as well. It's a quick sandbox that I like to use. And again, if you're beginning, this is a great place to learn some fundamental 3D concepts as well. So from the origins of this class, my idea was, hmm, what kind of interesting problem is going to a student work on? And again, another way to think about this for yourself if you're just learning how to program in Blender is to take some things that you know or might know how to use in Blender itself and, well, you have a solution. Someone else already has implemented things for computing and displaying normals or bisecting a mesh or computing convex holes or bonding boxes which we're going to create here. So it's kind of nice, you have a solution in some ways of something that you can look at. The code or at least a reference of a visual of something actually working. So, you know, thinking about some of these ideas, I thought something that was approachable was a bounding boxes, at least for a first programming project here. And it turns out that this problem itself was interesting enough and exposes you to enough interesting pieces of Blender 3D that again, I think it's a nice exercise for folks just getting started here. Okay, so in terms of getting started with Python scripting in Blender 3D, what do we need here? Well, of course we need to install Blender. Here at the Blender conference, I'm assuming everybody's got that set up here. So, you know, don't have to sell you too much on that. But, you know, keeping your Blender up-to-date is a good idea as the API and programming interfaces might evolve. Keeping your Python up-to-date, it's a version 3.10 or beyond, you know, it's pretty modern these days. And again, just a note that Blender does tend to keep up with the releases of Python as far as how it's progressing. But that's about it. Once you install Blender, you're pretty much good to go, whether that's for Windows, your favorite flavor of Linux and Mac as well. So, let's go ahead and get to the scripting layout here because that's the part that we're gonna be working in. And I'll go ahead and I have Blender open up here. And I've made it as large as I can. It'll have plenty of images in case you can't see or you can capture on the recording. And the first thing that I need to do is get to get to the scripting interface. Now, of course, looking here, I can't find it. So, I've got a scroll here. So, if you didn't know this guy's scrolls, you can find scripting way at the end here and go ahead and tap onto that. Of course, if you can't see it, sometimes when I'm working on an airplane or something, you can go to your preferences and adjust your resolution and grab it that way as well. Or page down also works. So, just a few little tricks. If you're like me writing a talk on an airplane, how to do some of these things. So, anyways, that brings us to this scripting interface which, again, if you've just worked in this tools and artists you might not have known about or maybe have hidden away from it, that's how I approached it when I first started. And we've got a few windows here. Of course, we've got our regular viewport here which we can move around here. That's this window here. They've got this Python interactive console which I'll get to us writing our first little program in a moment here. I've got an info log below the Python console here that's gonna kinda tell us what's going on in Blender. And on the right, we're gonna use this for writing more interesting or longer scripts here. So, I see we've got a bunch of more space here for writing our scripts. Now, of course, you can also use other external editors, VSCode, VIM, choose your favorite tool, whatever it might be, PyCharm, and you can write your scripts and those and load those in as well. But I'm gonna be working just in the text editor again. That's all you need to get started. You have it here. Okay, so the brief recap here. Here's our scripting workspace. We've got a script or Python scripts that we can write in here. Then again, you can see what version of Python you're using, hopefully something three dot, maybe 10 or later. But definitely greater than three. Your info log, which we're gonna follow along and see what's going on in Python. And then the text editor on the right where you can write many, many lines of code as you need. Alrighty, and here we're just my hints on finding the workspace if you need to find that as well, which I showed you. All right, so let's go ahead and write our first but not last Python Blender script. And again, this is gonna be, I think everybody in this room has done something like this. But just to make sure that things are working at the least if you install a fresh copy of, well, I hear Blender four is coming out soon. So you might wanna test that out. Just go ahead and type print and hello, Blender conference folks. And give that an enter and there you go. So your first script, everything's working and it's echoing back the text here. So printing out our text. Again, by the amount of hands I saw rows here, piece of cake for everybody. For those otherwise, this is a great way to make sure things are up and running. All right, so congratulations on that. The things are working and I'll let the animations play as well in case you're not able to or wanna follow along one piece at a time. But that's our first script here. Now, interestingly with the Python setup within the scripting workspace, you'll notice that there's a bunch of built-in modules here. We'll have to revisit some of these later, but this is basically telling us in our Python setup that we've imported a bunch of things here, Bpy, Blender Python, Bpy.data, Bpy.opt and so on. So these are some of the important modules that we're gonna probably wanna take a look at later on here. Those are already set up for us and the Python console here. But again, if you're writing your own scripts, you're gonna have to import these on your own. Okay, so that's our first script. Very exciting and things are working and good to go. And again, just as a little aside, hopefully you have a little bit of Python experience, but again, you don't need too, too much here. If you're pretty comfortable with a list and a dictionary and a tuple and a loop, maybe some if statements, that's pretty much it. So you can get started with Python relatively easy. Again, Python's a great language for just getting things up and running. And today, just again as a caveat, though I'd appreciate audience participation if you see something, I'm gonna keep the code as simple as possible. We don't have to do anything complex. We can tighten things up as needed. But this is really your cheat sheet as far as data structures go, which again, you can learn in a day or mess around with in a day's time. So pretty cool here. We have Python embedded in Blender 3D, which means that's basically the power of a full programming language at our fingertips here, which is awesome. So we can use all the different modules that we would otherwise have in Python. So things like the system module or creating random numbers. So again, just to follow along with a little example here, I'm gonna revisit over here on the screen and I can import something like random, which gives us access to random numbers here. And we can print off maybe a random number here. So print random. Let's do a random integer, zero to five, something like that. And I'll hit enter and we get some random integers here. Okay, simple enough here. Now again, the observation here again, is that we're able to access all of Python, but I did things pretty quickly here, which might have been a little slick. So just some shortcuts to help you save some time. Again, as you're typing stuff out, you can tab to autocomplete. So if I just type random and tab, it'll give me a good list of things that I can use here. So again, here's some random things I can use and then I can just autocomplete it and it's also giving me help there. So I'm hitting tab as I'm doing that. And then in order to not repeat myself, you can cycle up with the up arrow key to go back in your history and down vice versa. Again, just some time saving tips there for you if this is brand new for you. Alrighty, and here's a still capture of the code in case the animation was too distracting. And here are those productivity tips again, just for your review. Okay, so again, let's write another script here, maybe something interesting to do. And this will be something that's interesting in the sense of when you're actually writing your scripts, maybe I just wanna know how long something takes. The stuff we're gonna be doing today is relatively quick as far as the computation, but some of you and some of the great talks that I've been listening to are on render farms and building really complex stuff that might take a long time to render and draw. So you might wanna use something like time here. So let's just import time. And what time does is it gives us the current time here is this integer. But what we really care about is when time starts. So I'll assign a variable start time to whatever time it happens to be. And the elapsed time here is gonna be my, well, current time, minus my start time. Hit Enter and let's print out that variable. And again, I'm gonna tab to just autocomplete this. And there we go. So 10 seconds, that's my typing speed there. Not too shabby, I guess. But yeah, that's a general idea. So something again, useful and everything that you have available in Python for you. So if you need to plot some graphs or do something else interesting, you've got it. Alrighty, so that again is pretty interesting and you can leverage all of your Python skills here, but you've also got the power of Blender again at your fingertips here. So that means again, the Python API that's attached to Blender is again, these Python commands that we can use. We're gonna learn that these are different operations that we can capture here. But let's go ahead and just observe what's going on here behind the scenes. And this is a great way also to learn a little bit about what Blender is doing. So what I'm gonna do is just draw your attention here to my viewport window with a cube. Let's select this cube here and go into edit mode. Three for faces, I'm gonna hit Enter here. And let me pan my camera just a little bit here and zoom us in. And E for extrude, I'm just gonna move this cube up a little bit here and hit Enter here. Now, as soon as I did that, if you caught it here in the council log, which I'll highlight in the, what's over my shoulder here, the bottom left of the screen, you'll see that this is the command for doing an extrude. Wow, okay, that's a bunch of stuff here. But let's copy it here, okay? And let's go ahead and paste it in here. And I'm gonna go ahead, I'm gonna hit Enter here in one second and keep an eye on my viewport. I hit Enter there and we extruded. Hit up in our history, enter again, and we're repeating here, okay? So we can see our extrude command is being executed over and over and over again. Okay, so this is one way to kind of learn about what's going on in the Blender API here. And again, maybe asking you to memorize this function, that's not what I'm asking you to do. But what I am asking you to do is maybe just take a look here and say, okay, this is something in the Blender Python, something with ops, mesh, okay, and there is some extrude region move. That looks like some function with a bunch of default arguments, okay? So it's kind of pointing you in the right direction of where you can learn about stuff. Now, again, just for learning about stuff, you can just do things in your actual viewport here and see the result. So another little tip here for learning about what's going on in Blender, let's just go and edit preferences and turn on the Python tooltips. And if you just kind of hover around some stuff here, let's kind of hover around this here, object. And you'll immediately see not just the tooltip, but below it the Python API of what's going on. So you'll see object properties, okay, there's something in Bpy, dot data, dot screens, scripting, et cetera. Again, pointing us in the right direction here. Let's actually click into this and see something like our viewport display. I'm gonna highlight over bounds here because we might need that later. But again, object.showBounds, that's again sort of the category of things. And then bpy.data.objects, cube, and quotations.showBounds, okay? So that's what we're actually doing when we click here. We can see that this command is being processed. Now let me actually click on this cube here. Let's go and edit mode and toggle the bounds. And again, you'll see that over my shoulder here, something is toggling true to false, true to false, okay? So another great way to learn here. All right, so that's pretty cool. I love that does an exercise or when I saw that, and this is similar in some other 3D tools that shall not be named here. But this again is a great way to learn and explore a tool here and start programming things. So again, as an exercise, you can try that out here if you're following along. That's a great time to pause and try that. But we're gonna keep moving along here as we can get to our bounding box. And a few other things that are useful, right? There's built-in help and Blender. So if I stumble, I'm trying to get through this without making any errors. We'll see if that challenge is accomplished. But you can just type in help and then some sort of command or module here. So again, that bpy module is pretty interesting. So again, if I do help, type in bpy. Well, I get the help page here. And we can kind of see what this is about here. Give access to Blender data and utility functions. Okay, sounds like something that we want here. So that's just one thing that we can do. The other thing that's gonna be useful is if you wanna see the type of something. So again, maybe you're playing around with a user interface and trying to capture what sort of actions were happening. Maybe you can just do something like type here and see the type of something. Okay, so let me go ahead and jump ahead for a moment. And try that command out here. Let's scroll to the bottom. Use bpy, context, and let's see here. Active, again, kind of auto-completing. Again, maybe we don't know what all these things are, but object, okay, I'm just gonna hit enter here and it's telling me the active selected object is this cube here, okay? Now if I hit up in my history here, I'll assign this to variable, my object, and then I can see what's the type of my object, okay? Okay, it's a something bpytypes.object here. They can kind of explore around here a little bit. Now that I've got things in a variable, hit dot, see what's available. Data is one that I know about. Okay, that's something there and that is printing out the type here. Okay, so let's just go ahead and look at it here. Okay, so it looks like our objects, data is some sort of mesh, makes sense, some sort of geometry. So again, that's just exploring and playing around with our data here. All right, and then of course, the documentation's useful. Again, another pro tip, maybe you're familiar with this in scripting, but the pro tip is to download the offline version. It's a little bit faster. You don't have to wait for web requests, so if you are a power user, that can be useful. Okay, and then we did also enable our tooltips. Yes, question? Sure, yeah, because you can just use like F1 or whatever the built-in search is. I'm a two-screen user, so I always have the offline just up and running and then I just type in the search built-in. So the index in the browser. Yep, yeah, exactly. And if anyone knows how to do, look through the docs faster, please let me know. You can also kind of grab through the pages too if you're on Linux that can be useful sometimes, but the search is pretty good. Alrighty, so again, we enabled our Python tooltips. There's also these developer extras. That'll give you a little bit more power too. You can enable those when the time comes, but let's go ahead and keep moving on and start using our internal editor here. Oops. All right, so again, doing these little examples one line at a time and the console is great, great way to play around with, but eventually we wanna write some more meaningful script here and actually show what a series of commands can do and then of course maybe give those to some user so that they can recreate those commands as well. So I'm just gonna use again the internal editor here. It works well enough. Paste a little bit of code and we'll talk about it here, but again, use whatever tools you're productive in, VS Code, Vim and so on. And you can set it up such that if you're making changes in VS Code, those changes are reloaded in the text editor. That's also available. Now another little tip here as well is to launch Blender from the terminal. This might depend or the instructions may differ depending on if you're on Windows, Linux or Mac, but that'll give us some helpful error messages here. Now let's see, here's my terminal here where I launch things. I don't have anything printing out quite yet, but that's just another useful thing or you can capture the actual output from the terminal. Again, maybe something for our power users. Alrighty, so that's a little bit of an intro, getting us set up here, but let's actually solve the bounding box problem with our Python scripting. So again, gathering some tools from the Python API here. So let's just think about this a little bit for how to create a bounding box programmatically. So again, this is what I showed you as far as the goal that we were gonna try to achieve here, but let's see what we can explore here in our API. So, and again, I showed you that there's a little cheat code, so if you're just trying to, in a sense, complete this, you could just use the show the bounding box in the viewport for the actual object. And again, that might give you a hint of, maybe that's good enough for your particular solution. But for us, I wanna actually create the geometry so that I can see it, maybe I can use it in a physics simulation or some place where that might be useful. So let's actually implement that as part of the geometry. So, a little quick question here, and I'll give everybody a few moments to think about it here, but if you had to compute the bounding box, what's your strategy? What do you think you need to do here? Let me give everyone 10 or 20 seconds to think about it. Yeah, I'll take it. Okay, so the comment was, I could take the width and the height and maybe divide those. Right, I've got the dimensions in Blender, right? So I actually already know some of this information. Yeah, so that could be one solution, right? I could take the dimensions and do something interesting with it to surround this object, right? What else are folks thinking about? And there, yeah, so the comment was, just read the array of vertices, everything's got a position, and then just kinda figure out the min and the max. Okay, another solution. That's gonna happen to be the one. Now, did you see my slides? Maybe you did. But that could be another exact solution. Anybody come up with anything else? Yeah, there could be a couple different solutions for this, but let's go ahead and walk forward with that one. And I think Blender does give us accurate information, so we might wanna just take the balances suggested here. I'm gonna show you the vertices because it shows you how to dig into some of the geometry, which I think is interesting here. But let's go ahead and iterate through all the vertices, right, and then we'll get the X, Y, and Z values and figure out what the min and the max are. Okay, and that's gonna create our balance for a box. How wide of a box do we need? How high and how deep the box needs to be for the depth value. And as was suggested towards the front here, we do have a dot bound box. Again, it's built into Blender. So oftentimes you'll find you have some of these solutions built in, just depends how you wanna solve your problem. Do you need the raw vertices or not? I'm gonna say that I need them for this particular talk here. And you can see in the bottom right, if you're curious, how to just get the dot bound box. And again, these are things that I just learned by trying to recreate or solve a problem that's already implemented in Blender. So again, if you're just thinking about ideas of things to polish up on your scripting, you can take a solve problem and try to solve it. Another small caveat here is that we're gonna make this an access aligned bounding box, meaning that when I rotate the actual mesh, the bounding box will stay in rotation with the box. Okay, already. So in order to approach this problem again, here were the important modules that I mentioned. The Blender Python module, which is sort of gonna be the default, always import this module for most of your scripts if you're working with some of the geometry and so on. But there's these other ones that are of also interest that I snuck in here, bpy.context. So I used that earlier for getting the active object. And that's telling me whatever area that I'm actively in, whether it's a viewport or maybe part of the interface, tell me something about the context there and give me some information, okay? Then I've got bpydata and that stores the whatever information about the object that you're working with. So in the case of a mesh, that could be again, the vertices, edges and faces, which we're gonna care about for us today. And then finally there's bpy.ops, which are functions that are invoked by the interface generally. So some sort of operation that we're performing. Let's focus on these two for now. These are gonna be useful for selecting an object that we're interested in and then computing the bounding box. Okay, so let's start looking at a bounding box implementation here. And again, first and foremost, the first thing that I need to do is be able to figure out what object I'm interested in. Now again, depending on your script, you could iterate through all objects. I'm just gonna go ahead and grab the current object here, okay? So again, just to show that, I'll show it in the Python console, then we'll move to a script here. MyObject, bpy.context.activeObject. That's it, whatever object's selected here, okay? And then you can, oops, type it out here, MyObject. And we could see we have the cube, which matches, if I scroll down here a little bit, in our scene collection, the cube, okay? So it makes sense. Alrighty, so we've got an object, but how do we actually get the data from that object? Meaning the vertices, the edges and the faces? Well, I'll give you some hints here. Again, how I'm figuring these things out usually, I'm still going to Google, if I don't know, and saying, how do I get the geometry? So I can kind of point you in the right direction. Or you can type out MyObject. And then hit tab and you'll get a list of, well, what's available? Another way to explore. And then I put that in the documentation. So again, that's again, just thinking about how to learn this stuff. So what I'm getting here is the data, and sometimes you'll hear this referred to as a data block, right? Some internal data inside of Blender. Again, vertices, edges and polygons. So some collection or maybe it's a list of something or some other data structure, okay? So that's the idea here. Now let's go ahead and start putting part of this script together and looking at the code here. I'm gonna grab it here. So this is the GitHub repository. Again, you can find this, it's already publicly available, if you'd like. But I wanna talk about some of the code as it's here so we can see it. So I'm gonna go ahead and go over to text. Let's create a new file here. Just gonna dump it in and then we'll talk about the parts of interest here. Alrighty, so if I scroll over here. Again, I'm setting up our script so that we're importing modules of interests, maybe timing how long this actual script takes, selecting the active object. And then I wanna start grabbing some of the data here like the vertices, okay? And then we're just gonna follow along our bounding box algorithm, which means, well, storing all of our x, y and z values and then figuring out what is the max and the min of those dimensions here. Okay, so let me scroll us down here. And here we've got that process. So I'm gonna look through for whatever my active object is, all the vertices, okay, that's this correlating here. And again, just a regular loop in Python. Okay, and then I'm gonna append the v.co, co being the coordinates for x, y and z, three coordinates, to our arrays here, okay? And then you can use whatever sort of optimization you want here. You could do this all in one loop here, but I'm just gonna use the min and max values for our x and our y and z arrays, or excuse me, lists here in Python, okay? So hopefully that makes sense. I am doing one other funky thing here, which is just to show you something, a little bit of a teaser here, to just grab these selected vertices, because maybe I just want that bounding box to be like the character's head or something, you know, some sort of interesting attribute here. So I'm gonna play around with that and show you later how that works. And again, just this idea that when you start playing around with your code, you get some new ideas here. Okay, so let's go ahead and jump here. So again, revealing what we've done, the important parts here. Again, from our currently selected object, basically build out this array of x, y and z values, and then select the minimum and the maximum. So with this, we've got our dimensions of our actual bounding box here. All right, so I've got the sort of dimension, so I know the width, height and the depth of what this bounding box is supposed to be, but how do I create it? So again, this is something that you can think about. You've got a few different options. Immediately, if you're coming from a graphics programming background, maybe you're thinking about, okay, I have a mesh that I need to create. So that means I have the indices of some vertices and I need to link them together and figure out the edges and the faces. And again, that's a valid approach that you could go with. But again, we're in Blender. It's a little bit of a playground here. So we're gonna be creative. We can think creatively in this tool suite. And I'm gonna actually go with another second approach such that I don't have to worry so much about the connectivity of these vertices, right? That vertex one is linked with three and that makes an edge and I'm gonna make sure that there are triangles, perhaps if they have to be triangulated, maybe not, and depends on what you're doing. But again, that's usually what I'm thinking with my graphics hat on. But with my Blender scripting hat on, I'm just gonna say, well, there's already a way to make a cube. That's a box. So why don't we use that in Blender? And we already learned how to grab some operation that occurred. So again, the idea here is if I'm in Blender, I can go ahead and just add some object here, a mesh, a cube is exactly what I need for my bounding box and I've got it here. And I can go ahead and look down in my history, down in this corner over my shoulder here and figure out what the operation is to make a mesh. Simple enough here. All right, so that's what we're gonna use. Again, we could consider it a little bit of a, I call them cheat codes, but I just call it thinking creatively, right? We're just supposed to play around here. Previously I was working on a project where I had to get a shot from 45 separate degrees of angle one after the other. And I could either rotate one camera and have to worry about repositioning it 45 degrees or I could just create 45 cameras separated by one degree. Again, the choice is yours, whatever you think is simple and easy to maintain, it's a creative thing programming is. All right, so let me go ahead and just show you in the script here, if I scroll down here. And again, I'm giving myself a little bit of a cheat sheet here as you're learning things, right? Printing off what the bounds are. And we can verify these, right? By clicking on the object and seeing the dimensions. We can compute that. But here is creating our cube here, okay? So there we are. I'm just creating this temporary cube. I'm gonna make it the current active object and then I'm gonna grab the data, which is this next section that I wanna talk about here. Now I've got a cube, I've got its data, but again we wanna think just a little bit about how this data is stored here. So in Blender we have something called the B mesh, that's one of the internal data structures for representing meshes. And that's probably what's gonna be most relevant for us for creating some object. So again, when I looked at the type of our object earlier, we've got the dot mesh type here, okay? For the B mesh. Alrighty, so now that I've got all of my cube and it's my active object, I wanna be able to grab the data, the vertices, the edges, and the faces. Again, a bunch of ways that you can approach this problem here. But what I'm gonna do here is essentially flatten the data, meaning that I have all of my vertices. I wanna write those out as x, y, and z as a tuple here. Okay, so that's what I'm doing in this next block of code. And then I sort of wanna do the same thing for my edges. But my edges are just gonna come in as a pair. Again, a line segment or edges, two vertices. So again, I'm gonna grab those. And for my faces, well, I don't necessarily know how many, I should I suppose have three vertices at least, marking the face here. But it is a polygon, it could be unsighted, but I also need to iterate throughout that. So that's why I've got this iteration here. And this is kind of a fun thing to figure out here. How do I iterate through each of these data structures? But that's the idea here. So let me show you in the code. Again, here it is. So our purpose here is just to sort of flatten out our data and get our data into lists here. And I'm gonna show you why that's important later on because I'm gonna be creating a blender mesh that needs a list of vertices, a list of edges, and a list of polygons or faces provided to it. Alrighty, so now it's time to also build out our bounding box. Meaning, well, I've got the vertices, edges, and the faces of my cube, but I need to make sure that I adjust those vertices to our dimensions, the width, the height, and the depth of the box here. So effectively, what I'm gonna do is, again, capture from my cube, again, the temporary vertices, and assign them to, well, basically all the corners of a box here. And you might notice a little pattern here if you look through this, but I'm just manually assigning all eight of the vertices to some combination of minimum and maximum values for our x, y, and z. That's like a truth table where I've got min, min, min, max, max, min, min, max, max, et cetera. I'm sort of repeating down here, but all the combinations here. Alright, and now it's time that you've been waiting for is we're actually gonna build this thing. This looks like we've got our vertices adjusted. They've been moved to the locations we need. We've got the connectivity information for our edges and our faces to build the actual cube, and now it's time to add the mesh to our scene. So again, I'll go ahead and just show you in the code here in Blender. Let's make sure we can see all of it. This is the part that I'm gonna be focusing on. And I wanna create some new object here. That's gonna be added to our scene's collection of objects. I'm gonna prefix it with bounding underscore. Again, choose whatever convention you like, but we need some sort of unique name. And then I'm gonna create the new mesh here. So again, I'm gonna create a new mesh. Now creating the new mesh is important because that's gonna sort of update Blender's database of these objects exist, okay? So that's what I'm effectively doing, creating this new object. And then what I'm gonna do here is populate this mesh from whatever the Python data is with my vertices, from my bounding box, and the typical edges and the faces that make up a cube, okay? That I copied over from some cube that already existed, okay? And again, how you create that's sort of up to you. I like the Blender one. It was easy to work with. That's a quad based mesh, which probably makes sense here. And then finally, I need to do one or two other steps here. So for my bounding object here, I need to now create this object here with the name and the associated mesh here. And then finally, this step here at line 111 is gonna add to my collection. So let's just see what's going on here. Collection over here in my current scene by default and link it in here, okay? So that way we should see under whatever our object is the bounding box. And then finally, just little tiny touch here is to again, use what we learned from our viewport. So again, if I scroll down here in object and scroll over the Python tool tip for our bounds, I'm just gonna make it a wireframe view by default. Okay, so let's see how much this works here. And let's give ourselves a more interesting object. Cube's not a great one to test on. So I put in monkey here. And then I can alt P is gonna be my shortcut on Linux here for generating the bounding box and we get something like this here. Okay, so pretty neat here. Let's rotate it around. There it is. And we can kind of visually verify it here. Or you could again verify it against the bounds of the object. But I do see that it is added here under my object here. Okay, so a few more steps here and then we'll be almost complete. And this is the final step here, which is to parent our object for our bounding box under some other mesh. Now the advantage of this here is if I go back to my code here, show you in the script exactly what this is happening down here, then that means if I transform Suzanne, of course in the hierarchy, the bounding box moves with it. Okay, and you can think about how you might want otherwise handle this. You could update it with the rotation or scale under the location here. But you probably wanna just have it set as a parent so as you update your scene and updates with it. Again, just thinking creatively about how to approach this problem here. Okay, and the rest of this script does a little bit of cleanup to remove the temporary cube and so on. Okay, so that's our result here, which is quite nice. I think it's taught us how to kind of walk through this process or maybe just kinda think about how to create things. But we're not quite done yet because we wanna make this a little bit more useful, meaning asking somebody to just paste in a blob of code and execute it with alt P or whatever shortcut you have. We can make things a little bit more user-friendly. So I'll give you sort of the intro here to turn this script into what's an add-on. So again, an add-on being something that you can install from the community or an official Blender add-on. So what we're gonna need here for our code is to kind of prep our script here, give it a unique identifier so that we know what this command is here. So I've got this dictionary here called bl underscore info. Again, these things are just by convention where you need a name and sort of a category for the object and sort of a Blender version minimum, I suppose here. And then register and unregister, which are functions that I'll execute once you add this add-on or remove it for unregister. Okay, so that's gonna be the first step here. Then I'll show you an example and give you the code here in a moment. But again, we wanna make our command usable and this is where you can, when you register your command, you can maybe add it to the user interface. I believe there was a talk on the previous session which talked a little bit more about adding things to the UI. This particular code, again from the API docs, is gonna add it to our command menu so we can just hit F3, type the command and execute it. But that'll do the trick for us, which is the last step here. It is to prepare the execute function, which for me means basically taking our code, wrapping it in a class here, object compute bounding box, give it some name. It's gonna inherit it some type of operator, it's some ops or operation that when I press a key I can interact with and have this take place here. Okay, so let's go ahead and prepare this. Again, I've got another snippet for you for the add-on, which you can dig through and as good exercise, you can think about how you might abstract some things. Let's go ahead and pop this in here. Let's delete this object and start from over. Add our mesh back. And I'll go ahead and run it and then we'll do a quick code review here. So alt P, what happened? Well, I had something selected, nothing yet. Still need to select my mesh, can hit F3. And let's type out object, compute, bounding box, blender con, before the command here. And you can see the help tips and so on that pop up here. If I click on that, same result here. So now you've got something functioning that works as an add-on. The next step for you might be to think how useful is this, put it in a user interface, maybe toggle some parameters and so on for how you'd like that bounding box to behave. So brief code review, here was that dictionary that we needed here. And this is the first thing that comes in the file, that's important. I've had tips here to put space between the start. Again, just something to keep in mind. And then again, for this class here, it's some operation that we want to take place. Again, a little bit of metadata that we need. And then I've basically just put everything inside of this execute function and indented it over. I'll leave it up to you if you wanna abstract or clean up. And then our register and unregister functions here. Okay, and this is basically following the template from the API documentation. Okay, so we've got things working here, that's exciting. And then so, getting us to wrapping things up here. We took an introductory look through the Python API. I hope it was enjoyable or maybe you learned something here and just tried to go through and do a non-trivial or interesting problem that made us touch different parts of the Python API so that we could get started with geometry here. There's a couple of different homework features that you could sort of take on here that might be interesting for you to think about. Like, what if I need to recompute the bounding box because the geometry has changed? Well, we can implement some sort of handler to maybe recompute that bounding box, delete the old one, right? And that's something interesting to think about. Maybe we want different operations like bounding spheres or actual convex holes of different quality. And of course, with the code, we could abstract this. I bet 50 folks all had to unzip or do a little list comprehension that gets rid of 10 lines of code, right? Great exercise to take this code and just clean it up, right? And make sure that you understand, though, what's going step by step. And we probably want a little bit of resiliency in this script here. Could be a little bit brittle. Like, for instance, if I'm running this without selecting an object, haven't done it on accident yet, but it's not gonna execute or do the proper thing. So some try or accept blocks may be appropriate. Again, to build up our script and make it a little bit more interesting. Other things of use, right? Learning about Git or version control. Some of you might be using Perforce or some other tool to manage your assets. That's also great. Anything that can handle text-based files, right? As we're building these scripts up, they get longer and longer and you don't wanna lose them. And you wanna be able to refactor. And then there's more best practices as far as Blender goes here. So feel free to check those out. And the last thing I'll show here, just because I alluded to it, just to make things a little bit more interesting or if you said, yeah, that was too trivial. I wanna try something more fun, is to think about, how would you set this up? So if I had some object here and I'm gonna hit one for vertices and I select, I don't know, a chunk of it here. And I've gotta go back into edit mode because my script's a little bit brittle. And then actually recompute this bounding box again. And then you can see, well, it only computed the bounding box. Let's see, did it work properly? Yeah, just for the vertices that were highlighted. So that could be, again, kind of interesting, right? If you got characters with their head, torso, shoulders, et cetera, and maybe being able to pick just one point and form clusters. So again, simple problem, but how could you build on it and think a little bit creatively? So with that said, there's other random useful ideas here about time that I mentioned. And this is just how to implement a handler, just a little script here. In fact, it's small enough. Let's, again, let's just do a quick copy and paste because we've got two minutes and probably time for a question. I'm just gonna pop this in here. Alt P to execute it. And then what changed here? Well, that's the question here. Let's open up our terminal. And I've gotta add a cube to my scene actually here. Let's see, add a cube. And then every time I move my cube, it should be printing cube changed. Okay, that's the idea with that little handler if you wanna play around with it. If I move the monkey, and we've gotta make this a little bit smaller here just to demonstrate it. So grab the monkey G, move it around. Nothing updating on the terminal as I do stuff to the monkey. So move the cube around, you'll see cube changed. So again, you can think about different handlers that execute on things selectively. But again, just little ideas to play around with and have fun. So with that said, I'm happy to take any questions. Thank you for your time. Hopefully you learned something or some exercises you could try out. Thank you.