WEBVTT

1
00:00:00.840 --> 00:00:03.620
Hello and welcome to another episode of scripting for artists.

2
00:00:03.710 --> 00:00:06.260
My name is settled in and in this episode we will

3
00:00:06.260 --> 00:00:09.690
be looking at readability and understand ability of the code.

4
00:00:09.910 --> 00:00:12.560
Sometimes it can get tricky to get the computer to do exactly

5
00:00:12.560 --> 00:00:16.170
what you want and it's a great victory when things finally work,

6
00:00:16.260 --> 00:00:20.460
it's tempting to move on to the next task at hand because the code works right

7
00:00:22.440 --> 00:00:25.210
well, this is often a good moment to stop coding

8
00:00:25.380 --> 00:00:27.320
and to just give it another read through.

9
00:00:27.700 --> 00:00:28.600
Ask yourself,

10
00:00:28.730 --> 00:00:31.470
do I actually understand why the code is working?

11
00:00:31.780 --> 00:00:33.360
Do I understand what I wrote?

12
00:00:33.740 --> 00:00:37.710
Because often when I write the code it seems perfectly fine but when I take

13
00:00:37.710 --> 00:00:40.920
a step back and try to explain what I did to my rubber ducky,

14
00:00:40.960 --> 00:00:43.760
I start noticing some ugly or unclear bits

15
00:00:44.430 --> 00:00:45.250
in this video,

16
00:00:45.250 --> 00:00:49.420
we will look at some of blenders code and take some steps to improve its readability.

17
00:00:49.840 --> 00:00:52.370
The most important of this is that these steps do not

18
00:00:52.380 --> 00:00:55.650
require any understanding of what the code is actually doing.

19
00:00:55.690 --> 00:00:58.860
Only very superficial knowledge of python is required.

20
00:00:59.340 --> 00:01:01.480
This means that you can use these steps

21
00:01:01.480 --> 00:01:03.650
to improve the understand ability of your code

22
00:01:03.760 --> 00:01:05.060
even for yourself.

23
00:01:05.540 --> 00:01:06.050
Yes,

24
00:01:06.050 --> 00:01:08.690
restructuring code is actually a great way to gain a

25
00:01:08.690 --> 00:01:11.840
better understanding of the code and even to find mistakes,

26
00:01:12.540 --> 00:01:16.810
The coat that I want to look at, draws this panel right here or the camera,

27
00:01:16.810 --> 00:01:17.850
background images,

28
00:01:18.240 --> 00:01:21.670
you can click on an image for every image, you get a box.

29
00:01:21.680 --> 00:01:25.580
Every box allows you to select the source of the background image,

30
00:01:25.590 --> 00:01:28.710
whether it's an image or movie clip and then

31
00:01:28.720 --> 00:01:31.400
you can select the image or the movie clip,

32
00:01:31.400 --> 00:01:32.490
depending what you chose.

33
00:01:32.490 --> 00:01:35.020
And if there is an image or movie clip selected,

34
00:01:35.030 --> 00:01:37.460
you get all kinds of different options.

35
00:01:38.520 --> 00:01:40.780
Let's take a look at the code that draws all this.

36
00:01:42.240 --> 00:01:43.270
Here we are in the code,

37
00:01:43.270 --> 00:01:47.270
I have collapsed all the other classes that were not interested in at the moment.

38
00:01:47.410 --> 00:01:51.000
We're just going to look at the camera, background image class

39
00:01:51.120 --> 00:01:52.490
and the class has two functions,

40
00:01:52.490 --> 00:01:56.760
draw header and draw and draw header is really simple, so we'll skip that.

41
00:01:56.770 --> 00:01:59.760
That's fine. Draw is a different story though.

42
00:01:59.940 --> 00:02:04.260
If we quickly scroll through it, then you can see that there is a for loop

43
00:02:04.640 --> 00:02:08.889
and there is just some stuff happening and then there's an if and

44
00:02:08.889 --> 00:02:12.320
there's another if there's another if and there's another if and then there's

45
00:02:12.320 --> 00:02:17.190
stuff happening and there's else's and there's more ifs and there's another if

46
00:02:17.200 --> 00:02:22.130
um by now I've lost count of where we are in the code,

