 We'll come back catch from scratch episode 12 topic today is menuing so file edit view that kind of stuff drop-downs Things that happen when you click on the buttons. That's the plan today So we're using again x-win xlib x11 whatever you want to call it and There are a couple ways we can go about doing this right now if you look at our old function We just have a single render on the screen. The whole screen is a single window Well one option that we do have is to keep it that way keep the whole big red box as the render window and you know draw our you know body whatever it is inside there and Then on top of that draw like little rectangles like so You will have a file bar button there edit button View button help button whatever it will have drop-down buttons that may pop up below those You know, whatever you would expect in these You know in these drop-downs put them here and that's fine I mean you can do that and have them automatically opening close when you click on them That's fine But when you're just drawing rectangles and text to the screen, which is not hard to do in in this like in this way It's gonna be hard for us to determine what we're clicking on So if we have a mouse cursor and moving around the screen like this How do you know that you're on top of a button or not? Well, you're gonna have to go through every button every time and see when you click if below you is a button So you have checked these x coordinates and these white coordinates and see if you're between them for every single one of these Until you find where you are and that's not really that efficient in my opinion So I'm not gonna do that. There's actually a different way about doing it Which makes a little bit more sense to me and that is to Break up our big window our display. Maybe you would say just just just a sub window here This this main window that we're using to render our you know software to the screen and Then break it into smaller pieces. So we'll have an orange here We'll have our render window and on the render window will have you know that drawing or whatever we're rendering to the screen and Then above this maybe we'll have our you know our menu bar up here and maybe in yellow just for the just for the drawing here, maybe we'll have a Button there people will have a button here. We will have some drop-downs here You go out some drop-downs here All as different windows like sub windows and the advantage to this is a couple things one person Foremost is that cursor thing, you know if I click on this there's actually a way in you know X win to detect what window we're clicking on and that makes this super super easy And so that's what we're gonna take advantage of mostly But there are other advantages here as well like this hierarchy They could be of a lot of use for us in terms of how we're going to store all this information And so that's the plan for today And so what I really want to have let me just give an example really quick of well We're what I'm trying to do here in terms of these buttons. So just in this video I want to have two sets of buttons I want to have a Query button and for the query I want to be able to query things like the number of nodes in the model Things like the number of faces in the model Maybe we could have it have the number of or maybe like the centroid of the part Things that have to just do with general queries and Then I also want to have a View view buttons just to keep things simple for this short video. I want to have a beat from positive x y and z maybe from Negative x y and z You know those six options there. Maybe I want to have an isometric Option, maybe you can do a diametric option. There's different ways you can view things Maybe you want to change the perspective, you know, for right now, we're doing a orthogonal transformation Maybe you want to do a perspective or the gone all Perspective whatever, you know, maybe you want to do any of those different ones. Maybe you want to change that It's your options. It's kind of what I want to do today in this videos I have drop-downs and then have each of these things be usually exotic, you know things you click on Correspond to a function. So this we already have a function to count the nodes You have a function to count the faces probably not going to do this one just to keep it short These will have to code up changing the view But basically if you can look at this really quickly These functions here require the body as an input, you know, they require The body structure as an input to these functions These don't these functions down here. We're looking at you know about the view they require like You know the look at and the look from and different types of characteristics of our of our view frame access To in order to to render like, you know, these things as a useful reason to be different inputs And so in order to have different inputs, we'll have to use obviously function pointers to refer to these functions And on each button But we're also going to have to figure out a way that we can prototype these in C to you know Either be a body function or to be a I don't know if a view function So we'll have to address that in a few minutes. So just to get started really quick You only have to change a few files We have to change the main function and the to draw function of the to the true Draw files. So the draw header and the draw C file in the main File I just want to change our test case a little bit. I don't want to work with this hotter balloon anymore I want to work with just one of our primitives here cube and then we actually have a function for this we have a make Rectangular prism and we pass in some parameters here I think you pass in the the first coordinate and zero point five. I would have a unit Unit cube here. So everything's going to be a size side of one length a side of the one and then It'll be centered on zero zero here with this these inputs Okay, then look at and look from keep it simple. I'm just gonna change this to zero zero zero one one one Oh One more thing this reticular prism is not triangulated. It's just going to be a bunch of square faces. So Thankfully, we have a function for that. We just have triangulate body Cube done that makes triangles of the body At this point, we'll keep this draw style. We'll keep this draw body. You just got to change balloon to Cube So that's good. Now we can edit the draw dot H Header to enjoy each header. I want to do a couple things actually only only two things I want to create a structure for these many buttons. So many button like that And name as many button we have a bunch of parameters for each but as you would expect each button has a length and a width So we'll look at the ins. We'll say int length if I can spell int width Now I want to be able to store them, you know in certain positions So they need length and width also need a location in space. So I'm going to store in DX and dy These are going to be distances from their parent element. So this blue this blue, you know Rectangle is at zero zero on the yellow rectangle and this same in one is that I don't know like 50 zero on the yellow rectangle. So that's like where it is on the parent element DX and dy in pixels now I want to store in Not how many children there are so we'll say num sub buttons. So for example this teal Button has three sub buttons and same with the salmon one has three purple purple buttons. We also want to have a Well, you could put this as a bull, but I'm gonna put it as an int because I was having trouble earlier today making this kind of stuff work with With not aligned Data types, so I'm just gonna give everything an int if I can so int show Children I should work and Then now we need to be able to sort a couple different things first is an X text item I'll thought about this a little bit later. Basically, this is how we're going to store The text so where it says queer your count nodes or count faces or change view that'll be sorted in a text item And X actually provides this for us the X Lib. Oh speaking of X that I have to include X Live because we're gonna be referring to an X text item. So we'll say I include X11 X Lib. H. I think that's right X text item text item sure will also need a couple more things will need the window because obviously these are all gonna window That's the whole point of this was making them all a window. So we'll store the window And now we need what's called the graphics context These are basically ways you can store like the colors of different things So you want this to be you know gray like up here and different types of font color different border colors, whatever You could put those in a graphics context. So we'll have a couple of those will have graphics context for the fill and we'll have a kindness for the Border or that board and one for the font Now comes through the actual functions. So like the the callbacks or whatever the function pointers and for that There's two different options here We can have a function that takes in a body or functions that take in these other Parameters here. We don't need to even need this just goes to and for that We have to actually use a union. I've never used that before in my life, but now it's a good time to start using a union Basically you need to stores two different types of values in the same memory location So we need two different types of functions here. They're going to be just function pointers They're going to return void and we need a body function that takes in like I said before a struct body And then we need a view function That takes in I Guess just those there's a three Element floats two of them. So it's a float three Look one being look at one being a look from And what else I guess we have to name something we'll call that funk and Oh Obviously, we don't know which one we're using so for any given button We have to know whether or not it's going to be a body function to pass in the body Or a view function to pass in the view so we have to store that here So I'll say int which funk that'll be just one or two if it's one It's this one and two of it's this one and lastly the last day I want to store in the structure is the the children so we'll say struct menu button Sub-button so this will be an array of pointers to the other buttons that are children of this of this given parent button So the blue one has will have three elements and they'll all be in this array So that's that for this. We've we've finished our header file. Now. Let's go to our draw dot see now this one Couple things to change in this one We'll put all our functions right here so we can we can reference them So the first function we need to create is a function that returns a menu button just like a constructor So I'll be struct menu button pointer it'll return a pointer to the button. We'll call it create menu button And we'll pass in all the parameters. I just mentioned So let's see we need int width in Get rid of that for a second. I need that right now int width in tight into DX int dy We need a couple of RGB values and we have this function from last time that stores You know in one inch these RGB coordinates So we'll say int our our GB background Int RGB border Int our RGB Now we'll need some ints for the whether or not, you know, we're storing the buttons and how many we have so known sub buttons how many buttons Int show children Recall then we had Now for the X text, I don't we have to give it a careray of text and they have to tell it how many Is it an inch? I think it's an inch in cares It's how many characters are in this character array I'll get into how that works in a little bit and then we Also have a font so font I'll talk about that again later This is pretty challenging actually, but it's actually easy to implement the hard to understand what's going on I'll get into that in a minute and then we also need to pass in the display to know where we're putting this on the screen so the display pointer and disc and then a Window for what window it is the parent window and Lastly we'll need those function pointers. So we'll say int which funk and then Was it void? I guess I've done this before but it's kind of hard to remember what's going on when I do it, you know live so in here we have to first malloc the Amount of space and you have to pop away all these All like the fields in that structure. So I'll do that off camera and I'll be back in a few minutes Okay, I did most of it just to show what I did really quick. This is the malloc first off There's seven ince one text item one window three graphics context one void pointer That's to the to the function and then this number of sub buttons times pointers to the sub button So the chummy children buttons are there. So it's gonna vary the suffrage button. We create different different size of the structure So then I just have the obviously all the ince defined here with height dx dy sub buttons Which funk then the text item so text item is pretty much what we're gonna draw like we're on top of the So that we have text and characters and then a font. I'll talk about that font later We store that in a window. We create simple window This is actually making the window at the x and dy from the parent window with width and height this foreground and background color And then we have these graphics context for the font the border and the fill Create with x set foreground to use that to create the actual color So we have RGB font border and background as inputs put those in the structure and then return the The button last thing here is the actual function itself like the the callback or whatever you want to call it like the Function pointer that was gonna execute when we click on a button So that's gonna vary so based off which what value we have for which function this function pointer will have a different different value So we could say if Which funk is one Then menu button funk What is it body funk? Equals funk so basically we're saying this input function here Which is a void pointer to this input function this that this uh, yeah this funk input function here That will be stored in the in the unit we have called function in data structure in the body function element of that union So that's how that will work then if it's not one so else if Which funk equals to Then we have a menu Funk View funk equals funk So it's the different table to type and then lastly if there's no no function I guess we'll probably store null. So we'll say if else we'll say menu button funk and This you pick either one. It's it's the same memory address. So body funk equals null This basically tells us Which function to use in the you know in the actual button when we click on it This will give us you know this function in in this prototype versus this prototype because there's different parameters if you recall This one takes in a body as an input this one takes in two sets of floats So that's why we have that so that should be good for this this structure except for one last thing I didn't do We want one more helper function over here and that will be a Avoid function populate sub Buttons because I didn't set those up yet. So I want to make that server function. So I'll play some buttons as input We will take the structure to populate. So structure menu button menu button and Inputs will just pass in an array. So struct and you button sub buttons array and this function We'll just have to loop over and then fill this out. So we'll say for int I equals zero I less than menu button sub buttons and we will Just fill this out menu button sub buttons I equals sub That's good, and I'm just return I guess just for For fun. Okay, so that's that that's sort of everything you have to do just to populate these these menu buttons and then create them now the question is What are we creating like how do we? Set up this kind of a structure here. We have to be able to pass in values So we'll make a function for that and that will be sort of like I Guess we'll call it We're trying to structure to return a structure to like the the parent so we'll say struct menu button and we'll call this populate menu items and It will take you just a couple things as a parameter Just because we need just from the top level down and we have to pass through if you recall We have to pass in display and window here. So we'll pass in display and window here. So we'll display I believe that's a pointer and And Window win and then we'll pass in a font again. I'll talk about that in a second Just keep you bear with me for a few minutes. We'll set this all up So in here I'm just gonna take a few minutes aside and put this stuff in I'll explain what I did after I finished Okay, I'll see you in a few Okay, this should work. So basically I have I Call create menu button on a few things first things first. Let me show the drawing again I call it for the main menu. That's the yellow one that I'm calling it for the query button That's gonna be blue and the view button. That's gonna be the salmon color I'm passing in obviously the coordinates and length and the width in space Okay, no problem I'm passing in these colors this color here is is actually like a light gray Kind of like the one in the like the paint software here black and black for the border and the font The main menu is gonna have no words on it zero letters But the other two are gonna say query and view respectively. This is how many letters in each font display parent window. Oh You know what? That's not gonna matter actually, but this should this could be the menu window I'll I'll might go look at that later. That might be important if not Maybe change I'll take a look later at that. There's no there's no functions for these There's no like callback for those functions Then we're passing it into populate sub buttons in so in order to you fill those these two buttons into the main menu Then we repeat again with the sub buttons So here we have account nodes account faces that those will be in this the teal button query button So we'll have a count node account face option and then in the same an option will have these functions here will have a View from positive x positive y positive z negative x I forgot to change those Change those now. Good. Then I caught that negative y negative z and then isometric and so basically It's the same thing again. I'm just calling with it with function pointers like to each of those functions now the functions that I just created for this are Here so these are like this is how you make a function pointer with different input parameters So this is with the view functions so we can create a like these functions here as a In this way, however, we have to be able to Decreate these first off so these have to be declared above and then you can do this by passing the address to the function Into like this kind of a pointer. We have this for both the view functions and also the body functions So let's go above and let's make those Let's make those functions that we never calling so the first function to call is very simple. It's gonna be print node count that's the one I just called that takes input the struct body and Then it's simply it's going to print f something like query count nodes Equals percent d some spaces in here They could look nice And we'll simply call that function to be already made in a previous video We have something called count nodes pass in body and we're done Then we can return here. This is print nodes. What about print faces? Well, it's gonna be very different not close at all Print face count went print count faces Count faces Awesome now comes for the the view type stuff So this is gonna be a bit of a problem Let me just do the easy part first so We'll make some functions. Let me avoid functions again. So avoid view from positive x We'll take in floats Look at We'll pass a look from first. That's what makes more sense and look at in these functions Very simple. We just have to change the value in look from or this is a pointer It's pointing to the first element of look from so look from zero This is gonna be the x-coordinate where we're looking from obviously hold on Let me just do this x y and z obviously we're looking from positive x the x-coordinate is going to be Positive one and then these are gonna be zero and zero but now we need a way to Like recompute the look the look frame in a kind of like a modular way I don't have to program it in each one of these functions. So Let's make a new function here called recompute View frame and we'll pass in The same input so float look from size three float Look at size three And we'll create that above here and that will be another void So let's make that function So the logic here is going to be very much like logic from previously Let me let me go down and get that and this is actually a good opportunity to change something here. We go These these lines right here. This is largely what we have to do By computing the view frame axes once again We did this previously in our draw function, but we have to be able to recompute that whenever we click one of these Buttons obviously and so we have a u3 and you want I'm going to actually bring out you want to do for a reason So you won size three You too size three and so here's why I want to do this We because here's the actually there's actually a problem with what we did it before in it When the previous video we had a way to render to the screen in in a very orthogonal perspective in the orthogonal way where we didn't really care so much about the Where we're looking from and this algorithm that I put together for generating these look frames is this view frame axes it works for every combination of looking at something except exactly on the z-axis and And then we never had a problem with that up until now But because now we have these functions here that view on long the positive and negative z-axis We're gonna have to actually address this because this sort of functionality does not work If you're parallel with the z-axis, so we have to create a new type of new new logic here so the first thing we have to do is We'll say if So we'll say if it's not parallel So if if the x of my components of of u3, which is how we're looking are, you know non-zero, so we'll say you u3 0 or Where's the orbit? u3 1 so if either x or y components are non-zero we do the old thing This is the old thing that that works no problem with with the old the old stuff. However, if that's not the case We have to do something else and by the way, this is not going to work, of course because Stupid u3 1 is this u3 u1 1 is this u1 2 equals this u2 0 equals this u2 1 equals this And then u2 3 or 2 equals this Stupid, I hate that now else Very simple We have to just hard-coded an alternative for this because it's not going to compute these like cross products properly if we're if we're you know If we have parallel to the z-axis, so u1 is going to be Okay, so the u1 is actually which way it's right So I guess the best way to do this is just say that right is right So we'll say 1 0 0 is the coordinate for to the right 1 0 0 and the coordinate up you'd expect it's going to be 0 1 0 right however That's not quite right because we do have a u2 1 equals something and Then u2 2 equals 0 so basically we're going to hard-code that the right direction be the x-axis and at the up direction be the Z component the same the same number as the component It's going to be it's going to be a you know if we're if we're parallel with z z is going to be one direction So this will change sign and give us the right Oration for our view frame. I think u2 0 1 and 2 yet 0 u3 2 Zero yeah, that's right to me And actually now that we have this I can copy this down below You can just reuse this down below because that that did not work paste Okay, anyway, I'm going to go back I'm going to finish coding up these these different view from positive x positive y positive z routines and I'll be back in a few moments Okay, as you can see I Double this I copied this function a few times view from positive x at 1 0 0 now We have positive y which is 0 1 0 positive z which is 0 0 1 negative x is negative 1 0 0 negative y is 0 negative 1 0 Negative z is your 0 negative 1 and then lastly isometric is 1 1 1 very simple Then I went through and I realized that we could do one thing very easily if we use global variables We can actually make this function work a little bit better. So We were computing these you want you to and you three values like sort of float arrays in this function based off what we clicked here and in the drop-down menu and then we created this view frame for these coordinates and At this point we can set these values to you one new you you two new and you three new Which are what we use in the actual like a render loop? However, it's I said before if we do it in a global sense, it would be really nice So I'm gonna make a global variable for this and just use that so we'll say floats you one new three You two new three And you three new three Okay, that should be good now. I can actually go but go down here where we're Let me get rid of this white space or black space go down to where we're actually defining you you want to and You one you two and you three new and Comment that out because we don't need that anymore. See like this. Oh and over here if you look here GL front face Clockwise this was what we can mean in the previous video to render that hot air balloon But actually in in my implementation for the way we're making the software the The face loop is actually counterclockwise. So I'm gonna comment this out and put it counterclockwise Another I see that that's a good thing to change Well, I think it'll still work But just for the time being I want this to be accurate to what we're actually doing in this In this platform so counterclockwise is for the front face. That's fine And now comes the question is how we're gonna actually implement everything we just did in the actual draw body function and It's not really that hard. You can see we've changed our reframe access here as as before so We have our window here And you have a display and this window is our simple window This is our our big red window on the right that you can see Now we also would like though To break apart the render into a smaller window the smaller origin right now the render is in the red window We want the render to be in the orange window here. So to do that not hard I'm just gonna copy this again And we'll create a render window And it will be a member of the Window it'll be a child of the main window and The render window will it will start at 020 So we're gonna have 20 pixels of space You know for the yellow window here for the menu window and after 20 pixels will go right into the size of our Of our render, which will be a full width and then everything about 20 pixels in height The colors I don't think matter all that much. I think I'll just leave what it is I'm just gonna render over it. So it doesn't really make a difference and Honestly, I think that's like the biggest change to make in terms of that We do have to map that window. So where it says map window we have to map The render window to the display Render when and that store name is fine Okay, so I guess here's a good time to talk about the font so Now fonts work differently on different machines that the way we're going to work with it here in in like X win is that we're just going to load a query font and On my machine, there's like a billion fonts. You probably have the same fonts is made to be honest But you may not and so if you don't and it doesn't work you can you can change what we're gonna put in the quotes here But you know, honestly, it should just work out of the boxes is a very common problem We're going to use Lucida sans size 12, which is very very common So what you do is you create X font structure X font struct We'll call that font struct and we can Basically use that function dimension X load query font and The idea is that on display you can just query this font and you pass it in you can say fix I think fixed works, but it doesn't have every sort of it doesn't work for everything And it's also a fixed font size. So that will work on any machine, but for us, we're going to use Lucida Sans 12 So it's gonna look up the font and get everything about it from the machine And then we'll We'll just get the menu meant meant the menu buttons now. So we'll say struct menu button and while we'll call our Populate menu items and we'll pass in the parameters which were display window and Was it font I didn't remember If it is the font we pass in the font struct FID that gives us the idea of the font and then Last thing if you have to map that menu that menu window because here we've we've mapped the red window to the screen We've mapped the ornament of the screen. You can see we have to also map the yellow one over the screen So we'll say X map window this is the screen and We're gonna pass in menu button Window so the parents the first The first menu button window will be passed as the window to map here and now comes the actual rendering so We can actually render these main ones or out of the loop because they're not going to be in Overlapping this orange render render loop window So we can actually render these two out of a loop at least to begin with at least we should and so we'll say for int i equals zero i less than menu button Num sub buttons Plus plus so we're gonna loop over all the sub buttons in that in this big yellow container here Which is gonna be just two for us, but when we add more it will be you know five six seven or eight So we're gonna loop through and we're going to we're going to draw them this way So X map window display menu button sub buttons I Window So we're gonna map all the children basically like this So all the all the children are gonna have a pyramid map means make make appear basically So all the windows that corresponded the blue and the salmon are gonna appear just these two will appear and Now we have to actually draw on them because we just map the window, but we haven't drawn anything yet So we have to do X fill rectangle That will make through the background color. We have to do X Draw rectangle that will draw like the border and then we have to X draw text and that will draw the The actual like words so query and view to these boxes. So I'll do that and I'll be back in a minute Okay So I put these together We're filling a rectangle on display The window that corresponds to the the actual button that we're drawing We're gonna pass in the context for the fill the border and the font respectively Now the fill and the border are gonna start at zero zero, you know the top left of the box So stop here to start at the top left Now the width and height for the the background are going to be full You know width and height but the background for the border is going to be one pixel less because I want to be able to See the border on both sides And that's that's all that the matters for those two functions and then for the text draw text We're passing in the font color And we're gonna put it at 815 So we're gonna give it a little bit of space from the edges so we can actually kind of center the pitch center the words a little bit better in the in the boxes and Then pass the text item from the button and there's one text item. So that's all you have to do So honestly, that's that's it if we went it right now we would get the You would get the orange box yellow box obviously the red box the blue box and the salmon box We wouldn't get these green and purple ones yet. So those we have to actually do inside the The render loop So that's the plan now. I'm actually to copy this because that was gonna be very useful in a minute so let's let's go down into the render loop in here And so I'm gonna paste it here just for the time being but we have to do a few different things This is gonna kind of long. I'll do them right now, and I'll be back in a minute And I'll show you what I did be right back. Okay, I'll do this last part live because I think it's important. So I Won't allow you to be kind of different than what it is right now. So right now If we click anywhere on the screen it automatically goes into these events I want to break up the events by what we're clicking on so if we click on the render window I want to do the render events if they click on the the menu bar. I want to do the menu bar events. So Basically, I want to say I want to have an if statement here after this event. I want to break apart these events because of what kind of category there they are so I'll say if event X button sub window equals render window I guess That's that's it. Then we'll do these events here These are like kind of like scrolling in and out dragging the mouse Else We'll do these events. I just coded up and I will explain them in detail. So It's a very similar logic to what happened before. Let me just Show you so Basically, so if we're not on the render window and we are on the menu buttons I want to loop through the menu button. So loop through the You know the these on the list here in on the yellow bar Then we'll say If we've clicked on that particular button So that's what this line says here No, and it's a button press. So if we click on that particular window, then we can Look at if the window just showing already So if the children are already showing so if show children we're going to unmap those windows and Turn off show children, which is just a variable. We had to keep track of whether or not the We use these green bars and full bars are actually showing So that we set to zero and if those are not showing We map them. So we do show them we filled them like before we draw them like before we add text before and just draw To the screen those those objects. So when you click on the purple or click on this blue Button the green bars will come and go based off whether or not they're there or not So that's this that's very simple just a little bit of you know verbosity there and then The second part here is a little bit interesting So this is actually how we're going to go through the sub buttons. So you can see it was actually like a double loop here so we're looping through the the children I and J So we're looping so you put on this blue one and these green buttons are now showing now we're looping through these and we're seeing you know Uh what they do so basically Uh, if they have a function value to be one, that means they're a body function We can just execute that. So that's what this line here says execute the function Corresponding to the button that you clicked if it's the body function if it's a view function That means if this value here is two Then we're evaluating this view function function with those two parameters here look from and look at which are both floats of length three and then we're this here is just a little bit of um Little bit just of defining you want to be equal to the previous value Equal to the new value not the previous value. So we can kind of just keep things going and let it update in real time So that's good. Um, this should work. So basically now at this point This new logic here it it renders These green and purple bars if you click the blue and salmon bars And it also means that if you have if you click on these green and purple bars These functions are executed the ones that we encoded already in you know in that data structure So this is honestly i'm i'm sure this is not going to work. So we're going to have to go back and uh and fix this I think but i'll i'll i'll humor myself and uh, we'll uh Try to compile that. No, of course not. So what did I do wrong? I'll bear it back. I'll figure this out Okay, uh a few things Just a few things actually one one really bad thing and then a couple small things. So oops Oops, that's not right. Where is it? It's here So yeah, this needs to be the address of this text item Then um In this line here, I forgot to define the menu button that was just calling this function with nothing That was making a whole whole Fuss Then also up here I Kept the the word float in in this which does not does not work. I mean, so you can't do that. So Fix those and then lastly Looks like I called this a lamp this it's supposed to be height that's stupid. So yeah, no big deal. Um Let's see if it works now Okay, it's Doing something hold on. Let me see Okay, let's try again. Okay, so our render's now query works so Hold up So if I click query count nodes I get eight good count faces I got 12 good that that makes sense and then view I can view only two options. Why is that? Oh, I know why that is Uh, okay, hold on. Hold on. It's because I'm dumb. That's why This number should be seven. There we go. Copy and paste Actually hold on one more thing So let me show you what I changed. Um So this stupid thing here Swap buffers should be render window not the window because we changed the window that's rendering now It's the render window that's running up the not the full window now It's the orange frame not the red frame and also I like to change Uh this so the glx makes current so this is the current open gl context is now the render render window Not the regular window. Those two things made the rendering work And now I have to just comment out one thing debugging Where is it here and we're done Recompile Now it should all work. So query count nodes eight count faces 12 View here we go. I can view positive x positive y. Yep positive z negative x negative y negative z They're all the same except for negative z. You can see I screwed that one up and I coded up the Whatever and then isometric. So It's pretty nice, huh? And I kind of like how the the view menu stays open, you know, it's kind of cool how it just stays open Obviously, this is a problem, but uh, I kind of like how it stays open. So let's say you wanted to like Measure the area of a certain face. I could just say query, you know measure face area then click on a face and Face face a lot easier to happen to go through the stupid menu again You know, especially if it's a bunch of like drop downs like imagine it was like query face data face normal, you know Vector or whatever. So it would be a lot of work to keep going through. I kind of like how it stays open. That's kind of cool anyway, I Hope you enjoyed the video. I hope you learned something I just want to say one last thing this this video I looked for many many hours and days and even weeks trying to find a resource like this There is none there. There is none like I get all this information from this video just by reading the manual and it took me a very very long time so If you like this Then definitely like keep this link somewhere because this video is definitely a one of a kind resource that you're never going to find another one So anyway, thanks for watching