 All right. Good evening. Good afternoon. Good day. Happy Friday. Let's see. It looks like we got sound, which is good because I did just switch over to what I think is the right microphone. Looks like I got sound inside OBS. So let me shuffle a couple of these chats around. We will get this show in the road, but yes, here we could close this. So happy Friday, everybody. So for those of you that are new or just joining for the first time or watching this video after the fact, if you haven't seen any others, my name is Tim, and I go by FOMIGuy on GitHub and Discord. This is the Adafruit Deep Dive Stream, Circuit Python Deep Dive. We're working on Circuit Python-related stuff. It was originally started by Scott, the lead developer of Circuit Python, generally working on stuff inside the core. Scott is away on leave for another chunk of time here this year, so I've been taking over and doing the Deep Dive Streams. We're working on the Circuit Python project. If you're brand new to all of this and you don't know what that is, you can learn more at CircuitPython.org. But to give you the quick lowdown, it is basically an implementation of Python that can run on tiny computers called microcontrollers. There's a bunch of pictures of them over here on the downloads page on CircuitPython.org. Basically, these things are tiny computers, and we're running Python code on these tiny computers. It can interact with the IO pins along the sides there or around the sides of this one, or this one has got some key switches plugged into the IO pins. Our Python code can interact with those pins and interface with electronical devices that are plugged in, like sensors and beepers and buzzers, lights, speakers, buzzers, touch inputs, flex resistors. There's a million different kinds of things that you can use to sense the environment or to output some thing into the environment, be it sound or light or heat or whatever. We're able to write Python code to interact with all that stuff. Again, if you want to learn more, CircuitPython.org is the place to go. It's an open source project. There's lots of folks, the whole community built around this project of folks that work on the core code, but also folks who work on libraries and folks that work on projects and documentation and infrastructure and support for members of the community. All kinds of these wonderful and talented people come together inside this community to make this project what it is. If you're interested in getting started joining us, if you want to help contribute back to it, whether that's code or projects or documentation or just help or whatever, if you're interested in doing that, definitely join us over on the Discord, which is shown down below, ADAFRU.IT slash Discord. Another thing you can do is head to CircuitPython.org and go to the contributing link here. If you're looking specifically to get involved in software development, this is where to go, the contributing link. But like I said, there's lots and lots of ways that you can contribute and be involved in the project even beyond the software. So join us over on Discord to get involved. It is an open source project, but I will say it's primarily funded by this company, ADAFRU. This is their website, ADAFRU.com. They are a hardware and software company based out of New York in the United States. They create hardware devices and sell and ship from the New York factory here in the US. They also pay folks who are working on these projects to write the drivers, to write projects, to make guides, to make documentation. They're paying the folks who are working on CircuitPython. The team of folks that's employed full time is paid by ADAFRU. Some other members of the team are employed part-time to work on the project. Some folks work on an individual project basis. ADAFRU is paying the folks who are working on this project. So thank you to them. And if you want to help support the project, you can do that by purchasing hardware from ADAFRU so that they can keep money coming in and keep funding open source software like CircuitPython. So thank you to anybody who does want to purchase hardware. You can get all kinds of fun toys and microcontrollers and things to plug in and do with microcontrollers. You can find all sorts of stuff over there on ADAFRU's website. How's it going? Be out of graph over on the YouTube. Good afternoon. Happy Friday. So jumping a little bit more into today's topic, generally the stream is about CircuitPython. Specifically today what I will be working on is essentially this flippy clock which we have on the screen right here. So what I have here is the result of some animation trickery, essentially, where we pre-rendered a bunch of sprites and then we're just playing them back one after another, you know, in quick succession to make this animate and make it look like it's flipping down like this. How's it going, Paul SK? Happy Friday. So if you're interested in these sprites or the technique that's used in that, I would say go back onto my channel and you can watch the VODs from last night and a couple of nights ago. There's two videos where I worked on the code that generates all of these sprites. What I am going to work on here on the deep dive though is basically building the CircuitPython class, the helper class that's going to use these sprites and it's going to give us a nice easy to use interface to set whatever digit we want on this and we're going to make it look right, like look correct, I should say. Like right now, of course, the top half is going away, right? Like when it flips down, we can't see the top half. We need to fix that. We're going to have static ones back there. So we've got that kind of stuff in the mix and so this one that we have on the screen right now, this is definitely just a proof of concept of the animation itself, just flipping through the sprites in the sprite sheet and it does look pretty good. So the next thing to do is actually build some code, build some scaffold around this, some Python code that will make it much easier to interact with and make it easy to set the numbers to whatever we want and have it run the animation and then change to look like how we want. Let's see, I feel like I possibly heard the Twitch thing. I don't know if I'm hearing things. If somebody did, I don't have it pulled up so I can't see your name, but if somebody out there did follow me on Twitch, I do appreciate that, whoever you were. And it may have played through the stream actually, I guess because it's hooked up in OBS. I don't know if that one's in this scene, but I suppose I probably wouldn't have heard it if it wasn't on, so that may have splashed on the screen as well. If so, that's what that was about. So I'm just going to start right on the device. We're going to jump right into starting the code for this. So we'll take a quick peek. This is the sprite sheet for it. This is the bottom half animation sprite sheet. So you can see what we have are the numbers zero through nine. This is the bottom half of them. And then we have 10 sprites for each number and each one of our 10 sprites represents a different angle that that half of the number is at. So flip clock is the kind of thing we're after here. This represents, you know, essentially the angle of that flip clock flipping down to reveal the bottom half of the new number. Then I have top half over here. Top animation sheet. This shows the top halves, but it's the same deal. It's the each sprite represents a different angle of the top half of that number flipping down like that. So these are the sprites. We're just cycling through them inside of a tile grid showing those on the display. And right now the code that's doing that is just initializing the tile grids, loading up the sprite sheets, making the tile grids. They're both one by one tiles. And then they happen to be 48 by 50 pixels. But the scripts that we have that generate these sprite sheets, these can actually be manipulated to do different sizes. So this happens to be the size of the one I'm using. But ultimately what will publish will be a script where you can set it up to choose the colors and the fonts and the sizes for yourself. But right now it's just really proof of concept just, you know, for loop looping through the animations, showing each one one at a time, little tiny sleeps here and there just to make it so it's not going super fast. What we really want to do is start making a class. And I think should I just start putting it in lib or should I put it over here? I think I'll just put it inside the root for right now. Eventually this would end up inside a lib probably in a library. But let's just say flip. I want to start, I think I have two layers in mind for this, but I'm going to start at the inner layer. Really what I want is this one's going to be flip digit. And then we're also, I think, going to have flip clock after this. And the flip clock is going to hold some flip digits. One thing I want is display IO layout, because I want to extend widget. Let me use circup to install that. And now we can import it. Is this not update? Display IO layout. Display shapes. This installed shapes. Maybe it's not done yet. Looks like it's done. Oh, there it is. Inside of here is widget, which is what we want to extend. We're going to put that inside flip digit. Close some of these things down just so we don't have so much stuff open. Class flip digit. And this one's going to extend widget, which is going to come from here. So widget is basically a lot like group. It pretty much is a group, but it has a couple of other things like anchor point and anchor position, kind of like display text labels, and maybe a height and a width, maybe one or two other things. The anchor point and the anchor position are the main reason why I use it. Height width, anchor point, yeah, x, y. Pretty much this is what it's giving you. But beyond that, it's pretty much just a group. So display IO group, we can add other things to it. We can show it on displays. We can do all that kind of stuff with it. So that's what we're extending flip digit. Inside of this def init, we want four tile grids, two static and two animation. And when I say static, I don't mean that they never change. I just mean that they don't change as part of the animations. And the reason we want two of them is because we want top and bottom half. So I'm just going to go self dot top static tile grid equals a new tile grid. How's it going remix 40 over there on YouTube? Thanks for tuning in. We should import tile grid from display. Import tile grid. Tile grid takes an image. We need to load the image self dot. Actually, you know what we want to do is not just load the image. We want to actually accept the image preloaded if we can because we don't want to load the same sprite sheet four times once we get to the clock level. Right now I'm working on a single digit. Ultimately, we want a clock with four digits. We don't want to have four copies of the sprite sheet in memory. So I think what we want to do is be able to pass that sprite sheet. Chat isn't up on the stream. Uh-oh. Oh, you're right. It's not updating. That's interesting. Is it too tall? It's too tall. There we go. Thank you for the heads up. It should fit in there now. So we're going to just pass in the sprite sheet. Assume we already have it. What else does tile grid take? It takes, well, first of all, it's capital G and it takes pallet, which is called pixel shader though, not pallet. And that's going to be... Unfortunately, we're going to have to take that as well actually. Sprite sheet. Well, I don't know. No, it's not really unfortunate. I shouldn't have said that. How's it going, Sea Grover? Happy Friday. Pixel shader. Do we need anything else? Let me pull up the docs for tile grid. It's always good to keep the display IO docs handy. Circuit Python, display IO docs, native helpers, tile grid. We can give it X and Y, but we'll just leave those default for now. We need to give it height and width and tile height and tile width actually. So height and width, those are both going to be one because this is going to be a one by one tile. Tile width and tile height, those are going to be... It's 48 by 50, but eventually we're going to need a way to pass in your own across that bridge when we get to it though. Oh, and the thing is actually... Yeah, we actually have a static sprite sheet, static sprite sheet pallet, and then we actually also have animation, sprite sheet, animation, sprite sheet, pallet. We need both of these because we have two different sprite sheets. The ones I showed you before, actually we have top and bottom too. So these are the animation sprite sheets, and then this one is the static sprite sheet. And I don't ordinarily like... I'd probably just load this in here, but the thing is I want to... I know that I'm going to be making multiples of these, and I'm hoping that if I'm passing in the sprite sheet that we are not loading multiple copies of it. We can have multiple tile grids that reference it, but we're having one main copy of the sprite sheet itself because they are kind of big. Like these files are 241 kilobytes each, so that's close to 500, and then another 58 for this one. So we don't want four copies of that in memory. We can help it. Sprite sheet pallet. Okay, might as well break this up a bit more. All right, that's our static. We want the bottom half static, bottom. We want now the top animation, top anim tile grid, top anim sprite sheet, top anim... Do we just say pallet? Try to keep it a little less wordy. And these are actually the same size. So essentially I'm going to have the static ones in the back and the animation ones on top of those, so that that way when the animation ones are showing something, they are showing it on top of the static ones. This will all kind of come together, I'm hoping here. I have kind of a plan in mind for this. I didn't quite lay it out, so we'll kind of see it as it unfolds and we'll learn together if it's going to work I'm imagining, but did we not change the... oh, anim. We should keep that consistent too, right? Like this one... I kind of thought about this design the other night, not on stream. I will mention for any new folks that joined if you're interested in this project, specifically the code that generated these sprite sheets. There are a couple other streams over on my channel that you can catch where I wrote the code that generates these from last night and a couple of nights back. I didn't lay out my plan though, the planning I actually did off stream, just kind of as I was thinking about it one day. So yeah, also keep that in mind too, as I kind of thought about this. Like I'm not necessarily just pulling this right out of my head right now. I'm not not that good really to just sit down with a first try and flop the whole thing out like this, but I did think about it quite a bit and plan it out. So we've got our back static tile grids. We've got our front animation tile grids. We want to initialize our self instance of widget, which is actually also going to be the self instance of group. But this is wrong. It's like super. What is it? Super self super? Or just super? It's just super. And so very, very first thing like I'm going to do is so I can actually start testing and seeing how broken my code is or not is just add one to self self.append. So that's going to be the group append the self. We'll just say top static tile grid first. And let's just keep it right at that only for right now. Let's just we should have enough to see if this is going to be working. So I'm going to say this is called code flip animation test. This code is now empty except for that stuff. Actually, we want some more of that. You want this? We don't want these because we're creating our tile grids inside of that object now, but we do want these sprite sheets right here. And in fact, we actually want a static one also. Except actually the static one is the entire one not top and bottom. Although I am going to treat it as top and bottom probably if I can. But it is still just one. So static, sprite sheet, static, palette, static sheet. You know, one thing I don't know on the static sheet is if green is at index zero. Or if there's multiple greens, we actually got multiple greens on the other one. It's something I want to try to resolve that to only have a single index of green. But that one will be another other day probably we want map. Okay, only one, but it was not first. So I am going to move it and save this and then export this place that on our drive there. I am actually going to also export another copy of it to repos. Take a python. Can we search yet? Flip. I should look into how we can manipulate the palette from PIL. We might be able to change the indexes inside there and put green at zero. For now I have just saved it that way. So static palette dot make transparent zero to set that green to be transparent. And then let's go digit equals flip digit and static sprite sheet, whoa. Static, palette, top animation, sprite sheet, top animation, palette, bottom spreadsheet, bottom, palette. And what else? Make a group. Main group equals group. Board display show. We can comment this. We don't really need it right right now. I do want to keep it though while true pass. Yeah, that should be I think enough to do something or crash. Wrong on both counts. It does not crash and it also does not do anything. We didn't add it to the group. Main group dot append digit. That looks better. Okay. So our base infrastructure is fine. We've got our group, which is actually inside a widget. We're able to put tile grids on it and then show them on the display by adding the digit to our outer group here in codepie. So the sort of structure the scaffold behind the scenes is all working properly. So I'll add the rest of this stuff, self dot append, self dot bottom static, and we should change the, might as well change the location now I think self dot bottom static dot y needs to be the height. We should be passing this in, I think tile width. So then the y of this will be tile height, which will move it down below static. And we want to add static first. And then after static is in, we want to add animation tile grid, because it's going to be layered on top or in front, depending on how you want to think about it. Top animation tile grid, bottom animation tile grid. Let's go ahead and set that self dot bottom animation dot y tile height, save that. And we should see not enough arguments because we did not add tile height and tile width here, which is did I do width and then height 48 and 50. So that's not quite what I expected. Maybe let's hide these hidden true. Maybe these are, maybe these are on top and showing something that I'm not expecting. So those will spend a good chunk of the time hidden, but we'll make them visible when we want. Okay, yeah, this is fine. This is what I'm expecting more so it's not right. Doesn't look like what it needs to, but that is what I'm expecting. Oh, you know, I just had an idea about the line in the middle, we could just have it like this with a gap. Actually, we want a line in the middle, I think of the flip clock tiles and I was thinking of just adding it in the PIL script, but actually just have it like right here. Actually, I guess there's a gap at the top anyway. So we need, well, we need to just set it to the correct index, which would be, yeah, we need some information about this, I guess. I guess we could assume it's going to be three by four. Maybe that's fair. Zero, one, two, three, right, because I'm doing top and bottom as different tiles. So the top half of the zero is index zero, the top half of the one is index one, the top half of the two is index two, the bottom half of the zero is index three, bottom, static, let's, I think there's a default tile three. There we go. Okay, now our static looks good. And if we put that two back, then there will be the gap there. Ooh, not quite, huh? Oh, this is anim. Interesting. We'll see how it looks with the animation. I had imagined not having this gap here, but instead just having a black line in the image or whatever color. It doesn't have to be black line, but whatever color you want in there. We'll see what it looks like though. I'm interested. Okay, so we've got our statics. We've got our animations. Those are in front. One thing is this should be the same, right? If we're going to do plus four up there, we definitely want to do plus four down here as well. And we want to keep track of some things like the currently showing digit self. Do we just want to call it digit? That doesn't seem right, because then it would just be digit dot digit, flip digit display value. Maybe it should be value. Yeah. But I'm going to make properties. So I'm going to say underscore value. We are going to set it to zero. We're going to make properties. All characters are digits 0 through nine. That is it. We want length one as well actually symbol. Could it be an image of a cat, for example? Well, you could make your own cards like your own spreadsheets. So part of what I'll release is the PIL code that generates these images and also generates these variations of them, the perspective skewed ones. Right now it's pretty coupled together, but I could probably break it apart some and split out a few of the parts of it and then make it so if you create your own static spreadsheet like this and you could have whatever you want on it, right? Because like my code doesn't really know that these are numbers. I'm going to be tying it together with the API and then it will kind of know a little bit more that they're numbers, but the truth is it has no idea what's in here. It could just as easily be a cat or an emoji, a blink, a lars, whatever you wanted, slot machines, yeah, cherry, sevens, that kind of stuff, bar. Yeah, it would be possible. Today it's a little coupled together so like right now today there's not code that would be directly applicable and help you do it, but it could be hacked together with the code I have today and what I'll try to do is separate some of the PIL processes a bit to where you'll be able to just feed it a static spreadsheet and then it could generate the animation ones for you and then you can do with them whatever you want. This flip digit here, this one is going to assume digits zero through nine so it won't necessarily apply to a cat, although like I said there's nothing stopping you from putting a cat on seven and then just setting this to seven and it flips down and shows a cat, but you could also just reuse the tiles and make your own class or just use a tile grid and cycle through them. So if the new value string is, length of it is exactly one and if the new value is in the valid characters, then we want to go old value equals current value. So if that value equals new value and we need some animations and stuff here, animations and things, yeah, we'll just pretend those exist. One thing we will do first right now though is we do want to go set. Ah, how do we want that? I don't think I want another function for it. So I'm just going to do it straight here and we'll refactor later if we want a self dot top static zero because we only ever change zero because there's only a one tile equals what? How do we know? How do we know? I mean the lazy way is make a dictionary. So zero, one, two are easy but then three is actually zero, one, two, three, four, five, three is actually six, seven, eight, 10, 11, 12, 13, 14, 15, 16, 17, 18. Yeah, we're going to go lazy way with dictionary for right now. There's probably some math we could use so we didn't need to just have a dictionary but dictionaries exist and they're awesome and they're easy. Top, top, half, sprite, index, map. Don't you want to be able to flip to a blank digit for the leading characters sometimes? Good question, MD Roberts. Maybe, it's a definite maybe. Probably what we'll do is I could just add the last one here that's blank and then you'd be able to do blank the same way as all the others. Had not considered it before but yeah probably we will want that. So and then we'll make a blank set for this as well in the bottom half. This will be a dictionary, zero is zero. I just happen to know that one. I'll do them in rows, I guess, how they're laid out. So one is one, two is two. Those are the easy ones. Three is six. Four is seven. Five is eight. Six is 19, 11, 12. So these ones are double and then those plus one, there's something like times two plus one. There's some algorithm that makes these come out from a function instead of a dictionary but all right 14, nine is 18. That's 15, 16, 17, yeah. Bottom half. So this is where we get our gaps three, four, five and then nine, 10, 11. It's got to be that right? Let's double check it. Zero, one, two, so three, four, five, seven, eight, yeah, nine, 10, 11, okay. Which then puts these at 15, 16, 17, 18, 19, 20 because this actually counts 21 for the bottom half. Top half, index plus three. Nice, yeah that's true. Is there a way we could, we'll do that, we'll do that later. We could, I guess we could make one of these a function. One of them could be a dictionary, the other one could be a function, the one that's a function could just access the dictionary and then add the three, yeah. And then actually the one that is a dictionary could also probably be a function. We would just need to find the right math that makes this work. I'm going to keep it as a dictionary for now but yeah we'll do, we will do that because it'll get rid of having to have an extra dictionary. If our new value is valid, we get an old value to save, we really only need that for animations, we're not going to use that right now. We update the value field, we set this to top half, flip, digit top half, the new value. And then we go bottom, bottom static tile grid zero equals the bottom new value. So theoretically we should be able to set value and have it actually show top and bottom half correctly. That's zero, let's just go like now equals, no, let's go for i in range 10, digit dot value equals i time dot sleep 0.5. Fictionary approach is faster and more visual. That is true, that part's definitely true, I do like that about it. It kind of matches how the sprite is laid out. It was nice, I hadn't thought about that. Type int has no length, we need strings. Maybe we should allow, okay that's pretty fast but it is working. Maybe we should, I don't know if I like the line that way although we'll have to see how it looks with the animation. Truthfully with the animation is the real judgment of it. So the thing is these are actually going to happen at slightly different times and the animations and things is actually partially happening inside of here. So what we want to happen is when they set the new value we want to start showing the top half animation and when the first frame of the top half animation is visible we want to set the top static to the new value. We want to do that after the first frame of the top animation is visible that way this change is going to be occurring behind the first frame of that animation. We're not actually going to see this change happen, that animation frame is going to be in front of it blocking it. So first thing is we should actually be going self.top animation tile grid hidden equals false but the truth is even before we do that we should set the right index on it. So self.top animation tile grid zero equals this one is the value times n 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20. I think maybe we should actually have value be an int. So it would be if type is int and this one gets different instead of checking for one digit what we're going to say is um 0 is less than new value is less than 10 less than equal to 9 and I think we need this or something right there's an extra and now valid syntax that's fair so now our new value is going to be an int which means the thing we're setting here is actually just new value times 10 but we probably shouldn't just say times 10 because we're not guaranteed to end up with 10 being the amount of these that we want so we actually should have here animation frame count equals 10 because the pil scripts that I have are they have a variable for this we could generate like the ones I have here which have 10 frames per animation but it could also generate lower or higher amount of frames per animation the tradeoff is basically file size and RAM versus the smoothness of the animation so you can go less file size and RAM but less smooth animation or you can go more file size and RAM and more smooth animation try to strike a decent balance for the one that I release but you know people will be able to do it however they like so we're basically just getting all these invalid new values which is in this case now because they are strings and we might as well just raise honestly let's go back in here and make it actually pass in the ints instead of the strings and this will probably look super messed up or crash indeed crashed the int 0-9 I feel like it should have been int 0-9 oh you know what this is wrong right this needs equals are you only supporting incremental updates or do you want to be able to roll through the intervening values to get to your target digits my intention is to be able to change from any number to any other number without having to go through the ones in between which would not be possible on the physical implementation of this device would it the physical one has no choice but to scroll past the ones it doesn't want to use um the truth is I hadn't thought about it actually either way but what I was headed towards was just being able to change from any number to any other number in a single flip so you could flip from 0 to 1 but you could also flip from 1 to 9 and the animation would look the same for both is how I had planned but it wouldn't be that hard probably because I mean if nothing else you could just run it in a for loop of changing the value to get from where you're at to where you're going so to do that you might want it to flip faster if it's flipping through a bunch of things though so that's one thing to consider um good question and yeah that's my definitely the first thing I'm aiming for is just flip from one number to any other number with no extras in between but if we did have that then you could do it a bunch of times in succession shortest distance shortest distance well can they go backwards I assumed it could only go one direction is that what you mean shortest distance like if it had to go forward by three slots or backwards by 12 slots or whatever it would be to wrap back around again int 0 must be int 0 to 9 well something's not right because it definitely is int 0 to 9 but I did have I had this wrong but now we corrected it oh this one doesn't work now because that was a string that was fun some go both ways oh interesting I had no idea that someone went backwards looks cool when it's a full wall I have seen a video of that big wall somewhere I don't know where it's at or a video of a big wall somewhere with a bunch of these things on it it sounds really interesting and cool as well the for loop is a good compromise yeah and I think we'll we'll try to also have the animation speed be set up so you could set like a faster animation speed if you want to do the for loop way that way you don't have to wait as long okay that should fix this one right or not really code done it didn't rerun did it rerun I wish I had three separate if statements but I don't oh is this not int like this this is not it like this is it I should do an int actually it's like its own thing used to be common in airports in 36 here zero line 79 right these are numbers now yeah back in the day we had bi-directional process for monitoring displays before nixie tubes dnt so our animation one is showing now and it's visible one thing is the green is not transparent which is because we turned this back off well we turned it off but that was actually good because that proved to us that our animation tile grid is on top of our other one actually I guess it didn't really prove it per se but it showed that the showed us that it's visible at least it could have been behind I guess maybe I don't know so now inside of here we have set the top animation tile grid to its tile we have shown it with hidden false we will then update the top static tile grid we will then top flip animate we need to keep this thing on self self dot animation frame count frame count animation tile grid zero equals is it I it is I think we want this to take value and this is going to actually be old value and then we're looping zero through nine which is fine but we want to add to that value times 10 which is what we'll make it so that if we were looping four we'd have zero one two three so on but we'd start with four times 10 to get down to 40 and then just add the one all the way across what did I have in this one 0.02 spaces I'd like to know how they work ever take one apart how do you know how many spaces to put it seems arbitrary to me in the python code I mean if you mean spaces in between lines like this that part is pretty arbitrary if you mean spaces like this here the exact numbers arbitrary the important part are the levels of indention so if this def is going to be here you know and it's one two three four back to the edge then this def here also has to be four and this one here has to be four and then when we indent inside of here we also have four four is customary you could use two or three or other values if you wanted or you could use tab characters if you wanted and you like pain basically and so the exact number is unimportant as long as you stay consistent you have to have four you know if you use four you need to use four throughout the file but really the indention levels are how it works and you indent anytime you go inside of a block so if you're familiar with java or javascript or or maybe c or c++ code that has curly brackets um you know you signify a new block by opening the curly bracket and then you signify a closing block by closing the curly bracket in python we signify a new block by starting it with a colon and then indenting it down below inside this one is actually a wonky example because the way I've used the and and the slash here uh messes with the indention sum but this one here is a good example um we open the new block with a colon and then we indent all the lines that are inside that block in this case we just have one but if we had others you know here this one would be indented at the same level as the one below it and now both of these two lines of code are inside this block that's created by this colon here is there an auto indent yes I am using the pie charm editor and it has very extensive auto completion and auto indenting and all kinds of helper stuff like that built in so I don't have to micromanage the tabs very much uh I just press enter like for instance I get my cursor is right here I'm just going to press enter and it put me at the exact right level uh that I needed to be at you know or if I push enter here it puts me at the exact right level I need to be at um so generally I don't have to micromanage it too much whoops if you use a plain old text editor though then you would have to to um you know manage it yourself you'd have to make sure it's all consistent and everything best of both worlds at least it's four and not two shutter yeah two is two is rough I only I use two sometimes for html if it's like a html with a lot of levels but I don't like it I do it begrudgingly I use visual studio not code I gotcha okay yeah there should I would I would imagine there's auto indenting in that as well I don't have any experience with it um but I would guess there is can we not call this if this is down below no no no no no that's wrong we can it can be down here but it does need to be self and we need to keep anim demae uh anim delay oh that is not what we wanted to do back delay equals anim delay let me catch up also on the chat here um crazy mink says tabs recalls uh yeah recalls using typewriters and I understand how the flaps flip up I guess if it just rolls backwards yeah I'm not sure very similar to electromechanical telephone dialing like the old uh this thing all the way back I had one of those when I was a kid simple ones are just solenoid and a ratchet bi-directional has two solenoids and a slip clutch got two different teeth going two different ways or something salvaging electronics tonight but it has a broadcom chip which costs millions to get the data sheet for that is not good I don't have millions hopefully uh yeah hopefully one of these days that won't be the case uh so where are we at here we called top flip animate we passed in the old value which came in as value we're running through that we're sleeping our delay time eventually we might make an asynchronous version of this for right now I'm just going to go synchronous and call sleep here when we get to the end of this what do we want to do and we get to the end of this we want to hide the top animation tile grid and so at that point we have the top static showing the new value and so the next thing we want to do is animate the bottom side but the value for this one is actually going to be the new value because when it flips down we want it to be revealing the new value not revealing the old value when I say revealing I mean in the animation tile grid it's actually going to be covering up the static one so it's revealing the new one and covering the old one but you know that's kind of how I'm thinking of it is this one is revealing in the animation bottom flip animate for range in count this one will be bottom bottom here as well set it back to hidden after it's done except actually I don't think we want to do that in there I think we want to do that in here and then I guess we should keep it consistent truthfully so maybe let's not do this one in here because the reason why we need to do it back out here is after we're done animating but before we hide this we need to set the static one bottom static zero flip digit bottom half just the new new value new value new value so we run our bottom flip animate when it finishes it's going to be sitting on the last animation frame and it's going to be sitting in front of the static one static one is going to be showing the old bottom half value so we're going to update the static one which is behind and not visible yet we're going to update it to the new value bottom half then we're going to hide the animation one that way the static one that we just set will be revealed and that's actually this line so we can get rid of it but we do want it to happen before we set this to true and is this the same yeah I guess this is the same because top and bottom are basically the same I wish I could put electronics on my bicycles fix flap work like a card on a bike frame hitting the spokes flipping up requires going past the digit and then moving forward by one interesting horizontal or vertical tabs in the browser I don't know what you mean the browser I use or are in here horizontal but I use this a lot too which feels like vertical tabs but actually I have no idea which thing you're asking about uh I think this should work probably right maybe implicitly into object string implicitly uh 97 right right so we change this to want to be an instance so this should actually be zero not string zero bottom half doesn't look right but the top half does I feel like the bottom animation is not playing we didn't make it visible that would do it typewriters had vertical tabs too young to understand asking about tabs on the typewriter I see there we go I think I don't like the gap this way I don't think I want to do the gap this way because it actually makes it so they don't line up right like the seven it's particularly easy to see on the seven and the nine I guess as well because the four pixels in between make it taller and your brain tries to fill in the part between but it doesn't go straight probably a better way to explain that but that's what I got right now um I'm gonna get rid of this sweet so now we have this digit widget digit widget that's a fun one isn't it oh let me uh have this scrolled up electronics on the bike flip displays typically under tension at the top hanging at the bottom bench drum would pull past the top and it snapped down back up a whole lot yeah I can't even like fathom my my brain can't imagine the mechanisms maybe if I had played one in played with one in real life so this is looking pretty much how I wanted this is this is how I imagine this class working it does work one thing I will say is that the yellow blends together and makes it difficult to see it as well as I think I would like you to be able to see it um let me think about possible solutions bottom half animation starts right when the top half animation ends right let's take a look so new value comes in we validate it we save a variable with the old value we update the value field we set the first frame on the top animation then we show the top animation then we update the static one which is actually happening in the behind so we don't see it we run the top animation and then a few things a few things happen between the top animation in the bottom one of them is we set this hidden true another one is we set this hidden false and then we call bottom flip animation you know what we should do is uh we don't set the initial one here right we should basically be doing this before we say hidden false the same way we were up here so actually technically when this was getting shown it was on whatever it got left on we should have been updating it to this yellow should get darker yeah I was just thinking about darkening the sprite sheets for the animation yellow getting dimmer until it matches one thing is we don't I don't believe we have a super easy way to change the brightness live inside display IO of only particular regions or only particular images I don't think we have a great way to do that we can update the palette you can change the palette which will change how it looks on the screen to my knowledge though we don't have a like darkener algorithm we did have a darkener algorithm though we could just flip through the animation palette and make every single color inside of it you know x amount darker x percent darker or whatever animation BMP could have a gradient yes possibly well I mean definitely yes possibly we can figure out how to do it with ti l I think first thing I'm gonna try is just darken the entire sprite sheet how's it going buddy stripy cat here palette fader oh right palette fader this works per palette fade normalize so you go palette fader give it the source palette normalize true and then brightness and gamma I will definitely admit to not really knowing color theory too much so I know these are all words associated with colors but not as much the specific meaning behind them see what those values are docks in here too the pegs pages PDF how interesting it's like read the docs PDF source palette brightness and gamma and those default to 1.0 and the normalized defaults to false adjustment value range zero to one default is one maximum brightness palette brightness so then do you go normalize so you basically you initialize it and set the new brightness that you want you give it the source palette and then you set the new brightness by setting here brb what you getting into buddy get down from there that's climbing on a wire rack shelf it can barely walk on what about adding a shadow to the underside during the flip possibly shadows are gonna be tough again I guess it depends on how you mean like I mean I guess a shadow kind of is just a gradient between black and transparent so if we did figure out how to do gradients inside PIL then we could basically make what might look like a shadow by gradienting black and transparent and then we could maybe choose where to put it but I don't actually currently know how to do that gradient or if it's possible inside PIL you could of course go through and edit each of them manually but that would definitely take a long time then it creates a palette object with a new brightness background faded dot palette okay you access dot palette from it when you want okay okay uh is it on um is it in the community bundle or anything like that can we go circ up install cats can't live with them can't stir fry with them can't stir fry without them hope this cat's not involved in stir fry you probably would like to be though not in community bundle okay no worries we'll just go clone on that one terminal oh that's not where we want to be also I just bookmarked this accidentally repose circuit python get clone that one outfader into there and then we could do something like you know why this wants to always put circuit pie here and live so we actually want these first and then we here would go like this we also need to set the brightness which I didn't do yet helped with but not committed to chickens are dedicated to supplying breakfast brightness gamma normalize what is uh what is default for gamma okay if I just pass like 1.0 will it stay the same and I'll be able to just change the brightness or should those not be named why is this too many blank lines ooh okay seven is probably too much oh oh oh oh oh that's not how we want that nice I like it that is awesome thank you for sharing this here in the stream and also obviously for making this library this is super cool yeah I like that that definitely helps it right away I wonder should we not should we go brighter on the bottom and darker on the top can you go over 1.0 can I go like 1.1 is that actually brighter I mean brighter yellow is hard to conceptualize I guess ooh that wrapped back around and got darker interesting gamma burst is a gamma just to say I don't know I don't know the um I don't know color theory like at all truthfully so very very possibly yes I would defer to anybody who actually knows anything about it because I do not I sometimes know what colors look good together sometimes that's about the extent of my color theory knowledge okay this is an image all the rest of those actually are images do any of these go above 1.0 you do your base gamma is related to how our eye responds our colors of the spectrum so we could go static down a bit and then we'd have room to go back up alpha is transparency see grover do you know off top of your head is it possible to go above 1.0 or is it I shouldn't say possible but maybe intended like is it intended I should be able to go 1.1 and then make it brighter or is it really only for going down from whatever you started on should read the docs also apologies for not reading the doc shit probably mostly to go down right because it's really kind of about screen brightness for leds which makes total sense because yeah if you try to you try to show an image like on a matrix portal or something it'll blind you if you look at it but and then but there's only like there's a limited number of brightness settings as compared to a display but this allows you to play with those in between colors a lot more in between brightness is a lot more so it is probably just for going down that's my guess so what we'll do is we'll we're taking static one anyway here so let's just go before we do static static fader palette fader static so let's say static is going to be 0.9 you can go above one but if the color is already saturated it gets weird and wraps I see that's where my okay that's where my blackness was coming from in that one probably so we'll go down a bit here let's try 0.9 stick with 0.9 let's go small changes first you can always change it more 1.0 this will affect both top and bottom because they both come from the same spreadsheet for static so then we'll go self dot static fader palette so now static will be at 0.9 so then let's go bottom at where did those go right in here let's go let's go bottom at 1.1 1.0 top at 0.8 did I have those backwards before are these backwards we're getting brighter on the top and darker on the bottom I see top here bottom here static 0.9 top yeah that's what I was aiming for that looks pretty slick we could go a little bit more extreme if we went down to 0.8 here maybe we could then we stay 1.0 and then go to 0.7 maybe this kind of makes it it feel like the light source is out here doesn't it this is really cool I hadn't had a chance to play with this yet before I should not say that I didn't have a chance truthfully the truth is I just didn't do it didn't get to it basically but this is really cool thank you for making this seagrower this is actually super neat you could actually do a lot of stuff like this with shadows using this thing I almost think we want to go just it's so dark still but maybe just a touch darker still on the top I want a little bit more contrast between the static and the top six eight and one nice I like it that's awesome that really helps it I was thinking of making an outline maybe like just drawing a black line around the edge of the yellow box that way you would actually see the line as well that would help with the the depth perception but honestly this darkening and lightening this actually helps a lot with the depth perception I'm going to look at it straight on here the bottom is maybe a touch too bright I actually think so here's the deal I think it looks good on the screen right here I think it looks good coming through onto the screen looking straight on directly from the eye I think it's actually a touch too bright the the camera and the angle and whatever else the universe is just helping this one look a little better I think I guess we'll have to put palette fader in the community bundle after all that'd be awesome if you and if you don't if you like want help if you if you'd rather have somebody else add it I'm sure we could find somebody or I definitely would be willing to do that but that would be awesome if if you wanted to add that in there or if we got that in there I should say and it would definitely I mean I assume ultimately I'll be trying to make a learn guide for this so it would need to be available there in order for the packaging thing what is that called project project downloader project folder package I'm drawing a blank on the name but the thing that puts it all together for you that that can pull from the community bundle of course if it's not there right like I could still just provide it as a link on the page too it's not the end of the world project bundler that's the name of the thing I'm thinking yeah let's try down a bit what did I I had point eight let's try yeah let's try point nine yeah I like that maybe I'm gonna just take a look at 85 you know what I should do is scoot this over actually this got this tape in front of it I got my screen protector on and it still has tape let's scoot it over let's get an actual fair look at it without looking through the tape well fairish because I'm not going to take the screen protector off yet but it's clear it's not too dirty so let's just move that over we can do that in here digit dot x equals something bigger digit dot x equals 100 so it looks good from here as well nice thank you yeah thank you also Dexter for the idea about the shadow I think I really like the way this turned out with the shadow actually I hadn't it wasn't something I was thinking about in mind but it turned out to be really easy because of this library and I think it makes it look a lot nicer the other thing is to like people will be able to choose their color as well so like the you know I chose yellow just because it was easy to see when I was working in PIL but you could have blacks and whatever you want and we'll try to make it so you could do gradients in here because I do think it would look nice if that was a gradient so okay this one might be too far this one might be too far but stick with me for a minute if we darkened the bottom half static one while we were animating the bottom flippy one I think that would make sense right because technically it should be getting darker because the one coming down should be casting a shadow onto it you know what I mean when that comes down the one behind should get darker in order to do that though darker static fader I don't know can you change a can you change a pixel shader I I might I think actually I added that to the core you you didn't used to be able to and I think I did because of my button display button when I was working on that new version of display button I set it so you could do that that's right so we should this is actually awesome all of this comes together small world so what we want is while we're animating bottom pretty much just like after we show this it should be self dot bottom static tile grid pixel shader equals self dot darker and then when we're done we just put it back boop bundle fly yeah yeah for the project bundler yeah I think that's right bundle fly I think it's the name of the tool that does it could have five pallets so the shade is a little smoother yes I assume you mean yes so the one in behind getting back then you need a separate pallet for the static bottom yep you're right uh well I need to change it at least temporarily but yeah oh no pixel shader must be color converter oh uh uh palette and also actually palette here too why does that affect the top also oh uh hold up what have I done something else is what have I done here it does it it doesn't change the palette doesn't change the source palette does it maybe it does looks like it does I think this ends up changing this object let's see palette fader is a class brightness is a property source palette doesn't change it was never setting this one correct okay so now if I just uncomment this nothing changes I think that change I think that did change something though this feels brighter static fader this one is static fader palette static fader palette and I have these commented out so we're not doing them you can set brightness after instantiating as often as you want you have the brightness change smoothly possibly well change at each of the 10 animation frames potentially we could maybe so this it does it's not somehow it's changing a different one so I go maybe maybe I'm maybe I twisted up my code so oh and of course the camera just died on me okay so I go create static fader by making palette fader passing in static spreadsheet palette these numbers print the zero with one from the static fader palette and then we create a new thing self dot dark static fader which is a palette fader it takes the same one of these but different ones of these and then we print and importantly I'm printing static fader again not darker static fader and then when it prints the second time it is different a little bit so instantiating this one managed to change the colors back on this one or inside of here one or the other right oh I didn't put a hex they did change though does look like it changed really need to see the screen yet yeah the the source one does change rather than replacing the palette just use the faded palette brightness but I have to have different ones for the top and the bottom static otherwise the top will also get darker yeah but that will change both and I only want to change the bottom half so I essentially need them to be on different palettes for that time period when I want them to be different I do think for what it's worth though I do think this is changing the source palette so it might be worth double check in some of the logic inside there because it I print the zero with from the source palette first and then I initialize a palette fader using that same source palette and then I print from the source palette again after and it's different and I bet you should actually be a third color before this one I think because it would be should be a ff I think for green begin with I think green should be on zero save okay no I pushed control s inside here didn't I I hate that yeah it starts on ff and then cc and so it is going down a bit so no worries though because we could always just go we could make a copy an actual copy code doesn't modify the source I mean how else can this how else can this be changing right the only code in between here I'll I'll take it back to a let's take all the rest of this out of it I'll make a separate one new palette no new palette doesn't really matter let's just save five colors no we don't even need that many let's just say three colors it's not mixed uppercase and lowercase the actual colors we use don't matter just as long as we have a couple different and then we go fader equals palette fader p zero point seven 1.0 but before we do that we'll go print let's go print p let's go print p zero actually let's go let's make a def print palette palette four i and range length can you do length of a palette I think it behaves like a list right should be able to uh print palette i palette p print palette p so if the source uh if the source one p doesn't change then this should print the same thing both times I think internally makes a u-lab array so it's no longer a palette so we go I'll import this one instead of changing it to code pi we can go import code fader test call it index out of range import code fader yeah should have done hex values should have done hex values but I do think it changed hex test the first time we get the initial values that we had set and then the next time we get different values I am just printing p which is the original palette object in this one I'm not even ever actually accessing fader dot palette so definitely p is somehow ending up different maybe the u-lab array maybe the u-lab array is like doing some kind of weird pointer magic underneath the hood and causing it to change the original one well this does this uh you want me to drop the sample code in the discord will that help or like an issue or anywhere I can give you this reproducer code have to instantiate the class palette fader I mean I instantiate this one not sure what you mean though I well I instantiate let's see we instantiate palette and then we do instantiate palette fader and then we never did access you know palette fader dot palette but we could say you know like print fader this one is then we could go print palette again and we could do fader palette this would be the actual darkened one which will actually be the same I think as this one because it seems like what it's doing is it's just modifying that one in place in addition to essentially creating that new one fader test yeah that one was from p and that was from pader so they're the same have to instantiate okay yeah retouch um let me know if you if this would be helpful I mean there's not too much to it and you can see it here but I'm happy to share it if so uh what I can do though is we can totally still do this though right because we could just go uh we could just basically before we ever create one of these we could make a clone essentially so like self dot darker static fader now uh darker static palette equals a new palette which will have length of length static spreadsheet palette so it'll be the same size and then we'll just go for i in range length static self dot darker i equals static i so this will just loop over it loop over it set all the values into the new one which will be a totally separate one and so then at at that point let's see so then we get static fader we'll continue using static fader on the top but we'll go darker static fader this one will use self dot darker static palette go down to point seven then back here we'd be saying darker static fader dot palette and then this one would set it back to static fader dot palette yeah I think that gets us to the same place I think that's working but something with transparencies went weird I think oh oh oh we we will need to re we'll need to set the transparencies in that new um yeah we would need to set set them in this one which is gonna be weird because actually some of the code is out here but I'm just gonna steal it and put it back inside well but I but I cloned it I think it was preserving transparency but because I'm doing this one I've essentially cloned it to where I have now a whole new palette which did not ever get its transparency set um I was gonna try to hold out but I'm not gonna I shouldn't I'm gonna run to the restroom and then I'll be back in just a minute okay sorry about that that was not gonna make it I'm probably gonna call it a night here pretty quick anyway but bottom half is going all the way black now would that be palette let's print zero on this and see what we get the black or 00 cc sounds right actually and if we went down to 0.7 it'd be darker sleep extra in here just so we can actually see it has anything or not you know what I think I see there is the bottom half of the bottom half of the number is kind of outlined in there huh I'm being silly I am being silly this one does not have seven transparent colors this is the static palette the static palette only has one transparent color not seven okay yeah now our bottom half is darker we can see it right there we have this weird pause let's disable that that looks super slick we could even maybe go a hair darker and like you folks were talking about earlier we can actually update the brightness as a property it sounds like as well so we could possibly change it more gradually right now it's just hard cut change to the new brightness which looks pretty good certainly for display i o graphics but if we ease into it it will certainly look a lot smoother let me try just a touch darker I ended up with 0.6 is the top animation fader I like that that's like a nice it start darkening even as the top animation happens so right now we're not doing the ease into it we're just hard cut setting it so I will set it back at the beginning but that may I don't know if that will make it look weird no actually I do like that yeah I like that because now the bottom yeah yeah that's much better because now the bottom of the one flipping down is the same darkness as below it which makes sense because it's all part of the same shadow good call yeah that is really slick looking I'm really pleased with that curious what the speed looks like if we if we crank it up just a tad um where did I declare that back out here now I didn't actually declare it I think it has a default we try 0.01 instead oh a little too fast but it could just be this camera let me look straight on nope too fast didn't it was a okay yeah 0.02 engine and delay boy that feels more than twice as fast 015 I don't know that's still too fast that's weird that's animation delay I see we're not flipping through all of them um animation delay animation linear or sign uh think linear truth is I don't know though I would say watch you watch the previous streams you probably would have a better idea to tell me it's uh uh it's pretty much equally spaced based on how many frames were requested so the function that creates it you can tell it to create you spreadsheets with 10 frames and then it equally spaces all 10 of those frames so that that frame one is like all the way up and then frame two is like however many degrees 90 divided by the number of frames is so in our case 90 degrees divided by 10 frames that means each frame is about nine degrees apart and it's they're they're all the same amount apart they're all nine degrees away from the one before yeah those ones were on random like that was like I think last night and then like two or three nights ago I just popped on my own stream that was uh not like a regular planned one or anything why is this not is it not called animation delay or something what are we oh right right right anim we did anim on a bunch of those I don't know if I like that I am now acutely aware of how much space it takes though so is that actually faster because honestly that now kind of feels the same speed we actually used this we did okay so sign just not many frames is it not linear I guess I would assume that was linear please send me the test code is it sign it feels like that would be linear to me like if it was a graph it feels linear as opposed to like quadratic I don't know if that's the right term it's been a long time since I've been geometry on so I was never that good at geometry begin with geometry is probably my worst math so that one feels like it would be a pretty good for loop flippy one like if you were gonna flip you know x number of times in order to go all the way around if you wanted to mimic the actual physical real world one that looks like a pretty good speed I think that hitch right there was just the video stream to my computer not the actual display I think the display stays smooth I will say honestly the animation to the eye appears just a tad faster than it does on here honestly I feel like this is artificially slowing it down not a whole lot at all just a tiny bit but I do feel like that's slowing it down just a tad trying to fit all these features into diminishing platform or a tiny platform has diminishing returns I mean sometimes I think the goal the sweet spot is like enough features that it's super cool and interesting but not so many that it takes up too much space or that we can't do it and I definitely like the looks of this and this is a thing we couldn't really do before I mean obviously it's not like new to the core or whatever we didn't implement any new functionality but this widget and actually I'm really digging the way that the 3d looks with the shading this shading like I said before you could actually achieve a lot of really interesting perspective slash like 3d type shadowy stuff like this and I do like this I do think if we're not gonna do the multi flips that we're probably better off going just a tad slower I think that one's pretty good is that really but is that really twice as fast as what we started with I guess so yeah okay yeah and this one does feel unnaturally slow now as well that one feels like moon gravity or something that one feels pretty good though I think that's the one right there anyways to improve the simulation someone improve the perception that's true yeah no that's definitely true it's a bit of we got to find the whole 80 20 I guess if you think about it that way the the 20 percent of the stuff that will make it seem you know 80 percent of the way to all the way and then not try to really squeeze out that last 20 percent because 80 percent or 20 percent I don't know I probably butchered the explanation that's how I think of it though that 80 20 rule of like getting it most of the way there is fairly easy getting it perfected once you're past most of the way there is much harder and in our case is gonna definite I mean most likely is going to be having diminishing returns in terms of we have to write more and more and more code to make it more and more clever and all that new code is taking up space and ram so and if it's only changing the perception of it for like fractions of a second in the middle of the animation it may not be worth it I do think this bottom shadow though is super cool I think the bottom shadow during the flip animation actually turned out really well I'm I'm super happy with that okay if you're only doing one digit and nothing else you could afford to have more frames yeah we will be having we'll be having a total of four digits eventually which also brings up a good point eventually we might want to have it be a synchronous right now I'm straight up just calling time dot sleeping here which is totally making this be synchronous if we were trying to change two of these at the same time it wouldn't it wouldn't work out so um I may I don't know exactly how I'm gonna do it I may make it to where it can work either way I may make it to just be asynchronous I may keep it how it is and the rule will just be you can only change one at a time I don't know one of those one of those three ways will turn out to be how it works but I do know we are gonna want four of these basically two sets of two and then a colon in between and they're because like it's gonna be a clock right flip clock so there are gonna be times where we want multiples to change like if you have you know zero nine then it's gonna change to 10 which means the zero needs to flip to a one and the nine needs to flip to a zero so both of those really do need to change kind of at the same time I mean I they happened in succession it's not the end of the world but it probably would look nicer if they did just happen at the same time right um so yeah we'll probably want asynchronous somehow probably we'll probably want that I think I've talked myself into that way but I don't know for sure I still reserve the right to change my mind certainly but I think that's gonna do it for tonight I'm feeling pretty good about this we got our basic version of the of the widget done yep that's another 159 to 00 yep we got our basic version of the flippy done for the digit this is looking really really nice I like the way it turned out um so we'll work on the clock next I may do that a bit tomorrow I'm gonna circle back around and hit my uh uh game jam game from a couple weeks back from circuit python day we're gonna work on that a bit tomorrow for my stream in the morning um but we may get back into this as well after that we'll kind of see how tomorrow goes once we get there thank you everybody for watching thank you see grover for this pixel I mean palette fader thing this is again super super awesome I think this really added a super nice finishing touch to this that that really does make it look a lot better so thank you for sharing that and creating it thank you to everybody for watching um hope everybody has a good night again if you are interested in seeing more of this or more of me working on other circuit python stuff you can follow me on twitch at foamy guy underscore twitch that'll give you notifications when I stream the next time that I'll be back to stream is tomorrow morning at 10 a.m central time so about 15 and a half hours I think from right now if my math is right um so I'll be back then on that channel and yeah we'll get into some game stuff and then possibly get back into this uh and so yeah hope everybody has a good night and if I don't see you tomorrow then I hope you have a good weekend and beyond that I will catch you all next time see you