47
00:02:22.140 --> 00:02:23.450
what's happening.

48
00:02:23.540 --> 00:02:26.660
You can see the level of indentation is quite large.

49
00:02:27.840 --> 00:02:30.660
This can seriously be improved.

50
00:02:31.040 --> 00:02:32.860
So let's just start from the top,

51
00:02:33.340 --> 00:02:38.350
we get the layout and set some properties, some other properties are gotten.

52
00:02:38.360 --> 00:02:41.800
I don't care what this does. Exactly, I don't care what this does. Exactly.

53
00:02:41.800 --> 00:02:45.610
Some setting things, some getting things that's all fine and simple.

54
00:02:45.620 --> 00:02:47.760
The structure though is something different here

55
00:02:47.760 --> 00:02:49.670
we loop over or the background images.

56
00:02:49.670 --> 00:02:53.490
So it creates a box for every background image there is and I

57
00:02:53.490 --> 00:02:56.560
think it's a good idea to separate this into its own function.

58
00:02:56.840 --> 00:02:59.380
So we have a loop in this function which then calls

59
00:02:59.390 --> 00:03:02.820
a function to create the box for that particular image.

60
00:03:02.960 --> 00:03:05.900
That way, when writing the code that handles that one image,

61
00:03:05.910 --> 00:03:07.630
we don't even have to think about the

62
00:03:07.630 --> 00:03:10.760
fact that we're looping over other images as well

63
00:03:11.240 --> 00:03:16.390
as a rule of thumb, but I want to pass as little information as necessary to a function

64
00:03:16.840 --> 00:03:20.220
that means that you have a very clear picture of what goes into that function.

65
00:03:20.240 --> 00:03:22.750
For example, I could pass the entire context

66
00:03:22.860 --> 00:03:25.700
and then that function could do the same stuff as here.

67
00:03:25.700 --> 00:03:28.450
It could catch the camera, it could get other stuff from it,

68
00:03:28.940 --> 00:03:34.350
but then I don't really know what is being used there. Does it even use the camera?

69
00:03:34.360 --> 00:03:37.960
Does it even use the use multi view, whatever it is.

70
00:03:38.640 --> 00:03:41.760
So that's why I like passing things in explicitly.

71
00:03:42.340 --> 00:03:46.890
I think this layout is not used beyond these two lines,

72
00:03:46.890 --> 00:03:48.800
like you don't see any highlights here.

73
00:03:48.800 --> 00:03:54.760
So let's assume that it's only used to create that box, that the stuff should go into.

74
00:03:55.240 --> 00:04:00.180
So let's keep that here and only pass the box to the new function.

75
00:04:00.400 --> 00:04:05.000
I want to create this function on this class so that everything is grouped together.

76
00:04:05.040 --> 00:04:07.860
So that means the call has to start with self dot

77
00:04:08.240 --> 00:04:11.250
and because it's a function that is internal to this class.

78
00:04:11.250 --> 00:04:16.670
It's only for our private use and it's not meant to be called from outside of the class

79
00:04:17.089 --> 00:04:20.279
that I want to indicate with an underscore. So it starts with an underscore

80
00:04:20.430 --> 00:04:24.460
and it's going to draw one background image. So let's just call it

81
00:04:25.340 --> 00:04:25.760
come on

82
00:04:26.640 --> 00:04:27.660
background image

83
00:04:28.240 --> 00:04:29.950
then it needs the box.

84
00:04:30.340 --> 00:04:30.960
Well, does it,

85
00:04:31.740 --> 00:04:32.590
does it use box?

86
00:04:34.240 --> 00:04:35.900
It uses the box. So, yes,

87
00:04:36.090 --> 00:04:36.550
it

88
00:04:36.940 --> 00:04:40.020
I guess needs the I and the B G.

89
00:04:40.130 --> 00:04:43.150
I think it needs the camera as well

90
00:04:44.540 --> 00:04:45.260
or does it,

91
00:04:46.340 --> 00:04:48.350
nope. No, it does not.

92
00:04:48.740 --> 00:04:53.450
No highlighting of the camp name that's only used here then use multi view,

