Juce Tutorial 34- Animating Components Pt 1 w/ guest MatkatMusic

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey folks welcome to another developer blog video I want to give a shout out to the audio programmer for the opportunity to do this guest post on his channel this video I'm gonna be talking about how to do certain types of animation and you can put in your project so let's say you say you you know you finished your GUI and whatnot and it's just very static like you can move your knobs and whatnot but it doesn't do anything other than that so what we want to make happen is you know give a little interactivity when you mouse over stuff so you know when you when you mouse over button and it you know like a little halo highlights around it or something like that that's what we're gonna try to do here we're gonna do something similar to that and there are two different approaches you can use to get this functionality to happen in your application and I'm gonna talk about the first approach that I've found is pretty effective in this video in another video I'll demonstrate the second approach all right without further ado let's dig in as we did in the previous video we're gonna start with our we're gonna start with our sandbox project we're gonna make a new branch from the master branch this way we have a clean slate to start our you know little test projects from now let's dig into this okay we're on our animated component alright now let's pretend we have like some kind of animated component like a little button or whatever and when we mouse over it when our mouse interacts with it some kind of graphical animation happens with some kind maybe a little there's like a little shadow that slowly appears and then when you your mouse cursor leaves it this shadow kind of fades away so let's you know set up our our project thusly all right we're gonna make a struct it's going to be called animated component alright it's gonna just subclass I chose a struct because I want everything to be public for right now I don't want to have to deal with public or private member getters and setters and all that nonsense just yet this is gonna be nice and simple so first things first let's just you know get it on the screen making it look like it's something okay so to do that we need to override our paint method and let's implement that avoid animated component paint parameter to operate on all right so first thing we need to do is G dot fill all and we use colors white we want a white background and we're going to draw a just a rectangle around it all right G dot set color colors black and then g dot draw rect just so we know where we are on the screen get local bounds all right now we're not gonna see it until it's actually like added as a child somewhere so let's add it here I'll make a child animated component comp all right we're gonna add it as a child here and and make visible comp and then we'll set the position comp dot set bounds get local bounds with size keeping Center will do 400 by 300 all right now if we run this we're gonna see just a white rectangle with that we're gonna see like I'd yeah just a white rectangle with a black bar around it I'm gonna get rid of this fill all and there we go all right awesome okay so the next step is to figure out our intended behavior now what we want to have happen is when the mouse cursor goes within the bounds of the component we want some kind of animation to happen for this example I'm just gonna make it have some kind of color change slowly happen so in order to do that first we have to detect when the mouse cursor goes into the bounds of our components so to do that we need to override Mouse enter Mouse event and we need to you know if we want that effect to disappear when our mouse we need to have the event disappear we need to have the effect go away when the mouse leaves the bounds of the component all right so exit override okay so let's just get those two things to happen all right and just to demonstrate this behavior will just make it say we'll just make it say this keep an eye down here all right okay so now we know that our mouse messages are showing up in the right place now the there are two ways to accomplish this that I know of that work pretty well I'm sure there are others so I'm gonna explain the first one and talk about what what happens so the first thing that we want to have happen just to demonstrate what's going on and kind of give you an idea of how you can use your mouse events to propagate changes first of all make them call repaint at the end and then you know change some property like let's say we want the color to be drawn to be a different color okay so we'll add a color background color right like that and we'll set it to alpha all the way up and we'll just make it red right so we did alpha at max level red at max level RGB so this is green is zero and blue is zero like that okay so now what we can do we can say when the mouse enters we're gonna change what background color becomes all right background oh they're equals color all right we'll make it we'll make it blue we'll do that okay so 0x full alpha no red no green full blue and then the mouse exits we change it back for full alpha full red no green no blue all right and our fill all is going to be background color okay let's run that let's check it out all right so it's red and then when our cursor goes into it it changes it a little like that now so what we want to have happen is when our cursor enters it we want it to slowly change from one of the other now how do we make that happen so one way to think about this is if you imagine something that's refreshing 60 times a second and that's not actually what happens here the computer says does this need to be repainted yes it does okay and then once it's done it just kind of it's not gonna repaint again until you tell it to repaint so that means we need to have some kind of way to get the computer to keep repaying the screen as long as we need it to keep repainting the screen all right I'm gonna introduce a little utility function class that we can use and what it does is it it's based off of the timer class and it lets us do it lets us use the the ability to call a lambda after a certain period of time if you're not familiar with what lambdas are they're just little anonymous functions that you can call whenever you need to and they don't have to be related to the class or whatever I'm sure there's gonna be a link in the description that points to the CPP reference com page explaining what lambdas are all right so here's our little class okay all right here's our guy right here this delayed one-shot lambda in that we're gonna just call the singular function a single time so the way this works is it's sub it's derived from the timer class so that lets us you know start a timer at a specific interval and we have a member that's our us it's a void function that takes no arguments so that what that basically means is you have a function that doesn't return anything and it takes no arguments okay this gets passed in as the argument this is the lambda that I was talking about it gets stored as it gets stored as the private member now what happens is you know say we set this to 500 basically a timer starts running 500 milliseconds later this timer gets called and what happens is the timer deletes itself via this code and then it executes the lambda that you passed in all right and when this executes or when this deletes itself it calls the destructor which calls stop timer so it stops responding okay the way this works is you do something like this you would type something like new delayed one-shot lambda 500 milliseconds later I want this thing to happen okay this is the lambda syntax there are variables that are going to be captured from the surrounding scope meaning like we could be capturing this e we could be capturing background we could be capturing the animated component itself here are our parameters and if you remember this is a std function with no parameters so this must be empty and then here's the actual body of the lambda so we're gonna capture this five 500 milliseconds after the mouse cursor goes into the component we're gonna see a debug message that says the bounds of our guy this actually we don't even need to do that because this is captured it becomes if all the functions and whatnot that exists on the this object are available to us so even though I could type this I don't need to I can just say get local bounds dot two string so let's check it out actually we'll make that one second okay we go there we go you see that do you see that delay is that one more time cursor and the bounds pop up all right so we have something that can be called at a later time over and over and over okay so let's take this to the next step all right let's say that what we need to have happen we need some kind of counter say we want this to appear like say say we want something to change its value over the course of 10 steps alright we're not sure how fast those steps are gonna happen we just know that it's going to take ten steps all right so we'll just do Const int num steps pulls ten actually I needed like this alright now what we'll do when the mouse cursor enters the function is we'll start some kind of one-shot lambda that's going to call another function that's going to increment the accounts all right so we'll just do void increment count all right that's gonna take some parameter like this it's gonna do int C for count like that so what we're gonna do is we're gonna do first we're gonna fire it off okay so the new delayed one-shot lambda will say well we're gonna do this every half a second and then our lambda it's gonna capture this has no parameters and it's going to call no it's gonna call increment this shows up here call this in cream in count starting value of zero okay now what's gonna happen when we increment count all right increment count is going to check whether or not the value we passed in is less than num steps okay we go like this we go void animated component increment count slowly building this up slowly building up our functionality we're gonna do if C is less than no steps okay the value we pass in is less than 10 then we're gonna do this again but with one added to see all right so we'll go c++ like that hey i make it easier to understand for those of you that don't post scriptum piece for prescript postfix and prefix operators okay we'll go like that that's gonna increment it and we go new delayed one-shot lambda okay 500 milliseconds later do the same thing we did before we're gonna capture this we're gonna capture see because if we don't once the value of C once this function finishes the this value is just not gonna exist in memory okay this has no our lambda has no arguments all right we're gonna call this increment count ste like that okay and what we want to do let's just make it say what our number is okay debug increment count like that okay so we're gonna see zero then we're gonna see one and two then three D button all the way until we get to ten all right let's run that keep an eye down here this is where we're curious see what happens when he gets to ten all right and it stops when he gets to ten all right awesome that's awesome that's we want let's make it when we Mouse exit we go the other way okay so do the same thing we start at max num steps and this needs we're gonna need another function that goes the other way so void decrement count int C well just put that right here whatever cursor is gonna enter okay counter is gonna go up all right now when our cursor leaves counts down okay rat now something that we can do is let's speed this up okay and let's just make it so that I don't have to write I don't have to change these 500 to bunch different ways let's add a variable here floats refresh rate equals there are a thousand milliseconds in one second and we want this to refresh at 60 times per second and we'll just put that here now because this is such a simple lambda we're going to put this all on its own all right here we go let's check that out okay this is gonna refresh much faster so keep an eye on how much quicker that goes okay a lot faster all right so now what we can do we can simplify this a little bit like that you read this line anything here basically what this says is first compare see with num steps and then increment it all right so now what we do after we increment we called repaint does that make sense about how we do this one thing a few milliseconds later we're gonna call this function again with a changed value so now what we can do is we can use this background color we can modulate it all right so we know what are what we need to do is make a local value int current step set this to zero all right yeah we can just actually yeah we'll set that to zero make a local value and then every time that we call Mouse enter our mouse exit that's what's gonna get changed okay so when we enter the function first we need to do current step equals zero because we're gonna reset and this is what will you pass in current step like that all right now if current step is less than dumb steps all right we're gonna increment this and we want to keep track of we want to make sure that current step is set to our latest value so current step equals see like that because we're gonna use current step here to adjust the color alright we'll do the same thing for Mouse exit we pass in current step like that alright and then for dickering count say current step equals C if C is littler than we passing that value right there alright so now what we can then do is we're just gonna modulate our background color we're gonna go color C equals background color dot interpolated with some other color and our proportion is going to be float it's gonna be current step divided by num steps this needs to be a float okay just to kind of show what this looks like before we actually draw it will do this will do debug just to show the way the value changes all right now every time repaint is called we're gonna see some value between zero and one alright so before I do this let me just get rid of these decrement counts because we're we don't need to worry about whether or not those work anymore we know that it works okay so we're just gonna focus on this all right here we go remember we're looking for it to really afford to repaint and show the interpolation amount going from zero to one whenever the cursor goes over and sure enough there does that from zero to one and back down alright cool so now what we can do is use this background color dot interpolated with some other color now our background-color interpolated with let's see we want right now this is let's the a RGB so this is all red so we're gonna make it interpolate to blue all right so color 0 X full alpha no red full blue right now that's green RGB there we go all right like that okay so background color interpolated with this blue color now the way interpolated works with is if the value is 0 it's 100% background color if the value is 1 then the value is then the color is 100% this color alright let's check it out okay when I mouse over we'll see change now you'll notice that it's just changing it's doing a fade-out let's slow down that refresh rate first of all let's make this refresh 5 frames per second so we can actually see what's going on and actually we'll make this refresh we'll make it take 20 steps so we can really see what's going on see we can figure out this bug okay something's weird something weird is going on ah so the problem is because in our mouse enter we are changing what the background color should be all right so we get rid of those lines and here we go alright that was pretty neat and we fade out and it goes the other way alright let's bump this back up to 60 okay we'll speed this up a little bit to ten like that doesn't so it goes much quicker alright cool so now just to kind of show where this is somewhat useful I'm gonna make a bunch of these components and just randomly place them on the screen and you'll see how it you know how cool it looks I'm also gonna change this color a little bit all right let me view that and come back and in just a second alright so we've got this implemented now let me show you what it looks like and I'm gonna explain some of the flaws that it has in it and whatnot and also some things that it's good for and somethings that it's bad at all right here we go okay so here we have you know we got a bunch of these little animated components and if I mouse over one fades out mouse over another it fades out alright pretty handy okay so now where this has problems is when you mouse over faster if your mouse exit message happens faster than your refresh rate so say you have like a mouse enter come in and then let's let's say this will just say this is 50 so that way our refresh rate is 20 milliseconds let's say our mouse enter happens let me pull this back up alright say our mouse enter happens and then less than 20 milliseconds later our mouse exit happens so what that means is that this lambda is gonna fire 20 milliseconds after this happens and then also this same lambda is gonna fire at the same time or it's gonna fire before which means that our fade out is gonna happen faster than our fate in happens which means things get stuck like like you can see here alright now in the next video part 2 I'll talk about the other solution and that's gonna solve this problem all right this one will be a little this one will be a little bit easier just to you know go full circle with regard to the implementation the way this works is I've got a vector I've got an owned array part of that part of the reason behind having an owned arrays that components are not allowed to be copied if we go away down here wait the bottom of component scroll Scroll scroll Scroll wears Yeah right here Jews declare non copy bowl with a leak detector okay so we can't that what that means is we can't do things like this STD vector component more comps you can't do things like this more comps dot pushback see you can't do this all right watch for the error message all right call do deleted constructor of juice come on all right so the way to get around that is we have to use an owned array we're right here we have to use an owned array that's gonna hold a bunch of pointers to these animated components so that's what gets created here and then since I have a vector of these owned arrays that's what's going on here first I push back the owned array vector itself and then in this individual owned array I'm gonna add the new animated component that I just created here on the heap that gets pushed back into this owned array right and then that gets added here and then regarding painting I just you know first I grab a single row like this and then i iterate through each column like this alright and i just set the bounds uh as shown here alright i hope you enjoyed that thanks again to the audio programmer for letting me do a guest post on his channel you can check out my channel Matt cat music where I have like a few other these music related tutorial programming related tutorials but for the most part I just focus on doing regular music based stuff anyway I hope you dug that stick around for part two or I'm gonna actually explain the better solution than this this works really well if you just need singular stuff but if you have a bunch of components like shown here then and you need them to kind of you know do that this doesn't work so well so I'll show the other solution in the next video alright thanks again later
Info
Channel: The Audio Programmer
Views: 2,654
Rating: undefined out of 5
Keywords: juce, juce framework, c++, audio, tutorial, audio programming, creative programming, creative coding, dsp, digital signal processing, vst, create vst, create plugin, audio plugin, oscillator, synthesizer, maximilian, openframeworks, software development, beginner, easy, max msp, animation, draw, paint
Id: rPa_HCAMtFI
Channel Id: undefined
Length: 28min 51sec (1731 seconds)
Published: Fri Mar 16 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.