5 hours 41 minutes 40 seconds
🇬🇧 English
Speaker 1
04:00:00
In the beginning, they get drawn first, and then the closest ones to this viewpoint are gonna be second. We do that here, calling sort, And the callback function will be this 1. Comparison function that takes A and B, 2 polygons this time. And we write the result to be distance to point, to the viewpoint, minus a distance to point viewpoint.
Speaker 1
04:00:40
So we are sorting all of the sides, all of the polygons according to the distance to the viewpoint. But because we write it in this way with B first and A second, it means that we sort in reverse order. So the closest ones are going to be the last ones to draw. Let's save and refresh.
Speaker 1
04:01:05
And now you don't see that problem, that kind of empty box look anymore, but we still have some problems like this building being drawn before this building. The same logic goes here for the buildings as well, but we're going to use the base polys to decide which building to draw first. And actually trees as well. So here the tree goes underneath the building.
Speaker 1
04:01:34
So we need to group trees and buildings together and do this sorting via their base at the same time to get the 3D effect to work. So I'm going to go back to world.js here and let's combine these items into 1 array. I'm going to write here items, buildings, and trees and let's pass here items and this is item item We don't need the second loop anymore, because we're now drawing them with the single loop. Let's just see if this works.
Speaker 1
04:02:22
It should be so that now the trees are over the buildings, because they are drawn later. Save, refresh. So, yeah, same problems as before, but now Trees are over the buildings. So let's do that sorting now for these items here and It's the same thing really Sorting the items same kind of function, but now we tell the polies the base of these objects to calculate the distance to the point.
Speaker 1
04:03:06
A save and a refresh. And now this looks proper. You can see this tree here between this building and this other building quite nicely. And it changed relationship now.
Speaker 1
04:03:25
So now it's drawn before this building. Now it's drawn after this building. So this works just fine. You can see sometimes these weird lines here, but these are actually from the graph editor.
Speaker 1
04:03:43
It's not any glitch or anything like that. They won't appear when we just use the world without the editor showing. Now you can style these however you want. You can go further and make them look even nicer.
Speaker 1
04:03:59
I will have a special video for channel members and they will get to see how I made them have roofs and also how to make a more realistic 3D effect. Because this 1, if you pay attention what happens here, These buildings just get taller and taller like that and if your viewport is bigger and bigger they will just look really crazy. So something is not right here. You shouldn't exceed a size when looking at the building like this.
Speaker 1
04:04:33
And the building should have a proper height, not a height coefficient, whatever that means. So I will have a special video for that, it's not going to be very long, so not too much content in it. But the code from that I will put now and mix it together with this 1 and you can look at it afterwards and self-study it even if you don't watch that video. The worlds we can create now are much more complicated than that straight line we had in phase 1.
Speaker 1
04:05:05
But adding some traffic rules here will really give us a lot of flexibility in phase 3. We'll be able to teach the car all kinds of things. Because our world is really 2D apart from these tricks here, we will enforce these rules as markings on the road. I'll show you a clever way of adding the markings so they snap to the road and always have the correct orientation.
Speaker 1
04:05:29
We're not gonna have our users worry about things like that. They should work as little as possible to get something nice. Try to remember that as the general rule. We're going to start adding markings to the world, and we'll begin with stop markings.
Speaker 1
04:05:48
But to do this, we're going to need another editor, a stop editor, and a way to change from the graph editing mode to the stop editing mode. I'm going to do that here by adding 2 buttons for that. They're going to be mutually exclusive. Let's start by adding an empty space to separate from the save and load functionalities.
Speaker 1
04:06:14
And the first button is going to have an ID this time, because we're going to change the way it looks soon in JavaScript, and we need to access it. And when we click, we're going to set the mode to the graph. So This will enable the graph editing tools. And the second button is going to have an ID stopbtn, and on click it's going to set the mode to stop.
Speaker 1
04:06:47
Let me close this tag, and I'm going to style these buttons using emojis again. For the graph and 1 for the stop, like this. Let's save and refresh. The buttons are here, but let's style the buttons a bit better.
Speaker 1
04:07:07
They have this default view and I don't really like it. Let's make them bigger at least. In styles I'm going to add a style for the buttons. Let's put the background color white for maximum contrast and the font size 20 pixels.
Speaker 1
04:07:31
Refresh. And they're bigger but I would like them to look square as well. And I found that adding here a padding of 5 7 7 5 does the trick. Refresh.
Speaker 1
04:07:48
And it's fine. But this border here that the button has is a little bit nerdy and I will remove it and also add rounded corners as well. So here Border set to none and border radius 5. And refresh.
Speaker 1
04:08:10
Looks much better. Now this button, and maybe this 1 too, the contrast is not so good. It's not so easy for me to see this button. I'm gonna add also a drop shadow on the bottom right.
Speaker 1
04:08:23
So let's have a text shadow 1 1 black. And I like buttons to have this hand cursor when you're hovering them, so let me add also here this cursor pointer. Save and refresh. And now This looks good and feels good, I think.
Speaker 1
04:08:48
But pressing them does nothing. This set mode is not defined yet. So let's define it. I'm gonna go in index.html here at the bottom and say set mode.
Speaker 1
04:09:04
And the first thing that it will do is disable any editor all the editors disable everything and then we're gonna have a switch case that will enable the 1 with the given mode. But let's handle first this disable editors and only visually, so make the buttons look disabled, if they are disabled. And I'm gonna start with the graph button and give it a gray background color and I'm also going to remove the colors in the emojis by passing grayscale filter with the hundred percent like this And this we have to do also for the stop button, so stop button and stop button. Now if we save and refresh, press 1 of these buttons, no more error there and both of them are disabled now because this set mode was called.
Speaker 1
04:10:12
So after they're disabled let's enable the 1 that has been clicked depending on this mode. So switch, depending on the mode, if it was the graph, I'm going to set the background color of the graph button back to white and remove the filter as well. And let's break. Now I will copy this also for the stop using the stop button, stop button, save and refresh, and clicking on them now toggles the behavior.
Speaker 1
04:11:02
But when we refresh the page, 1 of them should be selected and I'm gonna enable this graph by default. So I will go above here where we, before we start the animation loop, and I will type setMode Graph. And now we can start talking about the functionality as well, not just the look and feel. So what we want to happen here in setMode is to enable the graph editor if we press on the graph button.
Speaker 1
04:11:39
And let's add this functionality to our graph editor. It doesn't have it yet. Enable. And here, disable editors.
Speaker 1
04:11:49
It's also going to need a way to disable it. Let's save and go inside our graph editor And the first thing we'll do is remove this call to adding event listeners, because we want that to happen in the enable method. So enable, we add event listeners, like this. And then the disable is going to remove event listeners Like that.
Speaker 1
04:12:34
Remove event listeners should look very much like add event listeners, but with remove in all of these parts. So remove, like this. Let's save and refresh. And now we are able to edit the graph here, to create a graph, and when we switch to the stop editing mode, which doesn't yet exist, but it should disable the graph editor, we still can edit the graph.
Speaker 1
04:13:14
The problem is, here, when we add event listeners and we call bind() on this method, it creates a new method where this inside of it is this. So removeEventListener expects to get the exact same thing here when removing it, not to create a new copy of handleMouseDown with this bound into it. This is a problem, and we're gonna need to fix it, and the best way I know how is just to store this version of the function here as an attribute and then use the attribute here and here. So hopefully you get the point.
Speaker 1
04:14:01
I'm going to store here the boundMouseDown function and let's just copy this from here and now put this here and here. The second 1 is going to be bound mouse move And we're going to cut this from here, and copy this here and here. And we have to do something for these as well, because they're anonymous functions, So actually here we create a function and here it's another function. They just do the same thing but it's not the same function that we want to remove here as well.
Speaker 1
04:14:59
So Let's do the mouse up is next. Mouse up is... I have it here, the last 1. Let's actually rearrange these, because...
Speaker 1
04:15:17
I think it's more logical to have the order like this, with the mouse events first and then this context menu at the end. And let me cut this here, and now we pass this here and here. And finally, the context menu. Context menu I think could be also removed forever.
Speaker 1
04:15:47
We never really need the context menu in this application, but I'm not gonna bother with that. Now I just keep this consistent and make sure that all the listeners are added and removed like this. Now save, refresh, try to add a graph, change to this stop, try to add more points, and It doesn't work. We can't select points.
Speaker 1
04:16:21
We can't do anything with the graph anymore now, but if we re-enable it We can and disabling it again has this weird artifact now because we still have a selected point there. So I'm going to go here where the disable is and let's pass also selected is false and hovered is false. Save, refresh and let's try 1 more time when pressing this that line disappeared so no more problem. And we can actually define a new graph here to use, because it's time to implement the stop marking as well.
Speaker 1
04:17:19
And we should add stops on something. I'm gonna keep this format now. Let's save it so when we refresh it loads this graph now and we can begin to implement the stop editor. We're gonna go in index.html and it's gonna work pretty much like this graph editor.
Speaker 1
04:17:40
Let me just copy this instantiation here and say stop editor is a new stop editor, but adding the stop markings on the road is going to need some information about the road itself, not just that graph, so how big the road is and something like that. So we're going to pass here instead of graph world for this 1. Otherwise, here when we do the display for the Graph Editor we're also going to have a display for our Stop Editor. Dispose, I'm not gonna deal with this now, we will handle it a little bit later, but then here this enable needs to happen here for the stop as well.
Speaker 1
04:18:34
And disable here. Let's implement the stop editor in a separate file and we will have more editors now. So I'm going to move Graph Editor and the Stop Editor into a new folder. Let's call this Editors, and I'm going to move this Editors here, above the items, so that these files that are directly in JavaScript are grouped together.
Speaker 1
04:19:08
And let's copy this graph editor with a stop editor and Create now the new folder in JS called editors Move graph editor inside it and create the new file stop editor JS next to it Now this functionality will be quite similar to the Graph Editor, so we will be copying some things from there. But let's first handle this constructor passing the viewport and the world, which is a little bit different, and store the viewport and the world as object attributes. And also add here a reference to the viewport canvas and a reference to the context. Stop Editor will also have a display method and these items will come in handy for that.
Speaker 1
04:20:19
Now, let's go to Graph Editor, and I'm gonna copy, enable, disable, and adding, removing the event listeners. I think they are pretty much the same, like this, but this selected and hovered will make no sense here. And we actually won't have a mouse up event listener. This editor is going to be simpler than the Graph Editor, so mouseup won't be needed and we won't be dragging anything.
Speaker 1
04:21:01
And let's begin to implement this mouse move private method here, handleMouseMove. I'm going to copy it from Graph Editor. Here. And to begin with, I want when hovering the mouse over some of these segments to highlight that segment.
Speaker 1
04:21:30
The thing is, these stops will be added on the roads themselves. So we're gonna use them as guides. Otherwise, it's gonna be very difficult to place that stop exactly at the location, and the end result won't look good. So we're going to use the segments that exist already as some kind of guides and our interface for using this stop editor is going to be much easier to use, much more user-friendly.
Speaker 1
04:22:00
So we begin by finding what is the nearest segment where we want to add this stop on. So this get nearest point is going to change to a get nearest segment. And we're going to store that segment in a constant, get nearest segment, and here let me align these a little bit better. They go out of the screen and it's going to use the graph segments but here we don't have this graph directly we have the world so the graph is part of this world graph segments like this and this dragging part we don't need it.
Speaker 1
04:22:55
What we do need to do is check if we do get a segment if there is a nearest segment under this threshold, and if there is, I'm going to define an attribute called Intent. Again, I want to show where the marking would appear if we would click the button. So the intent for now is going to be the segment itself. Otherwise, it's going to be null.
Speaker 1
04:23:27
Like this. And let's take out mouse and intent as attributes up here as well. Now to see this intent we need to implement the display method as well. If there is an intent, I'm just going to draw it under context with default styling.
Speaker 1
04:24:03
And We still need to implement this get nearest segment Function it's going to be in math Utils at the top next to the first function we implemented in this file, which was getNearestPoint. And now we're also gonna have getNearestSegment, which takes the location and a list of segments. Same threshold. And here we loop through each segment of segments.
Speaker 1
04:24:38
And when we calculate the distance, we can't use this Pythagorean theorem implementation to get the hypotenuse. We have to call from the segment the distance to point instead. And here the nearest will not be a point, it's going to be the segment that has been found with the smaller distance again and again, eventually leading to the 1 with the smallest distance. Now if we save and refresh we get an error here in the stop editor because it doesn't have yet a handle mouse down method.
Speaker 1
04:25:19
So let's just add an empty 1 here for now. We will handle it later. Save and refresh and switch to the stop editor. And now you can see that segment being highlighted, the nearest segment to our mouse location.
Speaker 1
04:25:40
It's not a strong highlight, but there is a highlight. So I want the stop to be generated at the location centered exactly on that segment. So next thing we'll do is project our mouse location on that nearest segment, if there is a nearest segment here, to get 1 point, the center of the stop marking. For that, we'll go here when we have the segment available, and I'm just going to project the point on the segment by doing this.
Speaker 1
04:26:21
And the projection may also fall outside of the segment, so that would be a weird error there. And I'm going to check here if the offset is really between 0 and 1, so if the projected point falls indeed on the segment not on the support line. And in this case the intent is going to become the projected point. Otherwise it's going to be null again.
Speaker 1
04:26:47
Otherwise, it's gonna be null again. Save, refresh, switch to the stop editor. And now we get a point there. And we don't have to worry about is the mouse exactly there or not, it's always going to be perfectly centered, just as we want it.
Speaker 1
04:27:10
And now it's time to define the marking itself. So it's going to be a polygon, but I'm going to have a specialized object for it. A stop object for storing and drawing the stop marking. So here we're going to need to pass some properties to that.
Speaker 1
04:27:32
The first 1 is going to be the point itself, so as before, but I want the marking to orient nicely according to the segment that it's on, So I'm also going to pass here the direction vector of this segment. And then a width and height. I want the width to span the whole road, really. And the height, Let's just use a factor of that, like half the road width, at least for now.
Speaker 1
04:28:06
Now to define this stop marking we go to index.html and we're going to do that in a folder called markings. So let me just copy EpiViewport here and say markings.stop. Let's close some of these folders here and create a new 1 in JS, markings, and in it our file stop.js, like this. The stop class is also going to be quite simple, but the constructor has 4 parameters now so it's the center location, the direction vector, the width and the height of this polygon.
Speaker 1
04:29:04
Let's store these as attributes and then generate that polygon somehow. So the direction vector is already normalized, which is nice. And height. And now, first thing for that polygon, I'm going to get a support, and it's going to be on the segment, and height, half of the height towards the front of the segment and half of the height towards the back of the segment.
Speaker 1
04:29:44
So we are going to define this support as a new segment relative to this center location by translating center at the angle of this direction vector half the height And the second point is going to be the same, but at a different angle, the opposite angle. You can either add pi here, or say that you want to translate the opposite way with the minus here. Let's debug and implement the draw method for this stop, where we just draw this support for now. Save, refresh, change to the stop editor, and hard to see, but it's there.
Speaker 1
04:30:41
This support vector with half the road width as its height. Let's convert it into a polygon and to do that I'm going to really use the envelope trick again. So we define a new envelope with this support vector and the width parameter and no roundness. I don't need any roundness here and just take the poly from this envelope object.
Speaker 1
04:31:16
And we debug now by drawing this poly instead. Save, refresh, select the stop editor, and there it is. And I just realized that I don't want this stop marking to be the whole road. I want it to be just on half of the road here for the cars that go this way, and they need to stop in this intersection.
Speaker 1
04:31:45
So we're gonna need to fix that. But this is still useful. This could be another marking, like maybe the crossing. It's pretty much exactly what the crossing should look like.
Speaker 1
04:31:58
But for the stop marking, We need some other guides, not these graph segments. We need something here, in the middle, between the borders of the road and the graph segment. So let's define those new lane guides, the middle of the lane, the right lane and the left lane. So they will be lane guides.
Speaker 1
04:32:25
In the stop editor, instead of using these, we will pass lane guides. And we have to go to world.js and define them. I will store them here as an array And below generate here we're going to need the function to generate them. It's a private method, generateLaneGuides, and I'm going to use the same trick that we used with generating buildings with these envelopes.
Speaker 1
04:33:08
So I will copy this here as well. These envelopes will be actually half the road's width like this. And now we're gonna take the union again so avoid those intersecting parts as before by considering the poly of every envelope and just returning these segments. We call this method here, and same as we did with the envelopes before, let's empty the lane guides, if they exist from a previous rendering, and then push.
Speaker 1
04:34:03
I'm just going to spread here the result of generateLaneGuides. Push can actually push multiple things if you pass them individually, not as an array. And let's quickly debug that these look as they should. I'm just going to go here at the end of the draw method and say looping through all of the lane guides segments, drawing them in red.
Speaker 1
04:34:41
Save and refresh, and they look good. And now when we switch to the stop editor, you can see it's centering now on these lane guides, but the width should be smaller. So going back to the stop editor, road width divided by 2. Save, refresh, switch to the stop editor and now it's good.
Speaker 1
04:35:11
Let's remove these guides and start styling our stop marking here. I'm going to draw a rotated text saying stop, so for that we need to do the translate and rotate trick. We first translate to center X and center Y and then rotate by the angle of this direction vector. Let's begin a path and I'm going to style the text by centering the baseline and also horizontally like this and it's gonna be a white text, and it will say stop at 0,0, Because this translate is already moving us to where we need to be and rotate helps us out as well.
Speaker 1
04:36:22
Now let's remember to restore to the original state without these translations and rotations. Save, refresh, select the stop editor and you can see now this stop text appearing there, but it should be rotated. So I'm gonna subtract half pi from that, and let's make it also bigger. Let's make it also bigger.
Speaker 1
04:36:48
Here we subtract 90 degrees and let's set the font size to be a fraction of the height. I think this should look good. Save, refresh, stop editor. Yeah, let's make it bold as well.
Speaker 1
04:37:21
Refresh, stop editor and good. And typically these markings are stretched a lot when they're displayed on the road so that when you're driving and they are stretched like this, you actually see them normally, somehow unstretched while driving. So let's do that as well. Here after we rotate, I'm going to scale this, not horizontally, but vertically by a factor of 2.
Speaker 1
04:37:50
And vertically here means in the new frame of reference after rotating, so save. Refresh. Stop editor. I think we can do even more, maybe 3.
Speaker 1
04:38:04
Refresh, stop editor. And for some reason it doesn't align exactly how I want it. I'm gonna give it an offset here. And now it's good.
Speaker 1
04:38:22
Let's draw also the line on top of it. That's the line that the cars shouldn't cross. So that's gonna be the border here. I will store it as an attribute because this border is really important for the cars to know about.
Speaker 1
04:38:39
So let's put it here at the top and it's gonna be the first segment of the poly. And now drawing this, we don't need to draw the poly anymore, it was there just for reference. And this 1 we style, I'm gonna give it thickness 5 and white, like the rest of the marking. Save, refresh, stop editor.
Speaker 1
04:39:11
Oh, it's not that segment, it should be the other 1, so segments of 2. Refresh, stop editor, that's how we want it. But we want to add it, not just see this intent here, so let's do that next. We're gonna need to go to the stop editor, mouse down, and start to implement it.
Speaker 1
04:39:38
So if we are going to press left click, left click, and if we have an intent here then markings push this intent And I'm going to also delete this Intent, set it to null, in case somebody presses multiple times in the same spot. Now for these markings, I'm going to do a trick here and say that these markings come from the world markings, taking advantage of references here. World markings doesn't exist yet so we need to go to world at the top and the world is going to contain markings. It's going to be an empty array in the beginning and then in the draw method.
Speaker 1
04:40:45
After drawing these envelopes, the grey polys, I'm going to draw the markings. Like so. Save, refresh, stop editor and now clicking actually adds the stop there at the intersection. Now saving doesn't work yet.
Speaker 1
04:41:17
If we save, nothing really happens except for saving the graph structure. For the markings, we're gonna have to do something else. We're gonna implement saving for the markings and actually for the whole world a little bit later. It makes sense to group everything together in 1 spot, but for now we can test them by just still using these buttons and clicking.
Speaker 1
04:41:44
It's not too much trouble, I think. We added markings. How about removing them as well? Maybe on right click?
Speaker 1
04:41:54
So let's go back to our stop editor and here on mouse down and here on mouse down if the event button is 2 so the right click we are going to loop through all of the markings all of the markings 1 by 1. Get the poly of that marking for ease of use and check to see if we clicked inside the poly. So if we clicked inside the poly of any marking, that marking will be removed. So if poly contains point our mouse location, we splice head I, 1 element, we remove it.
Speaker 1
04:42:58
And Now we can just return. We don't have to do I minus minus here because we return anyway. Save, refresh, stop editor, add some stops and remove some stops. Seems to work.
Speaker 1
04:43:18
But 1 thing that we should still deal with is this thing. Deleting the graph leaves the markings there. Let's clear them as well. So going to index.html in our dispose function I'm also going to say world markings length is 0 and now If we save, refresh, stop editor, add some markings here, and then we remove, they all go away.
Speaker 1
04:43:56
1 thing that you probably have noticed is that markings can exist without the graph, or outside of the graph, like this. I won't bother with that. They are not tied to the graph in any way. Users should just add those markings after they are happy with the graph structure.
Speaker 1
04:44:24
And in a way it's kind of what happens in the real world as well. You may end up with markings in some strange locations for weird reasons. I tried coming to a solution that is more friendly with this part but it was way too much trouble to teach it and I gave up. Instead I'm going to show you how to add some other markings.
Speaker 1
04:44:46
So let's make crossings, road crossings. Next. And the way we'll do that is pretty much the same that we did everything up till now for the stop. We have to do it again for the crossing.
Speaker 1
04:45:03
And after that we are gonna have a step where I'm gonna teach you about refactoring and see the similarities between those and remove the duplicate code. You'll see. So here let's copy this stop button and call it crossing button set mode to crossing and I will put here an emoji of this person walking And now every time this stop button is used, I'm gonna look for that and enter another entry for the crossing. Crossing BTN, crossing BTN.
Speaker 1
04:45:51
We will have also a crossing editor, crossing editor, enable, and then here this code, crossingbtn, crossingbtn, crossing editor. This code. Crossing BTN, crossing BTN, crossing editor. Let's look also for this stop editor.
Speaker 1
04:46:15
It has been also used here with this display, so crossing editor display And of course here where we initialize it to a new crossing editor. Crossing editor. And importing the file. So I'm going to copy this stop editor here and say crossing editor and markings stop.
Speaker 1
04:46:57
We will copy it to markings crossing and instead of making new files for crossing and crossing editor I'm just going to copy stop and stop editor so let's copy this stop editor and rename it to crossing Editor and let's copy stop JS and Rename it to crossing JS and in crossing JS, let's edit this real quick. So here, Crossing. Now, I won't bother with styling it just yet. Instead, I will just draw here the poly without any special styles and remove what we had previously for the stop.
Speaker 1
04:47:52
So we're done with this crossing for now. And in Crossing Editor we have to rename this to Crossing Editor. And we already know the things that we need to change to get it to work differently. Here, instead of the lane guides, we are going to have to use the graph segments again because it will center in the middle of the road, and here the width should be the full road width.
Speaker 1
04:48:25
And the object that we create is not a stop, it's a crossing, the 1 we just created. Let's save, refresh, and now we have the button here and they seem to toggle just fine. And when we try adding a crossing it looks like this, but adding a stop still looks polished like what we had it previously. Removing things works without actually changing to the other 1.
Speaker 1
04:48:56
I find this as a useful thing, because it's sometimes, quite often, that you want to add a crossing very close or instead of an existing other marking, so then you can just right-click, even though you have the crossing editor selected and remove the stop and create the crossing where you want it. So I think this is actually a pro even though the logic wasn't necessarily planned like that. Now let's style these crossings in a nice way. For that, we're gonna get a line that is perpendicular to this support line that we had previously, and then style that perpendicular line in some way.
Speaker 1
04:49:49
So let's go to Crossing.js here. And we don't need this poly anymore. We will just get this perpendicular line from this direction vector. This will also return a vector perpendicular to that 1.
Speaker 1
04:50:14
And the logic is actually quite similar to this, but I want to avoid using translate and the angle and show you another implementation using vectors and teach you the formula for this perpendicular vector as well. So you could implement it the same way, but I want to teach you things. So let's have here the line, a new segment, and now we add to the center point, and we scale this perpendicular vector by half the width and then copy this and scale it by half the width but with the minus in front, in the other direction. So you can see similarities here very much.
Speaker 1
04:51:03
And then let's draw this line. Now let's implement this perpendicular function. It's going to be in Math Utils, maybe here next to translate and it's a really easy given a point we just flip it so to speak by changing these coordinates in this way. Save, refresh, select the crossing editor, and now we get this perpendicular line there.
Speaker 1
04:51:46
All we need to do is style it, pretty much. So let's go back to our crossing.js and add here some styles, like so. The width is going to be the height of this marking, if that makes sense. Let's save and refresh.
Speaker 1
04:52:11
Select this crossing editor and now you see it at its full height, with the width of the line. This is a very thick line now. And next we are going to make it white and give it a dashed property like this. Let's save, refresh, select the crossing editor, and now it looks like that.
Speaker 1
04:52:36
When the cars are driving they will need to make a note of this border and this border here. So 2 borders are needed now. We have to record both of them here and I'm going to put them in an array like this. Let's debug, see what we did is working or not.
Speaker 1
04:53:02
I'm going to try to draw here all these borders. Save, refresh, crossing editor and they look okay. So no need for this debug anymore. And we are done with this crossing as well.
Speaker 1
04:53:24
But look at this crossing, especially this part right here and the stop. This part right here, they are pretty much the same. And now the stop editor even worse. Stop editor is very much like the crossing editor.
Speaker 1
04:53:47
The only difference are these target segments that we use here and the type of marking that is created. So let's begin by refactoring this stop editor and the crossing editor into a so-called marking editor and then we inherit from that most of the same functionality. Let's copy this stop editor like this, rename it to marking editor and here at the top this will be marking editor and here where we get this nearest segment we just pass this target segments. The target segments will come from the constructor, so this marking editor will be told what segments to look for and it's going to store them here in an attribute of this object.
Speaker 1
04:54:56
And the second thing that we need to do is add here a method for creating a marker. This should be a dynamic method that will be overwritten by the stop editor and the crossing editor in a different way. So this 1 needs the center location of the marker and a direction and that's it. The width and height are things that those subclasses that will inherit from this superclass will worry about.
Speaker 1
04:55:27
So I just return here this center as a point just to have something but this function will be overwritten, to be overwritten by the subclasses. So with this createMarking function in place we are going to call it here, this createMarking() and it doesn't need these last 2 parameters. And we are done with this marking editor. Now we go to stop editor and extend.
Speaker 1
04:56:07
So extends marking editor like this and instead of doing anything here in the constructor we just say super viewport world and the target segments will be the world lane guides in this case. Everything else just goes away because after extending Marking Editor the functionality is there. All we need to do is overwrite the CreateMarking method, given these properties, and I'm going to return a new stop in this case at the center and direction vector and now we can pass here the road width divided by 2 and the road width divided by 2. This square shape of the stop marking.
Speaker 1
04:57:14
And that's it. Now inside of the crossing editor we do the exact same thing. We extend marking editor like this. We remove the contents of the constructor.
Speaker 1
04:57:31
Super with the viewport world and the world graph segments this time so this is the difference and remove all this code implement the create marking function overwrite it actually it is already there it's just returning center if we don't do this, and return a new crossing this time at the center according to the direction vector and the full road width this time and the road width divided by 2. And we're done with this refactoring. We just need to include the marking editor as well. So here in index we should include it before the other editors so that inheriting it is possible.
Speaker 1
04:58:32
I'm going to put it here at the top above Graph Editor and say Marking Editor Save Refresh and now Everything still works as before but the code is much much better And we can do even better. We can refactor the marking as well. So In the same way, we are going to copy Stop here, rename this to Marking, And the border is something that is different between all of these markings so I will not have it there. And the draw method for this marking...
Speaker 1
04:59:26
We are not supposed to draw these objects, just inherit from them, But if we do, maybe we draw this poly here instead. So, poly draw and I'm just gonna use default styling. Remove this part of the stop drawing. And that's it.
Speaker 1
04:59:49
Now in stop.js we can extend marking and...
Omnivision Solutions Ltd