93
00:04:53.460 --> 00:04:55.270
I think that used their Yes.

94
00:04:55.270 --> 00:04:56.860
So it does need that

95
00:04:59.940 --> 00:05:01.160
and I think that's it.

96
00:05:02.640 --> 00:05:04.350
So now that we have our call, that's

97
00:05:04.940 --> 00:05:07.660
put all the code in there,

98
00:05:09.840 --> 00:05:13.760
we define the function, it also gets itself and the rest

99
00:05:14.340 --> 00:05:18.560
and now we can unintended all this other code by one level.

100
00:05:20.040 --> 00:05:22.910
What you can see now already is the advantage that we

101
00:05:22.910 --> 00:05:26.290
had instead of having to look for weather cam was used,

102
00:05:26.470 --> 00:05:30.180
we can see that it is used here is not passed to this function.

103
00:05:30.280 --> 00:05:33.930
So we have a much better understanding of the scope of this variable

104
00:05:34.100 --> 00:05:37.490
and this is the purpose of all that re factoring it's much easier

105
00:05:37.490 --> 00:05:41.550
to see which part of the code needs which part of the data.

106
00:05:42.340 --> 00:05:46.260
Another thing that I noticed now, by the way, is that layout dot active?

107
00:05:46.640 --> 00:05:48.030
It doesn't depend on I

108
00:05:48.240 --> 00:05:49.760
it doesn't depend on BJ.

109
00:05:50.240 --> 00:05:53.360
So it doesn't even need to be set inside of this for loop.

110
00:05:54.040 --> 00:05:56.650
And without all the clutter or the rest of the code,

111
00:05:57.240 --> 00:05:59.060
there's all of a sudden starts standing out.

112
00:05:59.740 --> 00:06:04.790
So let's move this all the way up there where we set the other things on layout,

113
00:06:04.800 --> 00:06:05.560
but then

114
00:06:06.740 --> 00:06:11.370
we need it like that. Okay, so this cleans up this function already quite nicely.

115
00:06:11.390 --> 00:06:12.460
Let's keep going.

116
00:06:13.440 --> 00:06:18.040
So here we create a row and some stuff happens depending on whether it's an

117
00:06:18.050 --> 00:06:21.130
image or movie clips or is er er a this all looks quite simple,

118
00:06:21.130 --> 00:06:22.160
so I'll just skip it.

119
00:06:22.540 --> 00:06:28.360
Um Then here we have the only use of that I parameter. So let's give that a better name.

120
00:06:28.370 --> 00:06:31.260
Press control D to select both instances,

121
00:06:32.540 --> 00:06:33.850
let's call it image index.

122
00:06:33.860 --> 00:06:39.290
BG is also dubious name, I think it's way too short, but it's used so often.

123
00:06:39.290 --> 00:06:41.060
Let's leave it alone for now.

124
00:06:41.840 --> 00:06:43.160
So this looks fine.

125
00:06:43.740 --> 00:06:47.200
And then here we have if BG dot show expanded

126
00:06:47.480 --> 00:06:51.370
and I think that's that little triangle that expands the box.

127
00:06:51.840 --> 00:06:54.410
To me. This means that there's two things happening here.

128
00:06:54.420 --> 00:06:57.060
There is drawing the part of the box that has always shown

129
00:06:57.440 --> 00:07:00.990
and then there's the optional expanded part of the box.

130
00:07:01.330 --> 00:07:03.680
This to me means that drawing the expanded stuff is

131
00:07:03.680 --> 00:07:06.260
a different thing and therefore belongs in a different function.

132
00:07:10.840 --> 00:07:15.850
So what do we need to give it? Well apparently we need the box and

133
00:07:16.240 --> 00:07:19.450
the image index was only used once. So we don't need to pass that.

134
00:07:19.840 --> 00:07:23.350
Use multi view wasn't used yet. So it's bound to be used below somewhere.

135
00:07:23.840 --> 00:07:26.260
And of course we need the background image itself

136
00:07:34.540 --> 00:07:35.950
and then the rest of the code

137
00:07:36.340 --> 00:07:38.390
an intense by yet another level.

138
00:07:40.440 --> 00:07:43.860
And now you can see that this function again became simpler.

