Andeventhoughthatmightnotsoundlikethemostinterestingofideas, itturnsoutthattheimplementationofsuch a thingwe'lluseseveral c++ tricksthatwe'venotseenonthechannelbefore.
And I thinkitturnedouttobequiteinterestingonthesolutionisquiteelegant.
Butbeforewestart, let's take a lookatwhat I'm building.
Sothemenulookslikethislittlepopupmenu, andit's probablyfamiliarthiopeoplethatenjoyretrogamesof a certainroleplayinggamefranchise.
Andtheideaisthefollowing.
Youhave a listoffcommandsthatyoucanchooseon.
Youcanseeherethatthelistcouldbescrollupanddown.
Sothepanelofthemenuis a fixedsiteonAikenSelect.
Oneoftheentrieson a separatesubmenupopsupon.
I canselectoneofthoseentrieson.
Wesee a tableofitemsthatcanbechosen, too, sotheitemswithinthepanelsdonotneedtobelistedinjust a verticalorder.
A tablecanbecreatedandwecanseewecanalsoblockoutcertainitemsfrombeingchosen.
Atanypoint, I compressthebackbuttonontochoose a differentmenu.
Solet's chooseAh, whitemagic.
Thistime, whenweget a differentsetofoptions, I can't movethecursortoeoptionsthatdon't exist.
Anditturnedoutyoucanalsoblockoffevensubmenu.
Soit's basically a hierarchicaltreestructurewhereweconsentthepropertiesthateachbranchandleafofthetree.
When I doselectanoptionsuchastheattack, thereisnosubmenu, sothesystemitelicits a smallevent.
I cangoanddosomethingwiththateventlateroninmyprogram.
Inthiscase, it's gotan I D.
101 on.
I canseethenameofit, too.
I'm goingtopopthemenubackupagain, andthistimetheinstituteBlackonwillchooseBiotoheresoyoucanseetheeventsappearin a nice, consistentway.
Inmanyways, thiscouldberegardedas a graphicaluserinterfaceondhe.
Unlikemanygraphicaluserinterfacetechnologies, I wantedtobuilditinsuch a waythatitwaseasyformetouseandtodemonstratethisratheroddly, I'm goingtolookatsomeofthefinalcodebeforewestartprogramming.
Now, eventhough I'vespecified a twodimensionaltable, I stilladdtotheitemstothemenuin a sequentialorder.
I canupdatesomeofthepropertiesoftheitemssimplybycallingthosepropertieswhileStancreatingtheitem.
Andinfact, I coulddothisatanypointaftertheitemhasbeencreated.
So I canchangethestatesoftheiteminrealtime, dependingontheconditionsofthegame.
SoifyourecallintheBlackMagicmenuthereweretwooptionswhichweredisabled, youseethisset I d everywhere.
That's actuallyanoptionalextra.
I couldverywellusethestringidentifytodeterminewhateventhasoccurred, butsometimesit's easiertoworkwithideasinyourprogramsowantedbothoptionsavailable, sothisisreallyanoptionalextra.
Infact, anythinglikethisisanoptionalextra.
Once I'veconstructedthefullmenuandthenbuilditandthatgoesandrecursive, Leeconstructsallofthepanelstobetherightsizeandsetsoffthelayoutandmakes a fewintelligentdecisionsaboutwhattodisplayon.
I tellthemenumanageryou'regoingtoworkwiththismenuobject, sothemenuobjectisthetree.
I'venotmade a videoaboutthisbefore, norhave I releasethesourcecodeforit.
Butitisactually a workingandflexiblewindowingsystemsforthepixelgameengine.
Sowe'vegotwindowsthatcanbeselectedandmovedaround.
Wecanchoosetheindividualcontrols, gotcontrolsthathighlightonmousecursoroveronthingssuchastextentryondifferentdialogscanbeselectedtwo, forexample, inthiscase, open a file.
Thisis a farmoresophisticatedgraphicaluserinterfaceframework, butyoupaythepriceforthatsophisticationbecausetheimplementationofitisalsoquitesophisticated.
Soallofthisisactuallyconcealedawayin a pixelgameengineextension, as I'vementionednotyetreleasedandwecanseetheconstructionoffthedialogue.
SothiswasthedialoguewiththeCzechbuttons, andthetestbuttonsonis a littlebitmorecomplicated.
Weneedtochoose a particularcomponenttype, setitsproperties, setitslocationandthenaddedto a parentwindowonallofthesecontrols.
JustAzzan, WXwidgetsand Q T.
Theseairalsoeligibletobeparentwindowssowecancustomizethingsatquite a finelevel.
OnthissortofapproachisgreatforWindowsbasedinterfaces, soifyou'vegot a mouseandlotsofoptions, whicharegoingtobefiddlyandlotsofmenusingyouneedbuttonsandscrollbarsandlistsandallthatsortofthingperfect.
Butifyoujustwant a quickpopupcontextualmenuinyourgame, thenthisobjectorientedapproachisconsiderablyoverkill.
Now I knowtosome, theconceptof a full, integrated, gooeyframeworkwouldbe a reallyexcitingvideo, andmaybe I'llmake a videoaboutthatinthefuture.
Butinthisinstance, I wantedsomethingthatwassimpleandquickandeasytouse.
Andthisthisentiremenusystemcouldbeputontopofwhateveryou'rerenderinginthebackground, forexample, a battlescene.
Andquiteimportantly, I feelitdoesn't requiretheuseofthemouse, sowecouldalsotieinsomecontrollerinputquiteeasily.
Solet's getstarted.
Butjustbeforewedo, I wantedtobringyourattentionto a smallcommunityendeavor.
Whateverthatinterestsusis a communityforotherstoseeon.
It's earlydaysyet, sothere's not a greatmanyarticleshere, buttherearesomealreadyparticularlytalkingabouthowtousethepixelgameengineincertainways.
Thisone, forexample, islookingathowwecanexplorebinarymathematicsontherulessofaristhatanythingthat's interestingto a memberofthecommunityiseligibletobeincludedontheplatform.
Soifyou'refeelingcreativeon, wanttowritefor a platformthatpeopledoactuallyvisitandwe'llseethearticles, thenshoutoutonthediscordserverfornow, andwe'llgetyousettlednowbacktothemenuINGsystem.
Weknowthatthemanualsystemisgoingtoconsistoffpanels, andeachpanelisgoingtocontain a tableonthetableconsistsof a certainnumberofcolumnsand a certainnumberofvisiblerose.
Sointhiscase, ourtableistwobyfour.
Candleitselfis a menuobjectonthetable.
Cellsalsocontainmenuobjects, andas I addmoremenuobjectstothetable, thetablegetspopulatedinthefollowingorder.
Thenameshighlightedarethetitlesofthemenuobject, andwedifferentiatebetweenthemenuobjectbeing a commandor a Supermanyoubasedonwhetherornotitis a leafofthisstructure.
So I thinkwe'veestablishednowthatallofthedataismenuobjects.
Buttomanagethecursorandthedrawingofthemenus, wehave a menumanagerbecausethisis a tree.
Thereisonlyonesingularpathfromthisitemthroughtothisitemhere, and I wanttodisplayallofthemenusthatwe'vetakentogettothatpath.
Andsothemenumanagerwillmaintain a sortoffstackwhereourrootmenusystemitisalwaysatthebottomofthestackonthemenucurrentlybeinginteractedwiththeuserisatthetopofthestack.
Themenuobjectsthemselvesareresponsibleforpositioning a cursor.
Weshouldhavebeentheprecedingmenuobject, sobecauseweonlyhavethissingularpaththroughto a finalaction, a Stackmakes a reallynicedatastructuretomaintainourrenderingorderondhededucewhereweneedtosendtheeventtointhistwodimensionaltablemenuOfcourse, theleftandrightkeysnowmattersothecursorcanbemovedanywherewithinthistable.
A newmenuobjecttoputonthetopofitsstack, andthereforeitopensupthismenuobject I mentioned a fewminutesagothatthespanelsareactuallywindowsintoinfinitelylongtables, tableswithaninfinitenumberofrows.
I'm almostdonewiththeslidesnow, and I'm goingtogothroughthecodequitequicklyforthisvideosimplybecause a lotofitisthecalculationsofdrawingpositions.
It's notveryinteresting, butthereisonefacet I dowanttotalkabout, andthatishowdowestorethedatainprinciple, I'm goingtouse a standardmaponWe'veseenstandardmaponthechannelbeforeinthecodeityourselfroleplayinggame, Siri's effectively.
Itallowsyoutostorekeysandvaluepairs.
Soin a verypseudoconceptuallevel, youcouldconsider, forexample, mapAppleequalsonemap.
Orangeequalstwo.
Andyes, I reallydomeanwecanuse a stringistheidentifysoitlookslikeanarray.
Butwecaneffectivelyuseanotherobjectastheindextothatarray, ratherthanjust a newmiracleindexwhatyouwouldwith a normalarrayordirector.
Butinmymap, insteadofjustpointingto a basicprimitivetypelikethat, I'm goingtostore a menuobjectonallofmymenu.
Objectsaregoingtohave a mapthatholdstheChildren.
Sotaking a menuobject, I couldlookatit's associativemappassingthenameoffsomesuppermenuobject, whichwouldreturn a newmenuobjectso I couldlookatitsmapandlookatthesubmenu.
Objectsreturnedthereonsoforth.
So I gotthissortofrecurrentdatastructureonbyoverloadingthearrayaccessoperator.
I canactuallygetridofthisbit, whichmeans I canaccess a specificmenuobjectinaneasytouseandveryclearsyntaxmanneron.
I'm goingtostartoutbydoingitlikethis, butwillquicklyseethereis a problemdoingitthisway.
Butlet's startwritingsomecode.
Asusual, I'm goingtousetheOLCpixelgameengine, andhere I justgot a blankpixelgameengineproject.
That I went, how a variable, topvisiblerowwereinthetable.
DowestartdrawingfromSinceweknowthere's a table, let's startsomepropertiesoffthevisibletable, so I'm goingtousetheVectortwo D interviewtypethatcomeswiththepixelgameenginetodothis.
Sothisiscurrentlyonecolumnwidezerorose.
Hi, I don't yetknowwhatthecellsizeinthetableneedstobe.
Inthiscase, I onlywanttopadinthe X axis, andit's goingtobetwopatchesworthofpaddingbetweencells, sincetheentiresystemreliesonrenderinginthespatialdomainoffpatchestheseightbyeightpixelsquares I'm goingtostoreHowbigis a patch, whichisjust a two d vectorcontainingeightbyeight?
But I alsoneedtoknowthesizeofthisifitbecomes a panelinpatches.
Finally, andmostimportantly, we'realsogoingtoneedourmaponthemapsgoingtotakein a string.
A CZ.
ThekeyvaluebutstoremenuobjectsisgoingtorepresenttheChildren I appreciate.
Thismightseemlike a lotofdatatoimmediatelygetstartedwith, butnearlyallofitwillbeselfcalculatedbytheobject.
I canthenchoosewhichpropertiesofthisfinalobject I wanttoset.
Sosetthe I d sayit's 101 butbecausetheset I d Functionalsoreturns a referencetothatobject, I cansettheotherproperties, too.
Now, ifyou'rejuststartingoutwith C plusplus, thisapproachmaylookquitestrange, butitdoesallowmetoconstructmenusquicklywithalloftheinformationthat I needwithoutneedingtostorelotsofinbetweenlinkages.
Wereliedonthestandardmapfunctiontodothatgenerationforus, and I'm quitehappyforthattobethecasebecauseitmeansnow I canaddfurthersubobjectstooneoftheinbetweenstagesonitwillsemanticallymakesenseInthisfirstline, thisblacksubmenuwascreated, soforthissecondline, it's alreadyexists.
Itknowswhichmenutoaccess.
Toaddtotheiceobjecttogoingbacktoourmanyobjects, I'm goingtowant a methodforittodrawitself.
Soinordertoaccessthepixelgameenginesdrawingroutinesonlytopassin a referencetothepixelgameenginewhen I wanttodrawthemenu, I'm alsogoingtopassin.
A pointedtotheSprite, whichcontainstheninepatchonthetwo d vector, weretodrawitonthescreen.
Fundamentally, thedrawerselfmethodisonlygoingtobecalledifthismenuobjectisindeed a panel, I ItwasanobjectthathassomeChildren, butwedon't knowwhatthedimensionsofthatpanelarejustyet, and I don't wanttocalculateiteverysingleframe.
I cancalculateallofthesefixeddimensionsonce I'vefinishedconstructingmymenu.
So I'lladdtothisbuildfunction, whichpopulatesthesevariablesdownherewiththerelevantsizesforwhentheobjectisdrawn.
Now I goontohavetocallthebuildfunctionforeverysinglemenyouobject.
There's absolutelynoneedtoourmenu.
Objectsarestoredin a treesowecanrecursiveLeenavigatethattreehierarchyaslongasweonlycallthebuildmenuon a rootmenuobject.
Andsothat's exactlywhat I'm goingtodo.
ItiteratedthroughalloftheChildreninmyItemsmap.
IftherearenoChildren, thissituationwroteoccur.
IfoneofmyChildrenhappenstohaveChildrenofitsown, then I'm goingtocallthebuildfunctiononthatchild.
Whatweseeisthattheorderoftheitemsisnotwhat I specified.
Here.
We'vegottenattack, defendescapeitemsandmagic.
Butinmycode, I'vegotattackmagicDefenseItemEscape.
I wantmymenusedtobeconstructedintheorderthat I constructthemsimplybecauseitiscustomarytoputthemostpopularoptionsatthestartofyourmenusotheuserdoesn't havetonavigatethemasmuch.
Fortunately, thereis a wayaroundthiswherewecanmaintaintheflexibilitybutalsoatordertoourmapandratherOddly, I'm goingtochangemymapfrom a maptoanunknownorderedMack, whichsoundscounterintuitive, Butthereasoningforthisisthisfollows a standardmap, isactually a verysophisticateddatastructureandhas a certaindegreeofcomputationalcomplexitywhenusingit.
Soeventhoughit's easyforustouse, thecomputerhastodo a lotofworkinordertomaintainthemap.
Sincewedon't careabouttheorderofthingsinthemapbeingmaintainedbystandardmap, I mightaswelluse a standardonorderedmap, whichisslightlymorecomputational e efficient.
However, asthenameimplies, thiswillnotenforceanyorderingitall.
Soit's stillnotsolved.
Theinitialproblem.
I wantmyobjectstoappearintheorderthat I createthem, so I needtostorethemin a datastructurethatmaintainsanorderlikethat.
Fortunately, wehavestandardvectorforthatjob, So I'm goingtostoremymenu, objectsin a standardvectorandcalltheseitems.
But I can't accessthevectorlike I didwithmymapinstead.
What I'm goingtousemymapforistostoretheindexesintothevector.
So I mapisnowgoingtobe a mapthatlinksnamesofmenustointroduce, andthoseinterviewsaregoingtobetheindexesintomyvector.
Thisapproachgivesmethebestofbothworlds.
Myvectoriscomputational e simpletoeworkwith, sowedon't reallygetanyperformancepenaltywhilstusingthemenu.
Italsomaintainstheorderofthingsinwhich I createdthemsoaestheticallyit's goingtolooklikehow I wantittolook.
But I liketheconvenienceofusingthemapaccesssyntaxinordertodefinethestructureofmytree.
Thischangerequiresustojustchange.
A coupleofotherlocationsareray.
Indexoverloadisnolongerasvalidasitshouldbe, but I wantedtobehaveinthesameway, Sothefirstthing I'lldoischeckinmymapofitempointers.
So I'm goingtoclampthatjusttomakesurewedon't gooutofboundsonourchildVector.
Thismeans, giventhesizeofthepanelthatwe'vespecifiedthroughthetabledimensions, I canworkouthowmanyvisibleitemsthereare, regardlessofwhetherit's a wandylistor a to D table, andthisallowsmethentoiteratedthroughallofthevisibleitemsin a linearfashion.
Manytimesonthischannel, we'veworkedouttheone D locationbasedon a two d coordinate.
Itswhytimeswithplus X.
I musthavesaidthatover 100 timesnow, butthisis a situationwherewewanttheoppositeweregiven a one D index, andwewanttoworkout a to D Coordinate, Weakendoeffectivelytheinversewherewecantakeourone d I andcalculateourcelllocation, X and y Thiswilleffectivelypropagatethroughthetablefromthetop, leftalonghorizontallyandthenontothenextrowallthewaytotheleft, allthewaytotherightandthenextroadlefttorightuntilwerunoutofvisibleitems.
If I knowthecelllocation, I canworkoutwhere I wanttostartdrawing.
Sothisisinpatchspace, andthisincludesthepaddock.
Once I'veworkedoutwhere I needtodrawinpatchspace, I canworkitoutinscreenspace.
Andsincethisis a panelandit's drawingthenamesofitsmenuobjectsasitsChildren, I'm goingtocallthedrawstringfunctionatthecorrectlocation.
I candetermineif I needtodrawthebottomscrollmarkerandin a verysimilarway, when I'm drawingtheChildren, I canalsodetermineifthechildhasChildrenofitsown.
Thenitistheheadof a submenuobject, andsoagain, calculatethelocationinpatchspace, thenscreenspace.
Choosetheappropriatepatchondrawittothescreen.
Sonowif I makesurethatourmenucannotdisplayallofthepossibleitemsthatcontainedinthemenu, weget a littleindicator.
Marketerssaytherearemoreitemsbelowhere.
It's difficulttotestthiswithoutthecursor, so I thinkit's timetoaddthatin.
It's importanttorememberthatourmenuobjectclassispurely a datastructureon.
I'm goingtodeferto a secondclassmenumanager, theresponsibilityoff, maintainingthecurseofpositionsandwhichmenusaredrawntothescreen.
Thisis a verysimpleclass, has a constructorthatdoesn't doanything, butitdoesmaintain a listofpanels.
Now I'm goingtobeusingthislistlike a stack, and I'm notusing a stackexplicitly, because I needtoaccessalloftheelementsinthestack.
NowStackwillonlygiveyouaccesstothetop.
I needtolookatalloftheelementssequentiallyonthisstackinordertodrawthem, becausethesearegoingtobethepanelsthatarenested.
Themenumanagerisassociatedwith a menuobjectbearonopenfunction.
Ifourcursethatgoesbeyondthetopvisiblerow, then I wanttodeckAmentourtopvisiblerope, sothiswillhavetheeffectofshiftingtheentiretableupwardsordownwardsdependsonyourperspective.
Onlikewise, wedon't wantourtopvisiblerowtogobelowzero, sohandlingthecursorintwo D spaceisverysimple, but I wanttomakesurethatwedon't enduppointingto a locationthatdoesn't containanitemasyou'veseenbefore.
Getthecurse a locationonDrawtheSpriteonin a similarwaybefore I'm justcashingthecurrentpixelmodesowedon't interruptwithwhatevertheuseriscurrentlytryingtodrawondhe.
I cutoutthehandspriteusingthedrawerpartialSpritefunctionandgiveittheappropriateparameterstodrawitonthescreen.
Nowthatwehave a menumanagerclass, it's timetogiveitcontrol.
It's onlynecessarytouseitinonuserupdate.
Soifthe n keyispressed.
I'm goingtoopen a particularmenuobjectbygivingittothemenumanager.
I'm thengoingtolinkthedirectionkeystothecorrespondingmenumanagerfunctionsthat I'm goingtocallthedrawer, functionoffthemenumanagertodrawthesystemtotake a look.
Sonothing.
I'm goingtopressthe M keyonourmenuhaspoppedup.
Wesee a cursor.
Itcouldbenavigatedaroundthemenu.
Andif I gobeyondthebottomofthevisiblemenu, itstartstoscrolldown.
Nowjustdothatagain.
So I'm onlygoingtopressdowninthisthirdcolumn, butseehowthecurseandmovedtothemiddle.