You don't need Generics in C

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
looks like we're live hello everyone and welcome to yet another recreational programming session let's make a little bit an announcement and officially start the stream as usual as usual and so let's wait for Discord right for very fast application uh uh live on Twitch and what are we doing today on Twitch at television website today we are writing asset manager for Mizer right so I'm going to give the link to where we doing all that twitch.tv/ and I'm going to Ping everyone who's interested in being pinged there we go the stream has officially started the stream has officially started today we continue working on visualizer which is music visualizer that we started to develop some time ago so I'm going to copy paste the link in the chat for beautiful people on Twitch and for beautiful people on YouTube it's going to be in the description right in the descript so uh it's a very simple idea right so essentially you have an application um uh which allows you to generate a pretty visualization of some music right so whatever music you want so let's actually start it up so this is how it looks like it greets you with Drag and Drop Music here right so this is how we supposed to work with it let's grab some music right so maybe this one right and as you can see it starts visualizing so it also has an interface uh right so you can actually jump to any point in music you can actually have several songs in here you can switch between them uh right in stuff like that and on the previous stream we edit an ability to actually go full screen right in case you just want visualization of particular music or put it on on the background or something like that right so and at some point you can press uh I think R and it will start start rendering the um MP4 video of that visualization for that music right we're not going to do the full thing because it it takes some time because it's a high quality video uh but you you get the idea right you get the idea that's basically Mizer right it's a music visualizer it's a music visualizer uh so uh on the previous stream we worked with a little bit of assets right so we worked with a little bit of assets specifically to add um icons right so essentially you can see in here there's a button for full screen and you when you hover over it it just like changes its icon and when I press it uh basically changes again so it switches between the states and stuff like that and um develop this particular thing was um it was okay right it was okay but it was a little bit difficult to use hot reloading feature right so our application does in fact support hot reloading features yes it is written in C in a native programming language but you still can hot reload things and by hot reloading I mean changing the behavior of the program without restarting the program yes it is not intrinsic to web applications it is not intrinsic to web applications you don't need a browser you don't need a dynamic language to be able to hot reload programs right it's a basic feature of any modern operating system right I know it's it's kind of weird it's it sounds kind of weird but it's been common knowledge for decades people just forgot about it isn't that contradicting to to itself right so common knowledge and people forgot about it I think it's these two statements are contradicting to each other but anyway uh right so it's been a common thing uh for decades right people just forgot about it people just forgot about it so I can actually demonstrate you right so we can go to the source code in here so we even have a table right so we even have a table uh for so-called accent so color accent is basically this bluish color right it's this bluish color uh I can change this entire thing to for example red right so as far as I know it's zero and then I can go and simply rebuild this entire thing and boom I didn't restart the application the application was not restarted but uh the accent the col accent has been changed and the the color was not safe in some sort of a text file I literally modified the source code C source code I modified C source code without restarting the application I reloaded the behavior you can do that so but it's a little bit difficult with uh assets right so specifically if I am about to add a new button with a new icon right what I'll have to do what I'll have to do so I have a special uh structure special G structure that uh stores the entire state of the application right so the way it works in the memory you have a chunk of memory that stores the state of the application right the whole state of the application then you have a chunk of memory that stores the code of the application that works on the data on the state of the application when you want to H reload something you unload the code you retain the data you retain the data but you only unload the code and load a new version of the code that works with the previous data if you change the schema of the data you still have to reload the whole application you still have to reload the whole application because the hot reloading feature does not work with the data it only reloads the code it doesn't reload the data so because of that uh right so if I want to add a new image in here I'll have to add uh a new field in here right specifically one of the buttons I would like to have in here or one of the elements that I would like to have in here is the control of the volume uh right and uh so what I'll have to do I'll have to add a new field into this structure uh volume um just a second volume image right and also for the texture of course uh right because we have an image and the texture so we can use that via the open gel all right and that will require the full reloading of the application and that is not convenient I want to be able to add new assets without uh having to reload everything without having to reload everything so and the way we load by the way is so in a plugin in it in a plugin in it so we just like call uh load that specific file by that specific path right so load that specific file by that specific path and uh so what I was thinking how we can solof that I was thinking how we can solve for that and I suppose the most logical solution would be to have some sort of a cache some sort of a like a cach asset manager I don't even know how to call that I suppose different people uh call that slightly differently uh right but essentially we can have uh some sort of a asset structure right it doesn't really matter what exactly it is right what it doesn't really matter what exactly it is uh we can Define it right before the plugin right so somewhere here uh and within the plug-in system we're going to have not aert asset right it's just uh you know um reflexes so maybe even assets because there are several of them so this is assets uh and essentially we can have um different methods for that specific class for that specific structure for example we can say asset image load and here we'll accept cep uh file path file path to the image that you want to load and this entire thing is going to return an image so how is that different from just loading the image well it's going to cat that specific path right so basically when you try to do asset load somewhere for the first time it will uh call the image load and then when you do that for the second time with the same path that was already loaded it is not going to load anything it will return you already cash thing so and the way you are supposed to use that right as the way I Envision Envision you're supposed to use that so let's actually find something like screen maybe texture I think I think texture is going to be better so in that case maybe we want to have something like texture 2D uh texture load right so full screen texture full screen texture and uh let me see so as you can see I want to I I want to try to draw a texture instead of call instead of using that field of the plugin I would do something like asset uh texture load right asset texture load and it will provide resources icons uh full screen PNG like literally like that uh when this thing is called for the first time of course it's going to be a little bit slower it's going to load the file but then on the next frame right so it's it's going to be called on each frame on the next frame is going to return that texture from a cache from a cache so and here is an interesting trick uh trick so every time we want to refer to um and assets we're going to be doing that through these kind of methods that cash everything uh right so and when you are about to uh reload the plugin so we have a pre- Reload we're going to have something like asset unload everything right before reloading the plugin before reloading the plugin we tell the asset manager unload everything you have in a cache right then the code reload itself and it starts to call into all of this you know asset uh things again and it loads new versions of everything and if it starts to call to a new asset that was not loaded before it's going to be loaded as well right so it sort of like refreshes the whole asset catalog right so this is basically how I see that and that way I'll will be able to add new icons and new buttons and stuff like that uh using hot reloading without reloading without restarting the whole application over and over again so I think that's actually kind of a interesting idea I think this is how it's done in game development at least this is what I heard game developers do uh right I'm not game developer myself I know nothing about like game development I only heard some rumors and stuff like that so but I think this is how you do that and uh since we sort of have this our own abstraction layer over the assets it doesn't really matter where the assets are coming from right so uh load texture right so where's the load texture let's find it load uh texture load I call it texture load for some reason okay so it doesn't really matter where they're coming from right so uh we here assume that it's coming from the file system but nothing stops us then later pack the entire resource folder the entire resource folder into like a single bundle like a web pack bundle right if I'm going to switch to to your Zoomer terminology right Zoomer web uh web terminology we're going to have like a sort of a bundle web pack bundle of all of the resources and then within that bundle we're going to have a map from this path ID to a sequence of bytes which is the uh the content of the file and that way we have everything compressed and packed into a single thing which uh makes it easier to ship to the end user or maybe we can bake the entire bundle into the executable so everything is within um the executable so it's like easier to to maintain so we don't have to deal with uh current working directory or anything like that uh right when we are in a development mode all of that is of course in the file system right because you want to be able to modify the file system and see the changes right away but when you're shipping that right in a release mode you can actually pack everything together right so similar to web pack right it's almost like a web pack for you Zoomers out there uh right so sounds good sounds Gucci sounds atama Gucci this is exactly what I want to implement today right so that's basically the topic for today's stream all right let's go ahead and do that so I think I'm going to just discard all of the changes that I've done uh so far I can even try to rebuild the entire thing and boom so it is back right it is back so uh let's go ahead uh and maybe introduce that magical magical asset manager uh right so uh plug where is the plug excuse me uh type Def struct and uh this is going to be assets um so how we going to go about that how we're going to go about that so obviously it's going to be some sort of um um associative array or something right I don't know how it's called yeah associative array so uh it would be nice to just have hash tables like you do in any modern programming language right but we are programming in c right so programming in c and because of that we can't just have uh we can't just have this kind of stuff right uh so medium so we obviously need to have things for images right so something like images uh right then we need to have things for textures right for textures do we need anything for sounds we managing sounds slightly differently so it doesn't really matter I I also want to actually store in the assets things like fonts right so uh I definitely want to store things like fonts uh right so then textures fonts and uh then we probably need shaders actually storing shaders in assets a good idea I think it is a good idea it will make it easier to just like work with them in the future right but the problem with shaders is that we may have several of them right so we may have like vertex Shader and fragment Shader um right so how we're going to store them and so to be fair like when you do load Shader right when you do load Shader okay so you provide like two of these things so the Shader actually has two IDs right so it has two IDs for the fragment and for the vertex it can be missing and stuff like that so maybe I'm not going to go into the shaders right away right so I'm not not not going to go into the shaders right away I'm going to stop at images textures and fonts right at images textures and fonts so uh let's go ahead and maybe create the structure for images right so this is going to be images and uh we're probably going to have have like items right so these are the items so I'm thinking about I want uh to have images as Dynamic array but at the same time um I want it to be like a hash table sort of speak if that makes any sense right so it will be kind of nice for that thing to be a hash table but that means that um this has to be something more than images right because we need to store the key somewhere right we need to store the key somewhere so maybe we need to have image key value or maybe image item but something right so maybe we need to have some sort of an additional structure an additional structure that stores the key right so there's going to be the key uh and the value itself which is the the image right so and essentially yeah there we go so and and in here you would have something like size t count and uh capacity right so something like this something like this right so you have a key you have a value and so on and so forth right so that way we can probably use uh di append the usual di append from knob that I like to use all the time so it's it's a very simple macro uh very simple macron so let's let me find where Noob is located so no a append so yeah there we go so it's a very simple macro that just um you know implements Dynamic Rays right that implements Dynamic array uh so it would be also nice to quickly find a thing within the images right so quickly find the thing within the images uh but can I make it a more a generic thing can I make it a more generic thing uh so probably not because one of the things one of the reasons why theend is generic is because it's a statement it doesn't return anything when you need to return something when you need to return something it's kind of difficult to make such macro right it's kind of difficult to make such macro so but we can create something like uh image uh images get by uh key right so maybe find right let's just call it find so and in here we accept the images and uh the key and what we can do in here we can just go ahead and find this entire thing linearly I know that all of the Cs students are literally shaking and crying right now because their Professor told them that you're not supposed to use linear arrays because they're slow uh right you're supposed to use hash tables you're supposed to use trees because that's what their Professor told them to use in these particular situations and the reason why this students trust their professors is because they paid huge amount of money to get this piece of paper so they can have a job uh in some mediocre company uh right and paid you know average salary right so they spend a lot of money so they can go into this elite club and that's why they're literally believing everything their Professor telling them and their Professor told them that you're not supposed to do things like that and uh partially I do agree with that state that it is slow right because it's linear uh right but we are not going for the speed right now we are not going for the speed right now we're just trying to implement something that will work right we are trying to implement something that will work and uh essentially if we write a code if we write a code uh that uses that specific interface and then at some point that code becomes slow we can just take whatever we have inside inside of this function and reimplement it using hash tables and the code that uses this interface doesn't have to be changed at all it doesn't have to be changed at all so we are consolidating the place where we have to make the changes to speed up this code it is fine that's what I'm saying it is fine I know that your professor told you that you're not supposed to do it like that right but we're making it so in the future it is super easy to to speed it up when it's actually needed when it's actually calm down everything's going to be fine just breathe I know that you spend a lot of money to get into University and your professor told you that you're not supposed to do it like that but Cal down this is just a random stream on the internet okay everything's going to be fine this her this code is not going to hurt you you're not going to support this code you not you don't even have to submit any requests just breathe everything's going to be fine yes we're going to be using linear algorithm um right because it's kind of weird how much um CS education radicalizes people right uh to the point that when they see a linear search they literally start shaking and crying and screaming right I do agree it is slow but right now it is fine and when it's not fine it's easy to fix it again right now it is fine but when it becomes not fine it is easy to fix it you get it you get it yeah all I pass three years of Union doing linear searches yeah what's funny is that the majority of situations you're going to be doing that anyway so but at the same time you need to know how in case of an emergency how to speed that thing up right so how to speed that thing up and we're definitely going to be using hash tables in here like 100% like I guarantee you because as we more and more different assets and stuff like that it's probably going to um um be slow especially considering that we're going to be calling this function on each frame right we're going to be calling this function on each frame furthermore we're probably going to precompute the hashes for the keys right we're probably going to precompute the hashes for the keys so you don't have to compute the hash of the string on each individual frame so essentially on each individual frame you you kind of know what kind of asset you want to query from the asset manager why not precompute the hash of that asset and instead of using um the string as the key use the hash as the key right and uh to make it work we'll probably will have to uh use a perfect hash table right so and since we know up front how many resources we have we can quite easily build a perfect hash you see what I'm talking about right so essentially uh once we get this thing to optimize as much as possible getting um an asset on each individual frame is going to be as fast as looking up um an element of an array by an index right if you have a perfect hash table and it's easy to build a perfect hash table in here because we know all of the keys up front we know all of the keys of front we can precompute their caches and stuff like that we can even autom made the entire process all right so we're going to do in here so we're going to just iterate this entire sh images uh count Plus+ I and uh so what we're going to do in here if strr CMP um so images items so this is going to be I we take key uh so this is the first thing and the key in here and if this thing is equal to zero we can right away uh right away just return the pointer to this entire thing right but we are returning like an image right so we're returning like an image so maybe we just have to do the value in here so we are returning the value and if we couldn't find anything we just return n right so we just return n just return [Music] n so yes yes yes similar thing with uh textur right so and I wonder how can I how can I uh basically generalize this entire interface I'm not sure if I can easily generalize it right because I want to have a similar thing for the textures right so I want to have a similar thing for the textures uh right so in here we're going to have a texture 2D so this is a texture item this is the texture item and this is the textures right so this is the textures and you basically repeat this entire stuff but for the textures uh but for the textures it would be kind of cool if I could just use macro right in here just turn this entire thing into a macro but then um the macro is supposed to return something right it's supposed to return something and you can't return things from macro you can't return things from macro and on top of that um so you can only use uh um string as a key you can only use a string as a key excuse me um so if I you want to use something else it's going to be a problem but let's actually not try to maybe generalize it too much let's not try to generalize it too much we can we can actually we can come up with a very interesting sort of function we can come up with a very interesting function so let's actually go back uh right so let's go back uh and we can um accept maybe pointer to the beginning of the items right so we accept the poin to the beginning of the items like to to here right where we starting to think in terms of like assembly we're going down to assembly uh so here we're going to just have that so uh let's actually think it like that so essentially you have uh items in here right and you have a poed to that so this is the items and we're passing this entire thing in here so what we need to be able to do we need to be able to actually get to the next item somehow to get to the next item we need to know the size of that item so we can pass that as a parameter as well item size you see we actually stripping off the types we're stripping off the types and we're talking about like actual sizes in bytes of the elements in memory right so because that that's the easiest way to write uh generic code in C uh right so once we know how to get to the next uh item we need to know how many items we have so let's actually pass items count right so it's a lot of different parameters but we're going to hide all of that behind other macros right so you will see you will see this is an interesting trick this is actually a very interesting trick um okay so we know the size of the item we know some other things and interestingly we can uh essentially um assume that the key is always going to be a string the key is always going to be the string so we know right we know uh how much space does the key take within the item we know how much space does the key take within the item it's eight bytes so we know that and because of that we know where to search for the value right where to search for the value and we know the size of the value because we know the size of the whole element and the size of the key so we can take the size of the whole element subtract the size of the whole key and we know the size of the value we know the size of the value so essentially this is enough information to actually find all of the necessary elements in here it's it's enough to find a specific image item it's enough to find the key it's enough to find the value regardless of the type of the value regardless of the type of the Val oh yeah there's also padding get Dam it okay but I mean here's an interesting thing uh key is 8 bytes so I'm pretty sure like whatever we have in there like you can just add eight bytes to the beginning of the item and you will get to the value maybe I mean we can pass an additional information for for the value but I mean is that yeah we'll need to think how uh how bad the entire thing is we can always pass the um item value of set if that's you know if that tials you fancy right so uh something like um item value of set and then when we call to this function we can always use ofet of right of certain thing so to take into account the padding and stuff like that is is that something better the the padding people in the chat can you see by the way what I'm doing in here so so the padding people in the chat what do you guys think is that a better solution so uh essentially we have the pointed to the beginning of the items the item size the item count all right we know uh that uh you know key starts at the beginning and then just to take into account the padding we're going to have item value of set just in case just in case uh Des used says uh padding is cringe I I agree with that I guess but it's needed on some platforms I suppose right is kind of required I heard there is this very scary platform platform where if you do unaligned reads and writes you're going to be slapped in a face really really hard to the point that you're going to be stripped off your CS degree and you will never be allowed to to work in in comp in in programming ever again these kind of platforms you know so anyway um yeah it is cringe but it is what it is uh so yes yes yes so on top of that uh we need to accept uh the key right so we also have to accept the key and uh that's basically it that is essentially it uh that is essentially it um so and we can say uh maybe we can call this entire thing not even images find but AO find so associative array find right AO find okay cool now uh so we can start basically copying this algorithm but uh accessing the array is using this information that we passed in here using this information so let's see how we can uh do that so we know how many items we have in here so it's pretty easy to organize the loop uh so this is going to be items count right so this is the items count there we go we organized the loop and at the end of the loop of course if we didn't find anything we have to put null in here there you go so uh then uh we need to access the E element we need to access the E element so we need to take the uh pointer to the beginning of the items right so where is my uh thingy in here so we take the pointer to the beginning of the items and we have to add I items to that specific thing but here is the interesting thing so we have to be very careful items is a void is a void and it is usually not allowed in C to do arithmetic like pointer arithmetic on voids because uh void doesn't store information about the elements right so it doesn't know how to properly upset usually it basically defaults to uh size of the element one but it's not recommended to do it like that so one of the things we want to do we want to cast this entire thing to a point to to the element with size of one BTE and th we're doing one bite pointer arithmetics right so uh by doing things like that we essentially uh you know located uh some sort of item in here right so now we know this is the pointer to the to the item right so uh we can even do something like uh pointer item um right so and what's interesting is that uh we know that the key the key is located at the very edge of the of the item right so the key is literally located somewhere here so let me actually replace this item uh to something like this right so here's the key one two ah God damn it it's actually two but yeah you get the idea so this is the the key what we can do what we can do now where am I uh we can cast this entire thing to const char star star and simply D reference this entire thing and we got the key which we can compare things with look at that look at that look at this expression this is how you write generic code in C templates who need templates just use pointer arithmetics now that's the peak of software you may not like that you may not like that but that's the peak software development anyway so uh items key item key let's actually called item key um so we can even probably um just split this into into like um separate things like for instance here uh I can do something like void star item there you go we located an item then uh we take this thing we cast it to this specific pointer and we do reference right so uh this is the item key and then we can have another thing which is item value right so this is going to be item value and uh item value is essentially we might as well maybe keep it as Char so it's easier to do arithmetics with this kind of stuff uh item value of set right so item value of Set uh and then since it's sort of like a yeah it's sort of like a point right and we store the value by value we can actually keep it like that right so we don't really have to don't have to do anything in here and that's basically it that is basically it if uh uh so Str Str CMP key and item key are equal to zero we found an item and we can just just return the item value there we go so we can just return the item value yeah and we don't even have to wrap this in parenthesis I suppose maybe this wrapping in parenthesis also is not particularly needed but it's not that much complicated than than this thing right it's just like we are working with the sizes of the elements ourselves we stripped off the type information and we're working with this stuff uh like like this which by the way quite often people make an argument that because of that c is slower than um languages like C++ and rust because in C++ and rust you have generics and templates and stuff like that and so the compiler knows more information about the types than for example in this specific case right so for example the size of the type uh here became a runtime value rather than a compile time value right so so you see the point right so uh in languages like rust and C++ this is the value that the compiler knows uh but in C it's a r time so it doesn't know because of that rust and C++ are uh you know faster than C on average or something like that but I wonder if uh you have a very aggressive C compiler can that aggressive C compiler in line so much stuff that it basically knows the size of this thing because the way you supposed to use this thing by the way the way you're supposed to use this thing uh you're supposed to create some sort of a macro right so you're supposed to um uh create some sort of a macro something like let's call it find right and in here you supposed to pass this images thing right so um it's going to be let's call it table uh and the key and you do a sock find you take table uh items right so you basically give it the pointer um then uh you can take the size of the item right size of uh items zero and uh then what you're supposed to do items count is going to be um so table count so this is how many items you have and then value of set you probably need to something like ofset off um and this is where it becomes kind of kind of painful right so but essentially you can probably do something like I forgot how to do a set of the problem with a set of is that you need to have a type right you need to have a type but there was a way to do that without a type uh but I forgot how to do that so I think I'm going to accept the type uh like this right now and um I'm going to fix that a little bit later so here you have to do the Valu so this is that and then you pass the key okay so that's besides the point that's besides the point how exactly you take the offset right so then you do find and then images uh then images and some sort of like a resources resources icons full screen PNG right so that will get expanded into this thing size of is known at compile time and since we have this hypothetical aggressive C compiler since it's known at compile time it will inline it and maybe evaluate something inside of this thing and still kind of know the size of the uh of the items and apply still apply some sort of a uh optimizations so this is what I was trying to say right so even though C uh C++ and rust compilers they do in fact know more about types uh at compile time if you have this hypothetical aggressive C compiler maybe it also knows enough at compile time and can achieve the same thing but I know personally uh it would be better if C just had some sort of a mechanism for generic functions right so the the same way for example ji implements them right it's just it's not even it's not even about performance it's about like ergonomics and convenience to use because this is not convenient to use like I don't care if there is a c compiler that makes this fast I literally don't give a if it if it could be as fast as in Rust I couldn't give a just make me make it less painful you know what I'm talking about right you know what I'm talking about it's just it's not about performance at this point anymore it's just like about ergonomics uh just check with GDOT well I mean to check it with GDOT I need to make it compilable this is not compilable yet so you know what I'm talking about um right so uh let me let me see so maybe one of the things we want to do I want to have um some sort of a playground where I could play with this entire thing but I'm not quite sure so so let me uh copy paste this entire stuff to uh maybe a so C A so C uh and this is what we're going to have in here so maybe here we're going to have an integer right so this is going to be int item this is the int items and this is in uh right so this is INS so we have a so value uh and here we can have um int find uh ins find uh right so and in here oh by the way since we kind of know the type uh since we kind of know the type we can have table items table items items table kind uh table count here it's ins value n key right ins value n key so what we want to do in here what we want to do in here I would like to maybe create ins and just populate it with something uh right so let's call it access something like this um now we probably want to include knob uh I think knob is located Inc knob Doh and I'm going to Define knob implementation right so this is the no implementation uh which allow me to append thing into that stuff right it would allow me toint things right so let's start iterating from 0 to 10 right so we're going to have something like this uh and uh I should be able to to int item I I um so when we already made the key a string God damn it all right so that means we need to have some sort of keys in in here con Char uh Keys uh what kind of keys we can have in here so let's say hello uh World F Bar uh Buzz your mom right okay so and uh that means that what we're going to be iterating in here we're going to be iterating from no array Len right no array link Keys uh right so let me actually try to print this entire thing uh keys I keys I all right so let's do clang o asok asok c let's just run it uh let's just run it so we for go the semicolon in here there we go so hello world F Barb M cool so now uh int item uh I I so the key in here is going to be uh let's keep it as integer the is going on emx keys I and uh the value is going to be I right so after that uh no di append no di append access I I so we're just copying this entire stuff in here just copying this entire stuff in here so maybe I'm build this entire thing with GDB uh right and then look at this uh thing from from the debugger right just to see because I don't want to print anything in here so it's going to be a sock and let me let me see so let's break at Main and let's run it right away and maybe run until here and we are ready to take a look at axis what do we have in axis so we have six of the things here are the items we can't really see all of them so maybe I want to do something like items uh D reference this entire thing but take exactly count of them uh and there we go here are all of the items that we can have in here you can just see them so there you go so hello world Fubar buz your mom 0 1 2 3 4 5 so here are all of the items in here so that's pretty cool isn't it I think that's pretty cool so uh the next thing we want to do we want to maybe take um you know think by a value right so let's do ins uh ins find we provide ACC do we provide XIs as by value yeah we do provide it by by value uh okay so we provided by value and what we're trying to find we're trying to find maybe F so this is going to be 0 1 two f is going to be two all right and we can even uh say the type we can even cast this entire thing to the type right so because because we know the type in here so we can make it a little bit more type safe isn't it cool I think it's pretty cool actually uh right so we can have a value in here uh and we can then have stuff like if value uh is equal to no uh right we can say print F could uh error could uh not find key s and this is going to be key and we can move this key to a separate variable so this is going to be key uh like so there we go and we can exit with non zero exit code uh right and then if everything is fine if everything is fine we can say uh something like this right so this is going to be key and this is going to be value that we manag to do reference and this entire thing is still um type safe and this entire thing is still type safe right so because we cast the corresponding types and stuff like that but we still have a generic algorithm that searches through all of that stuff okay good so let's try to compile this entire thing uh we're not going to run it uh right so it does not compile so implicit Declaration of ofet off okay so ofet off where it is located I think I have to include something to just have an access to or maybe I I did a walk it's it's actually single F okay so dyslexia freaking dyslexia okay uh it didn't really help all right uh this is because I have to provide the type of I uh int item all right so int item so that's what I have to do I have to provide the typle int item uh it's still inl declaration okay so I have to probably do SD dev then right so EST Dev or maybe SD Le estop usually includes SD def um no it's it's not enough so what about def then okay so def is like I thought for some reason for a longest time I thought that if you include it as Le it also kind of implies s Tod def was it not implying that like okay sure I mean I'm I'm not a c specialist right I don't really know much about C I'm sorry uh and let's actually try to run so everything seems to be compiling so can I just round this and and it's two look at it so yeah it's two so it's kind of cool actually right because now it doesn't really matter what kind of value what kind of type of value I have in here right so this code this code works with any of them because it doesn't work on the level of types right it doesn't work on a level of types uh it works on a level of offsets and stuff like that so speaking of aggressive optimizing C compiler right aggressive optimizing C compiler uh well I won't be be able to just copy paste it to go do because uh I need something from Noob uh let's actually try to command out this entire thing let's try to comment out this entire thing so Str Str CMP so we need string uh I'm going to copy paste uh stuff from knob uh so I can can copy paste all of that into good do not good do God bolt freaking God do good bolt and it's just like naming uh same um okay nope um all right so it's going to compile it's going to compile it's going to compile we'll see we'll see oh yeah so you need to have uh the init cap init the cap all right so implicit Declaration of NOA Lo okay so let's bring it there no a lock uh sure uh maybe it needs also assert just in case I'm going to put assert there as well uh just for you so um well assert it needs assert here as well go happy you're happy okay uh godbolt made by mad Godot my favorite C++ develop mad go I'm so sorry I'm so sorry uh so okay close close the sh compilation this failed to compile okay so what's wrong with that assert really so what what are you saying bra assert do H file not found am I web assembly clang who uses web assembly in 2023 bro uh so uh clang okay so let's let's use this one okay a sock find how can I know if this thing is aggressive enough or not how can I know that so okay I'm looking at the assembly but that doesn't doesn't really tell me that much doesn't really tell me that much uh add eight all right add eight so it adds eight but it's the size of the point um doing some stuff okay anyway uh so I'm kind of not in the mood of reading all of that and trying to comprehend it so I'm really sorry I could have actually why did I have to use um Godot by met Godot if I could use the the the debugger right so because I can do all of that in debugger and it could be actually more readable if you think about it right so it could be more readable right so let's give it a try so I'm going to break at this and there you go I can do contrl D can your Gadot do that can your Gadot do I don't think think anyway so um [Music] H but we don't yeah so for instance item size it uses roundtime value of item this was a good idea by the way this was a good idea I really like that because here this is straight up like a runtime value right so it didn't yeah and it also I didn't compile with any optimizations it does IM Mo and stuff right so I'm pretty sure we need to compile with all of the optimizations uh right so won't compile uh disable optimizations optimizations are already baked in into the executable right so optimizations is how the compiler arranged final instructions that going to be executed at CPU debugger does not uh reverse optimization by modifying the instructions that already generated by the comp it's not how it works right this is not imagine debugger when you run it analyzes your executable uh spots the patterns of the compiler and physically reverses them by undoing them in a sequence of instruct that would be actually hardcore right so it's this is not how it works uh right this is not how it works for sure uh anyway so let's actually try to enable uh a lot of optimizations um so and let's break uh a so find uh and let's run this into shisu and what okay so o oof oof oof oof all right uh so yeah we lost any resemblance of the original C I wait a second I think it literally like inlined holy it's in yeah it's entirely in lined yeah yeah God damn that's hardcore bro that's literally hardcore holy yeah pretty cool anyway so we have this thing so and and my point is that uh right so this thing um is generic but then with the right uh with the right macro rupper it still can stay uh type Save Right it still can stay type save right so it just automatically detects the size of the items it automatically detects the size of the value and everything uh so it's kind of close to how I do Dynamic Aras and maybe eventually I can turn this into like a hash table right so and if you want to Define your own hash table you probably need to do something like this uh right you need to do something like this so you can do a so find and if you want to add a new thing in here you just add it like that but we need a more convenient way to add an element element to this asso array right so we definitely need more convenient way of adding things because right now to add uh a new element you need to allocate this kind of thing on a stack right so this kind of thing on a stack and uh then do da a pant which is not particularly convenient so if we're going to have a macro that does that for us automatically so I want to be able to do something like a sock a pend where I can just do access uh keys I I that's what I want to be able to do um right and how can I even construct such macro how can I even construct such macro um oh by the way if I manage to somehow get rid of this thing I can make it more uh generic even but I'll have to think about it I have to think about it okay I've been doing all of that for almost an hour um so I would like to maybe make a small break and um refill my Capa tea and after a small break we're going to continue experimenting with this thing I know okay so I'm going to say at a front I could have just taken implementation of uh hash table from stb I could have just done that but I kind of want you to experiment with this kind of thing right uh so if anyone just wants a hash table in C you can just grab this thing right it's a like a ready to use implementation of hashtable Inc it's sbds and it also has Dynamic array implementation and stuff like that so I'm going to copy paste it in the chat and for people on YouTube uh is going to be here as well right so you can just use that uh and what's funny is that that Library does that like roughly under the hood it makes a couple of different technical decisions but roughly it does that so specifically what it does differently it stores its meta information about like item size item of set and stuff like that in a hidden header right before the beginning of the array so it kind of abstracts that away from you I I don't like that for a number of reasons primarily because it's hides a lot of technical details from the user of the API uh right so it's just like tries to hide this header and it's just like I don't particularly like it I like when everything is exposed and it's clear how this entire thing works even though it might be not particularly convenient all the time uh right and on top of that I would like to just explore this thing myself just explore this thing myself because it's kind of fun right so uh I'm into this computer science and lowlevel things and so uh you are because you're watching the stream so yeah why not explore because it's kind of fun uh like you know manipulating bits and then watching how that works in a debugger it's kind of interesting right so I think I think it's kind of interesting so anyway uh let's make a small break uh I'm going to refill my cup of tea and we're going to get back to this entire thing and see what we can do um all right so um one of the things I want to do I want to find a way to supply just the value in offset of except of the except the type instead of type Jesus Christ uh so in here uh the documentation says that you have to supply the type right so it has to be uh some sort of a port type and everything and what I want to be able to do I want to be able to say bruh accept the this thing right accept this thing so maybe it would be better to maybe do something like this uh right so we can see each an individual uh each and individual thing in here my neighbors are screaming like crazy right now uh probably because I live in Russia so that's why animals I swear to God anyway uh so uh I want to be able to do this kind stuff right so I want to be able to this to do this kind of stuff so here I probably want to also uh you know wrap it around because you never know how many tokens are going to be supplied in here right so here's an interesting sort of like a rule of thumb uh when you write in a macro don't think about arguments as values think about them as an array of tokens that going to be expanded in here right you don't know how many tokens key is going to become right and one of the tokens in the key could be uh comma maybe well I mean you can't really pass a comma in here without like um making syntactical um syntactical error of expanding a macro but I mean you never know what kind of you're going to haveen here but I mean maybe that's fine so this is one of the reasons why I put this thing in parenthesis as well because you don't you never know how many tokens this thing is going to be uh right yeah you you can pass it if you put parenthesis in here yeah so you can do something like that right and it can screw up things I suppose but can it I don't know but it's just like a you know uh percussion I basically do that as a habit just in case percussion right um okay so you can't really do that right so you can't put a value in here this is not a thing that you can uh actually do right so if I try to compile this and I think it's going to complain uh right so implicit Declaration of a sooka pent well uh this does not exist that's fine so in find and within this thing it complains about this thing being a value so one other way we can um solve that right so I want to find the offset of value so you can always take the pointer to the value right so essentially uh you have an element uh you have a key uh you have a value and here is the element um if you take a pointer to a value you get a pointer to here uh if you take a pointer to the element itself to just the element itself you get the poter to here well technically if both of them were pointers to character pointers to character you could have just like um subtract one from another and that would have been your no talking about right so uh uh so people suggesting uh to use things like type off but the question is is type off a standard thing of set off is a standard thing type off uh right so as far as I know in majority of the situation it is extension uh c23 are you a rust developer you sound like a rust developer you know why because it's fixed and nightly oh I swear to God uh every time I use rust I quite often encounter some sort of like mild inconvenience and you guess what it's already fixed and nightly and it's been like that for like 5 years for 5 years I occasionally try to use rust I encounter some mild inconvenience and you guess what was the response of the RAS developers that's fixed and nightly that and it never changes it's like five years same it's insane how consistent it is uh would you like it not to be fixed at all yeah that that's kind of interesting just like C right in C it's always inconvenient and it's never fixed I can't use that so let's continue um can we do it like that um well I mean we can probably just like put this in here and we never have to know the type of this entire stuff right so we never have to know it boom so this we can even say this is a sock find and this is sort of like an internal implementation uh right some sort of an internal implementation that uh you know has underscore in its name uh right so yeah so and this is a macro that sort of like extracts all of this necessary information right extracts all this information basically this macro does the job of the compiler this is what the compiler is supposed to do for me but for some freaking reason I have to do that myself anyways um so that's pretty cool so uh we can do a so find uh and maybe yeah let's actually try to recompile this en thing and try to run it uh and it seems to be working so I think I think that's a reasonable way to compute offset right since uh it's behind the macro anyway it doesn't really matter that it's so weird and so big and stuff like that because it's behind the macro anyway right so no no nobody's going to see that right so we just tucked it away so don't think about it too much um right so and yeah so now this entire thing works and um I can now even have a thing uh that replaces ins with floats right so now I can use floats in here if I want to um right so it can be repl like so so this is float um I don't really have to do like that so I want to make it in and here we're I'm going to just discussed it to float uh and this is going to be float and when I'm printing this entire thing uh I'm going to be printing float so yeah it doesn't really matter so it it really doesn't care about the type it only cares about this specific definition right people quite often uh ask me right like why um I like to Define this kind of structures manually why I like to Define this kind of structure manually and why didn't I create some sort of a uh template instantiator right so where I would say Okay Define uh you know a sock uh where I would have a type and here I would have like the type then the type something something and stuff like that and this is because um I want this thing to be duck typy duck typy right for instance um um I want uh to be able to say okay this is not ins anymore this is samples and this thing now also contains some additional things like for example file path where I save all of that right but since this thing still contains all of the fields those macros expect it still acts like ative array you know what I'm talking about right so the thing about this macro is that they expect a very specific set of fields and they don't care if we have more Fields so it's sort of like a dock typing and that's why I Define them manually because maybe I I will want to add more fields in there for some other things right so one thing could be several things simultaneously this thing is simultaneously associative array and dynamic array right you see so uh essentially I use a macro for dynamic arrays and then I use macro for associative arrays so this thing is sort of like it just like adapts depending on where you put it right it's duck typing you see what I mean does it make sense right that's why I just like explicitly like to Define it because I can explicitly control what kind of interfaces it conforms to if that makes any sense so I know it's a little bit more additional work but I kind of do that so just like a as a mental checklist or something I don't know it's kind of difficult to explain just like some sort of a preference that I have um uh so that's pretty cool uh so we have a sock and it's more or less generic but uh again I would like to have a sock a pent that doesn't require this kind of stuff but maybe that's fine maybe that's fine for this specific thing um and yeah I suppose that is basically it uh I can now copy paste this stuff to the plugin right uh so this is where we were doing all of these experimentations uh I can remove all of that uh so now we have this asso find uh we have images images item and we can quite easily work with all of that uh and also we may have textures um right we may have textures so this is probably going to be uh like image texture 2D boom uh and fonts right replace texture to D maybe like that font uhhuh it's going of be interesting interesting type so maybe I I should get rid of the 2D because if I remember correctly just texture is enough in the terminology of rip right I think it is enough in the terminology of rip so we have that so now we should be able to just work with all of that so do I have assets uh assets there we go uh and uh if I try to rebuild this entire thing what is going to okay so that build first try that buil first try uh so we want to have these sort of functions that allows to uh you know track like a query specific things all right so uh as asset um assets image um assets image let's just call it assets image so we're going to accept assets by a point we could actually uh but it kind of makes it difficult to to query right so if we're going to accept assets like that right so we always will have to call assets image with P assets and stuff like this and P is a global thing anyway so maybe we could make assets image to automatically extract the assets uh itself so this is something that probably makes sense I think I think it probably makes sense right so here we have something like con charart file path so that's fine so and essentially we can do assets uh assets images as so find we're trying to find the file path all right and that should give us the image so this is the image and what the is this if uh image is available we just return that image so we always return it right so we always return it if it's not available right so if it is equal to null what we have to do uh we have to uh load it somehow right but the word image is already taken right the word image is already taken maybe we have to do something else or maybe we can actually put that inside of the scope so we can reuse the word the name image uh right um so and just load image I just load image file path it can fail but it's fine in the context of rap so it kind of allows you to to load to to actually for this kind of operations to fail right so it's still kind of valid image it's just like not going to be displayed properly anyway right so so it's kind of fine so we load the image and the next thing we need to do we need to have image item all right so this is going to be the item and interestingly maybe it would make sense to actually do it like that uh right so item image and that freeze up the uh the name image so we can get rid of the scope it's kind of funny right so this is because I cannot plan things ahead right so I cannot simulate the code in my head I have to write it first and only then uh see that you can do do it like that right for example when I was writing this code uh like I didn't think that I can just do it like that and uh just use this name right I I had to first uh you know write it then go back and rewrite whatever I had before right so it's kind of interesting I I just personally find this kind of stuff interesting uh so key file path right and then we do Noob da append and we're just taking assets images uh right and we're appending the item uh but then we're just returning the the image that we loaded in here that's basically it I guess that's basically it so uh we are starting to have uh a little bit of a repetition again but in a form uh but in a case of the texture right so you could say that uh we do it like that so Qui replace image texture but with the texture it's a little bit more complicated right because uh you can't load there is no such thing as load texture right uh you can only load texture from image right so you first need to construct an image load an image and then turn it into texture it's kind of similar to uh surfaces and textures in sdl if you ever worked with sdl in sdl surface I think it's called surface right so yeah it is surface right it's a image in a CPU on a CPU on a ram but texture is on GPU so there is this kind of Distinction there is a CPU texture and there is a GPU texture you can construct a GPU texture from CPU texture the same thing in RP right so image is a CPU texture and um um texture is the GPU texture if you want to display it on the screen you have to first transfer it to GPU so uh and because of that so there's like a two we're going to have two layers of cache right to load the texture to take the assets as the texture we need to try to do assets image right assets image and uh there we go we've got an image we've got an image um so and then we'll have to constract the texture out of that but uh here's an interesting thing I think uh we'll first have to try to find a texture within the textures right so we have assets textures and if we found the texture we can just return it we just return the texture uh if we couldn't find it we have to create uh we have to query an image because maybe an image was already uh was already loaded so we can do um essentially assets image file path right so we get an image so this is an image then we create an item that so then we load it from an image so this becomes uh a value by the way I just realized that this has to be a value this has to be a value and then we append that to textures so this is how we essentially can do that right so texture doesn't load anything from a file right so it queries the image and image already loads this kind of thing um so yeah there we go there we go so and we probably want to maybe abstract this kind of stuff away right because we we're literally going to have repetition for fonts for instance right we literally going to have a repetition for fonts but maybe maybe I'm not going to do fonts right now but I already have the structure for fonts anyway let's try to compile this entire thing and see uh what kind of problems we have in here so this is the value uh what else do we have in here this is the value right there we go so for the fonts for the fonts uh it's literally as the images it's literally as the images um image uh actually image font [Music] mhm yeah so that should be it all right so uh I'm going to think about how to get rid of this duplication a little bit later right so I'm going to think how we can get rid of it later that should be basically it for now I think uh we can try to go uh we can try to go and uh get rid of all of this all of this stuff for instance uh fullcreen image full screen texture right so this is the um essentially the the assets that we're talking about font right so we should not have a font anymore uh I guess that's it right we don't really have that many assets anymore right but in the future I plan to have a lot of different assets right and that's why I want to have the asset manager so once I removed all of these things let's actually try to uh recompile this entire thing and let's let's see what's going on in here so here we're loading the font I'm going to yeah so this one is interesting because to load the font you also have to specify the size of the font and maybe that should become um the the key right so so far I was thinking about the key of the asset as just the string the path to the file where this entire thing stored but we also have different parameters with which like for example font can be rendered and everything so um yeah because of that maybe I'm going to remove the fonts from the asset management right now right I don't want to think about it too much right now uh right so let's just not have fonts and uh right so where is the font I'm going to bring it back mhm I'm going bring it back all right what else do we have in here so okay so as it's F so this thing is not a thing anymore uhhuh so that makes sense so we don't have to do that anymore so that doesn't exist and what else do we have in here okay so asset uh image uh actually texture texture and the texture that we need to load let me find the PATH just a second um yeah something weird is going on but yeah uh where is the plug in need so here is the path right so here is the path and um so this is what I have to put in here right so set texture filter ooh right so you also have additional parameters and stuff like that M but maybe that's fine I mean yeah damn so essentially we need to make the asset manager so you can have different parameters with which you sort of configure your asset and that is part of the key right right so and I couldn't see that up front either right so you can see the scope of the problem grows and grows and grows right uh so we can maybe move that set texture filter to um to the loader right so essentially asset uh texture um asset where where is the asset texture asset is it asset texture yeah SI texture um right when we are loading the texture right so maybe we want to set this thing but that means that everything that I load through the asset manager is going to have this bilinear filter but maybe that's fine maybe that's fine so let's just Implement something that is working at least right now uh write it in here asset texture uh right so I lost my path yet again and so here is the path uhhuh so here's the path and hopefully uh yeah so now it is compiling so we only have one asset essentially we only have one asset so yeah let's give it a try let's give it a try so this is going to build uh and what was it visualize them we go so probably want to to actually run it slightly differently usual and okay so it it's loading everything correctly so the reason why I want to be able to um to have this asset manager right for instance now uh I want to be able to add a completely new texture that I can render right so let's actually see if I can easily do that without restarting the application the application is still running right so the application is still running so now I can go to plug init and actually plug update right and at the end of this entire stuff so let's actually find a place where we want to do all of that stuff so we are currently uh rendering file dropped uh uhhuh so the the music is currently playing uh we handling some things in here we're not in a full screen okay so somewhere at the end in here somewhere at the end in here I want to be able to just draw a texture right so do we have a draw texture so draw texture Pro so this is tags uh right so somewhere in the resources somewhere in the resources I have icons not icons but logo right so this is the logo can I without restarting the application just start um you know rendering that logo can I just start rendering that logo I think I should be able to uh right so that should be something like this so this is going to be just assets texture assets texture and then I put this entire thing in here so now I have to also provide the rectangle so maybe I I picked a wrong draw texture I I think I need to pick the one that doesn't require too many parameters I think there was a simplified thing like that so let's go to Ray leap somewhere here Ray leap uh H R.H draw texture uh like this so this one is a little bit easier to to work with right I think I think so this is going to be zero this is going to be Zero The Tint is going to be white and that is it okay so I'm going to recompile my entire thing uh I didn't freaking this is not recompilation uh okay so I recompiled so it's still running and now it's it's rendering so essentially I didn't have to restart the application it's still running but I added a new asset to it before it was not possible without restarting the whole application right so because the assets were was not a dynamic catalog that I can just expand at run time now I can right so I can refer to the assets by its name and I can just like straight up render it uh it is slow it doesn't use the the hash table perer hash table but uh it will in the future right so it will in the future but right now it's it's fine so one of the things right now um that it doesn't support it doesn't reload the assets right so for instance I want to be able to all of a sudden start drawing a new thing and then modifying it and keep reloading it to be able to do this kind of thing by the way to be able to do this kind of thing I think we need to implement um an ability to unload everything right so let's do assets uh so we have image texture right so um let's do assets unload everything uh like so so and what we're going to do uh we're going to iterate through all the textures right so let's actually start with textures uh so it's going to be P assets uh textures uh right so this is going to be count Plus+ and let's just grab the uh items of this entire thing and uh the values so and there should be a thing unload texture I'm pretty sure there should something that unloads the texture there we go so we're just unloading all of the textures right so simply unloading all of the textures and then we can go and unload all of the images uh qu replace texture image boom right so we're unloading all of the images so and when we are about to reload right so look at that so we are about to reload the plugin we're going to go ahead and unload all of the assets which will clean up the entire cash which will force all of these SCS to assets texture reload everything from the hard drive that way we can even modify the um the assets and reload everything and have them updated so uh for example I will be able to modify icons and instantly see how the icons look like in the application without ever reloading this entire thing so it's going to feel like like a legit engine a legit game engine right so this is actually kind of cool this is like this is basically the dream that I had since this starting this project being able to just like hotload literally everything but I mean there's still some things that you can can't hot reload but 99% of the things are going to be hot reloadable in here for sure uh right so um let me let me see uh I I forgot to do another thing in here so after we unloaded all of these resources we have to set the count to zero right so to indicate that we can reuse this allocated space uh right so let's try to recompile this entire thing so uh valuse it's just a it's just a value all right so that should be fine uh unload everything so we unload everything in here okay so uh let me try to yeah let me try to run that let me try to run that uhuh so we're going to uh put some music in here okay so I'm going to put it in the background right so this is what we have right now I'm going to try to go through this use case that I already demonstrated right uh so full screen um full screen button so here is the full screen uh right all of a sudden I decided to draw a texture I'm trying to draw a new texture that this application never saw before so I'm going to do assets texture um resources logo logo 256 PNG there we go I'm going to draw it at z0 with a tint white I'm recompiling the entire thing and boom it is available now I don't like the color of the logo I don't like the color of the logo so I'm going to go into resources uh uh and here's the logo okay so I do have SVG in here so I'm going to open it in inkscape right so I'm open it in in inkscape all right that's cool so maybe I can uh just change the background a little bit so because it's a little bit too too harsh so how about making it something like like this I think that's a little bit better okay so let's take a look at the color of this entire thing so F uh this is a gradient if I'm not mistaken so what if I change this gradient to sort of like a redish thing the application is still running by the way this entire thing is still running uh I'm going to save this entire thing and I'm going to recompile the logo specifically so as far as I know no has logo right I'm recompiling this entire thing and uh here's the application still running and I just modified it so I can tweak things around uh for instance I don't like the fact that it's facing one way can I actually um you know change it and face it the other way uh like so right so then I recompile this entire thing the application is still running by the way the application is still running I can modify this entire stuff so and I keep adding new things and stuff like that funny enough now uh I can go and remove this draw call remove this draw call I probably have to rebuild everything uh right and I can hot reload and now this entire thing disappeared and in fact this logo even disappeared from the memory because when we hot reload we unload all of the resources so we unloaded all the resources and we know never loaded that thing again so it's fine right so now every time I need to add new resources I never have to actually reload this entire thing right I never have to actually reload this I think I can just work with that so icons like we have some icons in here I can start working with icons so uh let me see so I have some resources uh so here are the icons here are the icons I can go open them in inkscape um all right so we have these kind of things and maybe I don't like how this entire thing looks like so uh right I can I don't even know what I can do maybe for this specific specific thing I would like to make these Corners a little bit more rounded like so for whatever freaking reason right so maybe I just like how that looks like when they're rounded so I'm going to keep them rounded specifically for that spe uh for that case right I'm going to save that uh also I'll have to reconvert uh this entire thing so background non full non full screen SG full screen PNG I probably need to add it to the build tool but I mean it doesn't really matter right and now the application is still running the application is still running but now uh it has this rounded Corners right so I never have to rebuild anything I can just modify things and reload everything and all of that in purc right so and this is because of this asset manager and this asset manager is actually very dumb and very simple right it's just associative array right it's just associative array it would be again better if it was like a hash table but it doesn't really have to right when it becomes uh too much of a problem when we have like too many things uh we can turn it into a hash table right now it's SS for in fact we don't when we turn it into associative array we probably never have to modify any of the places where we call to assets texture right we never have to modify this place maybe a little bit maybe tiny bit but not too much uh right so Isn't that cool chat Isn't that cool so yeah we introduced like asset manager and now uh I don't have to restart the whole application when I just want to add a new asset stuff so it's still there are some limitations with this kind of thing because some of the assets when you load them they require some additional PR parameters like for example with a font uh right so when you load font uh you also have a font size and this is because I suppose rayap sort of like generates an atlas uh it generates an atlas and uh sort of bakes the specific sort of resolution of the font um right so that's basically what's going on in here and we need to come up with the asset manager that takes this kind of stuff into account as well right so basically add that to the key of the asset somehow uh but that's kind of outside of the scope of the today's stream right so it's kind of outside of the scope of the today's stream we spent like two hours working on this entire stuff but I think it was worth I think it was interesting wasn't it uh draw texture now I can so I it's it's drawing logo yet again so let me see if I uh recompile the whole thing in here uh right it is going to render this thing again yeah and by the way since I I keep that SVG right so I store all of the assets that I modify here in SVG uh I can revert the changes quite easily right then recompile the logo just recompile the logo and then reload this entire thing and the logo is back to be normal right so and logo is back to be and all of that is without restarting the application and it's not a dynamic language like C or Java or JavaScript God forbid right it's C it's that scary language that memes already told you not to learn because it's old and scary and unsafe oh my God this is kind of the you can do in it it's just like that's what we can do it's easy peasy is crazy what wow never thought you can read data from files and see exactly people didn't know that people thought that you need to have like uh multi-billion dollar Corporation and huge team of phds to create a r time that is capable of reading data from a file system people didn't know that you can just do that and see it's just like what the all right uh I guess that's it for day thanks everyone who's watching right now I really appreciate that have a good one and I see you all on the next recreational programming session with a all right love you [Music] all
Info
Channel: Tsoding Daily
Views: 58,555
Rating: undefined out of 5
Keywords:
Id: o94JcrQThaM
Channel Id: undefined
Length: 97min 38sec (5858 seconds)
Published: Fri Dec 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.