139
00:07:44.240 --> 00:07:45.950
So let's keep going further.

140
00:07:46.740 --> 00:07:48.450
Now we get some has book.

141
00:07:51.630 --> 00:07:52.760
I don't know what it means.

142
00:07:53.240 --> 00:07:53.860
Uh

143
00:07:54.540 --> 00:07:56.920
Then if sources image then

144
00:07:57.230 --> 00:07:58.260
stuff

145
00:07:58.740 --> 00:08:01.260
else if sources movie clip than stuff.

146
00:08:01.640 --> 00:08:02.620
And then

147
00:08:03.000 --> 00:08:04.160
we look at the house book.

148
00:08:06.440 --> 00:08:09.430
Okay so that is again a few different things happening.

149
00:08:09.540 --> 00:08:13.850
It makes a selection based on the selected source and then draw some stuff.

150
00:08:14.240 --> 00:08:16.760
So let's do the same trick again.

151
00:08:19.520 --> 00:08:22.970
And let's call this draw image. This will

152
00:08:23.940 --> 00:08:27.680
probably not use this road because it starts by creating a new row.

153
00:08:27.690 --> 00:08:34.490
So it will just get the box and PG and use multi view and then we can take this code

154
00:08:34.640 --> 00:08:38.760
and move it down here and indented so we can find it back again.

155
00:08:40.840 --> 00:08:41.559
There we are.

156
00:08:41.940 --> 00:08:42.150
Mhm.

157
00:08:43.140 --> 00:08:44.360
And there we are a function.

158
00:08:45.340 --> 00:08:48.460
Let's ignore the house book. For now we'll come back to that later.

159
00:08:49.440 --> 00:08:51.360
Now let's do the same for the movie clip.

160
00:08:54.640 --> 00:08:56.560
Control shift D to

161
00:08:56.700 --> 00:08:57.850
duplicate that line

162
00:08:58.740 --> 00:09:00.450
all down to move it down.

163
00:09:02.240 --> 00:09:03.050
Rename it,

164
00:09:03.640 --> 00:09:04.660
paste the code

165
00:09:05.540 --> 00:09:06.590
and an indian

166
00:09:07.040 --> 00:09:13.060
you can already see now my I D E draws use multi view in a darker blue

167
00:09:13.440 --> 00:09:18.450
and that means that that parameter is not even used. So let's just remove that

168
00:09:19.040 --> 00:09:21.370
and also removed from the call.

169
00:09:21.940 --> 00:09:24.460
And again, you can see that things are starting to clear up

170
00:09:24.840 --> 00:09:27.460
now you can see that that used most of you has only

171
00:09:27.460 --> 00:09:30.320
used in draw image and not in the wrong movie clip.

172
00:09:30.330 --> 00:09:33.400
Remember we haven't changed the functionality at all yet.

173
00:09:33.410 --> 00:09:36.890
We've just moved some lines of code around but their relation

174
00:09:36.890 --> 00:09:39.880
when it comes to in which order they get executed,

175
00:09:39.880 --> 00:09:41.060
which data they get.

176
00:09:41.440 --> 00:09:42.960
That's all still the same.

177
00:09:43.340 --> 00:09:46.030
So without understanding what it does exactly.

178
00:09:46.040 --> 00:09:48.500
We could make all these changes already.

179
00:09:48.940 --> 00:09:51.150
Now let's go back to the drawing image function

180
00:09:51.150 --> 00:09:54.250
because you can still see that it has double inventing

181
00:09:54.740 --> 00:09:59.870
and I don't like that. If b g dot images not none, then

182
00:10:00.030 --> 00:10:02.660
something happens otherwise, nothing happens.

183
00:10:03.340 --> 00:10:04.750
So why not just flip it around

184
00:10:06.240 --> 00:10:08.000
if BG dot image is none

185
00:10:08.160 --> 00:10:08.760
return,

186
00:10:09.340 --> 00:10:14.220
which an indians even more code. We could do the same for the views. Multi view.

187
00:10:14.230 --> 00:10:16.770
You could put that in a different function like this blog

188
00:10:16.780 --> 00:10:20.500
specifically for drawing multi view options but you've seen it already.

