12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219 |
- #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
- #define _CRT_SECURE_NO_WARNINGS
- #endif
- #include "imgui.h"
- #ifndef IMGUI_DISABLE
- #ifndef IMGUI_DEFINE_MATH_OPERATORS
- #define IMGUI_DEFINE_MATH_OPERATORS
- #endif
- #include "imgui_internal.h"
- #include <ctype.h>
- #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
- #include <stddef.h>
- #else
- #include <stdint.h>
- #endif
- #ifdef _MSC_VER
- #pragma warning (disable: 4127)
- #pragma warning (disable: 4996)
- #if defined(_MSC_VER) && _MSC_VER >= 1922
- #pragma warning (disable: 5054)
- #endif
- #pragma warning (disable: 26451)
- #pragma warning (disable: 26812)
- #endif
- #if defined(__clang__)
- #if __has_warning("-Wunknown-warning-option")
- #pragma clang diagnostic ignored "-Wunknown-warning-option"
- #endif
- #pragma clang diagnostic ignored "-Wunknown-pragmas"
- #pragma clang diagnostic ignored "-Wold-style-cast"
- #pragma clang diagnostic ignored "-Wfloat-equal"
- #pragma clang diagnostic ignored "-Wformat-nonliteral"
- #pragma clang diagnostic ignored "-Wsign-conversion"
- #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
- #pragma clang diagnostic ignored "-Wdouble-promotion"
- #pragma clang diagnostic ignored "-Wenum-enum-conversion"
- #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
- #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
- #elif defined(__GNUC__)
- #pragma GCC diagnostic ignored "-Wpragmas"
- #pragma GCC diagnostic ignored "-Wformat-nonliteral"
- #pragma GCC diagnostic ignored "-Wclass-memaccess"
- #endif
- static const float DRAGDROP_HOLD_TO_OPEN_TIMER = 0.70f;
- static const float DRAG_MOUSE_THRESHOLD_FACTOR = 0.50f;
- static const signed char IM_S8_MIN = -128;
- static const signed char IM_S8_MAX = 127;
- static const unsigned char IM_U8_MIN = 0;
- static const unsigned char IM_U8_MAX = 0xFF;
- static const signed short IM_S16_MIN = -32768;
- static const signed short IM_S16_MAX = 32767;
- static const unsigned short IM_U16_MIN = 0;
- static const unsigned short IM_U16_MAX = 0xFFFF;
- static const ImS32 IM_S32_MIN = INT_MIN;
- static const ImS32 IM_S32_MAX = INT_MAX;
- static const ImU32 IM_U32_MIN = 0;
- static const ImU32 IM_U32_MAX = UINT_MAX;
- #ifdef LLONG_MIN
- static const ImS64 IM_S64_MIN = LLONG_MIN;
- static const ImS64 IM_S64_MAX = LLONG_MAX;
- #else
- static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1;
- static const ImS64 IM_S64_MAX = 9223372036854775807LL;
- #endif
- static const ImU64 IM_U64_MIN = 0;
- #ifdef ULLONG_MAX
- static const ImU64 IM_U64_MAX = ULLONG_MAX;
- #else
- static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
- #endif
- static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source);
- static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
- static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
- void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
-
- if (text == text_end)
- text = text_end = "";
-
- const char* text_begin = text;
- if (text_end == NULL)
- text_end = text + strlen(text);
- const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
- const float wrap_pos_x = window->DC.TextWrapPos;
- const bool wrap_enabled = (wrap_pos_x >= 0.0f);
- if (text_end - text > 2000 && !wrap_enabled)
- {
-
-
-
-
-
- const char* line = text;
- const float line_height = GetTextLineHeight();
- ImVec2 text_size(0, 0);
-
- ImVec2 pos = text_pos;
- if (!g.LogEnabled)
- {
- int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height);
- if (lines_skippable > 0)
- {
- int lines_skipped = 0;
- while (line < text_end && lines_skipped < lines_skippable)
- {
- const char* line_end = (const char*)memchr(line, '\n', text_end - line);
- if (!line_end)
- line_end = text_end;
- if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
- text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
- line = line_end + 1;
- lines_skipped++;
- }
- pos.y += lines_skipped * line_height;
- }
- }
-
- if (line < text_end)
- {
- ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
- while (line < text_end)
- {
- if (IsClippedEx(line_rect, 0))
- break;
- const char* line_end = (const char*)memchr(line, '\n', text_end - line);
- if (!line_end)
- line_end = text_end;
- text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
- RenderText(pos, line, line_end, false);
- line = line_end + 1;
- line_rect.Min.y += line_height;
- line_rect.Max.y += line_height;
- pos.y += line_height;
- }
-
- int lines_skipped = 0;
- while (line < text_end)
- {
- const char* line_end = (const char*)memchr(line, '\n', text_end - line);
- if (!line_end)
- line_end = text_end;
- if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
- text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
- line = line_end + 1;
- lines_skipped++;
- }
- pos.y += lines_skipped * line_height;
- }
- text_size.y = (pos - text_pos).y;
- ImRect bb(text_pos, text_pos + text_size);
- ItemSize(text_size, 0.0f);
- ItemAdd(bb, 0);
- }
- else
- {
- const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
- const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
- ImRect bb(text_pos, text_pos + text_size);
- ItemSize(text_size, 0.0f);
- if (!ItemAdd(bb, 0))
- return;
-
- RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
- }
- }
- void ImGui::TextUnformatted(const char* text, const char* text_end)
- {
- TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
- }
- void ImGui::Text(const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- TextV(fmt, args);
- va_end(args);
- }
- void ImGui::TextV(const char* fmt, va_list args)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
-
- ImGuiContext& g = *GImGui;
- const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
- }
- void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- TextColoredV(col, fmt, args);
- va_end(args);
- }
- void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
- {
- PushStyleColor(ImGuiCol_Text, col);
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText);
- else
- TextV(fmt, args);
- PopStyleColor();
- }
- void ImGui::TextDisabled(const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- TextDisabledV(fmt, args);
- va_end(args);
- }
- void ImGui::TextDisabledV(const char* fmt, va_list args)
- {
- ImGuiContext& g = *GImGui;
- PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText);
- else
- TextV(fmt, args);
- PopStyleColor();
- }
- void ImGui::TextWrapped(const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- TextWrappedV(fmt, args);
- va_end(args);
- }
- void ImGui::TextWrappedV(const char* fmt, va_list args)
- {
- ImGuiContext& g = *GImGui;
- bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f);
- if (need_backup)
- PushTextWrapPos(0.0f);
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText);
- else
- TextV(fmt, args);
- if (need_backup)
- PopTextWrapPos();
- }
- void ImGui::LabelText(const char* label, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- LabelTextV(label, fmt, args);
- va_end(args);
- }
- void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const float w = CalcItemWidth();
- const char* value_text_begin = &g.TempBuffer[0];
- const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImVec2 pos = window->DC.CursorPos;
- const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2));
- const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2));
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, 0))
- return;
-
- RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f));
- if (label_size.x > 0.0f)
- RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
- }
- void ImGui::BulletText(const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- BulletTextV(fmt, args);
- va_end(args);
- }
- void ImGui::BulletTextV(const char* fmt, va_list args)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const char* text_begin = g.TempBuffer;
- const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
- const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y);
- ImVec2 pos = window->DC.CursorPos;
- pos.y += window->DC.CurrLineTextBaseOffset;
- ItemSize(total_size, 0.0f);
- const ImRect bb(pos, pos + total_size);
- if (!ItemAdd(bb, 0))
- return;
-
- ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col);
- RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
- }
- bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
-
- if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
- flags |= ImGuiButtonFlags_MouseButtonDefault_;
-
- if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0)
- flags |= ImGuiButtonFlags_PressedOnDefault_;
- ImGuiWindow* backup_hovered_window = g.HoveredWindow;
- const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
- if (flatten_hovered_children)
- g.HoveredWindow = window;
- #ifdef IMGUI_ENABLE_TEST_ENGINE
- if (id != 0 && g.LastItemData.ID != id)
- IMGUI_TEST_ENGINE_ITEM_ADD(bb, id);
- #endif
- bool pressed = false;
- bool hovered = ItemHoverable(bb, id);
-
- if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
- hovered = false;
-
- if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
- if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
- {
- hovered = true;
- SetHoveredID(id);
- if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER)
- {
- pressed = true;
- g.DragDropHoldJustPressedId = id;
- FocusWindow(window);
- }
- }
- if (flatten_hovered_children)
- g.HoveredWindow = backup_hovered_window;
-
- if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
- hovered = false;
-
- if (hovered)
- {
- if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
- {
-
- int mouse_button_clicked = -1;
- int mouse_button_released = -1;
- if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseClicked[0]) { mouse_button_clicked = 0; }
- else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseClicked[1]) { mouse_button_clicked = 1; }
- else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseClicked[2]) { mouse_button_clicked = 2; }
- if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseReleased[0]) { mouse_button_released = 0; }
- else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseReleased[1]) { mouse_button_released = 1; }
- else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseReleased[2]) { mouse_button_released = 2; }
- if (mouse_button_clicked != -1 && g.ActiveId != id)
- {
- if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere))
- {
- SetActiveID(id, window);
- g.ActiveIdMouseButton = mouse_button_clicked;
- if (!(flags & ImGuiButtonFlags_NoNavFocus))
- SetFocusID(id, window);
- FocusWindow(window);
- }
- if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked]))
- {
- pressed = true;
- if (flags & ImGuiButtonFlags_NoHoldingActiveId)
- ClearActiveID();
- else
- SetActiveID(id, window);
- if (!(flags & ImGuiButtonFlags_NoNavFocus))
- SetFocusID(id, window);
- g.ActiveIdMouseButton = mouse_button_clicked;
- FocusWindow(window);
- }
- }
- if ((flags & ImGuiButtonFlags_PressedOnRelease) && mouse_button_released != -1)
- {
-
- const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay;
- if (!has_repeated_at_least_once)
- pressed = true;
- if (!(flags & ImGuiButtonFlags_NoNavFocus))
- SetFocusID(id, window);
- ClearActiveID();
- }
-
-
- if (g.ActiveId == id && (flags & ImGuiButtonFlags_Repeat))
- if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, true))
- pressed = true;
- }
- if (pressed)
- g.NavDisableHighlight = true;
- }
-
-
- if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId))
- if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
- hovered = true;
- if (g.NavActivateDownId == id)
- {
- bool nav_activated_by_code = (g.NavActivateId == id);
- bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed);
- if (nav_activated_by_code || nav_activated_by_inputs)
- {
-
- pressed = true;
- SetActiveID(id, window);
- g.ActiveIdSource = ImGuiInputSource_Nav;
- if (!(flags & ImGuiButtonFlags_NoNavFocus))
- SetFocusID(id, window);
- }
- }
-
- bool held = false;
- if (g.ActiveId == id)
- {
- if (g.ActiveIdSource == ImGuiInputSource_Mouse)
- {
- if (g.ActiveIdIsJustActivated)
- g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
- const int mouse_button = g.ActiveIdMouseButton;
- IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
- if (g.IO.MouseDown[mouse_button])
- {
- held = true;
- }
- else
- {
- bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0;
- bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0;
- if ((release_in || release_anywhere) && !g.DragDropActive)
- {
-
- bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button];
- bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay;
- if (!is_double_click_release && !is_repeating_already)
- pressed = true;
- }
- ClearActiveID();
- }
- if (!(flags & ImGuiButtonFlags_NoNavFocus))
- g.NavDisableHighlight = true;
- }
- else if (g.ActiveIdSource == ImGuiInputSource_Nav)
- {
-
- if (g.NavActivateDownId != id)
- ClearActiveID();
- }
- if (pressed)
- g.ActiveIdHasBeenPressedBefore = true;
- }
- if (out_hovered) *out_hovered = hovered;
- if (out_held) *out_held = held;
- return pressed;
- }
- bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- ImVec2 pos = window->DC.CursorPos;
- if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset)
- pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y;
- ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
- const ImRect bb(pos, pos + size);
- ItemSize(size, style.FramePadding.y);
- if (!ItemAdd(bb, id))
- return false;
- if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
- flags |= ImGuiButtonFlags_Repeat;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
-
- const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
- RenderNavHighlight(bb, id);
- RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
- if (g.LogEnabled)
- LogSetNextTextDecoration("[", "]");
- RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
-
-
-
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- return pressed;
- }
- bool ImGui::Button(const char* label, const ImVec2& size_arg)
- {
- return ButtonEx(label, size_arg, ImGuiButtonFlags_None);
- }
- bool ImGui::SmallButton(const char* label)
- {
- ImGuiContext& g = *GImGui;
- float backup_padding_y = g.Style.FramePadding.y;
- g.Style.FramePadding.y = 0.0f;
- bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine);
- g.Style.FramePadding.y = backup_padding_y;
- return pressed;
- }
- bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
-
- IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
- const ImGuiID id = window->GetID(str_id);
- ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
- ItemSize(size);
- if (!ItemAdd(bb, id))
- return false;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
- return pressed;
- }
- bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiID id = window->GetID(str_id);
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
- const float default_size = GetFrameHeight();
- ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
- if (!ItemAdd(bb, id))
- return false;
- if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
- flags |= ImGuiButtonFlags_Repeat;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
-
- const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
- const ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderNavHighlight(bb, id);
- RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
- RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
- return pressed;
- }
- bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
- {
- float sz = GetFrameHeight();
- return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None);
- }
- bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
-
-
- const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
- ImRect bb_interact = bb;
- const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea();
- if (area_to_visible_ratio < 1.5f)
- bb_interact.Expand(ImFloor(bb_interact.GetSize() * -0.25f));
-
-
- bool is_clipped = !ItemAdd(bb_interact, id);
- bool hovered, held;
- bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held);
- if (is_clipped)
- return pressed;
-
-
- ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
- ImVec2 center = bb.GetCenter();
- if (hovered)
- window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
- float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
- ImU32 cross_col = GetColorU32(ImGuiCol_Text);
- center -= ImVec2(0.5f, 0.5f);
- window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
- window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
- return pressed;
- }
- bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
- ItemAdd(bb, id);
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
-
- ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
- ImU32 text_col = GetColorU32(ImGuiCol_Text);
- ImVec2 center = bb.GetCenter();
- if (hovered || held)
- window->DrawList->AddCircleFilled(center, g.FontSize * 0.5f + 1.0f, bg_col, 12);
- RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
-
- if (IsItemActive() && IsMouseDragging(0))
- StartMouseMovingWindow(window);
- return pressed;
- }
- ImGuiID ImGui::GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis)
- {
- return window->GetIDNoKeepAlive(axis == ImGuiAxis_X ? "#SCROLLX" : "#SCROLLY");
- }
- ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
- {
- const ImRect outer_rect = window->Rect();
- const ImRect inner_rect = window->InnerRect;
- const float border_size = window->WindowBorderSize;
- const float scrollbar_size = window->ScrollbarSizes[axis ^ 1];
- IM_ASSERT(scrollbar_size > 0.0f);
- if (axis == ImGuiAxis_X)
- return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x, outer_rect.Max.y);
- else
- return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x, inner_rect.Max.y);
- }
- void ImGui::Scrollbar(ImGuiAxis axis)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- const ImGuiID id = GetWindowScrollbarID(window, axis);
- KeepAliveID(id);
-
- ImRect bb = GetWindowScrollbarRect(window, axis);
- ImDrawFlags rounding_corners = ImDrawFlags_RoundCornersNone;
- if (axis == ImGuiAxis_X)
- {
- rounding_corners |= ImDrawFlags_RoundCornersBottomLeft;
- if (!window->ScrollbarY)
- rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
- }
- else
- {
- if ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar))
- rounding_corners |= ImDrawFlags_RoundCornersTopRight;
- if (!window->ScrollbarX)
- rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
- }
- float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
- float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
- ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners);
- }
- bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- const float bb_frame_width = bb_frame.GetWidth();
- const float bb_frame_height = bb_frame.GetHeight();
- if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f)
- return false;
-
- float alpha = 1.0f;
- if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f)
- alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f));
- if (alpha <= 0.0f)
- return false;
- const ImGuiStyle& style = g.Style;
- const bool allow_interaction = (alpha >= 1.0f);
- ImRect bb = bb_frame;
- bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
-
- const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight();
-
-
- IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f);
- const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
- const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
- const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
-
- bool held = false;
- bool hovered = false;
- ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
- float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
- float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
- float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
- if (held && allow_interaction && grab_h_norm < 1.0f)
- {
- float scrollbar_pos_v = bb.Min[axis];
- float mouse_pos_v = g.IO.MousePos[axis];
-
- const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
- SetHoveredID(id);
- bool seek_absolute = false;
- if (g.ActiveIdIsJustActivated)
- {
-
- seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm);
- if (seek_absolute)
- g.ScrollbarClickDeltaToGrabCenter = 0.0f;
- else
- g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
- }
-
-
- const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
- *p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);
-
- scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
- grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
-
- if (seek_absolute)
- g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
- }
-
- const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg);
- const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
- window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags);
- ImRect grab_rect;
- if (axis == ImGuiAxis_X)
- grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
- else
- grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
- window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
- return held;
- }
- void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
- if (border_col.w > 0.0f)
- bb.Max += ImVec2(2, 2);
- ItemSize(bb);
- if (!ItemAdd(bb, 0))
- return;
- if (border_col.w > 0.0f)
- {
- window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);
- window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col));
- }
- else
- {
- window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
- }
- }
- bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
- ItemSize(bb);
- if (!ItemAdd(bb, id))
- return false;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held);
-
- const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
- RenderNavHighlight(bb, id);
- RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
- if (bg_col.w > 0.0f)
- window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
- window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
- return pressed;
- }
- bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
-
- PushID((void*)(intptr_t)user_texture_id);
- const ImGuiID id = window->GetID("#image");
- PopID();
- const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding;
- return ImageButtonEx(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col);
- }
- bool ImGui::Checkbox(const char* label, bool* v)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const float square_sz = GetFrameHeight();
- const ImVec2 pos = window->DC.CursorPos;
- const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id))
- {
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
- return false;
- }
- bool hovered, held;
- bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
- if (pressed)
- {
- *v = !(*v);
- MarkItemEdited(id);
- }
- const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
- RenderNavHighlight(total_bb, id);
- RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
- ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
- bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
- if (mixed_value)
- {
-
-
- ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
- window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
- }
- else if (*v)
- {
- const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
- RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
- }
- ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
- if (g.LogEnabled)
- LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
- if (label_size.x > 0.0f)
- RenderText(label_pos, label);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
- return pressed;
- }
- template<typename T>
- bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
- {
- bool all_on = (*flags & flags_value) == flags_value;
- bool any_on = (*flags & flags_value) != 0;
- bool pressed;
- if (!all_on && any_on)
- {
- ImGuiContext& g = *GImGui;
- ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
- g.CurrentItemFlags |= ImGuiItemFlags_MixedValue;
- pressed = Checkbox(label, &all_on);
- g.CurrentItemFlags = backup_item_flags;
- }
- else
- {
- pressed = Checkbox(label, &all_on);
- }
- if (pressed)
- {
- if (all_on)
- *flags |= flags_value;
- else
- *flags &= ~flags_value;
- }
- return pressed;
- }
- bool ImGui::CheckboxFlags(const char* label, int* flags, int flags_value)
- {
- return CheckboxFlagsT(label, flags, flags_value);
- }
- bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
- {
- return CheckboxFlagsT(label, flags, flags_value);
- }
- bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value)
- {
- return CheckboxFlagsT(label, flags, flags_value);
- }
- bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value)
- {
- return CheckboxFlagsT(label, flags, flags_value);
- }
- bool ImGui::RadioButton(const char* label, bool active)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const float square_sz = GetFrameHeight();
- const ImVec2 pos = window->DC.CursorPos;
- const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
- const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id))
- return false;
- ImVec2 center = check_bb.GetCenter();
- center.x = IM_ROUND(center.x);
- center.y = IM_ROUND(center.y);
- const float radius = (square_sz - 1.0f) * 0.5f;
- bool hovered, held;
- bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
- if (pressed)
- MarkItemEdited(id);
- RenderNavHighlight(total_bb, id);
- window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
- if (active)
- {
- const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
- window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16);
- }
- if (style.FrameBorderSize > 0.0f)
- {
- window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
- window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
- }
- ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
- if (g.LogEnabled)
- LogRenderedText(&label_pos, active ? "(x)" : "( )");
- if (label_size.x > 0.0f)
- RenderText(label_pos, label);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- return pressed;
- }
- bool ImGui::RadioButton(const char* label, int* v, int v_button)
- {
- const bool pressed = RadioButton(label, *v == v_button);
- if (pressed)
- *v = v_button;
- return pressed;
- }
- void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- ImVec2 pos = window->DC.CursorPos;
- ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f);
- ImRect bb(pos, pos + size);
- ItemSize(size, style.FramePadding.y);
- if (!ItemAdd(bb, 0))
- return;
-
- fraction = ImSaturate(fraction);
- RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
- bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
- const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
- RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
-
- char overlay_buf[32];
- if (!overlay)
- {
- ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
- overlay = overlay_buf;
- }
- ImVec2 overlay_size = CalcTextSize(overlay, NULL);
- if (overlay_size.x > 0.0f)
- RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb);
- }
- void ImGui::Bullet()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize);
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
- ItemSize(bb);
- if (!ItemAdd(bb, 0))
- {
- SameLine(0, style.FramePadding.x * 2);
- return;
- }
-
- ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f), text_col);
- SameLine(0, style.FramePadding.x * 2.0f);
- }
- void ImGui::Spacing()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ItemSize(ImVec2(0, 0));
- }
- void ImGui::Dummy(const ImVec2& size)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
- ItemSize(size);
- ItemAdd(bb, 0);
- }
- void ImGui::NewLine()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
- window->DC.LayoutType = ImGuiLayoutType_Vertical;
- if (window->DC.CurrLineSize.y > 0.0f)
- ItemSize(ImVec2(0, 0));
- else
- ItemSize(ImVec2(0.0f, g.FontSize));
- window->DC.LayoutType = backup_layout_type;
- }
- void ImGui::AlignTextToFramePadding()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
- window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y);
- }
- void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
- IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)));
- float thickness_draw = 1.0f;
- float thickness_layout = 0.0f;
- if (flags & ImGuiSeparatorFlags_Vertical)
- {
-
- float y1 = window->DC.CursorPos.y;
- float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y;
- const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
- ItemSize(ImVec2(thickness_layout, 0.0f));
- if (!ItemAdd(bb, 0))
- return;
-
- window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
- if (g.LogEnabled)
- LogText(" |");
- }
- else if (flags & ImGuiSeparatorFlags_Horizontal)
- {
-
- float x1 = window->Pos.x;
- float x2 = window->Pos.x + window->Size.x;
-
- if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
- x1 += window->DC.Indent.x;
- ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
- if (columns)
- PushColumnsBackground();
-
- const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
- ItemSize(ImVec2(0.0f, thickness_layout));
- const bool item_visible = ItemAdd(bb, 0);
- if (item_visible)
- {
-
- window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator));
- if (g.LogEnabled)
- LogRenderedText(&bb.Min, "--------------------------------\n");
- }
- if (columns)
- {
- PopColumnsBackground();
- columns->LineMinY = window->DC.CursorPos.y;
- }
- }
- }
- void ImGui::Separator()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return;
-
- ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
- flags |= ImGuiSeparatorFlags_SpanAllColumns;
- SeparatorEx(flags);
- }
- bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
- g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
- bool item_add = ItemAdd(bb, id);
- g.CurrentItemFlags = item_flags_backup;
- if (!item_add)
- return false;
- bool hovered, held;
- ImRect bb_interact = bb;
- bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
- ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
- if (hovered)
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
- if (g.ActiveId != id)
- SetItemAllowOverlap();
- if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
- SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW);
- ImRect bb_render = bb;
- if (held)
- {
- ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
- float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
-
- float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
- float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
- if (mouse_delta < -size_1_maximum_delta)
- mouse_delta = -size_1_maximum_delta;
- if (mouse_delta > size_2_maximum_delta)
- mouse_delta = size_2_maximum_delta;
-
- if (mouse_delta != 0.0f)
- {
- if (mouse_delta < 0.0f)
- IM_ASSERT(*size1 + mouse_delta >= min_size1);
- if (mouse_delta > 0.0f)
- IM_ASSERT(*size2 - mouse_delta >= min_size2);
- *size1 += mouse_delta;
- *size2 -= mouse_delta;
- bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
- MarkItemEdited(id);
- }
- }
-
- const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
- window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f);
- return held;
- }
- static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs)
- {
- const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs;
- const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs;
- if (int d = (int)(b->Width - a->Width))
- return d;
- return (b->Index - a->Index);
- }
- void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess)
- {
- if (count == 1)
- {
- if (items[0].Width >= 0.0f)
- items[0].Width = ImMax(items[0].Width - width_excess, 1.0f);
- return;
- }
- ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
- int count_same_width = 1;
- while (width_excess > 0.0f && count_same_width < count)
- {
- while (count_same_width < count && items[0].Width <= items[count_same_width].Width)
- count_same_width++;
- float max_width_to_remove_per_item = (count_same_width < count && items[count_same_width].Width >= 0.0f) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
- if (max_width_to_remove_per_item <= 0.0f)
- break;
- float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item);
- for (int item_n = 0; item_n < count_same_width; item_n++)
- items[item_n].Width -= width_to_remove_per_item;
- width_excess -= width_to_remove_per_item * count_same_width;
- }
-
-
- width_excess = 0.0f;
- for (int n = 0; n < count; n++)
- {
- float width_rounded = ImFloor(items[n].Width);
- width_excess += items[n].Width - width_rounded;
- items[n].Width = width_rounded;
- }
- if (width_excess > 0.0f)
- for (int n = 0; n < count; n++)
- if (items[n].Index < (int)(width_excess + 0.01f))
- items[n].Width += 1.0f;
- }
- static float CalcMaxPopupHeightFromItemCount(int items_count)
- {
- ImGuiContext& g = *GImGui;
- if (items_count <= 0)
- return FLT_MAX;
- return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
- }
- bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags;
- g.NextWindowData.ClearFlags();
- if (window->SkipItems)
- return false;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview));
- const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
- const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id, &bb))
- return false;
-
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held);
- const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
- bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
- if (pressed && !popup_open)
- {
- OpenPopupEx(popup_id, ImGuiPopupFlags_None);
- popup_open = true;
- }
-
- const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
- const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
- RenderNavHighlight(bb, id);
- if (!(flags & ImGuiComboFlags_NoPreview))
- window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
- if (!(flags & ImGuiComboFlags_NoArrowButton))
- {
- ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
- ImU32 text_col = GetColorU32(ImGuiCol_Text);
- window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
- if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x)
- RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
- }
- RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
-
- if (flags & ImGuiComboFlags_CustomPreview)
- {
- g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
- IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
- preview_value = NULL;
- }
-
- if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
- {
- if (g.LogEnabled)
- LogSetNextTextDecoration("{", "}");
- RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
- }
- if (label_size.x > 0)
- RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);
- if (!popup_open)
- return false;
- g.NextWindowData.Flags = backup_next_window_data_flags;
- return BeginComboPopup(popup_id, bb, flags);
- }
- bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags)
- {
- ImGuiContext& g = *GImGui;
- if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None))
- {
- g.NextWindowData.ClearFlags();
- return false;
- }
-
- float w = bb.GetWidth();
- if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
- {
- g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
- }
- else
- {
- if ((flags & ImGuiComboFlags_HeightMask_) == 0)
- flags |= ImGuiComboFlags_HeightRegular;
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_));
- int popup_max_height_in_items = -1;
- if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
- else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
- else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
- SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
- }
-
- char name[16];
- ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size);
-
-
-
- if (ImGuiWindow* popup_window = FindWindowByName(name))
- if (popup_window->WasActive)
- {
-
- ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window);
- popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down;
- ImRect r_outer = GetPopupAllowedExtentRect(popup_window);
- ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox);
- SetNextWindowPos(pos);
- }
-
- ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;
- PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y));
- bool ret = Begin(name, NULL, window_flags);
- PopStyleVar();
- if (!ret)
- {
- EndPopup();
- IM_ASSERT(0);
- return false;
- }
- return true;
- }
- void ImGui::EndCombo()
- {
- EndPopup();
- }
- bool ImGui::BeginComboPreview()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
- if (window->SkipItems || !window->ClipRect.Overlaps(g.LastItemData.Rect))
- return false;
- IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y);
- if (!window->ClipRect.Contains(preview_data->PreviewRect))
- return false;
-
- preview_data->BackupCursorPos = window->DC.CursorPos;
- preview_data->BackupCursorMaxPos = window->DC.CursorMaxPos;
- preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
- preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
- preview_data->BackupLayout = window->DC.LayoutType;
- window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;
- window->DC.CursorMaxPos = window->DC.CursorPos;
- window->DC.LayoutType = ImGuiLayoutType_Horizontal;
- PushClipRect(preview_data->PreviewRect.Min, preview_data->PreviewRect.Max, true);
- return true;
- }
- void ImGui::EndComboPreview()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
-
- ImDrawList* draw_list = window->DrawList;
- if (window->DC.CursorMaxPos.x < preview_data->PreviewRect.Max.x && window->DC.CursorMaxPos.y < preview_data->PreviewRect.Max.y)
- if (draw_list->CmdBuffer.Size > 1)
- {
- draw_list->_CmdHeader.ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 2].ClipRect;
- draw_list->_TryMergeDrawCmds();
- }
- PopClipRect();
- window->DC.CursorPos = preview_data->BackupCursorPos;
- window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos);
- window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;
- window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;
- window->DC.LayoutType = preview_data->BackupLayout;
- preview_data->PreviewRect = ImRect();
- }
- static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
- {
- const char* const* items = (const char* const*)data;
- if (out_text)
- *out_text = items[idx];
- return true;
- }
- static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
- {
-
- const char* items_separated_by_zeros = (const char*)data;
- int items_count = 0;
- const char* p = items_separated_by_zeros;
- while (*p)
- {
- if (idx == items_count)
- break;
- p += strlen(p) + 1;
- items_count++;
- }
- if (!*p)
- return false;
- if (out_text)
- *out_text = p;
- return true;
- }
- bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
- {
- ImGuiContext& g = *GImGui;
-
- const char* preview_value = NULL;
- if (*current_item >= 0 && *current_item < items_count)
- items_getter(data, *current_item, &preview_value);
-
- if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
- SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
- if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
- return false;
-
-
- bool value_changed = false;
- for (int i = 0; i < items_count; i++)
- {
- PushID(i);
- const bool item_selected = (i == *current_item);
- const char* item_text;
- if (!items_getter(data, i, &item_text))
- item_text = "*Unknown item*";
- if (Selectable(item_text, item_selected))
- {
- value_changed = true;
- *current_item = i;
- }
- if (item_selected)
- SetItemDefaultFocus();
- PopID();
- }
- EndCombo();
- if (value_changed)
- MarkItemEdited(g.LastItemData.ID);
- return value_changed;
- }
- bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
- {
- const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
- return value_changed;
- }
- bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
- {
- int items_count = 0;
- const char* p = items_separated_by_zeros;
- while (*p)
- {
- p += strlen(p) + 1;
- items_count++;
- }
- bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
- return value_changed;
- }
- static const ImGuiDataTypeInfo GDataTypeInfo[] =
- {
- { sizeof(char), "S8", "%d", "%d" },
- { sizeof(unsigned char), "U8", "%u", "%u" },
- { sizeof(short), "S16", "%d", "%d" },
- { sizeof(unsigned short), "U16", "%u", "%u" },
- { sizeof(int), "S32", "%d", "%d" },
- { sizeof(unsigned int), "U32", "%u", "%u" },
- #ifdef _MSC_VER
- { sizeof(ImS64), "S64", "%I64d","%I64d" },
- { sizeof(ImU64), "U64", "%I64u","%I64u" },
- #else
- { sizeof(ImS64), "S64", "%lld", "%lld" },
- { sizeof(ImU64), "U64", "%llu", "%llu" },
- #endif
- { sizeof(float), "float", "%.3f","%f" },
- { sizeof(double), "double","%f", "%lf" },
- };
- IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
- static const char* PatchFormatStringFloatToInt(const char* fmt)
- {
- if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0)
- return "%d";
- const char* fmt_start = ImParseFormatFindStart(fmt);
- const char* fmt_end = ImParseFormatFindEnd(fmt_start);
- if (fmt_end > fmt_start && fmt_end[-1] == 'f')
- {
- #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
- if (fmt_start == fmt && fmt_end[0] == 0)
- return "%d";
- ImGuiContext& g = *GImGui;
- ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end);
- return g.TempBuffer;
- #else
- IM_ASSERT(0 && "DragInt(): Invalid format string!");
- #endif
- }
- return fmt;
- }
- const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type)
- {
- IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
- return &GDataTypeInfo[data_type];
- }
- int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format)
- {
-
- if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)
- return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data);
- if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
- return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data);
- if (data_type == ImGuiDataType_Float)
- return ImFormatString(buf, buf_size, format, *(const float*)p_data);
- if (data_type == ImGuiDataType_Double)
- return ImFormatString(buf, buf_size, format, *(const double*)p_data);
- if (data_type == ImGuiDataType_S8)
- return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data);
- if (data_type == ImGuiDataType_U8)
- return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data);
- if (data_type == ImGuiDataType_S16)
- return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data);
- if (data_type == ImGuiDataType_U16)
- return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data);
- IM_ASSERT(0);
- return 0;
- }
- void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg1, const void* arg2)
- {
- IM_ASSERT(op == '+' || op == '-');
- switch (data_type)
- {
- case ImGuiDataType_S8:
- if (op == '+') { *(ImS8*)output = ImAddClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
- if (op == '-') { *(ImS8*)output = ImSubClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
- return;
- case ImGuiDataType_U8:
- if (op == '+') { *(ImU8*)output = ImAddClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
- if (op == '-') { *(ImU8*)output = ImSubClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
- return;
- case ImGuiDataType_S16:
- if (op == '+') { *(ImS16*)output = ImAddClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
- if (op == '-') { *(ImS16*)output = ImSubClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
- return;
- case ImGuiDataType_U16:
- if (op == '+') { *(ImU16*)output = ImAddClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
- if (op == '-') { *(ImU16*)output = ImSubClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
- return;
- case ImGuiDataType_S32:
- if (op == '+') { *(ImS32*)output = ImAddClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
- if (op == '-') { *(ImS32*)output = ImSubClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
- return;
- case ImGuiDataType_U32:
- if (op == '+') { *(ImU32*)output = ImAddClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
- if (op == '-') { *(ImU32*)output = ImSubClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
- return;
- case ImGuiDataType_S64:
- if (op == '+') { *(ImS64*)output = ImAddClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
- if (op == '-') { *(ImS64*)output = ImSubClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
- return;
- case ImGuiDataType_U64:
- if (op == '+') { *(ImU64*)output = ImAddClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
- if (op == '-') { *(ImU64*)output = ImSubClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
- return;
- case ImGuiDataType_Float:
- if (op == '+') { *(float*)output = *(const float*)arg1 + *(const float*)arg2; }
- if (op == '-') { *(float*)output = *(const float*)arg1 - *(const float*)arg2; }
- return;
- case ImGuiDataType_Double:
- if (op == '+') { *(double*)output = *(const double*)arg1 + *(const double*)arg2; }
- if (op == '-') { *(double*)output = *(const double*)arg1 - *(const double*)arg2; }
- return;
- case ImGuiDataType_COUNT: break;
- }
- IM_ASSERT(0);
- }
- bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
- {
- while (ImCharIsBlankA(*buf))
- buf++;
-
-
- char op = buf[0];
- if (op == '+' || op == '*' || op == '/')
- {
- buf++;
- while (ImCharIsBlankA(*buf))
- buf++;
- }
- else
- {
- op = 0;
- }
- if (!buf[0])
- return false;
-
- const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
- ImGuiDataTypeTempStorage data_backup;
- memcpy(&data_backup, p_data, type_info->Size);
- if (format == NULL)
- format = type_info->ScanFmt;
-
- int arg1i = 0;
- if (data_type == ImGuiDataType_S32)
- {
- int* v = (int*)p_data;
- int arg0i = *v;
- float arg1f = 0.0f;
- if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
- return false;
-
- if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); }
- else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); }
- else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }
- else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; }
- }
- else if (data_type == ImGuiDataType_Float)
- {
-
- format = "%f";
- float* v = (float*)p_data;
- float arg0f = *v, arg1f = 0.0f;
- if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
- return false;
- if (sscanf(buf, format, &arg1f) < 1)
- return false;
- if (op == '+') { *v = arg0f + arg1f; }
- else if (op == '*') { *v = arg0f * arg1f; }
- else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; }
- else { *v = arg1f; }
- }
- else if (data_type == ImGuiDataType_Double)
- {
- format = "%lf";
- double* v = (double*)p_data;
- double arg0f = *v, arg1f = 0.0;
- if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
- return false;
- if (sscanf(buf, format, &arg1f) < 1)
- return false;
- if (op == '+') { *v = arg0f + arg1f; }
- else if (op == '*') { *v = arg0f * arg1f; }
- else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; }
- else { *v = arg1f; }
- }
- else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
- {
-
-
- if (sscanf(buf, format, p_data) < 1)
- return false;
- }
- else
- {
-
- int v32;
- if (sscanf(buf, format, &v32) < 1)
- return false;
- if (data_type == ImGuiDataType_S8)
- *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
- else if (data_type == ImGuiDataType_U8)
- *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX);
- else if (data_type == ImGuiDataType_S16)
- *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX);
- else if (data_type == ImGuiDataType_U16)
- *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX);
- else
- IM_ASSERT(0);
- }
- return memcmp(&data_backup, p_data, type_info->Size) != 0;
- }
- template<typename T>
- static int DataTypeCompareT(const T* lhs, const T* rhs)
- {
- if (*lhs < *rhs) return -1;
- if (*lhs > *rhs) return +1;
- return 0;
- }
- int ImGui::DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2)
- {
- switch (data_type)
- {
- case ImGuiDataType_S8: return DataTypeCompareT<ImS8 >((const ImS8* )arg_1, (const ImS8* )arg_2);
- case ImGuiDataType_U8: return DataTypeCompareT<ImU8 >((const ImU8* )arg_1, (const ImU8* )arg_2);
- case ImGuiDataType_S16: return DataTypeCompareT<ImS16 >((const ImS16* )arg_1, (const ImS16* )arg_2);
- case ImGuiDataType_U16: return DataTypeCompareT<ImU16 >((const ImU16* )arg_1, (const ImU16* )arg_2);
- case ImGuiDataType_S32: return DataTypeCompareT<ImS32 >((const ImS32* )arg_1, (const ImS32* )arg_2);
- case ImGuiDataType_U32: return DataTypeCompareT<ImU32 >((const ImU32* )arg_1, (const ImU32* )arg_2);
- case ImGuiDataType_S64: return DataTypeCompareT<ImS64 >((const ImS64* )arg_1, (const ImS64* )arg_2);
- case ImGuiDataType_U64: return DataTypeCompareT<ImU64 >((const ImU64* )arg_1, (const ImU64* )arg_2);
- case ImGuiDataType_Float: return DataTypeCompareT<float >((const float* )arg_1, (const float* )arg_2);
- case ImGuiDataType_Double: return DataTypeCompareT<double>((const double*)arg_1, (const double*)arg_2);
- case ImGuiDataType_COUNT: break;
- }
- IM_ASSERT(0);
- return 0;
- }
- template<typename T>
- static bool DataTypeClampT(T* v, const T* v_min, const T* v_max)
- {
-
- if (v_min && *v < *v_min) { *v = *v_min; return true; }
- if (v_max && *v > *v_max) { *v = *v_max; return true; }
- return false;
- }
- bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max)
- {
- switch (data_type)
- {
- case ImGuiDataType_S8: return DataTypeClampT<ImS8 >((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max);
- case ImGuiDataType_U8: return DataTypeClampT<ImU8 >((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max);
- case ImGuiDataType_S16: return DataTypeClampT<ImS16 >((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max);
- case ImGuiDataType_U16: return DataTypeClampT<ImU16 >((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max);
- case ImGuiDataType_S32: return DataTypeClampT<ImS32 >((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max);
- case ImGuiDataType_U32: return DataTypeClampT<ImU32 >((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max);
- case ImGuiDataType_S64: return DataTypeClampT<ImS64 >((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max);
- case ImGuiDataType_U64: return DataTypeClampT<ImU64 >((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max);
- case ImGuiDataType_Float: return DataTypeClampT<float >((float* )p_data, (const float* )p_min, (const float* )p_max);
- case ImGuiDataType_Double: return DataTypeClampT<double>((double*)p_data, (const double*)p_min, (const double*)p_max);
- case ImGuiDataType_COUNT: break;
- }
- IM_ASSERT(0);
- return false;
- }
- static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
- {
- static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
- if (decimal_precision < 0)
- return FLT_MIN;
- return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
- }
- template<typename TYPE>
- static const char* ImAtoi(const char* src, TYPE* output)
- {
- int negative = 0;
- if (*src == '-') { negative = 1; src++; }
- if (*src == '+') { src++; }
- TYPE v = 0;
- while (*src >= '0' && *src <= '9')
- v = (v * 10) + (*src++ - '0');
- *output = negative ? -v : v;
- return src;
- }
- static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
- {
- IM_UNUSED(fmt_out_size);
- const char* fmt_end = ImParseFormatFindEnd(fmt);
- IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size);
- while (fmt < fmt_end)
- {
- char c = *(fmt++);
- if (c != '\'' && c != '$' && c != '_')
- *(fmt_out++) = c;
- }
- *fmt_out = 0;
- }
- template<typename TYPE, typename SIGNEDTYPE>
- TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
- {
- const char* fmt_start = ImParseFormatFindStart(format);
- if (fmt_start[0] != '%' || fmt_start[1] == '%')
- return v;
-
- char fmt_sanitized[32];
- SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
- fmt_start = fmt_sanitized;
-
- char v_str[64];
- ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
- const char* p = v_str;
- while (*p == ' ')
- p++;
- if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
- v = (TYPE)ImAtof(p);
- else
- ImAtoi(p, (SIGNEDTYPE*)&v);
- return v;
- }
- template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
- bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiContext& g = *GImGui;
- const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
- const bool is_clamped = (v_min < v_max);
- const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
- const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
-
- if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
- v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
-
- float adjust_delta = 0.0f;
- if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
- {
- adjust_delta = g.IO.MouseDelta[axis];
- if (g.IO.KeyAlt)
- adjust_delta *= 1.0f / 100.0f;
- if (g.IO.KeyShift)
- adjust_delta *= 10.0f;
- }
- else if (g.ActiveIdSource == ImGuiInputSource_Nav)
- {
- const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
- adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis];
- v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
- }
- adjust_delta *= v_speed;
-
- if (axis == ImGuiAxis_Y)
- adjust_delta = -adjust_delta;
-
- if (is_logarithmic && (v_max - v_min < FLT_MAX) && ((v_max - v_min) > 0.000001f))
- adjust_delta /= (float)(v_max - v_min);
-
-
- bool is_just_activated = g.ActiveIdIsJustActivated;
- bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
- if (is_just_activated || is_already_past_limits_and_pushing_outward)
- {
- g.DragCurrentAccum = 0.0f;
- g.DragCurrentAccumDirty = false;
- }
- else if (adjust_delta != 0.0f)
- {
- g.DragCurrentAccum += adjust_delta;
- g.DragCurrentAccumDirty = true;
- }
- if (!g.DragCurrentAccumDirty)
- return false;
- TYPE v_cur = *v;
- FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
- float logarithmic_zero_epsilon = 0.0f;
- const float zero_deadzone_halfsize = 0.0f;
- if (is_logarithmic)
- {
-
- const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
- logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
-
- float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- float v_new_parametric = v_old_parametric + g.DragCurrentAccum;
- v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- v_old_ref_for_accum_remainder = v_old_parametric;
- }
- else
- {
- v_cur += (SIGNEDTYPE)g.DragCurrentAccum;
- }
-
- if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
- v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
-
- g.DragCurrentAccumDirty = false;
- if (is_logarithmic)
- {
-
- float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder);
- }
- else
- {
- g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v);
- }
-
- if (v_cur == (TYPE)-0)
- v_cur = (TYPE)0;
-
- if (*v != v_cur && is_clamped)
- {
- if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_floating_point))
- v_cur = v_min;
- if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_floating_point))
- v_cur = v_max;
- }
-
- if (*v == v_cur)
- return false;
- *v = v_cur;
- return true;
- }
- bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
- {
-
- IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
- ImGuiContext& g = *GImGui;
- if (g.ActiveId == id)
- {
- if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
- ClearActiveID();
- else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
- ClearActiveID();
- }
- if (g.ActiveId != id)
- return false;
- if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
- return false;
- switch (data_type)
- {
- case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
- case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
- case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
- case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
- case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, flags);
- case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, flags);
- case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, flags);
- case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, flags);
- case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, flags);
- case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, flags);
- case ImGuiDataType_COUNT: break;
- }
- IM_ASSERT(0);
- return false;
- }
- bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const float w = CalcItemWidth();
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
- const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
- const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
- return false;
-
- if (format == NULL)
- format = DataTypeGetInfo(data_type)->PrintFmt;
- else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
- format = PatchFormatStringFloatToInt(format);
-
- const bool hovered = ItemHoverable(frame_bb, id);
- bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
- if (!temp_input_is_active)
- {
- const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
- const bool clicked = (hovered && g.IO.MouseClicked[0]);
- const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
- if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
- {
- SetActiveID(id, window);
- SetFocusID(id, window);
- FocusWindow(window);
- g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
- if (temp_input_allowed)
- if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
- temp_input_is_active = true;
- }
-
- if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
- if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
- {
- g.NavActivateId = g.NavActivateInputId = id;
- g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
- temp_input_is_active = true;
- }
- }
- if (temp_input_is_active)
- {
-
- const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0);
- return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
- }
-
- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
- RenderNavHighlight(frame_bb, id);
- RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
-
- const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, flags);
- if (value_changed)
- MarkItemEdited(id);
-
- char value_buf[64];
- const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
- if (g.LogEnabled)
- LogSetNextTextDecoration("{", "}");
- RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
- if (label_size.x > 0.0f)
- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- return value_changed;
- }
- bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- bool value_changed = false;
- BeginGroup();
- PushID(label);
- PushMultiItemsWidths(components, CalcItemWidth());
- size_t type_size = GDataTypeInfo[data_type].Size;
- for (int i = 0; i < components; i++)
- {
- PushID(i);
- if (i > 0)
- SameLine(0, g.Style.ItemInnerSpacing.x);
- value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, flags);
- PopID();
- PopItemWidth();
- p_data = (void*)((char*)p_data + type_size);
- }
- PopID();
- const char* label_end = FindRenderedTextEnd(label);
- if (label != label_end)
- {
- SameLine(0, g.Style.ItemInnerSpacing.x);
- TextEx(label, label_end);
- }
- EndGroup();
- return value_changed;
- }
- bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- PushID(label);
- BeginGroup();
- PushMultiItemsWidths(2, CalcItemWidth());
- float min_min = (v_min >= v_max) ? -FLT_MAX : v_min;
- float min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max);
- ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0);
- bool value_changed = DragScalar("##min", ImGuiDataType_Float, v_current_min, v_speed, &min_min, &min_max, format, min_flags);
- PopItemWidth();
- SameLine(0, g.Style.ItemInnerSpacing.x);
- float max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min);
- float max_max = (v_min >= v_max) ? FLT_MAX : v_max;
- ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0);
- value_changed |= DragScalar("##max", ImGuiDataType_Float, v_current_max, v_speed, &max_min, &max_max, format_max ? format_max : format, max_flags);
- PopItemWidth();
- SameLine(0, g.Style.ItemInnerSpacing.x);
- TextEx(label, FindRenderedTextEnd(label));
- EndGroup();
- PopID();
- return value_changed;
- }
- bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags);
- }
- bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- PushID(label);
- BeginGroup();
- PushMultiItemsWidths(2, CalcItemWidth());
- int min_min = (v_min >= v_max) ? INT_MIN : v_min;
- int min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max);
- ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0);
- bool value_changed = DragInt("##min", v_current_min, v_speed, min_min, min_max, format, min_flags);
- PopItemWidth();
- SameLine(0, g.Style.ItemInnerSpacing.x);
- int max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min);
- int max_max = (v_min >= v_max) ? INT_MAX : v_max;
- ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0);
- value_changed |= DragInt("##max", v_current_max, v_speed, max_min, max_max, format_max ? format_max : format, max_flags);
- PopItemWidth();
- SameLine(0, g.Style.ItemInnerSpacing.x);
- TextEx(label, FindRenderedTextEnd(label));
- EndGroup();
- PopID();
- return value_changed;
- }
- #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
- bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
- {
- ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None;
- if (power != 1.0f)
- {
- IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
- IM_ASSERT(p_min != NULL && p_max != NULL);
- drag_flags |= ImGuiSliderFlags_Logarithmic;
- }
- return DragScalar(label, data_type, p_data, v_speed, p_min, p_max, format, drag_flags);
- }
- bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
- {
- ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None;
- if (power != 1.0f)
- {
- IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
- IM_ASSERT(p_min != NULL && p_max != NULL);
- drag_flags |= ImGuiSliderFlags_Logarithmic;
- }
- return DragScalarN(label, data_type, p_data, components, v_speed, p_min, p_max, format, drag_flags);
- }
- #endif
- template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
- float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
- {
- if (v_min == v_max)
- return 0.0f;
- IM_UNUSED(data_type);
- const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
- if (is_logarithmic)
- {
- bool flipped = v_max < v_min;
- if (flipped)
- ImSwap(v_min, v_max);
-
- FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
- FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max;
-
- if ((v_min == 0.0f) && (v_max < 0.0f))
- v_min_fudged = -logarithmic_zero_epsilon;
- else if ((v_max == 0.0f) && (v_min < 0.0f))
- v_max_fudged = -logarithmic_zero_epsilon;
- float result;
- if (v_clamped <= v_min_fudged)
- result = 0.0f;
- else if (v_clamped >= v_max_fudged)
- result = 1.0f;
- else if ((v_min * v_max) < 0.0f)
- {
- float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min);
- float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
- float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize;
- if (v == 0.0f)
- result = zero_point_center;
- else if (v < 0.0f)
- result = (1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(-v_min_fudged / logarithmic_zero_epsilon))) * zero_point_snap_L;
- else
- result = zero_point_snap_R + ((float)(ImLog((FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(v_max_fudged / logarithmic_zero_epsilon)) * (1.0f - zero_point_snap_R));
- }
- else if ((v_min < 0.0f) || (v_max < 0.0f))
- result = 1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / -v_max_fudged) / ImLog(-v_min_fudged / -v_max_fudged));
- else
- result = (float)(ImLog((FLOATTYPE)v_clamped / v_min_fudged) / ImLog(v_max_fudged / v_min_fudged));
- return flipped ? (1.0f - result) : result;
- }
-
- return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min));
- }
- template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
- TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
- {
- if (v_min == v_max)
- return v_min;
- const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
- TYPE result;
- if (is_logarithmic)
- {
-
- if (t <= 0.0f)
- result = v_min;
- else if (t >= 1.0f)
- result = v_max;
- else
- {
- bool flipped = v_max < v_min;
-
- FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
- FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max;
- if (flipped)
- ImSwap(v_min_fudged, v_max_fudged);
-
- if ((v_max == 0.0f) && (v_min < 0.0f))
- v_max_fudged = -logarithmic_zero_epsilon;
- float t_with_flip = flipped ? (1.0f - t) : t;
- if ((v_min * v_max) < 0.0f)
- {
- float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min);
- float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
- float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize;
- if (t_with_flip >= zero_point_snap_L && t_with_flip <= zero_point_snap_R)
- result = (TYPE)0.0f;
- else if (t_with_flip < zero_point_center)
- result = (TYPE)-(logarithmic_zero_epsilon * ImPow(-v_min_fudged / logarithmic_zero_epsilon, (FLOATTYPE)(1.0f - (t_with_flip / zero_point_snap_L))));
- else
- result = (TYPE)(logarithmic_zero_epsilon * ImPow(v_max_fudged / logarithmic_zero_epsilon, (FLOATTYPE)((t_with_flip - zero_point_snap_R) / (1.0f - zero_point_snap_R))));
- }
- else if ((v_min < 0.0f) || (v_max < 0.0f))
- result = (TYPE)-(-v_max_fudged * ImPow(-v_min_fudged / -v_max_fudged, (FLOATTYPE)(1.0f - t_with_flip)));
- else
- result = (TYPE)(v_min_fudged * ImPow(v_max_fudged / v_min_fudged, (FLOATTYPE)t_with_flip));
- }
- }
- else
- {
-
- if (is_floating_point)
- {
- result = ImLerp(v_min, v_max, t);
- }
- else
- {
-
-
-
-
- if (t < 1.0)
- {
- FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t;
- result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5)));
- }
- else
- {
- result = v_max;
- }
- }
- }
- return result;
- }
- template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
- bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb)
- {
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
- const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
- const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
- const float grab_padding = 2.0f;
- const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
- float grab_sz = style.GrabMinSize;
- SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
- if (!is_floating_point && v_range >= 0)
- grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize);
- grab_sz = ImMin(grab_sz, slider_sz);
- const float slider_usable_sz = slider_sz - grab_sz;
- const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f;
- const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f;
- float logarithmic_zero_epsilon = 0.0f;
- float zero_deadzone_halfsize = 0.0f;
- if (is_logarithmic)
- {
-
- const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
- logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
- zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f);
- }
-
- bool value_changed = false;
- if (g.ActiveId == id)
- {
- bool set_new_value = false;
- float clicked_t = 0.0f;
- if (g.ActiveIdSource == ImGuiInputSource_Mouse)
- {
- if (!g.IO.MouseDown[0])
- {
- ClearActiveID();
- }
- else
- {
- const float mouse_abs_pos = g.IO.MousePos[axis];
- clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;
- if (axis == ImGuiAxis_Y)
- clicked_t = 1.0f - clicked_t;
- set_new_value = true;
- }
- }
- else if (g.ActiveIdSource == ImGuiInputSource_Nav)
- {
- if (g.ActiveIdIsJustActivated)
- {
- g.SliderCurrentAccum = 0.0f;
- g.SliderCurrentAccumDirty = false;
- }
- const ImVec2 input_delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f);
- float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y;
- if (input_delta != 0.0f)
- {
- const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
- if (decimal_precision > 0)
- {
- input_delta /= 100.0f;
- if (IsNavInputDown(ImGuiNavInput_TweakSlow))
- input_delta /= 10.0f;
- }
- else
- {
- if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow))
- input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range;
- else
- input_delta /= 100.0f;
- }
- if (IsNavInputDown(ImGuiNavInput_TweakFast))
- input_delta *= 10.0f;
- g.SliderCurrentAccum += input_delta;
- g.SliderCurrentAccumDirty = true;
- }
- float delta = g.SliderCurrentAccum;
- if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
- {
- ClearActiveID();
- }
- else if (g.SliderCurrentAccumDirty)
- {
- clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f))
- {
- set_new_value = false;
- g.SliderCurrentAccum = 0.0f;
- }
- else
- {
- set_new_value = true;
- float old_clicked_t = clicked_t;
- clicked_t = ImSaturate(clicked_t + delta);
-
- TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
- v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new);
- float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- if (delta > 0)
- g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta);
- else
- g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta);
- }
- g.SliderCurrentAccumDirty = false;
- }
- }
- if (set_new_value)
- {
- TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
-
- if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
- v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new);
-
- if (*v != v_new)
- {
- *v = v_new;
- value_changed = true;
- }
- }
- }
- if (slider_sz < 1.0f)
- {
- *out_grab_bb = ImRect(bb.Min, bb.Min);
- }
- else
- {
-
- float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
- if (axis == ImGuiAxis_Y)
- grab_t = 1.0f - grab_t;
- const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
- if (axis == ImGuiAxis_X)
- *out_grab_bb = ImRect(grab_pos - grab_sz * 0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz * 0.5f, bb.Max.y - grab_padding);
- else
- *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f);
- }
- return value_changed;
- }
- bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb)
- {
-
- IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
- ImGuiContext& g = *GImGui;
- if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
- return false;
- switch (data_type)
- {
- case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
- case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
- case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
- case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
- case ImGuiDataType_S32:
- IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN / 2 && *(const ImS32*)p_max <= IM_S32_MAX / 2);
- return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_U32:
- IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX / 2);
- return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_S64:
- IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN / 2 && *(const ImS64*)p_max <= IM_S64_MAX / 2);
- return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_U64:
- IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX / 2);
- return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_Float:
- IM_ASSERT(*(const float*)p_min >= -FLT_MAX / 2.0f && *(const float*)p_max <= FLT_MAX / 2.0f);
- return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_Double:
- IM_ASSERT(*(const double*)p_min >= -DBL_MAX / 2.0f && *(const double*)p_max <= DBL_MAX / 2.0f);
- return SliderBehaviorT<double, double, double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, flags, out_grab_bb);
- case ImGuiDataType_COUNT: break;
- }
- IM_ASSERT(0);
- return false;
- }
- bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const float w = CalcItemWidth();
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
- const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
- const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
- return false;
-
- if (format == NULL)
- format = DataTypeGetInfo(data_type)->PrintFmt;
- else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
- format = PatchFormatStringFloatToInt(format);
-
- const bool hovered = ItemHoverable(frame_bb, id);
- bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
- if (!temp_input_is_active)
- {
- const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
- const bool clicked = (hovered && g.IO.MouseClicked[0]);
- if (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id)
- {
- SetActiveID(id, window);
- SetFocusID(id, window);
- FocusWindow(window);
- g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
- if (temp_input_allowed && (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id))
- temp_input_is_active = true;
- }
- }
- if (temp_input_is_active)
- {
-
- const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0;
- return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
- }
-
- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
- RenderNavHighlight(frame_bb, id);
- RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
-
- ImRect grab_bb;
- const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags, &grab_bb);
- if (value_changed)
- MarkItemEdited(id);
-
- if (grab_bb.Max.x > grab_bb.Min.x)
- window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
-
- char value_buf[64];
- const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
- if (g.LogEnabled)
- LogSetNextTextDecoration("{", "}");
- RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
- if (label_size.x > 0.0f)
- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- return value_changed;
- }
- bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- bool value_changed = false;
- BeginGroup();
- PushID(label);
- PushMultiItemsWidths(components, CalcItemWidth());
- size_t type_size = GDataTypeInfo[data_type].Size;
- for (int i = 0; i < components; i++)
- {
- PushID(i);
- if (i > 0)
- SameLine(0, g.Style.ItemInnerSpacing.x);
- value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, flags);
- PopID();
- PopItemWidth();
- v = (void*)((char*)v + type_size);
- }
- PopID();
- const char* label_end = FindRenderedTextEnd(label);
- if (label != label_end)
- {
- SameLine(0, g.Style.ItemInnerSpacing.x);
- TextEx(label, label_end);
- }
- EndGroup();
- return value_changed;
- }
- bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags)
- {
- if (format == NULL)
- format = "%.0f deg";
- float v_deg = (*v_rad) * 360.0f / (2 * IM_PI);
- bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags);
- *v_rad = v_deg * (2 * IM_PI) / 360.0f;
- return value_changed;
- }
- bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags);
- }
- bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags);
- }
- bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
- const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
- ItemSize(bb, style.FramePadding.y);
- if (!ItemAdd(frame_bb, id))
- return false;
-
- if (format == NULL)
- format = DataTypeGetInfo(data_type)->PrintFmt;
- else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
- format = PatchFormatStringFloatToInt(format);
- const bool hovered = ItemHoverable(frame_bb, id);
- if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavActivateInputId == id)
- {
- SetActiveID(id, window);
- SetFocusID(id, window);
- FocusWindow(window);
- g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
- }
-
- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
- RenderNavHighlight(frame_bb, id);
- RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
-
- ImRect grab_bb;
- const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags | ImGuiSliderFlags_Vertical, &grab_bb);
- if (value_changed)
- MarkItemEdited(id);
-
- if (grab_bb.Max.y > grab_bb.Min.y)
- window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
-
-
- char value_buf[64];
- const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
- RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
- if (label_size.x > 0.0f)
- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
- return value_changed;
- }
- bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
- {
- return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags);
- }
- bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
- {
- return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags);
- }
- #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
- bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
- {
- ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None;
- if (power != 1.0f)
- {
- IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
- slider_flags |= ImGuiSliderFlags_Logarithmic;
- }
- return SliderScalar(label, data_type, p_data, p_min, p_max, format, slider_flags);
- }
- bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
- {
- ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None;
- if (power != 1.0f)
- {
- IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
- slider_flags |= ImGuiSliderFlags_Logarithmic;
- }
- return SliderScalarN(label, data_type, v, components, v_min, v_max, format, slider_flags);
- }
- #endif
- const char* ImParseFormatFindStart(const char* fmt)
- {
- while (char c = fmt[0])
- {
- if (c == '%' && fmt[1] != '%')
- return fmt;
- else if (c == '%')
- fmt++;
- fmt++;
- }
- return fmt;
- }
- const char* ImParseFormatFindEnd(const char* fmt)
- {
-
- if (fmt[0] != '%')
- return fmt;
- const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A'));
- const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a'));
- for (char c; (c = *fmt) != 0; fmt++)
- {
- if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0)
- return fmt + 1;
- if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0)
- return fmt + 1;
- }
- return fmt;
- }
- const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_size)
- {
- const char* fmt_start = ImParseFormatFindStart(fmt);
- if (fmt_start[0] != '%')
- return fmt;
- const char* fmt_end = ImParseFormatFindEnd(fmt_start);
- if (fmt_end[0] == 0)
- return fmt_start;
- ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size));
- return buf;
- }
- int ImParseFormatPrecision(const char* fmt, int default_precision)
- {
- fmt = ImParseFormatFindStart(fmt);
- if (fmt[0] != '%')
- return default_precision;
- fmt++;
- while (*fmt >= '0' && *fmt <= '9')
- fmt++;
- int precision = INT_MAX;
- if (*fmt == '.')
- {
- fmt = ImAtoi<int>(fmt + 1, &precision);
- if (precision < 0 || precision > 99)
- precision = default_precision;
- }
- if (*fmt == 'e' || *fmt == 'E')
- precision = -1;
- if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX)
- precision = -1;
- return (precision == INT_MAX) ? default_precision : precision;
- }
- bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
- {
-
-
- ImGuiContext& g = *GImGui;
- const bool init = (g.TempInputId != id);
- if (init)
- ClearActiveID();
- g.CurrentWindow->DC.CursorPos = bb.Min;
- bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
- if (init)
- {
-
- IM_ASSERT(g.ActiveId == id);
- g.TempInputId = g.ActiveId;
- }
- return value_changed;
- }
- bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
- {
- ImGuiContext& g = *GImGui;
- char fmt_buf[32];
- char data_buf[32];
- format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
- DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
- ImStrTrimBlanks(data_buf);
- ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited;
- flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
- bool value_changed = false;
- if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
- {
-
- size_t data_type_size = DataTypeGetInfo(data_type)->Size;
- ImGuiDataTypeTempStorage data_backup;
- memcpy(&data_backup, p_data, data_type_size);
-
- DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
- if (p_clamp_min || p_clamp_max)
- {
- if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
- ImSwap(p_clamp_min, p_clamp_max);
- DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
- }
-
- value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
- if (value_changed)
- MarkItemEdited(id);
- }
- return value_changed;
- }
- bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- ImGuiStyle& style = g.Style;
- if (format == NULL)
- format = DataTypeGetInfo(data_type)->PrintFmt;
- char buf[64];
- DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
- bool value_changed = false;
- if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
- flags |= ImGuiInputTextFlags_CharsDecimal;
- flags |= ImGuiInputTextFlags_AutoSelectAll;
- flags |= ImGuiInputTextFlags_NoMarkEdited;
- if (p_step != NULL)
- {
- const float button_size = GetFrameHeight();
- BeginGroup();
- PushID(label);
- SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
- if (InputText("", buf, IM_ARRAYSIZE(buf), flags))
- value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
-
- const ImVec2 backup_frame_padding = style.FramePadding;
- style.FramePadding.x = style.FramePadding.y;
- ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups;
- if (flags & ImGuiInputTextFlags_ReadOnly)
- BeginDisabled();
- SameLine(0, style.ItemInnerSpacing.x);
- if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
- {
- DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
- value_changed = true;
- }
- SameLine(0, style.ItemInnerSpacing.x);
- if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
- {
- DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
- value_changed = true;
- }
- if (flags & ImGuiInputTextFlags_ReadOnly)
- EndDisabled();
- const char* label_end = FindRenderedTextEnd(label);
- if (label != label_end)
- {
- SameLine(0, style.ItemInnerSpacing.x);
- TextEx(label, label_end);
- }
- style.FramePadding = backup_frame_padding;
- PopID();
- EndGroup();
- }
- else
- {
- if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
- value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
- }
- if (value_changed)
- MarkItemEdited(g.LastItemData.ID);
- return value_changed;
- }
- bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- bool value_changed = false;
- BeginGroup();
- PushID(label);
- PushMultiItemsWidths(components, CalcItemWidth());
- size_t type_size = GDataTypeInfo[data_type].Size;
- for (int i = 0; i < components; i++)
- {
- PushID(i);
- if (i > 0)
- SameLine(0, g.Style.ItemInnerSpacing.x);
- value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags);
- PopID();
- PopItemWidth();
- p_data = (void*)((char*)p_data + type_size);
- }
- PopID();
- const char* label_end = FindRenderedTextEnd(label);
- if (label != label_end)
- {
- SameLine(0.0f, g.Style.ItemInnerSpacing.x);
- TextEx(label, label_end);
- }
- EndGroup();
- return value_changed;
- }
- bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
- {
- flags |= ImGuiInputTextFlags_CharsScientific;
- return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags);
- }
- bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
- }
- bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
- }
- bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
- }
- bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags)
- {
-
- const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
- return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags);
- }
- bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags);
- }
- bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags);
- }
- bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
- {
- return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags);
- }
- bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
- {
- flags |= ImGuiInputTextFlags_CharsScientific;
- return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags);
- }
- bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
- {
- IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline));
- return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
- }
- bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
- {
- return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
- }
- bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
- {
- IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline));
- return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
- }
- static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
- {
- int line_count = 0;
- const char* s = text_begin;
- while (char c = *s++)
- if (c == '\n')
- line_count++;
- s--;
- if (s[0] != '\n' && s[0] != '\r')
- line_count++;
- *out_text_end = s;
- return line_count;
- }
- static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
- {
- ImGuiContext& g = *GImGui;
- ImFont* font = g.Font;
- const float line_height = g.FontSize;
- const float scale = line_height / font->FontSize;
- ImVec2 text_size = ImVec2(0, 0);
- float line_width = 0.0f;
- const ImWchar* s = text_begin;
- while (s < text_end)
- {
- unsigned int c = (unsigned int)(*s++);
- if (c == '\n')
- {
- text_size.x = ImMax(text_size.x, line_width);
- text_size.y += line_height;
- line_width = 0.0f;
- if (stop_on_new_line)
- break;
- continue;
- }
- if (c == '\r')
- continue;
- const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
- line_width += char_width;
- }
- if (text_size.x < line_width)
- text_size.x = line_width;
- if (out_offset)
- *out_offset = ImVec2(line_width, text_size.y + line_height);
- if (line_width > 0 || text_size.y == 0.0f)
- text_size.y += line_height;
- if (remaining)
- *remaining = s;
- return text_size;
- }
- namespace ImStb
- {
- static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; }
- static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { return obj->TextW[idx]; }
- static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
- static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
- static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
- static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
- {
- const ImWchar* text = obj->TextW.Data;
- const ImWchar* text_remaining = NULL;
- const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
- r->x0 = 0.0f;
- r->x1 = size.x;
- r->baseline_y_delta = size.y;
- r->ymin = 0.0f;
- r->ymax = size.y;
- r->num_chars = (int)(text_remaining - (text + line_start_idx));
- }
- static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
- static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
- static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
- #ifdef __APPLE__
- static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
- static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
- #else
- static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
- #endif
- #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL
- #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
- static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
- {
- ImWchar* dst = obj->TextW.Data + pos;
-
- obj->Edited = true;
- obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
- obj->CurLenW -= n;
-
- const ImWchar* src = obj->TextW.Data + pos + n;
- while (ImWchar c = *src++)
- *dst++ = c;
- *dst = '\0';
- }
- static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len)
- {
- const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
- const int text_len = obj->CurLenW;
- IM_ASSERT(pos <= text_len);
- const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
- if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
- return false;
-
- if (new_text_len + text_len + 1 > obj->TextW.Size)
- {
- if (!is_resizable)
- return false;
- IM_ASSERT(text_len < obj->TextW.Size);
- obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
- }
- ImWchar* text = obj->TextW.Data;
- if (pos != text_len)
- memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));
- memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
- obj->Edited = true;
- obj->CurLenW += new_text_len;
- obj->CurLenA += new_text_len_utf8;
- obj->TextW[obj->CurLenW] = '\0';
- return true;
- }
- #define STB_TEXTEDIT_K_LEFT 0x200000
- #define STB_TEXTEDIT_K_RIGHT 0x200001
- #define STB_TEXTEDIT_K_UP 0x200002
- #define STB_TEXTEDIT_K_DOWN 0x200003
- #define STB_TEXTEDIT_K_LINESTART 0x200004
- #define STB_TEXTEDIT_K_LINEEND 0x200005
- #define STB_TEXTEDIT_K_TEXTSTART 0x200006
- #define STB_TEXTEDIT_K_TEXTEND 0x200007
- #define STB_TEXTEDIT_K_DELETE 0x200008
- #define STB_TEXTEDIT_K_BACKSPACE 0x200009
- #define STB_TEXTEDIT_K_UNDO 0x20000A
- #define STB_TEXTEDIT_K_REDO 0x20000B
- #define STB_TEXTEDIT_K_WORDLEFT 0x20000C
- #define STB_TEXTEDIT_K_WORDRIGHT 0x20000D
- #define STB_TEXTEDIT_K_PGUP 0x20000E
- #define STB_TEXTEDIT_K_PGDOWN 0x20000F
- #define STB_TEXTEDIT_K_SHIFT 0x400000
- #define STB_TEXTEDIT_IMPLEMENTATION
- #include "imstb_textedit.h"
- static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len)
- {
- stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
- ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
- if (text_len <= 0)
- return;
- if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len))
- {
- state->cursor = text_len;
- state->has_preferred_x = 0;
- return;
- }
- IM_ASSERT(0);
- }
- }
- void ImGuiInputTextState::OnKeyPressed(int key)
- {
- stb_textedit_key(this, &Stb, key);
- CursorFollow = true;
- CursorAnimReset();
- }
- ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
- {
- memset(this, 0, sizeof(*this));
- }
- void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
- {
- IM_ASSERT(pos + bytes_count <= BufTextLen);
- char* dst = Buf + pos;
- const char* src = Buf + pos + bytes_count;
- while (char c = *src++)
- *dst++ = c;
- *dst = '\0';
- if (CursorPos >= pos + bytes_count)
- CursorPos -= bytes_count;
- else if (CursorPos >= pos)
- CursorPos = pos;
- SelectionStart = SelectionEnd = CursorPos;
- BufDirty = true;
- BufTextLen -= bytes_count;
- }
- void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
- {
- const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
- const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
- if (new_text_len + BufTextLen >= BufSize)
- {
- if (!is_resizable)
- return;
-
- ImGuiContext& g = *GImGui;
- ImGuiInputTextState* edit_state = &g.InputTextState;
- IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
- IM_ASSERT(Buf == edit_state->TextA.Data);
- int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
- edit_state->TextA.reserve(new_buf_size + 1);
- Buf = edit_state->TextA.Data;
- BufSize = edit_state->BufCapacityA = new_buf_size;
- }
- if (BufTextLen != pos)
- memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
- memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
- Buf[BufTextLen + new_text_len] = '\0';
- if (CursorPos >= pos)
- CursorPos += new_text_len;
- SelectionStart = SelectionEnd = CursorPos;
- BufDirty = true;
- BufTextLen += new_text_len;
- }
- static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source)
- {
- IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard);
- unsigned int c = *p_char;
-
- bool apply_named_filters = true;
- if (c < 0x20)
- {
- bool pass = false;
- pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline));
- pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput));
- if (!pass)
- return false;
- apply_named_filters = false;
- }
- if (input_source != ImGuiInputSource_Clipboard)
- {
-
- if (c == 127)
- return false;
-
- if (c >= 0xE000 && c <= 0xF8FF)
- return false;
- }
-
- if (c > IM_UNICODE_CODEPOINT_MAX)
- return false;
-
- if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)))
- {
-
-
-
-
-
- ImGuiContext& g = *GImGui;
- const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint;
-
- if (flags & ImGuiInputTextFlags_CharsDecimal)
- if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
- return false;
-
- if (flags & ImGuiInputTextFlags_CharsScientific)
- if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
- return false;
-
- if (flags & ImGuiInputTextFlags_CharsHexadecimal)
- if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
- return false;
-
- if (flags & ImGuiInputTextFlags_CharsUppercase)
- if (c >= 'a' && c <= 'z')
- *p_char = (c += (unsigned int)('A' - 'a'));
- if (flags & ImGuiInputTextFlags_CharsNoBlank)
- if (ImCharIsBlankW(c))
- return false;
- }
-
- if (flags & ImGuiInputTextFlags_CallbackCharFilter)
- {
- ImGuiInputTextCallbackData callback_data;
- memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
- callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
- callback_data.EventChar = (ImWchar)c;
- callback_data.Flags = flags;
- callback_data.UserData = user_data;
- if (callback(&callback_data) != 0)
- return false;
- *p_char = callback_data.EventChar;
- if (!callback_data.EventChar)
- return false;
- }
- return true;
- }
- bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- IM_ASSERT(buf != NULL && buf_size >= 0);
- IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline)));
- IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput)));
- ImGuiContext& g = *GImGui;
- ImGuiIO& io = g.IO;
- const ImGuiStyle& style = g.Style;
- const bool RENDER_SELECTION_WHEN_INACTIVE = false;
- const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
- const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
- const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
- const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
- const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
- if (is_resizable)
- IM_ASSERT(callback != NULL);
- if (is_multiline)
- BeginGroup();
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f);
- const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
- const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size);
- ImGuiWindow* draw_window = window;
- ImVec2 inner_size = frame_size;
- ImGuiItemStatusFlags item_status_flags = 0;
- if (is_multiline)
- {
- ImVec2 backup_pos = window->DC.CursorPos;
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
- {
- EndGroup();
- return false;
- }
- item_status_flags = g.LastItemData.StatusFlags;
- window->DC.CursorPos = backup_pos;
-
-
- PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
- PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
- PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
- bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove);
- PopStyleVar(2);
- PopStyleColor();
- if (!child_visible)
- {
- EndChild();
- EndGroup();
- return false;
- }
- draw_window = g.CurrentWindow;
- draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent);
- draw_window->DC.CursorPos += style.FramePadding;
- inner_size.x -= draw_window->ScrollbarSizes.x;
- }
- else
- {
-
- ItemSize(total_bb, style.FramePadding.y);
- if (!(flags & ImGuiInputTextFlags_MergedItem))
- if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
- return false;
- item_status_flags = g.LastItemData.StatusFlags;
- }
- const bool hovered = ItemHoverable(frame_bb, id);
- if (hovered)
- g.MouseCursor = ImGuiMouseCursor_TextInput;
-
- ImGuiInputTextState* state = GetInputTextState(id);
- const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
- const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
- const bool user_clicked = hovered && io.MouseClicked[0];
- const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
- const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
- bool clear_active_id = false;
- bool select_all = false;
- float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
- const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
- const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
- const bool init_state = (init_make_active || user_scroll_active);
- if ((init_state && g.ActiveId != id) || init_changed_specs)
- {
-
- state = &g.InputTextState;
- state->CursorAnimReset();
-
-
- const int buf_len = (int)strlen(buf);
- state->InitialTextA.resize(buf_len + 1);
- memcpy(state->InitialTextA.Data, buf, buf_len + 1);
-
- const char* buf_end = NULL;
- state->TextW.resize(buf_size + 1);
- state->TextA.resize(0);
- state->TextAIsValid = false;
- state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end);
- state->CurLenA = (int)(buf_end - buf);
-
-
- const bool recycle_state = (state->ID == id && !init_changed_specs);
- if (recycle_state)
- {
-
-
- state->CursorClamp();
- }
- else
- {
- state->ID = id;
- state->ScrollX = 0.0f;
- stb_textedit_initialize_state(&state->Stb, !is_multiline);
- }
- if (!is_multiline)
- {
- if (flags & ImGuiInputTextFlags_AutoSelectAll)
- select_all = true;
- if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
- select_all = true;
- if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl))
- select_all = true;
- }
- if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
- state->Stb.insert_mode = 1;
- }
- if (g.ActiveId != id && init_make_active)
- {
- IM_ASSERT(state && state->ID == id);
- SetActiveID(id, window);
- SetFocusID(id, window);
- FocusWindow(window);
-
- IM_ASSERT(ImGuiNavInput_COUNT < 32);
- g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
- if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
- g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
- g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);
- g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End);
- if (is_multiline)
- g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown);
- if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput))
- g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab);
- }
-
- if (g.ActiveId == id && state == NULL)
- ClearActiveID();
-
- if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active)
- clear_active_id = true;
-
- const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
- bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
- bool value_changed = false;
- bool enter_pressed = false;
-
-
- if (is_readonly && state != NULL && (render_cursor || render_selection))
- {
- const char* buf_end = NULL;
- state->TextW.resize(buf_size + 1);
- state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end);
- state->CurLenA = (int)(buf_end - buf);
- state->CursorClamp();
- render_selection &= state->HasSelection();
- }
-
- const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid;
- const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
-
- if (is_password && !is_displaying_hint)
- {
- const ImFontGlyph* glyph = g.Font->FindGlyph('*');
- ImFont* password_font = &g.InputTextPasswordFont;
- password_font->FontSize = g.Font->FontSize;
- password_font->Scale = g.Font->Scale;
- password_font->Ascent = g.Font->Ascent;
- password_font->Descent = g.Font->Descent;
- password_font->ContainerAtlas = g.Font->ContainerAtlas;
- password_font->FallbackGlyph = glyph;
- password_font->FallbackAdvanceX = glyph->AdvanceX;
- IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
- PushFont(password_font);
- }
-
- int backup_current_text_length = 0;
- if (g.ActiveId == id)
- {
- IM_ASSERT(state != NULL);
- backup_current_text_length = state->CurLenA;
- state->Edited = false;
- state->BufCapacityA = buf_size;
- state->Flags = flags;
- state->UserCallback = callback;
- state->UserCallbackData = callback_user_data;
-
-
- g.ActiveIdAllowOverlap = !io.MouseDown[0];
- g.WantTextInputNextFrame = 1;
-
- const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
- const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
- const bool is_osx = io.ConfigMacOSXBehaviors;
- if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
- {
- state->SelectAll();
- state->SelectedAllMouseLock = true;
- }
- else if (hovered && is_osx && io.MouseDoubleClicked[0])
- {
-
- state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
- state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
- }
- else if (io.MouseClicked[0] && !state->SelectedAllMouseLock)
- {
- if (hovered)
- {
- stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
- state->CursorAnimReset();
- }
- }
- else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
- {
- stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y);
- state->CursorAnimReset();
- state->CursorFollow = true;
- }
- if (state->SelectedAllMouseLock && !io.MouseDown[0])
- state->SelectedAllMouseLock = false;
-
-
- const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
- if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
- if (!io.InputQueueCharacters.contains('\t'))
- {
- unsigned int c = '\t';
- if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
- state->OnKeyPressed((int)c);
- }
-
-
- if (io.InputQueueCharacters.Size > 0)
- {
- if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
- for (int n = 0; n < io.InputQueueCharacters.Size; n++)
- {
-
- unsigned int c = (unsigned int)io.InputQueueCharacters[n];
- if (c == '\t' && io.KeyShift)
- continue;
- if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
- state->OnKeyPressed((int)c);
- }
-
- io.InputQueueCharacters.resize(0);
- }
- }
-
- bool cancel_edit = false;
- if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)
- {
- IM_ASSERT(state != NULL);
- IM_ASSERT(io.KeyMods == GetMergedKeyModFlags() && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
- const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1);
- state->Stb.row_count_per_page = row_count_per_page;
- const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
- const bool is_osx = io.ConfigMacOSXBehaviors;
- const bool is_osx_shift_shortcut = is_osx && (io.KeyMods == (ImGuiKeyModFlags_Super | ImGuiKeyModFlags_Shift));
- const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl;
- const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt;
- const bool is_ctrl_key_only = (io.KeyMods == ImGuiKeyModFlags_Ctrl);
- const bool is_shift_key_only = (io.KeyMods == ImGuiKeyModFlags_Shift);
- const bool is_shortcut_key = g.IO.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiKeyModFlags_Super) : (io.KeyMods == ImGuiKeyModFlags_Ctrl);
- const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
- const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection());
- const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_readonly;
- const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable);
- const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable;
-
- const bool is_validate_enter = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter);
- const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressedMap(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
- const bool is_cancel = IsKeyPressedMap(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed);
- if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
- else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
- else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
- else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
- {
- if (!state->HasSelection())
- {
- if (is_wordmove_key_down)
- state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT);
- else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl)
- state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT);
- }
- state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
- }
- else if (is_validate_enter)
- {
- bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
- if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
- {
- enter_pressed = clear_active_id = true;
- }
- else if (!is_readonly)
- {
- unsigned int c = '\n';
- if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
- state->OnKeyPressed((int)c);
- }
- }
- else if (is_validate_nav)
- {
- IM_ASSERT(!is_validate_enter);
- enter_pressed = clear_active_id = true;
- }
- else if (is_cancel)
- {
- clear_active_id = cancel_edit = true;
- }
- else if (is_undo || is_redo)
- {
- state->OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO);
- state->ClearSelection();
- }
- else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
- {
- state->SelectAll();
- state->CursorFollow = true;
- }
- else if (is_cut || is_copy)
- {
-
- if (io.SetClipboardTextFn)
- {
- const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0;
- const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW;
- const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
- char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
- ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
- SetClipboardText(clipboard_data);
- MemFree(clipboard_data);
- }
- if (is_cut)
- {
- if (!state->HasSelection())
- state->SelectAll();
- state->CursorFollow = true;
- stb_textedit_cut(state, &state->Stb);
- }
- }
- else if (is_paste)
- {
- if (const char* clipboard = GetClipboardText())
- {
-
- const int clipboard_len = (int)strlen(clipboard);
- ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar));
- int clipboard_filtered_len = 0;
- for (const char* s = clipboard; *s; )
- {
- unsigned int c;
- s += ImTextCharFromUtf8(&c, s, NULL);
- if (c == 0)
- break;
- if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard))
- continue;
- clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
- }
- clipboard_filtered[clipboard_filtered_len] = 0;
- if (clipboard_filtered_len > 0)
- {
- stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len);
- state->CursorFollow = true;
- }
- MemFree(clipboard_filtered);
- }
- }
-
- render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
- }
-
- if (g.ActiveId == id)
- {
- IM_ASSERT(state != NULL);
- const char* apply_new_text = NULL;
- int apply_new_text_length = 0;
- if (cancel_edit)
- {
-
- if (!is_readonly && strcmp(buf, state->InitialTextA.Data) != 0)
- {
-
- apply_new_text = state->InitialTextA.Data;
- apply_new_text_length = state->InitialTextA.Size - 1;
- ImVector<ImWchar> w_text;
- if (apply_new_text_length > 0)
- {
- w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1);
- ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length);
- }
- stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0);
- }
- }
-
-
-
- bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
- if (apply_edit_back_to_user_buffer)
- {
-
-
-
-
- if (!is_readonly)
- {
- state->TextAIsValid = true;
- state->TextA.resize(state->TextW.Size * 4 + 1);
- ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL);
- }
-
- if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
- {
- IM_ASSERT(callback != NULL);
-
- ImGuiInputTextFlags event_flag = 0;
- ImGuiKey event_key = ImGuiKey_COUNT;
- if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))
- {
- event_flag = ImGuiInputTextFlags_CallbackCompletion;
- event_key = ImGuiKey_Tab;
- }
- else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow))
- {
- event_flag = ImGuiInputTextFlags_CallbackHistory;
- event_key = ImGuiKey_UpArrow;
- }
- else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))
- {
- event_flag = ImGuiInputTextFlags_CallbackHistory;
- event_key = ImGuiKey_DownArrow;
- }
- else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited)
- {
- event_flag = ImGuiInputTextFlags_CallbackEdit;
- }
- else if (flags & ImGuiInputTextFlags_CallbackAlways)
- {
- event_flag = ImGuiInputTextFlags_CallbackAlways;
- }
- if (event_flag)
- {
- ImGuiInputTextCallbackData callback_data;
- memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
- callback_data.EventFlag = event_flag;
- callback_data.Flags = flags;
- callback_data.UserData = callback_user_data;
- callback_data.EventKey = event_key;
- callback_data.Buf = state->TextA.Data;
- callback_data.BufTextLen = state->CurLenA;
- callback_data.BufSize = state->BufCapacityA;
- callback_data.BufDirty = false;
-
- ImWchar* text = state->TextW.Data;
- const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor);
- const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start);
- const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end);
-
- callback(&callback_data);
-
- IM_ASSERT(callback_data.Buf == state->TextA.Data);
- IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
- IM_ASSERT(callback_data.Flags == flags);
- const bool buf_dirty = callback_data.BufDirty;
- if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
- if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
- if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
- if (buf_dirty)
- {
- IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf));
- if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
- state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length));
- state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL);
- state->CurLenA = callback_data.BufTextLen;
- state->CursorAnimReset();
- }
- }
- }
-
- if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
- {
- apply_new_text = state->TextA.Data;
- apply_new_text_length = state->CurLenA;
- }
- }
-
- if (apply_new_text)
- {
-
-
-
- IM_ASSERT(apply_new_text_length >= 0);
- if (is_resizable)
- {
- ImGuiInputTextCallbackData callback_data;
- callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
- callback_data.Flags = flags;
- callback_data.Buf = buf;
- callback_data.BufTextLen = apply_new_text_length;
- callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
- callback_data.UserData = callback_user_data;
- callback(&callback_data);
- buf = callback_data.Buf;
- buf_size = callback_data.BufSize;
- apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
- IM_ASSERT(apply_new_text_length <= buf_size);
- }
-
-
- ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
- value_changed = true;
- }
-
- state->Flags = ImGuiInputTextFlags_None;
- state->UserCallback = NULL;
- state->UserCallbackData = NULL;
- }
-
- if (clear_active_id && g.ActiveId == id)
- ClearActiveID();
-
- if (!is_multiline)
- {
- RenderNavHighlight(frame_bb, id);
- RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
- }
- const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y);
- ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
- ImVec2 text_size(0.0f, 0.0f);
-
-
-
- const int buf_display_max_length = 2 * 1024 * 1024;
- const char* buf_display = buf_display_from_state ? state->TextA.Data : buf;
- const char* buf_display_end = NULL;
- if (is_displaying_hint)
- {
- buf_display = hint;
- buf_display_end = hint + strlen(hint);
- }
-
-
- if (render_cursor || render_selection)
- {
- IM_ASSERT(state != NULL);
- if (!is_displaying_hint)
- buf_display_end = buf_display + state->CurLenA;
-
-
-
-
-
-
-
- const ImWchar* text_begin = state->TextW.Data;
- ImVec2 cursor_offset, select_start_offset;
- {
-
- const ImWchar* searches_input_ptr[2] = { NULL, NULL };
- int searches_result_line_no[2] = { -1000, -1000 };
- int searches_remaining = 0;
- if (render_cursor)
- {
- searches_input_ptr[0] = text_begin + state->Stb.cursor;
- searches_result_line_no[0] = -1;
- searches_remaining++;
- }
- if (render_selection)
- {
- searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
- searches_result_line_no[1] = -1;
- searches_remaining++;
- }
-
-
- searches_remaining += is_multiline ? 1 : 0;
- int line_count = 0;
-
- for (const ImWchar* s = text_begin; *s != 0; s++)
- if (*s == '\n')
- {
- line_count++;
- if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
- if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
- }
- line_count++;
- if (searches_result_line_no[0] == -1)
- searches_result_line_no[0] = line_count;
- if (searches_result_line_no[1] == -1)
- searches_result_line_no[1] = line_count;
-
- cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
- cursor_offset.y = searches_result_line_no[0] * g.FontSize;
- if (searches_result_line_no[1] >= 0)
- {
- select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
- select_start_offset.y = searches_result_line_no[1] * g.FontSize;
- }
-
- if (is_multiline)
- text_size = ImVec2(inner_size.x, line_count * g.FontSize);
- }
-
- if (render_cursor && state->CursorFollow)
- {
-
- if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll))
- {
- const float scroll_increment_x = inner_size.x * 0.25f;
- const float visible_width = inner_size.x - style.FramePadding.x;
- if (cursor_offset.x < state->ScrollX)
- state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x));
- else if (cursor_offset.x - visible_width >= state->ScrollX)
- state->ScrollX = IM_FLOOR(cursor_offset.x - visible_width + scroll_increment_x);
- }
- else
- {
- state->ScrollX = 0.0f;
- }
-
- if (is_multiline)
- {
-
- if (cursor_offset.y - g.FontSize < scroll_y)
- scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
- else if (cursor_offset.y - inner_size.y >= scroll_y)
- scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f;
- const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f);
- scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y);
- draw_pos.y += (draw_window->Scroll.y - scroll_y);
- draw_window->Scroll.y = scroll_y;
- }
- state->CursorFollow = false;
- }
-
- const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f);
- if (render_selection)
- {
- const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
- const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end);
- ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f);
- float bg_offy_up = is_multiline ? 0.0f : -1.0f;
- float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
- ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
- for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
- {
- if (rect_pos.y > clip_rect.w + g.FontSize)
- break;
- if (rect_pos.y < clip_rect.y)
- {
-
-
- while (p < text_selected_end)
- if (*p++ == '\n')
- break;
- }
- else
- {
- ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
- if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f);
- ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
- rect.ClipWith(clip_rect);
- if (rect.Overlaps(clip_rect))
- draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
- }
- rect_pos.x = draw_pos.x - draw_scroll.x;
- rect_pos.y += g.FontSize;
- }
- }
-
- if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
- {
- ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
- draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
- }
-
- if (render_cursor)
- {
- state->CursorAnim += io.DeltaTime;
- bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
- ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll);
- ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
- if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
- draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
-
- if (!is_readonly)
- g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
- }
- }
- else
- {
-
- if (is_multiline)
- text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize);
- else if (!is_displaying_hint && g.ActiveId == id)
- buf_display_end = buf_display + state->CurLenA;
- else if (!is_displaying_hint)
- buf_display_end = buf_display + strlen(buf_display);
- if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
- {
- ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
- draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
- }
- }
- if (is_password && !is_displaying_hint)
- PopFont();
- if (is_multiline)
- {
- Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y));
- EndChild();
- EndGroup();
- }
-
- if (g.LogEnabled && (!is_password || is_displaying_hint))
- {
- LogSetNextTextDecoration("{", "}");
- LogRenderedText(&draw_pos, buf_display, buf_display_end);
- }
- if (label_size.x > 0)
- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
- if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
- MarkItemEdited(id);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
- return enter_pressed;
- else
- return value_changed;
- }
- bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
- {
- return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
- }
- static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V)
- {
-
-
-
-
-
-
- ImGuiContext& g = *GImGui;
- if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
- return;
-
-
- if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1))
- *H = g.ColorEditLastHue;
-
- if (*V == 0.0f)
- *S = g.ColorEditLastSat;
- }
- bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const float square_sz = GetFrameHeight();
- const float w_full = CalcItemWidth();
- const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
- const float w_inputs = w_full - w_button;
- const char* label_display_end = FindRenderedTextEnd(label);
- g.NextItemData.ClearFlags();
- BeginGroup();
- PushID(label);
-
- const ImGuiColorEditFlags flags_untouched = flags;
- if (flags & ImGuiColorEditFlags_NoInputs)
- flags = (flags & (~ImGuiColorEditFlags_DisplayMask_)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions;
-
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- ColorEditOptionsPopup(col, flags);
-
- if (!(flags & ImGuiColorEditFlags_DisplayMask_))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_);
- if (!(flags & ImGuiColorEditFlags_DataTypeMask_))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_);
- if (!(flags & ImGuiColorEditFlags_PickerMask_))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_);
- if (!(flags & ImGuiColorEditFlags_InputMask_))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_);
- flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_));
- const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
- const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
- const int components = alpha ? 4 : 3;
-
- float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
- if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB))
- ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
- else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV))
- {
-
- ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
- ColorEditRestoreHS(col, &f[0], &f[1], &f[2]);
- }
- int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) };
- bool value_changed = false;
- bool value_changed_as_float = false;
- const ImVec2 pos = window->DC.CursorPos;
- const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f;
- window->DC.CursorPos.x = pos.x + inputs_offset_x;
- if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
- {
-
- const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components));
- const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
- const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
- static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
- static const char* fmt_table_int[3][4] =
- {
- { "%3d", "%3d", "%3d", "%3d" },
- { "R:%3d", "G:%3d", "B:%3d", "A:%3d" },
- { "H:%3d", "S:%3d", "V:%3d", "A:%3d" }
- };
- static const char* fmt_table_float[3][4] =
- {
- { "%0.3f", "%0.3f", "%0.3f", "%0.3f" },
- { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" },
- { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" }
- };
- const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1;
- for (int n = 0; n < components; n++)
- {
- if (n > 0)
- SameLine(0, style.ItemInnerSpacing.x);
- SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last);
-
- if (flags & ImGuiColorEditFlags_Float)
- {
- value_changed |= DragFloat(ids[n], &f[n], 1.0f / 255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
- value_changed_as_float |= value_changed;
- }
- else
- {
- value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
- }
- }
- else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
- {
-
- char buf[64];
- if (alpha)
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255));
- else
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
- SetNextItemWidth(w_inputs);
- if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
- {
- value_changed = true;
- char* p = buf;
- while (*p == '#' || ImCharIsBlankA(*p))
- p++;
- i[0] = i[1] = i[2] = 0;
- i[3] = 0xFF;
- int r;
- if (alpha)
- r = sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]);
- else
- r = sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
- IM_UNUSED(r);
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
- }
- ImGuiWindow* picker_active_window = NULL;
- if (!(flags & ImGuiColorEditFlags_NoSmallPreview))
- {
- const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x;
- window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y);
- const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);
- if (ColorButton("##ColorButton", col_v4, flags))
- {
- if (!(flags & ImGuiColorEditFlags_NoPicker))
- {
-
- g.ColorPickerRef = col_v4;
- OpenPopup("picker");
- SetNextWindowPos(g.LastItemData.Rect.GetBL() + ImVec2(-1, style.ItemSpacing.y));
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
- if (BeginPopup("picker"))
- {
- picker_active_window = g.CurrentWindow;
- if (label != label_display_end)
- {
- TextEx(label, label_display_end);
- Spacing();
- }
- ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
- ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
- SetNextItemWidth(square_sz * 12.0f);
- value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
- EndPopup();
- }
- }
- if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
- {
- const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x;
- window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y);
- TextEx(label, label_display_end);
- }
-
- if (value_changed && picker_active_window == NULL)
- {
- if (!value_changed_as_float)
- for (int n = 0; n < 4; n++)
- f[n] = i[n] / 255.0f;
- if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB))
- {
- g.ColorEditLastHue = f[0];
- g.ColorEditLastSat = f[1];
- ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
- g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0));
- }
- if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV))
- ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
- col[0] = f[0];
- col[1] = f[1];
- col[2] = f[2];
- if (alpha)
- col[3] = f[3];
- }
- PopID();
- EndGroup();
-
-
- if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
- {
- bool accepted_drag_drop = false;
- if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
- {
- memcpy((float*)col, payload->Data, sizeof(float) * 3);
- value_changed = accepted_drag_drop = true;
- }
- if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
- {
- memcpy((float*)col, payload->Data, sizeof(float) * components);
- value_changed = accepted_drag_drop = true;
- }
-
- if (accepted_drag_drop && (flags & ImGuiColorEditFlags_InputHSV))
- ColorConvertRGBtoHSV(col[0], col[1], col[2], col[0], col[1], col[2]);
- EndDragDropTarget();
- }
-
- if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
- g.LastItemData.ID = g.ActiveId;
- if (value_changed)
- MarkItemEdited(g.LastItemData.ID);
- return value_changed;
- }
- bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
- {
- float col4[4] = { col[0], col[1], col[2], 1.0f };
- if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha))
- return false;
- col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
- return true;
- }
- static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
- {
- ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha);
- ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8));
- ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8));
- ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8));
- ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8));
- }
- bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImDrawList* draw_list = window->DrawList;
- ImGuiStyle& style = g.Style;
- ImGuiIO& io = g.IO;
- const float width = CalcItemWidth();
- g.NextItemData.ClearFlags();
- PushID(label);
- BeginGroup();
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- flags |= ImGuiColorEditFlags_NoSmallPreview;
-
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- ColorPickerOptionsPopup(col, flags);
-
- if (!(flags & ImGuiColorEditFlags_PickerMask_))
- flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
- if (!(flags & ImGuiColorEditFlags_InputMask_))
- flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_));
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
-
- int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
- bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
- ImVec2 picker_pos = window->DC.CursorPos;
- float square_sz = GetFrameHeight();
- float bars_width = square_sz;
- float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x));
- float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
- float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
- float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f);
- float backup_initial_col[4];
- memcpy(backup_initial_col, col, components * sizeof(float));
- float wheel_thickness = sv_picker_size * 0.08f;
- float wheel_r_outer = sv_picker_size * 0.50f;
- float wheel_r_inner = wheel_r_outer - wheel_thickness;
- ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f);
-
- float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
- ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f);
- ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f);
- ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f);
- float H = col[0], S = col[1], V = col[2];
- float R = col[0], G = col[1], B = col[2];
- if (flags & ImGuiColorEditFlags_InputRGB)
- {
-
- ColorConvertRGBtoHSV(R, G, B, H, S, V);
- ColorEditRestoreHS(col, &H, &S, &V);
- }
- else if (flags & ImGuiColorEditFlags_InputHSV)
- {
- ColorConvertHSVtoRGB(H, S, V, R, G, B);
- }
- bool value_changed = false, value_changed_h = false, value_changed_sv = false;
- PushItemFlag(ImGuiItemFlags_NoNav, true);
- if (flags & ImGuiColorEditFlags_PickerHueWheel)
- {
-
- InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
- if (IsItemActive())
- {
- ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
- ImVec2 current_off = g.IO.MousePos - wheel_center;
- float initial_dist2 = ImLengthSqr(initial_off);
- if (initial_dist2 >= (wheel_r_inner - 1) * (wheel_r_inner - 1) && initial_dist2 <= (wheel_r_outer + 1) * (wheel_r_outer + 1))
- {
-
- H = ImAtan2(current_off.y, current_off.x) / IM_PI * 0.5f;
- if (H < 0.0f)
- H += 1.0f;
- value_changed = value_changed_h = true;
- }
- float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
- float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
- if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
- {
-
- ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
- if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
- current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
- float uu, vv, ww;
- ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
- V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
- S = ImClamp(uu / V, 0.0001f, 1.0f);
- value_changed = value_changed_sv = true;
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
- }
- else if (flags & ImGuiColorEditFlags_PickerHueBar)
- {
-
- InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
- if (IsItemActive())
- {
- S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
- V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
-
- if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
- H = g.ColorEditLastHue;
- value_changed = value_changed_sv = true;
- }
- if (!(flags & ImGuiColorEditFlags_NoOptions))
- OpenPopupOnItemClick("context");
-
- SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
- InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
- if (IsItemActive())
- {
- H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
- value_changed = value_changed_h = true;
- }
- }
-
- if (alpha_bar)
- {
- SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
- InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
- if (IsItemActive())
- {
- col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
- value_changed = true;
- }
- }
- PopItemFlag();
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- {
- SameLine(0, style.ItemInnerSpacing.x);
- BeginGroup();
- }
- if (!(flags & ImGuiColorEditFlags_NoLabel))
- {
- const char* label_display_end = FindRenderedTextEnd(label);
- if (label != label_display_end)
- {
- if ((flags & ImGuiColorEditFlags_NoSidePreview))
- SameLine(0, style.ItemInnerSpacing.x);
- TextEx(label, label_display_end);
- }
- }
- if (!(flags & ImGuiColorEditFlags_NoSidePreview))
- {
- PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
- ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
- if ((flags & ImGuiColorEditFlags_NoLabel))
- Text("Current");
- ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip;
- ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2));
- if (ref_col != NULL)
- {
- Text("Original");
- ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
- if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)))
- {
- memcpy(col, ref_col, components * sizeof(float));
- value_changed = true;
- }
- }
- PopItemFlag();
- EndGroup();
- }
-
- if (value_changed_h || value_changed_sv)
- {
- if (flags & ImGuiColorEditFlags_InputRGB)
- {
- ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]);
- g.ColorEditLastHue = H;
- g.ColorEditLastSat = S;
- g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0));
- }
- else if (flags & ImGuiColorEditFlags_InputHSV)
- {
- col[0] = H;
- col[1] = S;
- col[2] = V;
- }
- }
-
- bool value_changed_fix_hue_wrap = false;
- if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
- {
- PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
- ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;
- ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
- if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
- if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB))
- {
-
-
- value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap);
- value_changed = true;
- }
- if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
- value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);
- if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
- value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex);
- PopItemWidth();
- }
-
- if (value_changed_fix_hue_wrap && (flags & ImGuiColorEditFlags_InputRGB))
- {
- float new_H, new_S, new_V;
- ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
- if (new_H <= 0 && H > 0)
- {
- if (new_V <= 0 && V != new_V)
- ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
- else if (new_S <= 0)
- ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
- }
- }
- if (value_changed)
- {
- if (flags & ImGuiColorEditFlags_InputRGB)
- {
- R = col[0];
- G = col[1];
- B = col[2];
- ColorConvertRGBtoHSV(R, G, B, H, S, V);
- ColorEditRestoreHS(col, &H, &S, &V);
- }
- else if (flags & ImGuiColorEditFlags_InputHSV)
- {
- H = col[0];
- S = col[1];
- V = col[2];
- ColorConvertHSVtoRGB(H, S, V, R, G, B);
- }
- }
- const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha);
- const ImU32 col_black = IM_COL32(0,0,0,style_alpha8);
- const ImU32 col_white = IM_COL32(255,255,255,style_alpha8);
- const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8);
- const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) };
- ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
- ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
- ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha));
- ImVec2 sv_cursor_pos;
- if (flags & ImGuiColorEditFlags_PickerHueWheel)
- {
-
- const float aeps = 0.5f / wheel_r_outer;
- const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
- for (int n = 0; n < 6; n++)
- {
- const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
- const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
- const int vert_start_idx = draw_list->VtxBuffer.Size;
- draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
- draw_list->PathStroke(col_white, 0, wheel_thickness);
- const int vert_end_idx = draw_list->VtxBuffer.Size;
-
- ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
- ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
- ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n + 1]);
- }
-
- float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
- float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
- ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
- float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
- int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
- draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
- draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
- draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
-
- ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
- ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
- ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
- ImVec2 uv_white = GetFontTexUvWhitePixel();
- draw_list->PrimReserve(6, 6);
- draw_list->PrimVtx(tra, uv_white, hue_color32);
- draw_list->PrimVtx(trb, uv_white, hue_color32);
- draw_list->PrimVtx(trc, uv_white, col_white);
- draw_list->PrimVtx(tra, uv_white, 0);
- draw_list->PrimVtx(trb, uv_white, col_black);
- draw_list->PrimVtx(trc, uv_white, 0);
- draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
- sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
- }
- else if (flags & ImGuiColorEditFlags_PickerHueBar)
- {
-
- draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
- draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
- RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
- sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2);
- sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
-
- for (int i = 0; i < 6; ++i)
- draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
- float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size);
- RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
- RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
- }
-
- float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
- draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
- draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12);
- draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
-
- if (alpha_bar)
- {
- float alpha = ImSaturate(col[3]);
- ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
- RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
- draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
- float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size);
- RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
- RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
- }
- EndGroup();
- if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
- value_changed = false;
- if (value_changed)
- MarkItemEdited(g.LastItemData.ID);
- PopID();
- return value_changed;
- }
- bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiID id = window->GetID(desc_id);
- float default_size = GetFrameHeight();
- if (size.x == 0.0f)
- size.x = default_size;
- if (size.y == 0.0f)
- size.y = default_size;
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
- ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
- if (!ItemAdd(bb, id))
- return false;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held);
- if (flags & ImGuiColorEditFlags_NoAlpha)
- flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf);
- ImVec4 col_rgb = col;
- if (flags & ImGuiColorEditFlags_InputHSV)
- ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
- ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
- float grid_step = ImMin(size.x, size.y) / 2.99f;
- float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
- ImRect bb_inner = bb;
- float off = 0.0f;
- if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
- {
- off = -0.75f;
- bb_inner.Expand(off);
- }
- if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
- {
- float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f);
- RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight);
- window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft);
- }
- else
- {
-
- ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha;
- if (col_source.w < 1.0f)
- RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
- else
- window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
- }
- RenderNavHighlight(bb, id);
- if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
- {
- if (g.Style.FrameBorderSize > 0.0f)
- RenderFrameBorder(bb.Min, bb.Max, rounding);
- else
- window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding);
- }
-
-
- if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource())
- {
- if (flags & ImGuiColorEditFlags_NoAlpha)
- SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
- else
- SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
- ColorButton(desc_id, col, flags);
- SameLine();
- TextEx("Color");
- EndDragDropSource();
- }
-
- if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
- ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
- return pressed;
- }
- void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
- {
- ImGuiContext& g = *GImGui;
- if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0)
- flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_;
- if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0)
- flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_;
- if ((flags & ImGuiColorEditFlags_PickerMask_) == 0)
- flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_;
- if ((flags & ImGuiColorEditFlags_InputMask_) == 0)
- flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_;
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_));
- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_));
- g.ColorEditOptions = flags;
- }
- void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
- {
- ImGuiContext& g = *GImGui;
- BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip);
- const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
- if (text_end > text)
- {
- TextEx(text, text_end);
- Separator();
- }
- ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2);
- ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
- int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
- ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);
- SameLine();
- if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_))
- {
- if (flags & ImGuiColorEditFlags_NoAlpha)
- Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);
- else
- Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);
- }
- else if (flags & ImGuiColorEditFlags_InputHSV)
- {
- if (flags & ImGuiColorEditFlags_NoAlpha)
- Text("H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]);
- else
- Text("H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]);
- }
- EndTooltip();
- }
- void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
- {
- bool allow_opt_inputs = !(flags & ImGuiColorEditFlags_DisplayMask_);
- bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_);
- if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
- return;
- ImGuiContext& g = *GImGui;
- ImGuiColorEditFlags opts = g.ColorEditOptions;
- if (allow_opt_inputs)
- {
- if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;
- if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHSV;
- if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHex;
- }
- if (allow_opt_datatype)
- {
- if (allow_opt_inputs) Separator();
- if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Uint8;
- if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Float;
- }
- if (allow_opt_inputs || allow_opt_datatype)
- Separator();
- if (Button("Copy as..", ImVec2(-1, 0)))
- OpenPopup("Copy");
- if (BeginPopup("Copy"))
- {
- int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
- char buf[64];
- ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
- if (Selectable(buf))
- SetClipboardText(buf);
- ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
- if (Selectable(buf))
- SetClipboardText(buf);
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb);
- if (Selectable(buf))
- SetClipboardText(buf);
- if (!(flags & ImGuiColorEditFlags_NoAlpha))
- {
- ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca);
- if (Selectable(buf))
- SetClipboardText(buf);
- }
- EndPopup();
- }
- g.ColorEditOptions = opts;
- EndPopup();
- }
- void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
- {
- bool allow_opt_picker = !(flags & ImGuiColorEditFlags_PickerMask_);
- bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
- if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
- return;
- ImGuiContext& g = *GImGui;
- if (allow_opt_picker)
- {
- ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f));
- PushItemWidth(picker_size.x);
- for (int picker_type = 0; picker_type < 2; picker_type++)
- {
-
- if (picker_type > 0) Separator();
- PushID(picker_type);
- ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoSidePreview | (flags & ImGuiColorEditFlags_NoAlpha);
- if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
- if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
- ImVec2 backup_pos = GetCursorScreenPos();
- if (Selectable("##selectable", false, 0, picker_size))
- g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
- SetCursorScreenPos(backup_pos);
- ImVec4 previewing_ref_col;
- memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
- ColorPicker4("##previewing_picker", &previewing_ref_col.x, picker_flags);
- PopID();
- }
- PopItemWidth();
- }
- if (allow_opt_alpha_bar)
- {
- if (allow_opt_picker) Separator();
- CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
- }
- EndPopup();
- }
- bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- bool is_open = TreeNodeExV(str_id, 0, fmt, args);
- va_end(args);
- return is_open;
- }
- bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);
- va_end(args);
- return is_open;
- }
- bool ImGui::TreeNode(const char* label)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
- }
- bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
- {
- return TreeNodeExV(str_id, 0, fmt, args);
- }
- bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
- {
- return TreeNodeExV(ptr_id, 0, fmt, args);
- }
- bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
- }
- bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- bool is_open = TreeNodeExV(str_id, flags, fmt, args);
- va_end(args);
- return is_open;
- }
- bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);
- va_end(args);
- return is_open;
- }
- bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
- }
- bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
- return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
- }
- bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
- {
- if (flags & ImGuiTreeNodeFlags_Leaf)
- return true;
-
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- ImGuiStorage* storage = window->DC.StateStorage;
- bool is_open;
- if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
- {
- if (g.NextItemData.OpenCond & ImGuiCond_Always)
- {
- is_open = g.NextItemData.OpenVal;
- storage->SetInt(id, is_open);
- }
- else
- {
-
- const int stored_value = storage->GetInt(id, -1);
- if (stored_value == -1)
- {
- is_open = g.NextItemData.OpenVal;
- storage->SetInt(id, is_open);
- }
- else
- {
- is_open = stored_value != 0;
- }
- }
- }
- else
- {
- is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
- }
-
-
- if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && (window->DC.TreeDepth - g.LogDepthRef) < g.LogDepthToExpand)
- is_open = true;
- return is_open;
- }
- bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
- const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y));
- if (!label_end)
- label_end = FindRenderedTextEnd(label);
- const ImVec2 label_size = CalcTextSize(label, label_end, false);
-
- const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2);
- ImRect frame_bb;
- frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
- frame_bb.Min.y = window->DC.CursorPos.y;
- frame_bb.Max.x = window->WorkRect.Max.x;
- frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
- if (display_frame)
- {
-
-
- frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f);
- frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
- }
- const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2);
- const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset);
- const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f);
- ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
- ItemSize(ImVec2(text_width, frame_height), padding.y);
-
- ImRect interact_bb = frame_bb;
- if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0)
- interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f;
-
-
-
- const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
- bool is_open = TreeNodeBehaviorIsOpen(id, flags);
- if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
- window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
- bool item_add = ItemAdd(interact_bb, id);
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
- g.LastItemData.DisplayRect = frame_bb;
- if (!item_add)
- {
- if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
- TreePushOverrideID(id);
- IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
- return is_open;
- }
- ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
- if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
- button_flags |= ImGuiButtonFlags_AllowItemOverlap;
- if (!is_leaf)
- button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
-
-
-
- const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
- const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
- const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
- if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
- button_flags |= ImGuiButtonFlags_NoKeyModifiers;
-
-
-
-
-
-
-
-
-
- if (is_mouse_x_over_arrow)
- button_flags |= ImGuiButtonFlags_PressedOnClick;
- else if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
- button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
- else
- button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
- bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
- const bool was_selected = selected;
- bool hovered, held;
- bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
- bool toggled = false;
- if (!is_leaf)
- {
- if (pressed && g.DragDropHoldJustPressedId != id)
- {
- if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
- toggled = true;
- if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
- toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover;
- if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
- toggled = true;
- }
- else if (pressed && g.DragDropHoldJustPressedId == id)
- {
- IM_ASSERT(button_flags & ImGuiButtonFlags_PressedOnDragDropHold);
- if (!is_open)
- toggled = true;
- }
- if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open)
- {
- toggled = true;
- NavMoveRequestCancel();
- }
- if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open)
- {
- toggled = true;
- NavMoveRequestCancel();
- }
- if (toggled)
- {
- is_open = !is_open;
- window->DC.StateStorage->SetInt(id, is_open);
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen;
- }
- }
- if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
- SetItemAllowOverlap();
-
- if (selected != was_selected)
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
-
- const ImU32 text_col = GetColorU32(ImGuiCol_Text);
- ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
- if (display_frame)
- {
-
- const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
- RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
- RenderNavHighlight(frame_bb, id, nav_highlight_flags);
- if (flags & ImGuiTreeNodeFlags_Bullet)
- RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
- else if (!is_leaf)
- RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
- else
- text_pos.x -= text_offset_x;
- if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
- frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
- if (g.LogEnabled)
- LogSetNextTextDecoration("###", "###");
- RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
- }
- else
- {
-
- if (hovered || selected)
- {
- const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
- RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
- }
- RenderNavHighlight(frame_bb, id, nav_highlight_flags);
- if (flags & ImGuiTreeNodeFlags_Bullet)
- RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
- else if (!is_leaf)
- RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
- if (g.LogEnabled)
- LogSetNextTextDecoration(">", NULL);
- RenderText(text_pos, label, label_end, false);
- }
- if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
- TreePushOverrideID(id);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
- return is_open;
- }
- void ImGui::TreePush(const char* str_id)
- {
- ImGuiWindow* window = GetCurrentWindow();
- Indent();
- window->DC.TreeDepth++;
- PushID(str_id);
- }
- void ImGui::TreePush(const void* ptr_id)
- {
- ImGuiWindow* window = GetCurrentWindow();
- Indent();
- window->DC.TreeDepth++;
- PushID(ptr_id);
- }
- void ImGui::TreePushOverrideID(ImGuiID id)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- Indent();
- window->DC.TreeDepth++;
- PushOverrideID(id);
- }
- void ImGui::TreePop()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- Unindent();
- window->DC.TreeDepth--;
- ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
-
- if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
- if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask))
- {
- SetNavID(window->IDStack.back(), g.NavLayer, 0, ImRect());
- NavMoveRequestCancel();
- }
- window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1;
- IM_ASSERT(window->IDStack.Size > 1);
- PopID();
- }
- float ImGui::GetTreeNodeToLabelSpacing()
- {
- ImGuiContext& g = *GImGui;
- return g.FontSize + (g.Style.FramePadding.x * 2.0f);
- }
- void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
- {
- ImGuiContext& g = *GImGui;
- if (g.CurrentWindow->SkipItems)
- return;
- g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
- g.NextItemData.OpenVal = is_open;
- g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always;
- }
- bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label);
- }
- bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- if (p_visible && !*p_visible)
- return false;
- ImGuiID id = window->GetID(label);
- flags |= ImGuiTreeNodeFlags_CollapsingHeader;
- if (p_visible)
- flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton;
- bool is_open = TreeNodeBehavior(id, flags, label);
- if (p_visible != NULL)
- {
-
-
-
- ImGuiContext& g = *GImGui;
- ImGuiLastItemData last_item_backup = g.LastItemData;
- float button_size = g.FontSize;
- float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);
- float button_y = g.LastItemData.Rect.Min.y;
- ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id);
- if (CloseButton(close_button_id, ImVec2(button_x, button_y)))
- *p_visible = false;
- g.LastItemData = last_item_backup;
- }
- return is_open;
- }
- bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
-
- ImGuiID id = window->GetID(label);
- ImVec2 label_size = CalcTextSize(label, NULL, true);
- ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
- ImVec2 pos = window->DC.CursorPos;
- pos.y += window->DC.CurrLineTextBaseOffset;
- ItemSize(size, 0.0f);
-
-
- const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0;
- const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x;
- const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x;
- if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
- size.x = ImMax(label_size.x, max_x - min_x);
-
- const ImVec2 text_min = pos;
- const ImVec2 text_max(min_x + size.x, pos.y + size.y);
-
- ImRect bb(min_x, pos.y, text_max.x, text_max.y);
- if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
- {
- const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x;
- const float spacing_y = style.ItemSpacing.y;
- const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
- const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
- bb.Min.x -= spacing_L;
- bb.Min.y -= spacing_U;
- bb.Max.x += (spacing_x - spacing_L);
- bb.Max.y += (spacing_y - spacing_U);
- }
-
-
- const float backup_clip_rect_min_x = window->ClipRect.Min.x;
- const float backup_clip_rect_max_x = window->ClipRect.Max.x;
- if (span_all_columns)
- {
- window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
- window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
- }
- const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;
- const bool item_add = ItemAdd(bb, id, NULL, disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None);
- if (span_all_columns)
- {
- window->ClipRect.Min.x = backup_clip_rect_min_x;
- window->ClipRect.Max.x = backup_clip_rect_max_x;
- }
- if (!item_add)
- return false;
- const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
- if (disabled_item && !disabled_global)
- BeginDisabled();
-
-
- if (span_all_columns && window->DC.CurrentColumns)
- PushColumnsBackground();
- else if (span_all_columns && g.CurrentTable)
- TablePushBackgroundChannel();
-
- ImGuiButtonFlags button_flags = 0;
- if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; }
- if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; }
- if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; }
- if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
- if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
- const bool was_selected = selected;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
-
-
-
-
-
-
-
- if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)
- if (g.NavJustMovedToId == id)
- selected = pressed = true;
-
- if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
- {
- if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
- {
- SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos));
- g.NavDisableHighlight = true;
- }
- }
- if (pressed)
- MarkItemEdited(id);
- if (flags & ImGuiSelectableFlags_AllowItemOverlap)
- SetItemAllowOverlap();
-
- if (selected != was_selected)
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
-
- if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld))
- hovered = true;
- if (hovered || selected)
- {
- const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
- RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
- }
- RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
- if (span_all_columns && window->DC.CurrentColumns)
- PopColumnsBackground();
- else if (span_all_columns && g.CurrentTable)
- TablePopBackgroundChannel();
- RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
-
- if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup))
- CloseCurrentPopup();
- if (disabled_item && !disabled_global)
- EndDisabled();
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- return pressed;
- }
- bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
- {
- if (Selectable(label, *p_selected, flags, size_arg))
- {
- *p_selected = !*p_selected;
- return true;
- }
- return false;
- }
- bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
-
-
- ImVec2 size = ImFloor(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f));
- ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
- ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
- ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
- g.NextItemData.ClearFlags();
- if (!IsRectVisible(bb.Min, bb.Max))
- {
- ItemSize(bb.GetSize(), style.FramePadding.y);
- ItemAdd(bb, 0, &frame_bb);
- return false;
- }
-
- BeginGroup();
- if (label_size.x > 0.0f)
- {
- ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y);
- RenderText(label_pos, label);
- window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size);
- }
- BeginChildFrame(id, frame_bb.GetSize());
- return true;
- }
- #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
- bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
- {
-
- ImGuiContext& g = *GImGui;
- float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f;
- ImVec2 size;
- size.x = 0.0f;
- size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f;
- return BeginListBox(label, size);
- }
- #endif
- void ImGui::EndListBox()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?");
- IM_UNUSED(window);
- EndChildFrame();
- EndGroup();
- }
- bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items)
- {
- const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
- return value_changed;
- }
- bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
- {
- ImGuiContext& g = *GImGui;
-
- if (height_in_items < 0)
- height_in_items = ImMin(items_count, 7);
- float height_in_items_f = height_in_items + 0.25f;
- ImVec2 size(0.0f, ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f));
- if (!BeginListBox(label, size))
- return false;
-
-
- bool value_changed = false;
- ImGuiListClipper clipper;
- clipper.Begin(items_count, GetTextLineHeightWithSpacing());
- while (clipper.Step())
- for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
- {
- const char* item_text;
- if (!items_getter(data, i, &item_text))
- item_text = "*Unknown item*";
- PushID(i);
- const bool item_selected = (i == *current_item);
- if (Selectable(item_text, item_selected))
- {
- *current_item = i;
- value_changed = true;
- }
- if (item_selected)
- SetItemDefaultFocus();
- PopID();
- }
- EndListBox();
- if (value_changed)
- MarkItemEdited(g.LastItemData.ID);
- return value_changed;
- }
- int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return -1;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
- if (frame_size.x == 0.0f)
- frame_size.x = CalcItemWidth();
- if (frame_size.y == 0.0f)
- frame_size.y = label_size.y + (style.FramePadding.y * 2);
- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
- const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
- const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
- ItemSize(total_bb, style.FramePadding.y);
- if (!ItemAdd(total_bb, 0, &frame_bb))
- return -1;
- const bool hovered = ItemHoverable(frame_bb, id);
-
- if (scale_min == FLT_MAX || scale_max == FLT_MAX)
- {
- float v_min = FLT_MAX;
- float v_max = -FLT_MAX;
- for (int i = 0; i < values_count; i++)
- {
- const float v = values_getter(data, i);
- if (v != v)
- continue;
- v_min = ImMin(v_min, v);
- v_max = ImMax(v_max, v);
- }
- if (scale_min == FLT_MAX)
- scale_min = v_min;
- if (scale_max == FLT_MAX)
- scale_max = v_max;
- }
- RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
- const int values_count_min = (plot_type == ImGuiPlotType_Lines) ? 2 : 1;
- int idx_hovered = -1;
- if (values_count >= values_count_min)
- {
- int res_w = ImMin((int)frame_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
- int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
-
- if (hovered && inner_bb.Contains(g.IO.MousePos))
- {
- const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
- const int v_idx = (int)(t * item_count);
- IM_ASSERT(v_idx >= 0 && v_idx < values_count);
- const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
- const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
- if (plot_type == ImGuiPlotType_Lines)
- SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1);
- else if (plot_type == ImGuiPlotType_Histogram)
- SetTooltip("%d: %8.4g", v_idx, v0);
- idx_hovered = v_idx;
- }
- const float t_step = 1.0f / (float)res_w;
- const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min));
- float v0 = values_getter(data, (0 + values_offset) % values_count);
- float t0 = 0.0f;
- ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) );
- float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f);
- const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
- const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
- for (int n = 0; n < res_w; n++)
- {
- const float t1 = t0 + t_step;
- const int v1_idx = (int)(t0 * item_count + 0.5f);
- IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
- const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
- const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
-
- ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
- ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
- if (plot_type == ImGuiPlotType_Lines)
- {
- window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
- }
- else if (plot_type == ImGuiPlotType_Histogram)
- {
- if (pos1.x >= pos0.x + 2.0f)
- pos1.x -= 1.0f;
- window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
- }
- t0 = t1;
- tp0 = tp1;
- }
- }
-
- if (overlay_text)
- RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f));
- if (label_size.x > 0.0f)
- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
-
-
- return idx_hovered;
- }
- struct ImGuiPlotArrayGetterData
- {
- const float* Values;
- int Stride;
- ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; }
- };
- static float Plot_ArrayGetter(void* data, int idx)
- {
- ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;
- const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
- return v;
- }
- void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
- {
- ImGuiPlotArrayGetterData data(values, stride);
- PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
- }
- void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
- {
- PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
- }
- void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
- {
- ImGuiPlotArrayGetterData data(values, stride);
- PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
- }
- void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
- {
- PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
- }
- void ImGui::Value(const char* prefix, bool b)
- {
- Text("%s: %s", prefix, (b ? "true" : "false"));
- }
- void ImGui::Value(const char* prefix, int v)
- {
- Text("%s: %d", prefix, v);
- }
- void ImGui::Value(const char* prefix, unsigned int v)
- {
- Text("%s: %d", prefix, v);
- }
- void ImGui::Value(const char* prefix, float v, const char* float_format)
- {
- if (float_format)
- {
- char fmt[64];
- ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
- Text(fmt, prefix, v);
- }
- else
- {
- Text("%s: %.3f", prefix, v);
- }
- }
- void ImGuiMenuColumns::Update(float spacing, bool window_reappearing)
- {
- if (window_reappearing)
- memset(Widths, 0, sizeof(Widths));
- Spacing = (ImU16)spacing;
- CalcNextTotalWidth(true);
- memset(Widths, 0, sizeof(Widths));
- TotalWidth = NextTotalWidth;
- NextTotalWidth = 0;
- }
- void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets)
- {
- ImU16 offset = 0;
- bool want_spacing = false;
- for (int i = 0; i < IM_ARRAYSIZE(Widths); i++)
- {
- ImU16 width = Widths[i];
- if (want_spacing && width > 0)
- offset += Spacing;
- want_spacing |= (width > 0);
- if (update_offsets)
- {
- if (i == 1) { OffsetLabel = offset; }
- if (i == 2) { OffsetShortcut = offset; }
- if (i == 3) { OffsetMark = offset; }
- }
- offset += width;
- }
- NextTotalWidth = offset;
- }
- float ImGuiMenuColumns::DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark)
- {
- Widths[0] = ImMax(Widths[0], (ImU16)w_icon);
- Widths[1] = ImMax(Widths[1], (ImU16)w_label);
- Widths[2] = ImMax(Widths[2], (ImU16)w_shortcut);
- Widths[3] = ImMax(Widths[3], (ImU16)w_mark);
- CalcNextTotalWidth(false);
- return (float)ImMax(TotalWidth, NextTotalWidth);
- }
- bool ImGui::BeginMenuBar()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- if (!(window->Flags & ImGuiWindowFlags_MenuBar))
- return false;
- IM_ASSERT(!window->DC.MenuBarAppending);
- BeginGroup();
- PushID("##menubar");
-
-
- ImRect bar_rect = window->MenuBarRect();
- ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y));
- clip_rect.ClipWith(window->OuterRectClipped);
- PushClipRect(clip_rect.Min, clip_rect.Max, false);
-
- window->DC.CursorPos = window->DC.CursorMaxPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y);
- window->DC.LayoutType = ImGuiLayoutType_Horizontal;
- window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
- window->DC.MenuBarAppending = true;
- AlignTextToFramePadding();
- return true;
- }
- void ImGui::EndMenuBar()
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return;
- ImGuiContext& g = *GImGui;
-
- if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
- {
-
- ImGuiWindow* nav_earliest_child = g.NavWindow;
- while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
- nav_earliest_child = nav_earliest_child->ParentWindow;
- if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
- {
-
-
- const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
- IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer));
- FocusWindow(window);
- SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
- g.NavDisableHighlight = true;
- g.NavDisableMouseHover = g.NavMousePosDirty = true;
- NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags);
- }
- }
- IM_MSVC_WARNING_SUPPRESS(6011);
- IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);
- IM_ASSERT(window->DC.MenuBarAppending);
- PopClipRect();
- PopID();
- window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x;
- g.GroupStack.back().EmitItem = false;
- EndGroup();
- window->DC.LayoutType = ImGuiLayoutType_Vertical;
- window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
- window->DC.MenuBarAppending = false;
- }
- bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags)
- {
- IM_ASSERT(dir != ImGuiDir_None);
- ImGuiWindow* bar_window = FindWindowByName(name);
- if (bar_window == NULL || bar_window->BeginCount == 0)
- {
-
- ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)(viewport_p ? viewport_p : GetMainViewport());
- ImRect avail_rect = viewport->GetBuildWorkRect();
- ImGuiAxis axis = (dir == ImGuiDir_Up || dir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
- ImVec2 pos = avail_rect.Min;
- if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
- pos[axis] = avail_rect.Max[axis] - axis_size;
- ImVec2 size = avail_rect.GetSize();
- size[axis] = axis_size;
- SetNextWindowPos(pos);
- SetNextWindowSize(size);
-
- if (dir == ImGuiDir_Up || dir == ImGuiDir_Left)
- viewport->BuildWorkOffsetMin[axis] += axis_size;
- else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right)
- viewport->BuildWorkOffsetMax[axis] -= axis_size;
- }
- window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
- PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
- PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0));
- bool is_open = Begin(name, NULL, window_flags);
- PopStyleVar(2);
- return is_open;
- }
- bool ImGui::BeginMainMenuBar()
- {
- ImGuiContext& g = *GImGui;
- ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
-
-
-
- g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
- ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
- float height = GetFrameHeight();
- bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags);
- g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
- if (is_open)
- BeginMenuBar();
- else
- End();
- return is_open;
- }
- void ImGui::EndMainMenuBar()
- {
- EndMenuBar();
-
-
- ImGuiContext& g = *GImGui;
- if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
- FocusTopMostWindowUnderOne(g.NavWindow, NULL);
- End();
- }
- bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = window->GetID(label);
- bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
-
- ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
- if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
- flags |= ImGuiWindowFlags_ChildWindow;
-
-
-
- if (g.MenusIdSubmittedThisFrame.contains(id))
- {
- if (menu_is_open)
- menu_is_open = BeginPopupEx(id, flags);
- else
- g.NextWindowData.ClearFlags();
- return menu_is_open;
- }
-
- g.MenusIdSubmittedThisFrame.push_back(id);
- ImVec2 label_size = CalcTextSize(label, NULL, true);
- bool pressed;
- bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
- ImGuiWindow* backed_nav_window = g.NavWindow;
- if (menuset_is_open)
- g.NavWindow = window;
-
-
-
- ImVec2 popup_pos, pos = window->DC.CursorPos;
- PushID(label);
- if (!enabled)
- BeginDisabled();
- const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
- if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
- {
-
-
-
- popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
- window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
- PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
- float w = label_size.x;
- ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
- pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups, ImVec2(w, 0.0f));
- RenderText(text_pos, label);
- PopStyleVar();
- window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f));
- }
- else
- {
-
-
-
- popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
- float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
- float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
- float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w);
- float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
- ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
- pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
- RenderText(text_pos, label);
- if (icon_w > 0.0f)
- RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
- RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
- }
- if (!enabled)
- EndDisabled();
- const bool hovered = (g.HoveredId == id) && enabled;
- if (menuset_is_open)
- g.NavWindow = backed_nav_window;
- bool want_open = false;
- bool want_close = false;
- if (window->DC.LayoutType == ImGuiLayoutType_Vertical)
- {
-
-
- bool moving_toward_other_child_menu = false;
- ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
- if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
- {
- float ref_unit = g.FontSize;
- ImRect next_window_rect = child_menu_window->Rect();
- ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
- ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
- ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
- float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f);
- ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f;
- tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f);
- tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f);
- moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
-
- }
- if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu)
- want_close = true;
-
- if (!menu_is_open && pressed)
- want_open = true;
- else if (!menu_is_open && hovered && !moving_toward_other_child_menu)
- want_open = true;
- if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right)
- {
- want_open = true;
- NavMoveRequestCancel();
- }
- }
- else
- {
-
- if (menu_is_open && pressed && menuset_is_open)
- {
- want_close = true;
- want_open = menu_is_open = false;
- }
- else if (pressed || (hovered && menuset_is_open && !menu_is_open))
- {
- want_open = true;
- }
- else if (g.NavId == id && g.NavMoveDir == ImGuiDir_Down)
- {
- want_open = true;
- NavMoveRequestCancel();
- }
- }
- if (!enabled)
- want_close = true;
- if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None))
- ClosePopupToLevel(g.BeginPopupStack.Size, true);
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
- PopID();
- if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
- {
-
- OpenPopup(label);
- return false;
- }
- menu_is_open |= want_open;
- if (want_open)
- OpenPopup(label);
- if (menu_is_open)
- {
- SetNextWindowPos(popup_pos, ImGuiCond_Always);
- menu_is_open = BeginPopupEx(id, flags);
- }
- else
- {
- g.NextWindowData.ClearFlags();
- }
- return menu_is_open;
- }
- bool ImGui::BeginMenu(const char* label, bool enabled)
- {
- return BeginMenuEx(label, NULL, enabled);
- }
- void ImGui::EndMenu()
- {
-
-
-
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
- if (g.NavWindow && (g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow == window)
- {
- ClosePopupToLevel(g.BeginPopupStack.Size, true);
- NavMoveRequestCancel();
- }
- EndPopup();
- }
- bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled)
- {
- ImGuiWindow* window = GetCurrentWindow();
- if (window->SkipItems)
- return false;
- ImGuiContext& g = *GImGui;
- ImGuiStyle& style = g.Style;
- ImVec2 pos = window->DC.CursorPos;
- ImVec2 label_size = CalcTextSize(label, NULL, true);
-
-
- bool pressed;
- PushID(label);
- if (!enabled)
- BeginDisabled();
- const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
- const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
- if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
- {
-
-
- float w = label_size.x;
- window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
- ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
- PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
- pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
- PopStyleVar();
- RenderText(text_pos, label);
- window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f));
- }
- else
- {
-
-
-
- float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
- float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
- float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
- float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w);
- float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
- pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
- RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
- if (icon_w > 0.0f)
- RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
- if (shortcut_w > 0.0f)
- {
- PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
- RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false);
- PopStyleColor();
- }
- if (selected)
- RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
- }
- IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
- if (!enabled)
- EndDisabled();
- PopID();
- return pressed;
- }
- bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)
- {
- return MenuItemEx(label, NULL, shortcut, selected, enabled);
- }
- bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)
- {
- if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled))
- {
- if (p_selected)
- *p_selected = !*p_selected;
- return true;
- }
- return false;
- }
- struct ImGuiTabBarSection
- {
- int TabCount;
- float Width;
- float Spacing;
- ImGuiTabBarSection() { memset(this, 0, sizeof(*this)); }
- };
- namespace ImGui
- {
- static void TabBarLayout(ImGuiTabBar* tab_bar);
- static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
- static float TabBarCalcMaxTabWidth();
- static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
- static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections);
- static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar);
- static ImGuiTabItem* TabBarTabListPopupButton(ImGuiTabBar* tab_bar);
- }
- ImGuiTabBar::ImGuiTabBar()
- {
- memset(this, 0, sizeof(*this));
- CurrFrameVisible = PrevFrameVisible = -1;
- LastTabItemIdx = -1;
- }
- static inline int TabItemGetSectionIdx(const ImGuiTabItem* tab)
- {
- return (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
- }
- static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs)
- {
- const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
- const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
- const int a_section = TabItemGetSectionIdx(a);
- const int b_section = TabItemGetSectionIdx(b);
- if (a_section != b_section)
- return a_section - b_section;
- return (int)(a->IndexDuringLayout - b->IndexDuringLayout);
- }
- static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs)
- {
- const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
- const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
- return (int)(a->BeginOrder - b->BeginOrder);
- }
- static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref)
- {
- ImGuiContext& g = *GImGui;
- return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index);
- }
- static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar)
- {
- ImGuiContext& g = *GImGui;
- if (g.TabBars.Contains(tab_bar))
- return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar));
- return ImGuiPtrOrIndex(tab_bar);
- }
- bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- ImGuiID id = window->GetID(str_id);
- ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
- ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2);
- tab_bar->ID = id;
- return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused);
- }
- bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- if ((flags & ImGuiTabBarFlags_DockNode) == 0)
- PushOverrideID(tab_bar->ID);
-
- g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
- g.CurrentTabBar = tab_bar;
-
- tab_bar->BackupCursorPos = window->DC.CursorPos;
- if (tab_bar->CurrFrameVisible == g.FrameCount)
- {
- window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY);
- tab_bar->BeginCount++;
- return true;
- }
-
- if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable)))
- if (tab_bar->Tabs.Size > 1)
- ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
- tab_bar->TabsAddedNew = false;
-
- if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
- flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
- tab_bar->Flags = flags;
- tab_bar->BarRect = tab_bar_bb;
- tab_bar->WantLayout = true;
- tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
- tab_bar->CurrFrameVisible = g.FrameCount;
- tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight;
- tab_bar->CurrTabsContentsHeight = 0.0f;
- tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
- tab_bar->FramePadding = g.Style.FramePadding;
- tab_bar->TabsActiveCount = 0;
- tab_bar->BeginCount = 1;
-
- window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY);
-
- const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive);
- const float y = tab_bar->BarRect.Max.y - 1.0f;
- {
- const float separator_min_x = tab_bar->BarRect.Min.x - IM_FLOOR(window->WindowPadding.x * 0.5f);
- const float separator_max_x = tab_bar->BarRect.Max.x + IM_FLOOR(window->WindowPadding.x * 0.5f);
- window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
- }
- return true;
- }
- void ImGui::EndTabBar()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return;
- ImGuiTabBar* tab_bar = g.CurrentTabBar;
- if (tab_bar == NULL)
- {
- IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!");
- return;
- }
-
- if (tab_bar->WantLayout)
- TabBarLayout(tab_bar);
-
- const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
- if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
- {
- tab_bar->CurrTabsContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, tab_bar->CurrTabsContentsHeight);
- window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->CurrTabsContentsHeight;
- }
- else
- {
- window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight;
- }
- if (tab_bar->BeginCount > 1)
- window->DC.CursorPos = tab_bar->BackupCursorPos;
- if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
- PopID();
- g.CurrentTabBarStack.pop_back();
- g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
- }
- static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
- {
- ImGuiContext& g = *GImGui;
- tab_bar->WantLayout = false;
-
-
- int tab_dst_n = 0;
- bool need_sort_by_section = false;
- ImGuiTabBarSection sections[3];
- for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++)
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n];
- if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose)
- {
-
- if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; }
- if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; }
- if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; }
- continue;
- }
- if (tab_dst_n != tab_src_n)
- tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n];
- tab = &tab_bar->Tabs[tab_dst_n];
- tab->IndexDuringLayout = (ImS16)tab_dst_n;
-
- int curr_tab_section_n = TabItemGetSectionIdx(tab);
- if (tab_dst_n > 0)
- {
- ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1];
- int prev_tab_section_n = TabItemGetSectionIdx(prev_tab);
- if (curr_tab_section_n == 0 && prev_tab_section_n != 0)
- need_sort_by_section = true;
- if (prev_tab_section_n == 2 && curr_tab_section_n != 2)
- need_sort_by_section = true;
- }
- sections[curr_tab_section_n].TabCount++;
- tab_dst_n++;
- }
- if (tab_bar->Tabs.Size != tab_dst_n)
- tab_bar->Tabs.resize(tab_dst_n);
- if (need_sort_by_section)
- ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection);
-
- sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f;
- sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f;
-
- ImGuiID scroll_to_tab_id = 0;
- if (tab_bar->NextSelectedTabId)
- {
- tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
- tab_bar->NextSelectedTabId = 0;
- scroll_to_tab_id = tab_bar->SelectedTabId;
- }
-
- if (tab_bar->ReorderRequestTabId != 0)
- {
- if (TabBarProcessReorder(tab_bar))
- if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId)
- scroll_to_tab_id = tab_bar->ReorderRequestTabId;
- tab_bar->ReorderRequestTabId = 0;
- }
-
- const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0;
- if (tab_list_popup_button)
- if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar))
- scroll_to_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
-
-
- int shrink_buffer_indexes[3] = { 0, sections[0].TabCount + sections[2].TabCount, sections[0].TabCount };
- g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size);
-
- ImGuiTabItem* most_recently_selected_tab = NULL;
- int curr_section_n = -1;
- bool found_selected_tab_id = false;
- for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
- IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible);
- if ((most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected) && !(tab->Flags & ImGuiTabItemFlags_Button))
- most_recently_selected_tab = tab;
- if (tab->ID == tab_bar->SelectedTabId)
- found_selected_tab_id = true;
- if (scroll_to_tab_id == 0 && g.NavJustMovedToId == tab->ID)
- scroll_to_tab_id = tab->ID;
-
-
-
- const char* tab_name = tab_bar->GetTabName(tab);
- const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
- tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x;
- int section_n = TabItemGetSectionIdx(tab);
- ImGuiTabBarSection* section = §ions[section_n];
- section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f);
- curr_section_n = section_n;
-
- IM_MSVC_WARNING_SUPPRESS(6385);
- int shrink_buffer_index = shrink_buffer_indexes[section_n]++;
- g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n;
- g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth;
- IM_ASSERT(tab->ContentWidth > 0.0f);
- tab->Width = tab->ContentWidth;
- }
-
- tab_bar->WidthAllTabsIdeal = 0.0f;
- for (int section_n = 0; section_n < 3; section_n++)
- tab_bar->WidthAllTabsIdeal += sections[section_n].Width + sections[section_n].Spacing;
-
-
- if ((tab_bar->WidthAllTabsIdeal > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll))
- if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar))
- {
- scroll_to_tab_id = scroll_and_select_tab->ID;
- if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0)
- tab_bar->SelectedTabId = scroll_to_tab_id;
- }
-
- float section_0_w = sections[0].Width + sections[0].Spacing;
- float section_1_w = sections[1].Width + sections[1].Spacing;
- float section_2_w = sections[2].Width + sections[2].Spacing;
- bool central_section_is_visible = (section_0_w + section_2_w) < tab_bar->BarRect.GetWidth();
- float width_excess;
- if (central_section_is_visible)
- width_excess = ImMax(section_1_w - (tab_bar->BarRect.GetWidth() - section_0_w - section_2_w), 0.0f);
- else
- width_excess = (section_0_w + section_2_w) - tab_bar->BarRect.GetWidth();
-
- if (width_excess > 0.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible))
- {
- int shrink_data_count = (central_section_is_visible ? sections[1].TabCount : sections[0].TabCount + sections[2].TabCount);
- int shrink_data_offset = (central_section_is_visible ? sections[0].TabCount + sections[2].TabCount : 0);
- ShrinkWidths(g.ShrinkWidthBuffer.Data + shrink_data_offset, shrink_data_count, width_excess);
-
- for (int tab_n = shrink_data_offset; tab_n < shrink_data_offset + shrink_data_count; tab_n++)
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index];
- float shrinked_width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width);
- if (shrinked_width < 0.0f)
- continue;
- int section_n = TabItemGetSectionIdx(tab);
- sections[section_n].Width -= (tab->Width - shrinked_width);
- tab->Width = shrinked_width;
- }
- }
-
- int section_tab_index = 0;
- float tab_offset = 0.0f;
- tab_bar->WidthAllTabs = 0.0f;
- for (int section_n = 0; section_n < 3; section_n++)
- {
- ImGuiTabBarSection* section = §ions[section_n];
- if (section_n == 2)
- tab_offset = ImMin(ImMax(0.0f, tab_bar->BarRect.GetWidth() - section->Width), tab_offset);
- for (int tab_n = 0; tab_n < section->TabCount; tab_n++)
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n];
- tab->Offset = tab_offset;
- tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f);
- }
- tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f);
- tab_offset += section->Spacing;
- section_tab_index += section->TabCount;
- }
-
- if (found_selected_tab_id == false)
- tab_bar->SelectedTabId = 0;
- if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
- scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
-
- tab_bar->VisibleTabId = tab_bar->SelectedTabId;
- tab_bar->VisibleTabWasSubmitted = false;
-
- if (scroll_to_tab_id != 0)
- TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
- tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
- tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
- if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
- {
-
-
- tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize);
- tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f);
- const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize);
- tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed);
- }
- else
- {
- tab_bar->ScrollingSpeed = 0.0f;
- }
- tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing;
- tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing;
-
- if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
- tab_bar->TabsNames.Buf.resize(0);
-
- ImGuiWindow* window = g.CurrentWindow;
- window->DC.CursorPos = tab_bar->BarRect.Min;
- ItemSize(ImVec2(tab_bar->WidthAllTabs, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
- window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, tab_bar->BarRect.Min.x + tab_bar->WidthAllTabsIdeal);
- }
- static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
- {
- if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
- {
- ImGuiID id = ImHashStr(label);
- KeepAliveID(id);
- return id;
- }
- else
- {
- ImGuiWindow* window = GImGui->CurrentWindow;
- return window->GetID(label);
- }
- }
- static float ImGui::TabBarCalcMaxTabWidth()
- {
- ImGuiContext& g = *GImGui;
- return g.FontSize * 20.0f;
- }
- ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
- {
- if (tab_id != 0)
- for (int n = 0; n < tab_bar->Tabs.Size; n++)
- if (tab_bar->Tabs[n].ID == tab_id)
- return &tab_bar->Tabs[n];
- return NULL;
- }
- void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
- {
- if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
- tab_bar->Tabs.erase(tab);
- if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; }
- if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; }
- if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; }
- }
- void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
- {
- IM_ASSERT(!(tab->Flags & ImGuiTabItemFlags_Button));
- if (!(tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
- {
-
-
- tab->WantClose = true;
- if (tab_bar->VisibleTabId == tab->ID)
- {
- tab->LastFrameVisible = -1;
- tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0;
- }
- }
- else
- {
-
- if (tab_bar->VisibleTabId != tab->ID)
- tab_bar->NextSelectedTabId = tab->ID;
- }
- }
- static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
- {
- scrolling = ImMin(scrolling, tab_bar->WidthAllTabs - tab_bar->BarRect.GetWidth());
- return ImMax(scrolling, 0.0f);
- }
- static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections)
- {
- ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
- if (tab == NULL)
- return;
- if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
- return;
- ImGuiContext& g = *GImGui;
- float margin = g.FontSize * 1.0f;
- int order = tab_bar->GetTabOrder(tab);
-
-
- float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
-
- float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);
- float tab_x2 = tab->Offset - sections[0].Width + tab->Width + (order + 1 < tab_bar->Tabs.Size - sections[2].TabCount ? margin : 1.0f);
- tab_bar->ScrollingTargetDistToVisibility = 0.0f;
- if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= scrollable_width))
- {
-
- tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f);
- tab_bar->ScrollingTarget = tab_x1;
- }
- else if (tab_bar->ScrollingTarget < tab_x2 - scrollable_width)
- {
-
- tab_bar->ScrollingTargetDistToVisibility = ImMax((tab_x1 - scrollable_width) - tab_bar->ScrollingAnim, 0.0f);
- tab_bar->ScrollingTarget = tab_x2 - scrollable_width;
- }
- }
- void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
- {
- IM_ASSERT(offset != 0);
- IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
- tab_bar->ReorderRequestTabId = tab->ID;
- tab_bar->ReorderRequestOffset = (ImS16)offset;
- }
- void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
- {
- ImGuiContext& g = *GImGui;
- IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
- if ((tab_bar->Flags & ImGuiTabBarFlags_Reorderable) == 0)
- return;
- const bool is_central_section = (src_tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
- const float bar_offset = tab_bar->BarRect.Min.x - (is_central_section ? tab_bar->ScrollingTarget : 0);
-
- const int dir = (bar_offset + src_tab->Offset) > mouse_pos.x ? -1 : +1;
- const int src_idx = tab_bar->Tabs.index_from_ptr(src_tab);
- int dst_idx = src_idx;
- for (int i = src_idx; i >= 0 && i < tab_bar->Tabs.Size; i += dir)
- {
-
- const ImGuiTabItem* dst_tab = &tab_bar->Tabs[i];
- if (dst_tab->Flags & ImGuiTabItemFlags_NoReorder)
- break;
- if ((dst_tab->Flags & ImGuiTabItemFlags_SectionMask_) != (src_tab->Flags & ImGuiTabItemFlags_SectionMask_))
- break;
- dst_idx = i;
-
- const float x1 = bar_offset + dst_tab->Offset - g.Style.ItemInnerSpacing.x;
- const float x2 = bar_offset + dst_tab->Offset + dst_tab->Width + g.Style.ItemInnerSpacing.x;
-
- if ((dir < 0 && mouse_pos.x > x1) || (dir > 0 && mouse_pos.x < x2))
- break;
- }
- if (dst_idx != src_idx)
- TabBarQueueReorder(tab_bar, src_tab, dst_idx - src_idx);
- }
- bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
- {
- ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId);
- if (tab1 == NULL || (tab1->Flags & ImGuiTabItemFlags_NoReorder))
- return false;
-
- int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
- if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
- return false;
-
-
- ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
- if (tab2->Flags & ImGuiTabItemFlags_NoReorder)
- return false;
- if ((tab1->Flags & ImGuiTabItemFlags_SectionMask_) != (tab2->Flags & ImGuiTabItemFlags_SectionMask_))
- return false;
- ImGuiTabItem item_tmp = *tab1;
- ImGuiTabItem* src_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 + 1 : tab2;
- ImGuiTabItem* dst_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 : tab2 + 1;
- const int move_count = (tab_bar->ReorderRequestOffset > 0) ? tab_bar->ReorderRequestOffset : -tab_bar->ReorderRequestOffset;
- memmove(dst_tab, src_tab, move_count * sizeof(ImGuiTabItem));
- *tab2 = item_tmp;
- if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
- MarkIniSettingsDirty();
- return true;
- }
- static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f);
- const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
- const ImVec2 backup_cursor_pos = window->DC.CursorPos;
-
- int select_dir = 0;
- ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
- arrow_col.w *= 0.5f;
- PushStyleColor(ImGuiCol_Text, arrow_col);
- PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
- const float backup_repeat_delay = g.IO.KeyRepeatDelay;
- const float backup_repeat_rate = g.IO.KeyRepeatRate;
- g.IO.KeyRepeatDelay = 0.250f;
- g.IO.KeyRepeatRate = 0.200f;
- float x = ImMax(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.x - scrolling_buttons_width);
- window->DC.CursorPos = ImVec2(x, tab_bar->BarRect.Min.y);
- if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
- select_dir = -1;
- window->DC.CursorPos = ImVec2(x + arrow_button_size.x, tab_bar->BarRect.Min.y);
- if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
- select_dir = +1;
- PopStyleColor(2);
- g.IO.KeyRepeatRate = backup_repeat_rate;
- g.IO.KeyRepeatDelay = backup_repeat_delay;
- ImGuiTabItem* tab_to_scroll_to = NULL;
- if (select_dir != 0)
- if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
- {
- int selected_order = tab_bar->GetTabOrder(tab_item);
- int target_order = selected_order + select_dir;
-
- while (tab_to_scroll_to == NULL)
- {
-
- tab_to_scroll_to = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order];
-
-
- if (tab_to_scroll_to->Flags & ImGuiTabItemFlags_Button)
- {
- target_order += select_dir;
- selected_order += select_dir;
- tab_to_scroll_to = (target_order < 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL;
- }
- }
- }
- window->DC.CursorPos = backup_cursor_pos;
- tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f;
- return tab_to_scroll_to;
- }
- static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
-
- const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y;
- const ImVec2 backup_cursor_pos = window->DC.CursorPos;
- window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y);
- tab_bar->BarRect.Min.x += tab_list_popup_button_width;
- ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
- arrow_col.w *= 0.5f;
- PushStyleColor(ImGuiCol_Text, arrow_col);
- PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
- bool open = BeginCombo("##v", NULL, ImGuiComboFlags_NoPreview | ImGuiComboFlags_HeightLargest);
- PopStyleColor(2);
- ImGuiTabItem* tab_to_select = NULL;
- if (open)
- {
- for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
- if (tab->Flags & ImGuiTabItemFlags_Button)
- continue;
- const char* tab_name = tab_bar->GetTabName(tab);
- if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
- tab_to_select = tab;
- }
- EndCombo();
- }
- window->DC.CursorPos = backup_cursor_pos;
- return tab_to_select;
- }
- bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- ImGuiTabBar* tab_bar = g.CurrentTabBar;
- if (tab_bar == NULL)
- {
- IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!");
- return false;
- }
- IM_ASSERT(!(flags & ImGuiTabItemFlags_Button));
- bool ret = TabItemEx(tab_bar, label, p_open, flags);
- if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
- {
- ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
- PushOverrideID(tab->ID);
- }
- return ret;
- }
- void ImGui::EndTabItem()
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return;
- ImGuiTabBar* tab_bar = g.CurrentTabBar;
- if (tab_bar == NULL)
- {
- IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
- return;
- }
- IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
- ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
- if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
- PopID();
- }
- bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags)
- {
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- ImGuiTabBar* tab_bar = g.CurrentTabBar;
- if (tab_bar == NULL)
- {
- IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
- return false;
- }
- return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder);
- }
- bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
- {
-
- if (tab_bar->WantLayout)
- TabBarLayout(tab_bar);
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- if (window->SkipItems)
- return false;
- const ImGuiStyle& style = g.Style;
- const ImGuiID id = TabBarCalcTabID(tab_bar, label);
-
-
- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
- if (p_open && !*p_open)
- {
- ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
- return false;
- }
- IM_ASSERT(!p_open || !(flags & ImGuiTabItemFlags_Button));
- IM_ASSERT((flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing));
-
- if (flags & ImGuiTabItemFlags_NoCloseButton)
- p_open = NULL;
- else if (p_open == NULL)
- flags |= ImGuiTabItemFlags_NoCloseButton;
-
- ImVec2 size = TabItemCalcSize(label, p_open != NULL);
-
- ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
- bool tab_is_new = false;
- if (tab == NULL)
- {
- tab_bar->Tabs.push_back(ImGuiTabItem());
- tab = &tab_bar->Tabs.back();
- tab->ID = id;
- tab->Width = size.x;
- tab_bar->TabsAddedNew = true;
- tab_is_new = true;
- }
- tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab);
- tab->ContentWidth = size.x;
- tab->BeginOrder = tab_bar->TabsActiveCount++;
- const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
- const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
- const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount);
- const bool is_tab_button = (flags & ImGuiTabItemFlags_Button) != 0;
- tab->LastFrameVisible = g.FrameCount;
- tab->Flags = flags;
-
- tab->NameOffset = (ImS32)tab_bar->TabsNames.size();
- tab_bar->TabsNames.append(label, label + strlen(label) + 1);
-
- if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
- if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
- if (!is_tab_button)
- tab_bar->NextSelectedTabId = id;
- if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id))
- if (!is_tab_button)
- tab_bar->NextSelectedTabId = id;
-
-
- bool tab_contents_visible = (tab_bar->VisibleTabId == id);
- if (tab_contents_visible)
- tab_bar->VisibleTabWasSubmitted = true;
-
- if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing)
- if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
- tab_contents_visible = true;
-
-
- if (tab_appearing && (!tab_bar_appearing || tab_is_new))
- {
- ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
- if (is_tab_button)
- return false;
- return tab_contents_visible;
- }
- if (tab_bar->SelectedTabId == id)
- tab->LastFrameSelected = g.FrameCount;
-
- const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
-
- const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
- size.x = tab->Width;
- if (is_central_section)
- window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
- else
- window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
- ImVec2 pos = window->DC.CursorPos;
- ImRect bb(pos, pos + size);
-
- const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX);
- if (want_clip_rect)
- PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
- ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
- ItemSize(bb.GetSize(), style.FramePadding.y);
- window->DC.CursorMaxPos = backup_cursor_max_pos;
- if (!ItemAdd(bb, id))
- {
- if (want_clip_rect)
- PopClipRect();
- window->DC.CursorPos = backup_main_cursor_pos;
- return tab_contents_visible;
- }
-
- ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowItemOverlap);
- if (g.DragDropActive)
- button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
- bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
- if (pressed && !is_tab_button)
- tab_bar->NextSelectedTabId = id;
-
- if (g.ActiveId != id)
- SetItemAllowOverlap();
-
- if (held && !tab_appearing && IsMouseDragging(0))
- {
- if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
- {
-
- if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
- {
- TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
- }
- else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
- {
- TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
- }
- }
- }
- #if 0
- if (hovered && g.HoveredIdNotActiveTimer > TOOLTIP_DELAY && bb.GetWidth() < tab->ContentWidth)
- {
-
- bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)));
- display_draw_list = GetForegroundDrawList(window);
- TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
- }
- #endif
-
- ImDrawList* display_draw_list = window->DrawList;
- const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused));
- TabItemBackground(display_draw_list, bb, flags, tab_col);
- RenderNavHighlight(bb, id);
-
- const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
- if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
- if (!is_tab_button)
- tab_bar->NextSelectedTabId = id;
- if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
- flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
-
- const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0;
- bool just_closed;
- bool text_clipped;
- TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped);
- if (just_closed && p_open != NULL)
- {
- *p_open = false;
- TabBarCloseTab(tab_bar, tab);
- }
-
- if (want_clip_rect)
- PopClipRect();
- window->DC.CursorPos = backup_main_cursor_pos;
-
-
-
-
-
- if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered())
- if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
- SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
- IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button));
- if (is_tab_button)
- return pressed;
- return tab_contents_visible;
- }
- void ImGui::SetTabItemClosed(const char* label)
- {
- ImGuiContext& g = *GImGui;
- bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode);
- if (is_within_manual_tab_bar)
- {
- ImGuiTabBar* tab_bar = g.CurrentTabBar;
- ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
- if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
- tab->WantClose = true;
- }
- }
- ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button)
- {
- ImGuiContext& g = *GImGui;
- ImVec2 label_size = CalcTextSize(label, NULL, true);
- ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f);
- if (has_close_button)
- size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize);
- else
- size.x += g.Style.FramePadding.x + 1.0f;
- return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y);
- }
- void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col)
- {
-
- ImGuiContext& g = *GImGui;
- const float width = bb.GetWidth();
- IM_UNUSED(flags);
- IM_ASSERT(width > 0.0f);
- const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
- const float y1 = bb.Min.y + 1.0f;
- const float y2 = bb.Max.y - 1.0f;
- draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
- draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
- draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
- draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
- draw_list->PathFillConvex(col);
- if (g.Style.TabBorderSize > 0.0f)
- {
- draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
- draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
- draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
- draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
- draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
- }
- }
- void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped)
- {
- ImGuiContext& g = *GImGui;
- ImVec2 label_size = CalcTextSize(label, NULL, true);
- if (out_just_closed)
- *out_just_closed = false;
- if (out_text_clipped)
- *out_text_clipped = false;
- if (bb.GetWidth() <= 1.0f)
- return;
-
-
- #if 0
- const float backup_alpha = g.Style.Alpha;
- if (!is_contents_visible)
- g.Style.Alpha *= 0.7f;
- #endif
-
- ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
- ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
-
- if (out_text_clipped)
- {
- *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x;
-
- }
- const float button_sz = g.FontSize;
- const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x * 2.0f - button_sz), bb.Min.y);
-
-
-
-
-
- bool close_button_pressed = false;
- bool close_button_visible = false;
- if (close_button_id != 0)
- if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton))
- if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id)
- close_button_visible = true;
- bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x);
- if (close_button_visible)
- {
- ImGuiLastItemData last_item_backup = g.LastItemData;
- PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);
- if (CloseButton(close_button_id, button_pos))
- close_button_pressed = true;
- PopStyleVar();
- g.LastItemData = last_item_backup;
-
- if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2))
- close_button_pressed = true;
- }
- else if (unsaved_marker_visible)
- {
- const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz) + g.Style.FramePadding * 2.0f);
- RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));
- }
-
-
-
- float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
- if (close_button_visible || unsaved_marker_visible)
- {
- text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);
- text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
- ellipsis_max_x = text_pixel_clip_bb.Max.x;
- }
- RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
- #if 0
- if (!is_contents_visible)
- g.Style.Alpha = backup_alpha;
- #endif
- if (out_just_closed)
- *out_just_closed = close_button_pressed;
- }
- #endif
|