WEBVTT 0 00:00:00.140 --> 00:00:02.110 Hello and welcome to scripting for artists. 1 00:00:02.110 --> 00:00:04.050 My name is civilian and in this episode we're 2 00:00:04.050 --> 00:00:06.270 going to take a look at custom properties. 3 00:00:06.450 --> 00:00:10.280 In the last video we created a panel and added existing properties to it 4 00:00:10.570 --> 00:00:13.730 and this is already quite powerful and if that is enough for 5 00:00:13.730 --> 00:00:17.000 your situation then please don't make it any more complex on that 6 00:00:17.180 --> 00:00:18.560 simpler is often better. 7 00:00:19.040 --> 00:00:19.460 However, 8 00:00:19.460 --> 00:00:21.530 there are these situations though where you want 9 00:00:21.530 --> 00:00:23.990 to attach your own data to things in blender 10 00:00:24.540 --> 00:00:25.070 to start, 11 00:00:25.070 --> 00:00:28.220 let's take a look at the kind of properties there are throughout the series, 12 00:00:28.220 --> 00:00:32.950 you've seen existing properties like object location or context not seen. 13 00:00:32.960 --> 00:00:34.850 Then there are the custom properties that you 14 00:00:34.850 --> 00:00:37.370 can create in the Custom properties panel. 15 00:00:37.380 --> 00:00:40.950 Maybe you've also seen these properties where the edit button is gone 16 00:00:41.140 --> 00:00:45.460 and where it says api defined and this means it's been defined from python. 17 00:00:45.740 --> 00:00:48.770 This is what we're also going to look at in this video to give 18 00:00:48.770 --> 00:00:52.780 us a concrete goal to work towards will be creating a maso BJ importer. 19 00:00:52.790 --> 00:00:55.460 Each scene will get a property that contains the 20 00:00:55.460 --> 00:00:58.190 path of the folder that contains its object files. 21 00:00:58.200 --> 00:01:02.400 And then we'll create an operator that loads all the object files from that folder. 22 00:01:02.410 --> 00:01:03.050 And finally, 23 00:01:03.050 --> 00:01:07.760 we'll look into creating an operator that reloads those object files from disk. 24 00:01:07.840 --> 00:01:11.720 So in that way you can have one button reload of all your O J files. 25 00:01:11.730 --> 00:01:15.450 This is quite a bit of work. So let's get started for this episode. 26 00:01:15.450 --> 00:01:18.430 We're going to create a new add on and I've started already. 27 00:01:18.440 --> 00:01:20.450 I've added a new python file. 28 00:01:20.450 --> 00:01:24.760 I've installed it as an ad unloaded in my editor which is visual studio code. 29 00:01:25.040 --> 00:01:27.560 I will quickly raise through this because you've seen 30 00:01:27.560 --> 00:01:29.690 all of this before in the previous videos. 31 00:01:29.690 --> 00:01:31.140 If you haven't seen this yet, 32 00:01:31.150 --> 00:01:33.950 please take a look at the videos about creating your own add on 33 00:01:34.140 --> 00:01:38.290 and creating user interfaces. So we start with the bill info dictionary. 34 00:01:38.300 --> 00:01:41.770 I've said the name to the add on to scripting for artists mass importer. 35 00:01:42.030 --> 00:01:45.730 The rest of the information is pretty much as she would expect import beep. 36 00:01:45.730 --> 00:01:46.950 I of course comes next. 37 00:01:47.040 --> 00:01:49.870 Then I want to have everything that we're going to do available 38 00:01:49.870 --> 00:01:52.300 to us in a panel there we can show the buttons, 39 00:01:52.300 --> 00:01:54.860 we can show the properties we can do everything we want. 40 00:01:54.940 --> 00:01:57.770 I've created a new panel by copying the code we had for 41 00:01:57.770 --> 00:02:00.750 a monkey grid and then adjusting it so it's pretty much the same 42 00:02:00.900 --> 00:02:06.240 except that it has the label mass import and that is also reflected in the class name. 43 00:02:06.260 --> 00:02:10.560 It's now called View three D. P. T. For panel type mass import. 44 00:02:11.140 --> 00:02:13.460 We're going to draw something but not just yet. 45 00:02:13.470 --> 00:02:16.270 Then of course we have to register and unregistered functions. 46 00:02:16.310 --> 00:02:18.250 Those are necessary for any adult. 47 00:02:18.840 --> 00:02:21.690 We're going to add more classes to this file so we'll have 48 00:02:21.690 --> 00:02:24.910 an operator for doing the mass import and then also will have an 49 00:02:24.910 --> 00:02:29.000 operator for doing a single reimport of an object and then also 50 00:02:29.000 --> 00:02:32.460 an operator for doing a mass reimport of all the imported objects. 51 00:02:32.840 --> 00:02:34.680 So we're going to have more and I didn't 52 00:02:34.680 --> 00:02:37.950 want to copy paste the beep Mariota's registered class. 53 00:02:37.960 --> 00:02:41.120 And then make sure that in the unregistered also copied 54 00:02:41.120 --> 00:02:43.990 to the unregistered class and and managing all of that. 55 00:02:44.000 --> 00:02:47.460 So instead of that, I've created a list called blender classes, 56 00:02:47.470 --> 00:02:50.560 in which I have only the panel that we have now. 57 00:02:51.040 --> 00:02:54.660 And then in the registered unregistered, we look over it with a for loop. 58 00:02:55.040 --> 00:02:58.160 So for blended class and gender classes will go over this list. 59 00:02:58.160 --> 00:02:59.880 And for every item in that list it will 60 00:02:59.880 --> 00:03:03.500 call people you to register class or unregistered clasp. 61 00:03:03.510 --> 00:03:07.150 And this makes it a little bit easier to add new stuff later because new classes, 62 00:03:07.150 --> 00:03:08.960 we can just add to this list. 63 00:03:09.140 --> 00:03:10.960 Now that our code is really simple. 64 00:03:10.960 --> 00:03:14.040 Let's see that it actually works in blender so that we can be sure 65 00:03:14.040 --> 00:03:17.750 that when we start adding stuff we added on a basis that actually works. 66 00:03:18.640 --> 00:03:21.460 So in the years of preferences enable the add on. 67 00:03:22.040 --> 00:03:25.600 And then here in our monkey stop, we can see our mass import panel. 68 00:03:25.660 --> 00:03:28.680 Of course there's nothing drawn yet, but that is what we expected. 69 00:03:28.690 --> 00:03:31.320 So the basis for a code the registering the 70 00:03:31.320 --> 00:03:34.270 unregistered and the existence of the panel itself. 71 00:03:34.280 --> 00:03:35.360 That's all correct. 72 00:03:36.440 --> 00:03:39.820 Okay, so let's start creating these properties that we wanted to have. 73 00:03:39.940 --> 00:03:41.450 This is quite simple actually. 74 00:03:43.140 --> 00:03:47.120 You know that there's a lot of stuff in the product types and we want to have a property 75 00:03:47.120 --> 00:03:52.510 on the scene that contains the important path of the O J files that we want to have. 76 00:03:52.520 --> 00:03:56.360 So we start with the pipe types dot scene with a capital c, 77 00:03:57.140 --> 00:03:59.030 dots and then the name of her property. 78 00:04:00.640 --> 00:04:02.530 Let's call it mass import path. 79 00:04:02.540 --> 00:04:06.230 Now it's very similar to adding your own properties to your own operator. 80 00:04:06.240 --> 00:04:10.490 Except that with the operator we had our own class that we could use to declare 81 00:04:10.490 --> 00:04:14.950 the properties and now that class is already there so we cannot add anything to it. 82 00:04:14.950 --> 00:04:19.260 So it's a little bit different. So instead of using the column, we used the equal sign 83 00:04:19.540 --> 00:04:21.850 and then again we assign property 84 00:04:22.640 --> 00:04:22.850 and 85 00:04:23.440 --> 00:04:25.020 they live in the pilot props 86 00:04:25.190 --> 00:04:29.350 and a file path or a directory path is just a string. 87 00:04:30.740 --> 00:04:32.750 So that gives us a string property. 88 00:04:33.440 --> 00:04:36.170 Now for the user interface we may want to give it a nice name. 89 00:04:36.180 --> 00:04:38.960 So let's call it a BJ folder 90 00:04:39.440 --> 00:04:42.580 and they always end up with a coma because then I can add stuff on 91 00:04:42.580 --> 00:04:46.700 the next line without having to go back up and at that coma again, 92 00:04:46.750 --> 00:04:50.660 this is valid python and it makes your changes a bit more localized. 93 00:04:50.660 --> 00:04:54.460 You can now add other stuff here without changing the line above. 94 00:04:54.940 --> 00:04:57.690 This is in the register function. So there we add a property. 95 00:04:57.690 --> 00:05:01.750 Of course we have to delete it again in the unregistered to clean up what we did. 96 00:05:02.740 --> 00:05:06.440 Then basically you take this and you say del 97 00:05:06.450 --> 00:05:10.360 that property and that tells python just delete the thing 98 00:05:10.740 --> 00:05:14.220 and this is enough. So let's see how this looks in blender here. 99 00:05:14.220 --> 00:05:17.440 We have to reload our code in blender 2.83 100 00:05:17.580 --> 00:05:19.980 nearer. You can do that here with reload scripts. 101 00:05:19.990 --> 00:05:23.610 If you run an older version of blender press F three 102 00:05:24.110 --> 00:05:25.910 and then type reload scripts. 103 00:05:25.920 --> 00:05:28.520 They both do the same thing except that through the menu you 104 00:05:28.520 --> 00:05:31.350 can add it to the quick menu when you press Q. 105 00:05:31.440 --> 00:05:33.770 And this is the approach that will use from now on. 106 00:05:33.780 --> 00:05:36.960 So we've reloaded our code and let's take a look at the scene. 107 00:05:39.940 --> 00:05:43.390 There you go. We have our own property. Mass import path. 108 00:05:43.400 --> 00:05:46.540 The default is empty because we haven't set any default 109 00:05:46.550 --> 00:05:49.360 and it's just there and every scene will have it. 110 00:05:49.840 --> 00:05:53.440 We can also change the property from python and keep your eyes 111 00:05:53.450 --> 00:05:57.890 on the Custom Properties panel here which is in the scene tab. 112 00:05:57.900 --> 00:06:01.360 Take a look at that. What happens when I actually assign a value. 113 00:06:02.240 --> 00:06:02.560 Mhm. 114 00:06:03.440 --> 00:06:06.440 You have to whether your mouth a little bit to make it redraw but 115 00:06:06.440 --> 00:06:09.490 you can see that now that we have assigned a value to it. 116 00:06:09.630 --> 00:06:12.560 It is actually stored in the custom properties. 117 00:06:13.040 --> 00:06:17.230 It's a p I defined which means that you cannot just delete it. 118 00:06:17.330 --> 00:06:21.080 And this is one of the major advantages of using your properties like this 119 00:06:21.090 --> 00:06:24.460 instead of just clicking the add button here and creating a new one. 120 00:06:25.240 --> 00:06:28.440 When you create it through python, you can be sure that the property is there, 121 00:06:28.450 --> 00:06:31.160 even if it hasn't been set, it will have a default. 122 00:06:31.170 --> 00:06:33.360 So it's one less thing to worry about. 123 00:06:33.940 --> 00:06:37.240 The other advantage is that we can set subtypes and this 124 00:06:37.240 --> 00:06:40.830 will indicate to blender what kind of string we're talking about. 125 00:06:40.840 --> 00:06:42.460 So this is going to be a path 126 00:06:42.640 --> 00:06:46.490 and it would be nice if it had like a little button that you could have a file 127 00:06:46.490 --> 00:06:48.950 browser that selects the path for you instead of 128 00:06:48.950 --> 00:06:50.640 having to type it in the python console. 129 00:06:50.650 --> 00:06:55.860 All of this is done by blender. Once you set the subtype correctly. So let's do that. 130 00:06:56.630 --> 00:06:58.530 The subtype is set by 131 00:06:59.740 --> 00:07:03.760 the sub type parameter and then yet pass a string that indicates 132 00:07:03.760 --> 00:07:07.560 a subtype in order to find the subtypes for a specific property. 133 00:07:08.140 --> 00:07:09.580 You can go back to blender, 134 00:07:10.340 --> 00:07:10.960 help, 135 00:07:11.940 --> 00:07:13.290 python, api reference 136 00:07:13.740 --> 00:07:16.240 and search for bp dot props of string property. 137 00:07:16.250 --> 00:07:18.900 And there will tell you which sometimes there are in 138 00:07:18.900 --> 00:07:22.160 our case it's a directory path or deer path. 139 00:07:22.840 --> 00:07:25.200 So now let's reload the code and see what 140 00:07:25.200 --> 00:07:27.660 happens here in this corner of the interface. 141 00:07:29.430 --> 00:07:30.210 There you go. 142 00:07:30.490 --> 00:07:32.060 It has a button to browse 143 00:07:32.640 --> 00:07:34.460 and you can select directories 144 00:07:34.840 --> 00:07:36.960 because I set it to a silly value. 145 00:07:37.440 --> 00:07:41.060 It will just start at a silly directory because it's not a valid path. 146 00:07:41.440 --> 00:07:44.420 But if I change this to slash slash which 147 00:07:44.430 --> 00:07:47.050 indicates the current directory of the blend file. 148 00:07:47.640 --> 00:07:47.850 Mm 149 00:07:48.240 --> 00:07:53.460 It will open it here and I can navigate to my O B J files directory, click accept. 150 00:07:53.840 --> 00:07:55.760 And then it has said here the path 151 00:07:56.540 --> 00:07:58.130 and this is exactly what you wanted. 152 00:07:58.140 --> 00:08:03.160 Except that we want this behavior in our own panel of course. And let's do that 153 00:08:03.540 --> 00:08:04.350 in our panel code. 154 00:08:04.350 --> 00:08:06.320 We can remove the past because we're actually going to 155 00:08:06.320 --> 00:08:10.760 do something and let's start with getting the layout. 156 00:08:11.240 --> 00:08:14.090 So we didn't do this before but do know that every 157 00:08:14.090 --> 00:08:17.400 self dot something will do a little dance to see. 158 00:08:17.410 --> 00:08:21.350 Is it defined on this class. If not look at the parents is defined there. 159 00:08:21.350 --> 00:08:23.780 If not look at the grandparents et cetera. 160 00:08:23.790 --> 00:08:26.450 So we're saying layout equals self taught layout. 161 00:08:26.460 --> 00:08:30.760 We only do this dance once and then just use the found layout object. 162 00:08:30.940 --> 00:08:32.049 That's not a column. 163 00:08:32.640 --> 00:08:33.659 Okay. 164 00:08:34.039 --> 00:08:35.450 And then at the property 165 00:08:35.840 --> 00:08:40.350 the property was defined on the scene which is context dot scene. 166 00:08:40.360 --> 00:08:42.850 And the property name was mass 167 00:08:42.990 --> 00:08:44.750 import path. That's it. 168 00:08:46.440 --> 00:08:50.250 Well look the code and there we have our property browse button and all. 169 00:08:51.240 --> 00:08:53.590 Now let's go and create an operator that imports 170 00:08:53.590 --> 00:08:55.820 all the O B J files from that directory. 171 00:08:56.000 --> 00:08:58.530 And I want to name it quite similar to the 172 00:08:58.530 --> 00:09:02.140 operator that already exists for importing a BJ files. 173 00:09:02.150 --> 00:09:03.560 So let's take a look at that 174 00:09:04.040 --> 00:09:07.340 That is be piled on top start import scene that LBJ. 175 00:09:07.340 --> 00:09:11.270 So let's call our operator importing that LBJ mass. 176 00:09:11.280 --> 00:09:14.290 So here we have an empty operator. You've seen this before. 177 00:09:14.300 --> 00:09:17.530 I just named it differently. It's called importing that LBJ mass. 178 00:09:17.540 --> 00:09:19.160 It has an execute function. 179 00:09:19.170 --> 00:09:23.000 Are put in this little comment as a reference and then it calls self report. 180 00:09:23.010 --> 00:09:26.490 This takes a report type which can be info or warning 181 00:09:26.490 --> 00:09:29.370 or error and then a strain that is um reported. 182 00:09:29.380 --> 00:09:34.180 It returns councils because nothing is done yet again, I'm taking small steps. 183 00:09:34.180 --> 00:09:37.420 I first make sure that the operator is there and that it registered properly. 184 00:09:37.420 --> 00:09:38.630 Then we can add it to a panel. 185 00:09:38.630 --> 00:09:39.800 We can click on the button, 186 00:09:39.810 --> 00:09:43.250 we can see that it works before adding more complexities to it. 187 00:09:43.840 --> 00:09:45.000 So the operator is here. 188 00:09:45.000 --> 00:09:48.620 Now I copied this name, I go to the blender classes list, 189 00:09:48.630 --> 00:09:50.290 I add the name to the list and that 190 00:09:50.290 --> 00:09:52.590 takes care of the registering and the un registering. 191 00:09:52.680 --> 00:09:55.040 So what is left now is added to the panel. 192 00:09:56.140 --> 00:09:57.660 So all we need is the 193 00:09:58.040 --> 00:10:02.430 B O I D. Name, paste it in, save in blender. 194 00:10:02.440 --> 00:10:05.240 Reload the script and we have a button, we click on it. 195 00:10:05.250 --> 00:10:07.150 It says no code to load from slash slash 196 00:10:07.540 --> 00:10:09.250 which is the error that we expected. 197 00:10:09.820 --> 00:10:13.130 Now the next step is finding the object files and importing them 198 00:10:13.140 --> 00:10:16.000 and afterwards we want to be able to re import them. 199 00:10:16.000 --> 00:10:19.520 So we have to keep track of which object was imported from which file, 200 00:10:19.750 --> 00:10:23.330 the best way to do that is to add another property to the object types. 201 00:10:23.330 --> 00:10:26.650 So let's do that. Now, before we start actually importing them 202 00:10:27.140 --> 00:10:28.380 here in a register function, 203 00:10:28.380 --> 00:10:31.630 we're going to do the same thing as we did to a scene but then to an object 204 00:10:32.140 --> 00:10:32.460 because 205 00:10:34.540 --> 00:10:39.850 and then it also becomes a string property. 206 00:10:40.710 --> 00:10:43.260 But then with BJ file instead of O J folder, 207 00:10:43.260 --> 00:10:48.040 so the folder and the file name combined will give us the final path of the O J file 208 00:10:48.160 --> 00:10:51.390 because there is no subtype for just a file name. 209 00:10:51.410 --> 00:10:54.360 It's only for a full file path or full directory path. 210 00:10:54.740 --> 00:10:57.760 We'll just keep this as a string and don't define any subtype. 211 00:10:58.140 --> 00:11:01.760 So before we look at the importing that's at this property to the panel, 212 00:11:03.140 --> 00:11:04.660 we have the panel code here, 213 00:11:05.240 --> 00:11:06.690 let's create a new column for this 214 00:11:13.020 --> 00:11:16.900 and there we have the property. But remember context object can be none. 215 00:11:16.910 --> 00:11:18.960 So we have to add a little guard around this. 216 00:11:19.340 --> 00:11:19.550 Okay? 217 00:11:24.220 --> 00:11:25.140 Yeah. 218 00:11:28.040 --> 00:11:28.250 Mhm. 219 00:11:28.640 --> 00:11:32.660 None is considered false. With python and a real object is considered true. 220 00:11:32.670 --> 00:11:35.370 So if context object will evaluate it true if 221 00:11:35.370 --> 00:11:37.690 it's real object and then draw the property. 222 00:11:37.700 --> 00:11:38.990 It will evaluate to false. 223 00:11:39.000 --> 00:11:42.560 If there is no active object and then it will draw the label instead. 224 00:11:43.140 --> 00:11:44.360 Let's give it a try. 225 00:11:44.840 --> 00:11:45.040 Yeah. 226 00:11:46.140 --> 00:11:51.860 And there we have our property and we can set it for object as you can see 227 00:11:53.440 --> 00:11:55.570 now, let's build the importing itself. 228 00:11:55.580 --> 00:11:58.040 So here we are at our mass importer operator, 229 00:11:58.050 --> 00:12:04.990 let's write a little layout of what it is supposed to do, has to find the object files. 230 00:12:05.000 --> 00:12:06.760 And for each file, 231 00:12:08.010 --> 00:12:09.110 import it 232 00:12:10.940 --> 00:12:14.060 and record his file name in the object property. 233 00:12:14.440 --> 00:12:15.670 Let's look at that first step. 234 00:12:15.670 --> 00:12:17.940 This is going to take a few steps actually 235 00:12:17.950 --> 00:12:20.290 because for finding files we have to use python 236 00:12:20.290 --> 00:12:23.920 functionality and python doesn't understand the blender specific slash 237 00:12:23.920 --> 00:12:26.510 slash meaning of relative to the current blend file. 238 00:12:26.520 --> 00:12:29.530 So we have to convert it to something that python understands. 239 00:12:29.670 --> 00:12:31.840 Then use that to find the O B J files. 240 00:12:31.850 --> 00:12:34.200 Then convert it back to something blender understands 241 00:12:34.440 --> 00:12:35.670 and import the files. 242 00:12:35.680 --> 00:12:36.250 First of all, 243 00:12:36.250 --> 00:12:39.240 we have to turn that slash slash into something absolute And 244 00:12:39.240 --> 00:12:41.850 this is done through a function in bp dot path. 245 00:12:45.540 --> 00:12:45.750 Mhm. 246 00:12:46.240 --> 00:12:46.450 Okay. 247 00:12:46.840 --> 00:12:51.070 Be part of the path of a B S path or absolute path will 248 00:12:51.070 --> 00:12:53.680 give us the absolute path of the file that we want to import. 249 00:12:53.720 --> 00:12:57.280 We can check this by reporting this in our error message. 250 00:12:57.400 --> 00:13:01.060 Just pause the video, give this a try and then come back here. 251 00:13:01.640 --> 00:13:05.560 Now we have to convert this to a path object from python's path lib library 252 00:13:12.360 --> 00:13:15.720 and then we can use this import path variable to find all the 253 00:13:15.720 --> 00:13:19.460 O B J files and loop over them in one go like this. 254 00:13:20.440 --> 00:13:20.760 Mm. 255 00:13:24.140 --> 00:13:28.950 This will find everything that matches. Start at LBJ. 256 00:13:28.950 --> 00:13:32.040 So files or directories ending in dot oh, BJ. 257 00:13:32.050 --> 00:13:32.230 Now, 258 00:13:32.230 --> 00:13:34.090 for now we'll just assume that you won't 259 00:13:34.090 --> 00:13:37.190 create any subdirectory called something 0.0.0 b J. 260 00:13:37.200 --> 00:13:41.050 And that everything is an actual LBJ file that we can import now. 261 00:13:41.050 --> 00:13:42.560 All we have to do is import it, 262 00:13:43.440 --> 00:13:44.460 your blood sugar. 263 00:13:45.440 --> 00:13:50.060 Go to the LBJ importer and press control C and then you can control V in your code. 264 00:13:57.040 --> 00:13:59.600 This converts that path object that we have back 265 00:13:59.610 --> 00:14:02.260 into a string so that blender understands it. 266 00:14:03.140 --> 00:14:05.660 And then this whole line will import the LBJ file. 267 00:14:07.040 --> 00:14:10.060 So now we have covered the for each file imported. 268 00:14:10.740 --> 00:14:13.650 And the only thing that's left is recording its file name. 269 00:14:14.440 --> 00:14:17.160 Part of the working of this import operator is that it 270 00:14:17.160 --> 00:14:20.720 dislikes everything and then it selects the objects that are imported. 271 00:14:20.730 --> 00:14:22.860 And this means that we can loop over all selected 272 00:14:22.860 --> 00:14:25.860 objects and then assign our custom property to them. 273 00:14:38.040 --> 00:14:44.830 This is why I like the path lib objects so much. It's quite simple to work with. 274 00:14:44.840 --> 00:14:47.790 If you just want to have the final name, component of a path, 275 00:14:47.800 --> 00:14:50.270 you can just do the path dot name. 276 00:14:50.280 --> 00:14:53.060 If you want to have to drive letter, you do not drive 277 00:14:53.540 --> 00:14:57.650 and it's a very object oriented approach to paths and 278 00:14:58.240 --> 00:14:59.220 I quite like that. 279 00:14:59.440 --> 00:15:02.630 Now we're importing, we record the file name where it came from. 280 00:15:02.740 --> 00:15:04.750 So this should be it. Let's give it a try. 281 00:15:05.140 --> 00:15:07.150 I'll throw out the existing objects 282 00:15:08.440 --> 00:15:10.260 browse to my O J. Fast directory 283 00:15:11.440 --> 00:15:13.190 and then mass import everything. 284 00:15:13.490 --> 00:15:15.490 And there we are. The files are imported. 285 00:15:15.490 --> 00:15:18.490 They're all at the origin and each of them has the O. J. 286 00:15:18.490 --> 00:15:21.160 File name said to whichever they came from. 287 00:15:21.940 --> 00:15:25.370 Now all that's left for us is to make an operator that reloads the O. 288 00:15:25.370 --> 00:15:30.090 B J file to keep it simple. Let's not do this a mass and just reload the active object. 289 00:15:30.100 --> 00:15:33.490 That means deleting the object from the scene and then loading it again from the O. 290 00:15:33.490 --> 00:15:34.270 J file. 291 00:15:34.280 --> 00:15:34.810 Of course, 292 00:15:34.810 --> 00:15:36.640 before we deleted from the scene we have to make 293 00:15:36.640 --> 00:15:39.330 sure that we stored the transform of the object so that 294 00:15:39.330 --> 00:15:42.410 when we reloaded it can be restored so that it's positioned 295 00:15:42.410 --> 00:15:45.100 in the same way as it was before we reloaded it 296 00:15:45.440 --> 00:15:48.760 1st. Let's start with a new operator. 297 00:15:49.840 --> 00:15:54.120 Let's call it a BJ. Reload here. I select some text. I press Control D. 298 00:15:54.120 --> 00:15:56.740 And that will select the next occurrence of that text. 299 00:15:56.750 --> 00:16:00.090 So then I can just type reload and both the class name 300 00:16:00.100 --> 00:16:02.450 and the idea name will will change to 20 B J. 301 00:16:02.460 --> 00:16:02.950 Reload 302 00:16:04.240 --> 00:16:07.590 let's say reload mass, imported O B J. 303 00:16:07.600 --> 00:16:10.070 And then we can read the execute function for this code. 304 00:16:10.080 --> 00:16:13.280 I will assume that every O B J has one object in it. 305 00:16:13.290 --> 00:16:17.320 You can extend the code so that it can handle multiple objects for a BJ. 306 00:16:17.330 --> 00:16:18.960 But let's keep it simple for now 307 00:16:19.340 --> 00:16:21.950 we're going to refer to the active object quite a few times. 308 00:16:21.960 --> 00:16:24.650 So let's make life simple for us 309 00:16:25.720 --> 00:16:29.400 and just call it a job. So let's make a little overview for ourselves. Again, 310 00:16:29.610 --> 00:16:33.550 first we have to store what we want to remember, 311 00:16:33.940 --> 00:16:39.160 remove the object from the scene, load the LBJ file 312 00:16:39.860 --> 00:16:41.580 and restore what we remembered, 313 00:16:42.440 --> 00:16:47.110 loading the A P. J file will not automatically set our custom property in the end. 314 00:16:47.110 --> 00:16:48.560 That's what we want to restore. 315 00:16:48.570 --> 00:16:51.910 And we want to be able to restore the transform as well. 316 00:16:53.600 --> 00:16:56.470 Let's remember the file name 317 00:16:59.390 --> 00:17:01.810 and let's take a copy of the matrix. 318 00:17:01.820 --> 00:17:04.040 If I wouldn't make a copy of the Matrix, 319 00:17:04.040 --> 00:17:08.650 then the variable Matrix world would be a reference to the objects matrix. 320 00:17:08.660 --> 00:17:12.190 And if we delete the object, that reference won't be valid anymore. 321 00:17:12.200 --> 00:17:14.670 And you can get all kinds of weird results. 322 00:17:15.839 --> 00:17:16.040 Now, 323 00:17:16.040 --> 00:17:18.690 removing the object from the scene actually means removing 324 00:17:18.690 --> 00:17:21.170 the object from all the collections that it's in. 325 00:17:21.180 --> 00:17:26.460 Fortunately blender gives us a list of all those collections. 326 00:17:31.540 --> 00:17:31.770 Yeah, 327 00:17:33.610 --> 00:17:36.360 this will unlinked the object from all the collections. 328 00:17:37.040 --> 00:17:39.540 But the problem is that of course as soon 329 00:17:39.540 --> 00:17:41.960 as we unlinked the object from the first collection, 330 00:17:42.040 --> 00:17:44.580 this thing that we're looping over will change. 331 00:17:44.590 --> 00:17:47.900 Changing something while you're looking over. It is never a good idea. 332 00:17:47.910 --> 00:17:51.260 We can do this. List, update users collections 333 00:17:51.640 --> 00:17:53.770 and this will create a new list for us. 334 00:17:54.120 --> 00:17:55.590 That new list is a copy. 335 00:17:55.600 --> 00:17:59.320 So it won't be altered by removing the objects from the collections. 336 00:17:59.390 --> 00:18:01.090 Making this for loop safe 337 00:18:01.200 --> 00:18:04.630 if you want. You can also remove the object from being part of data now. 338 00:18:04.790 --> 00:18:08.670 But this is only safe if it's not referenced from anything else. 339 00:18:08.870 --> 00:18:10.920 Again, blended to the rescue. 340 00:18:11.540 --> 00:18:12.050 Okay, 341 00:18:14.540 --> 00:18:17.100 update users will give us the user account 342 00:18:17.110 --> 00:18:19.750 and that is that tiny little square that you 343 00:18:19.750 --> 00:18:23.080 see also with materials and measures when you use 344 00:18:23.080 --> 00:18:25.510 them in different places throughout the blend file. 345 00:18:25.520 --> 00:18:27.190 If this number is zero, 346 00:18:27.190 --> 00:18:29.400 that means that the object is no longer used 347 00:18:29.410 --> 00:18:31.670 and we can actually remove it from lenders memory. 348 00:18:32.240 --> 00:18:32.450 Mhm 349 00:18:32.940 --> 00:18:33.350 Yeah. 350 00:18:35.530 --> 00:18:36.450 And there we go 351 00:18:36.940 --> 00:18:38.150 from this point on. 352 00:18:38.160 --> 00:18:42.270 We can no longer refer to ob because it's been removed from lender. 353 00:18:42.840 --> 00:18:46.350 So to prevent this from ever using it again, 354 00:18:46.740 --> 00:18:51.560 I just say dal ob. This removes the job name from python's memory. 355 00:18:52.140 --> 00:18:56.150 That means that if I say up the location here, 356 00:18:56.160 --> 00:19:00.220 python will scream at us because it doesn't know what that means anymore. 357 00:19:00.230 --> 00:19:01.510 After this mine, 358 00:19:01.560 --> 00:19:04.100 it's just a little bit of security for ourselves so 359 00:19:04.100 --> 00:19:06.660 that we don't use something that maybe no longer valid 360 00:19:07.470 --> 00:19:10.430 now. We need to load the LBJ file again. We treat them before. 361 00:19:10.430 --> 00:19:11.870 So let's take a look at that code. 362 00:19:12.100 --> 00:19:14.590 We'll have to do this trick again and then we 363 00:19:14.590 --> 00:19:18.130 have to do this line for just that one object. 364 00:19:18.140 --> 00:19:21.670 So let's put this into a function that we can call from both places. 365 00:19:34.140 --> 00:19:34.350 Okay 366 00:19:34.740 --> 00:19:36.790 here, I've created a new function 367 00:19:36.980 --> 00:19:41.820 that takes a scene and this means that it will return a path lit dot path. 368 00:19:41.830 --> 00:19:45.320 And I like this notation quite a lot because then you can see what 369 00:19:45.320 --> 00:19:49.050 something returns without having to dive in the code and see what happens. 370 00:19:49.540 --> 00:19:51.730 This is not something that will be checked by python. 371 00:19:51.730 --> 00:19:53.930 So it's up to you to actually live up to your word. 372 00:19:53.960 --> 00:19:58.190 This code is now pretty much the same as this and it returns to new path object. 373 00:19:58.200 --> 00:19:59.950 That means that we can remove this line 374 00:20:00.760 --> 00:20:02.180 and we can just do 375 00:20:02.520 --> 00:20:04.660 mass import path 376 00:20:05.140 --> 00:20:06.670 contact. Start seeing here. 377 00:20:07.540 --> 00:20:10.560 I specifically past is seen and not the context 378 00:20:11.240 --> 00:20:13.060 how to fix a little mistake here, 379 00:20:13.860 --> 00:20:17.600 I explicitly passed the scene and not the entire context. 380 00:20:17.660 --> 00:20:20.480 It would have worked fine if we were to pass the context, 381 00:20:20.570 --> 00:20:23.410 but then you wouldn't be able to see which part 382 00:20:23.410 --> 00:20:25.890 of the context was actually used by this function. 383 00:20:25.920 --> 00:20:29.430 This is why I wanted to pass a scene itself and not the context. 384 00:20:29.440 --> 00:20:31.590 Of course we could have also passed context. 385 00:20:31.590 --> 00:20:35.350 Not seen that mass import path, but that would make the call of a little bit longer. 386 00:20:35.350 --> 00:20:39.320 And I think this is a nice middle ground. But of course you do with your coat. 387 00:20:39.320 --> 00:20:40.550 Whatever you think is best. 388 00:20:40.740 --> 00:20:44.270 Now we have two code to get the import path. We can copy this line 389 00:20:46.040 --> 00:20:47.770 into a reload operator. 390 00:20:49.040 --> 00:20:51.170 And then we can get this line 391 00:20:53.040 --> 00:20:54.200 and put that here 392 00:20:54.340 --> 00:20:56.270 And now all we have to do is 393 00:20:56.740 --> 00:21:00.800 get from the import path which is a directory to the import file path, 394 00:21:00.800 --> 00:21:01.860 which is a file name. 395 00:21:02.540 --> 00:21:07.620 And the import file path is the import path slash mass 396 00:21:07.630 --> 00:21:12.170 import file name that we took a copy of up there. 397 00:21:13.440 --> 00:21:16.120 Path objects in python supports the slash notation. 398 00:21:16.130 --> 00:21:19.400 It will work correctly automatically for any platforms on windows. 399 00:21:19.400 --> 00:21:23.660 It uses the backslash on Lennox and a macro as it uses the forward slash 400 00:21:23.890 --> 00:21:25.740 now that we have constructed the file name, 401 00:21:25.750 --> 00:21:28.470 we can pass it to the operator that loads the LBJ file. 402 00:21:28.590 --> 00:21:31.950 Now all that's left is to restore whatever we wanted to restore. 403 00:21:32.240 --> 00:21:36.770 So again we have to loop over the selected objects and set the mass import file name. 404 00:21:39.140 --> 00:21:39.860 Mm hmm. 405 00:21:44.240 --> 00:21:45.950 Now we have to restore the matrix. 406 00:21:47.040 --> 00:21:47.270 Okay. 407 00:21:49.940 --> 00:21:53.360 We'll tell blender that the operator did his job. 408 00:21:55.230 --> 00:21:56.960 And then we fix two typos 409 00:21:57.340 --> 00:21:58.860 Emily here Colin 410 00:21:59.440 --> 00:22:02.460 and here it has to be user collection, not user collections. 411 00:22:03.240 --> 00:22:03.920 Finally, 412 00:22:03.920 --> 00:22:06.240 what we have to do is registered and unregistered 413 00:22:06.240 --> 00:22:08.460 the operator and add a button to the panel. 414 00:22:10.240 --> 00:22:14.050 We copy the class name we added to this list. 415 00:22:15.140 --> 00:22:15.560 Mm hmm. 416 00:22:16.240 --> 00:22:17.080 We copy 417 00:22:17.190 --> 00:22:20.080 the blog name and added to the panel. 418 00:22:20.740 --> 00:22:20.950 Okay, 419 00:22:23.740 --> 00:22:24.760 save the file. 420 00:22:25.540 --> 00:22:26.710 Reload the script 421 00:22:26.940 --> 00:22:28.170 and there we have our button. 422 00:22:30.240 --> 00:22:35.010 As you can see we click on it and as you use from importing LBJ files, 423 00:22:35.020 --> 00:22:37.310 there is no active object anymore and they're just 424 00:22:37.310 --> 00:22:40.670 imported objects are selected in this case Suzanne. 425 00:22:41.140 --> 00:22:42.850 Now let's see if it really, really looked. 426 00:22:44.000 --> 00:22:46.270 I put a new file in their cube, that LBJ 427 00:22:46.940 --> 00:22:49.460 and now it should replace Suzanne with that cube 428 00:22:50.040 --> 00:22:53.610 and it does. So there we have it. Our code is working. 429 00:22:53.610 --> 00:22:58.430 We can mass load O J files and we can select individual objects to reload. 430 00:22:58.440 --> 00:23:02.460 I will leave it as an exercise for you to make a mass reload operator 431 00:23:02.460 --> 00:23:06.500 that it rains over all the objects or maybe only all the selected objects. 432 00:23:06.590 --> 00:23:07.670 I'll leave that up to you. 433 00:23:08.140 --> 00:23:10.950 So this is it for this episode description for artists. 434 00:23:11.010 --> 00:23:13.600 This is not the last time we'll talk about custom properties, 435 00:23:13.600 --> 00:23:16.360 but I think this video has gone on long enough already. 436 00:23:16.370 --> 00:23:20.170 If you have any questions or commons, leave them below and I will see you soon.