189
00:10:20.500 --> 00:10:24.850
So let's skip that for now. I think there has been more interesting

190
00:10:25.400 --> 00:10:28.960
remember that. It used to be one big block of code. So

191
00:10:29.540 --> 00:10:33.650
by default it was set to false in certain specific cases

192
00:10:34.140 --> 00:10:35.220
it accepted true.

193
00:10:35.230 --> 00:10:37.900
So that means that these two functions know

194
00:10:37.900 --> 00:10:41.510
something that this function now doesn't know anymore.

195
00:10:41.540 --> 00:10:45.750
In other words we need to get some information out of draw image and draw movie clip

196
00:10:46.140 --> 00:10:48.000
and get that returned

197
00:10:48.200 --> 00:10:49.110
to this function

198
00:10:49.340 --> 00:10:50.250
and therein lies the key.

199
00:10:50.250 --> 00:10:54.260
We can just return true or false depending on what has book has to be

200
00:10:55.340 --> 00:11:00.200
here. It is such a true, which means that before this it will be such a false.

201
00:11:00.210 --> 00:11:03.330
So let's declare that this function returns a

202
00:11:03.330 --> 00:11:06.860
boolean and here we can just return false and

203
00:11:07.240 --> 00:11:08.560
in other cases

204
00:11:10.640 --> 00:11:12.040
we can just return true.

205
00:11:12.390 --> 00:11:15.050
Now we have completely eliminated that variable here

206
00:11:15.440 --> 00:11:19.960
and we just return true or false depending on whether there is an image available

207
00:11:20.740 --> 00:11:23.040
the thing, the same logic will apply to

208
00:11:23.190 --> 00:11:24.160
draw movie clip.

209
00:11:26.840 --> 00:11:31.270
So if use camera clip or BG dot clip as it is true.

210
00:11:31.270 --> 00:11:34.320
Otherwise it would have gotten the default false.

211
00:11:34.340 --> 00:11:36.950
So what we can do is something like this,

212
00:11:37.740 --> 00:11:41.890
but then you set it and then you said it again to something else which is not so nice.

213
00:11:41.940 --> 00:11:45.560
We could also do this of course, but what does this code mean?

214
00:11:45.560 --> 00:11:48.440
It means that if this expression is true this

215
00:11:48.440 --> 00:11:51.640
variable becomes true and if this expression is false,

216
00:11:51.650 --> 00:11:53.030
this variable becomes false.

217
00:11:53.110 --> 00:11:55.790
So you can just do this

218
00:11:56.340 --> 00:12:03.860
has book equals use camera clip or clip and now we can just say return, has book

219
00:12:05.740 --> 00:12:07.150
all that is left now

220
00:12:07.540 --> 00:12:09.360
is to actually use the return value

221
00:12:11.200 --> 00:12:13.280
and again we have this pattern of

222
00:12:13.550 --> 00:12:14.650
setting a variable

223
00:12:14.810 --> 00:12:16.960
and then setting it to something else again,

224
00:12:17.340 --> 00:12:18.700
which is not so nice.

225
00:12:19.140 --> 00:12:22.480
So what we can do is to hear else

226
00:12:22.810 --> 00:12:24.830
and the structure is starting to become a little bit

227
00:12:24.830 --> 00:12:27.790
clearer depending on the type of the image source,

228
00:12:27.800 --> 00:12:32.130
we draw something specific to that type and that function returns whether

229
00:12:32.260 --> 00:12:34.590
that image is actually there.

230
00:12:34.770 --> 00:12:35.850
So maybe

231
00:12:36.540 --> 00:12:38.100
we should rename this variable

232
00:12:38.500 --> 00:12:39.060
too

233
00:12:39.440 --> 00:12:41.970
as source, depending on the source,

234
00:12:41.980 --> 00:12:44.410
we do something with it that returns whether there

235
00:12:44.410 --> 00:12:46.840
is a source of that type available at all.

236
00:12:46.850 --> 00:12:48.840
And I think this is a lot clearer already

237
00:12:49.050 --> 00:12:53.850
now finally if has source is true, then this code is executed,

238
00:12:53.860 --> 00:12:55.470
otherwise nothing is executed.

239
00:12:56.040 --> 00:12:57.850
Which means that we can just say

240
00:12:57.950 --> 00:13:00.950
if not has source return because the work is done

241
00:13:01.180 --> 00:13:04.210
and finally we have this else has source is false

242
00:13:04.940 --> 00:13:07.380
and we already know that if it's false,

243
00:13:07.380 --> 00:13:10.690
then we will return in order to know what happens when you said it defaults,

244
00:13:10.690 --> 00:13:13.930
you have to read on and think about what's happening.

245
00:13:13.930 --> 00:13:18.260
I don't like that. So let's stop using our brain and just say else return.

246
00:13:19.140 --> 00:13:22.760
And I think now we have much much nicer code,

247
00:13:23.440 --> 00:13:26.100
let's go through it from the top again, we have a draw function,

248
00:13:26.480 --> 00:13:28.630
this, it reads over all the background images

249
00:13:28.980 --> 00:13:29.870
creates a box

250
00:13:30.340 --> 00:13:31.210
and fills the box

251
00:13:31.740 --> 00:13:32.360
and simple.

252
00:13:32.840 --> 00:13:35.000
And the rest of the code is equally simple.

253
00:13:35.160 --> 00:13:38.660
Now, if we scroll through it, keep an eye on the indentation level,

254
00:13:39.640 --> 00:13:41.950
you can see that there's the indentation for the class

255
00:13:41.950 --> 00:13:45.060
for the function and then for one condition or a loop

256
00:13:45.740 --> 00:13:46.590
and that's it.

257
00:13:47.740 --> 00:13:50.460
Our code is completely flattened.

258
00:13:50.840 --> 00:13:54.860
No nesting of conditions, it's all much easier to understand.

259
00:13:55.940 --> 00:14:00.290
So what we've done is actually reduced what they call cognitive complexity.

260
00:14:00.300 --> 00:14:05.860
This is a metric that gives you a score to how complex certain code is. Basically.

261
00:14:05.860 --> 00:14:09.560
It penalizes conditions inside conditions inside conditions,

262
00:14:10.140 --> 00:14:12.960
every condition that you add at another point

263
00:14:13.440 --> 00:14:20.160
plus the nesting level of where you put it. So if inside an F gets three points.

264
00:14:20.640 --> 00:14:21.930
Two for the two ifs.

265
00:14:21.940 --> 00:14:26.050
And because the second if is inside the other, if it gets another point,

266
00:14:26.280 --> 00:14:27.080
I'll show you

267
00:14:27.230 --> 00:14:30.060
here. We have a simple function. Score is zero.

268
00:14:30.440 --> 00:14:33.760
Here we have a function of score. One because it just has one condition

269
00:14:34.240 --> 00:14:39.250
Until we have a function that nests to conditions. So this gets three points

270
00:14:39.740 --> 00:14:42.010
plus one for the initial condition

271
00:14:42.400 --> 00:14:44.090
and plus two for the nested.

272
00:14:44.090 --> 00:14:47.940
+11 for the condition itself, and one for the fact that it is nested.

273
00:14:48.170 --> 00:14:50.170
If you were to nest another one that would get

274
00:14:50.180 --> 00:14:52.250
two for the nesting and one for the condition.

275
00:14:52.940 --> 00:14:56.560
So by reducing the nesting level of all this code,

276
00:14:56.570 --> 00:15:00.860
we really reduced this particular metric for complexity.

277
00:15:01.440 --> 00:15:04.640
We've reached the end of this episode of scripting for artist.

278
00:15:04.650 --> 00:15:07.040
I hope you've learned a bit about how to

279
00:15:07.040 --> 00:15:10.230
massage your code into something more readable and get a

280
00:15:10.230 --> 00:15:12.700
bit more feeling for what to put in a separate

281
00:15:12.700 --> 00:15:15.270
function and what to keep in the same function.

282
00:15:15.550 --> 00:15:17.420
There's lots more to be said about this,

283
00:15:17.420 --> 00:15:20.660
and I'm sure I'll cover that in some future video for now.

284
00:15:20.670 --> 00:15:22.050
Thank you very much for watching.


