raygui.h 273 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757
  1. /*******************************************************************************************
  2. *
  3. * raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library
  4. *
  5. * DESCRIPTION:
  6. * raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
  7. * available as a standalone library, as long as input and drawing functions are provided.
  8. *
  9. * FEATURES:
  10. * - Immediate-mode gui, minimal retained data
  11. * - +25 controls provided (basic and advanced)
  12. * - Styling system for colors, font and metrics
  13. * - Icons supported, embedded as a 1-bit icons pack
  14. * - Standalone mode option (custom input/graphics backend)
  15. * - Multiple support tools provided for raygui development
  16. *
  17. * POSSIBLE IMPROVEMENTS:
  18. * - Better standalone mode API for easy plug of custom backends
  19. * - Externalize required inputs, allow user easier customization
  20. *
  21. * LIMITATIONS:
  22. * - No editable multi-line word-wraped text box supported
  23. * - No auto-layout mechanism, up to the user to define controls position and size
  24. * - Standalone mode requires library modification and some user work to plug another backend
  25. *
  26. * NOTES:
  27. * - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for
  28. * font atlas recs and glyphs, freeing that memory is (usually) up to the user,
  29. * no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads
  30. * by default any previously loaded font (texture, recs, glyphs).
  31. * - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions
  32. *
  33. * CONTROLS PROVIDED:
  34. * # Container/separators Controls
  35. * - WindowBox --> StatusBar, Panel
  36. * - GroupBox --> Line
  37. * - Line
  38. * - Panel --> StatusBar
  39. * - ScrollPanel --> StatusBar
  40. * - TabBar --> Button
  41. *
  42. * # Basic Controls
  43. * - Label
  44. * - LabelButton --> Label
  45. * - Button
  46. * - Toggle
  47. * - ToggleGroup --> Toggle
  48. * - ToggleSlider
  49. * - CheckBox
  50. * - ComboBox
  51. * - DropdownBox
  52. * - TextBox
  53. * - ValueBox --> TextBox
  54. * - Spinner --> Button, ValueBox
  55. * - Slider
  56. * - SliderBar --> Slider
  57. * - ProgressBar
  58. * - StatusBar
  59. * - DummyRec
  60. * - Grid
  61. *
  62. * # Advance Controls
  63. * - ListView
  64. * - ColorPicker --> ColorPanel, ColorBarHue
  65. * - MessageBox --> Window, Label, Button
  66. * - TextInputBox --> Window, Label, TextBox, Button
  67. *
  68. * It also provides a set of functions for styling the controls based on its properties (size, color).
  69. *
  70. *
  71. * RAYGUI STYLE (guiStyle):
  72. * raygui uses a global data array for all gui style properties (allocated on data segment by default),
  73. * when a new style is loaded, it is loaded over the global style... but a default gui style could always be
  74. * recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one
  75. *
  76. * The global style array size is fixed and depends on the number of controls and properties:
  77. *
  78. * static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)];
  79. *
  80. * guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
  81. *
  82. * Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style
  83. * used for all controls, when any of those base values is set, it is automatically populated to all
  84. * controls, so, specific control values overwriting generic style should be set after base values.
  85. *
  86. * After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those
  87. * properties are actually common to all controls and can not be overwritten individually (like BASE ones)
  88. * Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR
  89. *
  90. * Custom control properties can be defined using the EXTENDED properties for each independent control.
  91. *
  92. * TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler
  93. *
  94. *
  95. * RAYGUI ICONS (guiIcons):
  96. * raygui could use a global array containing icons data (allocated on data segment by default),
  97. * a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set
  98. * must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded
  99. *
  100. * Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon
  101. * requires 8 integers (16*16/32) to be stored in memory.
  102. *
  103. * When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set.
  104. *
  105. * The global icons array size is fixed and depends on the number of icons and size:
  106. *
  107. * static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS];
  108. *
  109. * guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
  110. *
  111. * TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons
  112. *
  113. * RAYGUI LAYOUT:
  114. * raygui currently does not provide an auto-layout mechanism like other libraries,
  115. * layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it.
  116. *
  117. * TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout
  118. *
  119. * CONFIGURATION:
  120. * #define RAYGUI_IMPLEMENTATION
  121. * Generates the implementation of the library into the included file.
  122. * If not defined, the library is in header only mode and can be included in other headers
  123. * or source files without problems. But only ONE file should hold the implementation.
  124. *
  125. * #define RAYGUI_STANDALONE
  126. * Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
  127. * internally in the library and input management and drawing functions must be provided by
  128. * the user (check library implementation for further details).
  129. *
  130. * #define RAYGUI_NO_ICONS
  131. * Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB)
  132. *
  133. * #define RAYGUI_CUSTOM_ICONS
  134. * Includes custom ricons.h header defining a set of custom icons,
  135. * this file can be generated using rGuiIcons tool
  136. *
  137. * #define RAYGUI_DEBUG_RECS_BOUNDS
  138. * Draw control bounds rectangles for debug
  139. *
  140. * #define RAYGUI_DEBUG_TEXT_BOUNDS
  141. * Draw text bounds rectangles for debug
  142. *
  143. * VERSIONS HISTORY:
  144. * 4.5-dev (Sep-2024) Current dev version...
  145. * ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
  146. * ADDED: GuiValueBoxFloat()
  147. * ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
  148. * ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH
  149. * ADDED: Multiple new icons
  150. * REVIEWED: GuiTabBar(), close tab with mouse middle button
  151. * REVIEWED: GuiScrollPanel(), scroll speed proportional to content
  152. * REVIEWED: GuiDropdownBox(), support roll up and hidden arrow
  153. * REVIEWED: GuiTextBox(), cursor position initialization
  154. * REVIEWED: GuiSliderPro(), control value change check
  155. * REVIEWED: GuiGrid(), simplified implementation
  156. * REVIEWED: GuiIconText(), increase buffer size and reviewed padding
  157. * REVIEWED: GuiDrawText(), improved wrap mode drawing
  158. * REVIEWED: GuiScrollBar(), minor tweaks
  159. * REVIEWED: Functions descriptions, removed wrong return value reference
  160. * REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion
  161. *
  162. * 4.0 (12-Sep-2023) ADDED: GuiToggleSlider()
  163. * ADDED: GuiColorPickerHSV() and GuiColorPanelHSV()
  164. * ADDED: Multiple new icons, mostly compiler related
  165. * ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE
  166. * ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode
  167. * ADDED: Support loading styles with custom font charset from external file
  168. * REDESIGNED: GuiTextBox(), support mouse cursor positioning
  169. * REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only)
  170. * REDESIGNED: GuiProgressBar() to be more visual, progress affects border color
  171. * REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText()
  172. * REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value
  173. * REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value
  174. * REDESIGNED: GuiComboBox(), get parameters by reference and return result value
  175. * REDESIGNED: GuiCheckBox(), get parameters by reference and return result value
  176. * REDESIGNED: GuiSlider(), get parameters by reference and return result value
  177. * REDESIGNED: GuiSliderBar(), get parameters by reference and return result value
  178. * REDESIGNED: GuiProgressBar(), get parameters by reference and return result value
  179. * REDESIGNED: GuiListView(), get parameters by reference and return result value
  180. * REDESIGNED: GuiColorPicker(), get parameters by reference and return result value
  181. * REDESIGNED: GuiColorPanel(), get parameters by reference and return result value
  182. * REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value
  183. * REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value
  184. * REDESIGNED: GuiGrid(), get parameters by reference and return result value
  185. * REDESIGNED: GuiGrid(), added extra parameter
  186. * REDESIGNED: GuiListViewEx(), change parameters order
  187. * REDESIGNED: All controls return result as int value
  188. * REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars
  189. * REVIEWED: All examples and specially controls_test_suite
  190. * RENAMED: gui_file_dialog module to gui_window_file_dialog
  191. * UPDATED: All styles to include ISO-8859-15 charset (as much as possible)
  192. *
  193. * 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER
  194. * ADDED: GuiLoadStyleFromMemory() (binary only)
  195. * REVIEWED: GuiScrollBar() horizontal movement key
  196. * REVIEWED: GuiTextBox() crash on cursor movement
  197. * REVIEWED: GuiTextBox(), additional inputs support
  198. * REVIEWED: GuiLabelButton(), avoid text cut
  199. * REVIEWED: GuiTextInputBox(), password input
  200. * REVIEWED: Local GetCodepointNext(), aligned with raylib
  201. * REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds
  202. *
  203. * 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle()
  204. * ADDED: Helper functions to split text in separate lines
  205. * ADDED: Multiple new icons, useful for code editing tools
  206. * REMOVED: Unneeded icon editing functions
  207. * REMOVED: GuiTextBoxMulti(), very limited and broken
  208. * REMOVED: MeasureTextEx() dependency, logic directly implemented
  209. * REMOVED: DrawTextEx() dependency, logic directly implemented
  210. * REVIEWED: GuiScrollBar(), improve mouse-click behaviour
  211. * REVIEWED: Library header info, more info, better organized
  212. * REDESIGNED: GuiTextBox() to support cursor movement
  213. * REDESIGNED: GuiDrawText() to divide drawing by lines
  214. *
  215. * 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes
  216. * REMOVED: GuiScrollBar(), only internal
  217. * REDESIGNED: GuiPanel() to support text parameter
  218. * REDESIGNED: GuiScrollPanel() to support text parameter
  219. * REDESIGNED: GuiColorPicker() to support text parameter
  220. * REDESIGNED: GuiColorPanel() to support text parameter
  221. * REDESIGNED: GuiColorBarAlpha() to support text parameter
  222. * REDESIGNED: GuiColorBarHue() to support text parameter
  223. * REDESIGNED: GuiTextInputBox() to support password
  224. *
  225. * 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool)
  226. * REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures
  227. * REVIEWED: External icons usage logic
  228. * REVIEWED: GuiLine() for centered alignment when including text
  229. * RENAMED: Multiple controls properties definitions to prepend RAYGUI_
  230. * RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency
  231. * Projects updated and multiple tweaks
  232. *
  233. * 3.0 (04-Nov-2021) Integrated ricons data to avoid external file
  234. * REDESIGNED: GuiTextBoxMulti()
  235. * REMOVED: GuiImageButton*()
  236. * Multiple minor tweaks and bugs corrected
  237. *
  238. * 2.9 (17-Mar-2021) REMOVED: Tooltip API
  239. * 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle()
  240. * 2.7 (20-Feb-2020) ADDED: Possible tooltips API
  241. * 2.6 (09-Sep-2019) ADDED: GuiTextInputBox()
  242. * REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox()
  243. * REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle()
  244. * Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties
  245. * ADDED: 8 new custom styles ready to use
  246. * Multiple minor tweaks and bugs corrected
  247. *
  248. * 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner()
  249. * 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed
  250. * Refactor all controls drawing mechanism to use control state
  251. * 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls
  252. * 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string
  253. * REDESIGNED: Style system (breaking change)
  254. * 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts
  255. * REVIEWED: GuiComboBox(), GuiListView()...
  256. * 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()...
  257. * 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout
  258. * 1.5 (21-Jun-2017) Working in an improved styles system
  259. * 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones)
  260. * 1.3 (12-Jun-2017) Complete redesign of style system
  261. * 1.1 (01-Jun-2017) Complete review of the library
  262. * 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria.
  263. * 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria.
  264. * 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria.
  265. *
  266. * DEPENDENCIES:
  267. * raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
  268. *
  269. * STANDALONE MODE:
  270. * By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled
  271. * with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs.
  272. *
  273. * The following functions should be redefined for a custom backend:
  274. *
  275. * - Vector2 GetMousePosition(void);
  276. * - float GetMouseWheelMove(void);
  277. * - bool IsMouseButtonDown(int button);
  278. * - bool IsMouseButtonPressed(int button);
  279. * - bool IsMouseButtonReleased(int button);
  280. * - bool IsKeyDown(int key);
  281. * - bool IsKeyPressed(int key);
  282. * - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
  283. *
  284. * - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
  285. * - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
  286. *
  287. * - Font GetFontDefault(void); // -- GuiLoadStyleDefault()
  288. * - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle()
  289. * - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
  290. * - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
  291. * - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
  292. * - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
  293. * - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
  294. * - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
  295. * - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
  296. * - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
  297. *
  298. * CONTRIBUTORS:
  299. * Ramon Santamaria: Supervision, review, redesign, update and maintenance
  300. * Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019)
  301. * Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018)
  302. * Adria Arranz: Testing and implementation of additional controls (2018)
  303. * Jordi Jorba: Testing and implementation of additional controls (2018)
  304. * Albert Martos: Review and testing of the library (2015)
  305. * Ian Eito: Review and testing of the library (2015)
  306. * Kevin Gato: Initial implementation of basic components (2014)
  307. * Daniel Nicolas: Initial implementation of basic components (2014)
  308. *
  309. *
  310. * LICENSE: zlib/libpng
  311. *
  312. * Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
  313. *
  314. * This software is provided "as-is", without any express or implied warranty. In no event
  315. * will the authors be held liable for any damages arising from the use of this software.
  316. *
  317. * Permission is granted to anyone to use this software for any purpose, including commercial
  318. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  319. *
  320. * 1. The origin of this software must not be misrepresented; you must not claim that you
  321. * wrote the original software. If you use this software in a product, an acknowledgment
  322. * in the product documentation would be appreciated but is not required.
  323. *
  324. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  325. * as being the original software.
  326. *
  327. * 3. This notice may not be removed or altered from any source distribution.
  328. *
  329. **********************************************************************************************/
  330. #ifndef RAYGUI_H
  331. #define RAYGUI_H
  332. #define RAYGUI_VERSION_MAJOR 4
  333. #define RAYGUI_VERSION_MINOR 5
  334. #define RAYGUI_VERSION_PATCH 0
  335. #define RAYGUI_VERSION "4.5-dev"
  336. #if !defined(RAYGUI_STANDALONE)
  337. #include "raylib.h"
  338. #endif
  339. // Function specifiers in case library is build/used as a shared library (Windows)
  340. // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
  341. #if defined(_WIN32)
  342. #if defined(BUILD_LIBTYPE_SHARED)
  343. #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
  344. #elif defined(USE_LIBTYPE_SHARED)
  345. #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
  346. #endif
  347. #endif
  348. // Function specifiers definition
  349. #ifndef RAYGUIAPI
  350. #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers)
  351. #endif
  352. //----------------------------------------------------------------------------------
  353. // Defines and Macros
  354. //----------------------------------------------------------------------------------
  355. // Allow custom memory allocators
  356. #ifndef RAYGUI_MALLOC
  357. #define RAYGUI_MALLOC(sz) malloc(sz)
  358. #endif
  359. #ifndef RAYGUI_CALLOC
  360. #define RAYGUI_CALLOC(n,sz) calloc(n,sz)
  361. #endif
  362. #ifndef RAYGUI_FREE
  363. #define RAYGUI_FREE(p) free(p)
  364. #endif
  365. // Simple log system to avoid printf() calls if required
  366. // NOTE: Avoiding those calls, also avoids const strings memory usage
  367. #define RAYGUI_SUPPORT_LOG_INFO
  368. #if defined(RAYGUI_SUPPORT_LOG_INFO)
  369. #define RAYGUI_LOG(...) printf(__VA_ARGS__)
  370. #else
  371. #define RAYGUI_LOG(...)
  372. #endif
  373. //----------------------------------------------------------------------------------
  374. // Types and Structures Definition
  375. // NOTE: Some types are required for RAYGUI_STANDALONE usage
  376. //----------------------------------------------------------------------------------
  377. #if defined(RAYGUI_STANDALONE)
  378. #ifndef __cplusplus
  379. // Boolean type
  380. #ifndef true
  381. typedef enum { false, true } bool;
  382. #endif
  383. #endif
  384. // Vector2 type
  385. typedef struct Vector2 {
  386. float x;
  387. float y;
  388. } Vector2;
  389. // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV()
  390. typedef struct Vector3 {
  391. float x;
  392. float y;
  393. float z;
  394. } Vector3;
  395. // Color type, RGBA (32bit)
  396. typedef struct Color {
  397. unsigned char r;
  398. unsigned char g;
  399. unsigned char b;
  400. unsigned char a;
  401. } Color;
  402. // Rectangle type
  403. typedef struct Rectangle {
  404. float x;
  405. float y;
  406. float width;
  407. float height;
  408. } Rectangle;
  409. // TODO: Texture2D type is very coupled to raylib, required by Font type
  410. // It should be redesigned to be provided by user
  411. typedef struct Texture2D {
  412. unsigned int id; // OpenGL texture id
  413. int width; // Texture base width
  414. int height; // Texture base height
  415. int mipmaps; // Mipmap levels, 1 by default
  416. int format; // Data format (PixelFormat type)
  417. } Texture2D;
  418. // Image, pixel data stored in CPU memory (RAM)
  419. typedef struct Image {
  420. void *data; // Image raw data
  421. int width; // Image base width
  422. int height; // Image base height
  423. int mipmaps; // Mipmap levels, 1 by default
  424. int format; // Data format (PixelFormat type)
  425. } Image;
  426. // GlyphInfo, font characters glyphs info
  427. typedef struct GlyphInfo {
  428. int value; // Character value (Unicode)
  429. int offsetX; // Character offset X when drawing
  430. int offsetY; // Character offset Y when drawing
  431. int advanceX; // Character advance position X
  432. Image image; // Character image data
  433. } GlyphInfo;
  434. // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
  435. // It should be redesigned to be provided by user
  436. typedef struct Font {
  437. int baseSize; // Base size (default chars height)
  438. int glyphCount; // Number of glyph characters
  439. int glyphPadding; // Padding around the glyph characters
  440. Texture2D texture; // Texture atlas containing the glyphs
  441. Rectangle *recs; // Rectangles in texture for the glyphs
  442. GlyphInfo *glyphs; // Glyphs info data
  443. } Font;
  444. #endif
  445. // Style property
  446. // NOTE: Used when exporting style as code for convenience
  447. typedef struct GuiStyleProp {
  448. unsigned short controlId; // Control identifier
  449. unsigned short propertyId; // Property identifier
  450. int propertyValue; // Property value
  451. } GuiStyleProp;
  452. /*
  453. // Controls text style -NOT USED-
  454. // NOTE: Text style is defined by control
  455. typedef struct GuiTextStyle {
  456. unsigned int size;
  457. int charSpacing;
  458. int lineSpacing;
  459. int alignmentH;
  460. int alignmentV;
  461. int padding;
  462. } GuiTextStyle;
  463. */
  464. // Gui control state
  465. typedef enum {
  466. STATE_NORMAL = 0,
  467. STATE_FOCUSED,
  468. STATE_PRESSED,
  469. STATE_DISABLED
  470. } GuiState;
  471. // Gui control text alignment
  472. typedef enum {
  473. TEXT_ALIGN_LEFT = 0,
  474. TEXT_ALIGN_CENTER,
  475. TEXT_ALIGN_RIGHT
  476. } GuiTextAlignment;
  477. // Gui control text alignment vertical
  478. // NOTE: Text vertical position inside the text bounds
  479. typedef enum {
  480. TEXT_ALIGN_TOP = 0,
  481. TEXT_ALIGN_MIDDLE,
  482. TEXT_ALIGN_BOTTOM
  483. } GuiTextAlignmentVertical;
  484. // Gui control text wrap mode
  485. // NOTE: Useful for multiline text
  486. typedef enum {
  487. TEXT_WRAP_NONE = 0,
  488. TEXT_WRAP_CHAR,
  489. TEXT_WRAP_WORD
  490. } GuiTextWrapMode;
  491. // Gui controls
  492. typedef enum {
  493. // Default -> populates to all controls when set
  494. DEFAULT = 0,
  495. // Basic controls
  496. LABEL, // Used also for: LABELBUTTON
  497. BUTTON,
  498. TOGGLE, // Used also for: TOGGLEGROUP
  499. SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER
  500. PROGRESSBAR,
  501. CHECKBOX,
  502. COMBOBOX,
  503. DROPDOWNBOX,
  504. TEXTBOX, // Used also for: TEXTBOXMULTI
  505. VALUEBOX,
  506. SPINNER, // Uses: BUTTON, VALUEBOX
  507. LISTVIEW,
  508. COLORPICKER,
  509. SCROLLBAR,
  510. STATUSBAR
  511. } GuiControl;
  512. // Gui base properties for every control
  513. // NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
  514. typedef enum {
  515. BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL
  516. BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL
  517. TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL
  518. BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED
  519. BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED
  520. TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED
  521. BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED
  522. BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED
  523. TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED
  524. BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED
  525. BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED
  526. TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED
  527. BORDER_WIDTH, // Control border size, 0 for no border
  528. //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls
  529. //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls
  530. //TEXT_LINE_SPACING // Control text spacing between lines -> GLOBAL for all controls
  531. TEXT_PADDING, // Control text padding, not considering border
  532. TEXT_ALIGNMENT, // Control text horizontal alignment inside control text bound (after border and padding)
  533. //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls
  534. } GuiControlProperty;
  535. // TODO: Which text styling properties should be global or per-control?
  536. // At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while
  537. // TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and
  538. // should be configured by user as needed while defining the UI layout
  539. // Gui extended properties depend on control
  540. // NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties)
  541. //----------------------------------------------------------------------------------
  542. // DEFAULT extended properties
  543. // NOTE: Those properties are common to all controls or global
  544. // WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT?
  545. typedef enum {
  546. TEXT_SIZE = 16, // Text size (glyphs max height)
  547. TEXT_SPACING, // Text spacing between glyphs
  548. LINE_COLOR, // Line control color
  549. BACKGROUND_COLOR, // Background color
  550. TEXT_LINE_SPACING, // Text spacing between lines
  551. TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding)
  552. TEXT_WRAP_MODE // Text wrap-mode inside text bounds
  553. //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline
  554. //TEXT_DECORATION_THICK // Text decoration line thickness
  555. } GuiDefaultProperty;
  556. // Other possible text properties:
  557. // TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change
  558. // TEXT_INDENT // Text indentation -> Now using TEXT_PADDING...
  559. // Label
  560. //typedef enum { } GuiLabelProperty;
  561. // Button/Spinner
  562. //typedef enum { } GuiButtonProperty;
  563. // Toggle/ToggleGroup
  564. typedef enum {
  565. GROUP_PADDING = 16, // ToggleGroup separation between toggles
  566. } GuiToggleProperty;
  567. // Slider/SliderBar
  568. typedef enum {
  569. SLIDER_WIDTH = 16, // Slider size of internal bar
  570. SLIDER_PADDING // Slider/SliderBar internal bar padding
  571. } GuiSliderProperty;
  572. // ProgressBar
  573. typedef enum {
  574. PROGRESS_PADDING = 16, // ProgressBar internal padding
  575. } GuiProgressBarProperty;
  576. // ScrollBar
  577. typedef enum {
  578. ARROWS_SIZE = 16, // ScrollBar arrows size
  579. ARROWS_VISIBLE, // ScrollBar arrows visible
  580. SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding
  581. SCROLL_SLIDER_SIZE, // ScrollBar slider size
  582. SCROLL_PADDING, // ScrollBar scroll padding from arrows
  583. SCROLL_SPEED, // ScrollBar scrolling speed
  584. } GuiScrollBarProperty;
  585. // CheckBox
  586. typedef enum {
  587. CHECK_PADDING = 16 // CheckBox internal check padding
  588. } GuiCheckBoxProperty;
  589. // ComboBox
  590. typedef enum {
  591. COMBO_BUTTON_WIDTH = 16, // ComboBox right button width
  592. COMBO_BUTTON_SPACING // ComboBox button separation
  593. } GuiComboBoxProperty;
  594. // DropdownBox
  595. typedef enum {
  596. ARROW_PADDING = 16, // DropdownBox arrow separation from border and items
  597. DROPDOWN_ITEMS_SPACING, // DropdownBox items separation
  598. DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden
  599. DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down)
  600. } GuiDropdownBoxProperty;
  601. // TextBox/TextBoxMulti/ValueBox/Spinner
  602. typedef enum {
  603. TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable
  604. } GuiTextBoxProperty;
  605. // Spinner
  606. typedef enum {
  607. SPIN_BUTTON_WIDTH = 16, // Spinner left/right buttons width
  608. SPIN_BUTTON_SPACING, // Spinner buttons separation
  609. } GuiSpinnerProperty;
  610. // ListView
  611. typedef enum {
  612. LIST_ITEMS_HEIGHT = 16, // ListView items height
  613. LIST_ITEMS_SPACING, // ListView items separation
  614. SCROLLBAR_WIDTH, // ListView scrollbar size (usually width)
  615. SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
  616. LIST_ITEMS_BORDER_WIDTH // ListView items border width
  617. } GuiListViewProperty;
  618. // ColorPicker
  619. typedef enum {
  620. COLOR_SELECTOR_SIZE = 16,
  621. HUEBAR_WIDTH, // ColorPicker right hue bar width
  622. HUEBAR_PADDING, // ColorPicker right hue bar separation from panel
  623. HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height
  624. HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow
  625. } GuiColorPickerProperty;
  626. #define SCROLLBAR_LEFT_SIDE 0
  627. #define SCROLLBAR_RIGHT_SIDE 1
  628. //----------------------------------------------------------------------------------
  629. // Global Variables Definition
  630. //----------------------------------------------------------------------------------
  631. // ...
  632. //----------------------------------------------------------------------------------
  633. // Module Functions Declaration
  634. //----------------------------------------------------------------------------------
  635. #if defined(__cplusplus)
  636. extern "C" { // Prevents name mangling of functions
  637. #endif
  638. // Global gui state control functions
  639. RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state)
  640. RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state)
  641. RAYGUIAPI void GuiLock(void); // Lock gui controls (global state)
  642. RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state)
  643. RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state)
  644. RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
  645. RAYGUIAPI void GuiSetState(int state); // Set gui state (global state)
  646. RAYGUIAPI int GuiGetState(void); // Get gui state (global state)
  647. // Font set/get functions
  648. RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state)
  649. RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state)
  650. // Style set/get functions
  651. RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property
  652. RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property
  653. // Styles loading functions
  654. RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs)
  655. RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style
  656. // Tooltips management functions
  657. RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state)
  658. RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state)
  659. RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string
  660. // Icons functionality
  661. RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported)
  662. #if !defined(RAYGUI_NO_ICONS)
  663. RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size
  664. RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer
  665. RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data
  666. RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position
  667. #endif
  668. // Controls
  669. //----------------------------------------------------------------------------------------------------------
  670. // Container/separator controls, useful for controls organization
  671. RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed
  672. RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
  673. RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
  674. RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
  675. RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
  676. RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
  677. // Basic controls set
  678. RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control
  679. RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked
  680. RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked
  681. RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control
  682. RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control
  683. RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control
  684. RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active
  685. RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control
  686. RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control
  687. RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control
  688. RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers
  689. RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values
  690. RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text
  691. RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control
  692. RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control
  693. RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control
  694. RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text
  695. RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders
  696. RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control
  697. // Advance controls set
  698. RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
  699. RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
  700. RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
  701. RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
  702. RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
  703. RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control
  704. RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control
  705. RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control
  706. RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls)
  707. RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV()
  708. //----------------------------------------------------------------------------------------------------------
  709. #if !defined(RAYGUI_NO_ICONS)
  710. #if !defined(RAYGUI_CUSTOM_ICONS)
  711. //----------------------------------------------------------------------------------
  712. // Icons enumeration
  713. //----------------------------------------------------------------------------------
  714. typedef enum {
  715. ICON_NONE = 0,
  716. ICON_FOLDER_FILE_OPEN = 1,
  717. ICON_FILE_SAVE_CLASSIC = 2,
  718. ICON_FOLDER_OPEN = 3,
  719. ICON_FOLDER_SAVE = 4,
  720. ICON_FILE_OPEN = 5,
  721. ICON_FILE_SAVE = 6,
  722. ICON_FILE_EXPORT = 7,
  723. ICON_FILE_ADD = 8,
  724. ICON_FILE_DELETE = 9,
  725. ICON_FILETYPE_TEXT = 10,
  726. ICON_FILETYPE_AUDIO = 11,
  727. ICON_FILETYPE_IMAGE = 12,
  728. ICON_FILETYPE_PLAY = 13,
  729. ICON_FILETYPE_VIDEO = 14,
  730. ICON_FILETYPE_INFO = 15,
  731. ICON_FILE_COPY = 16,
  732. ICON_FILE_CUT = 17,
  733. ICON_FILE_PASTE = 18,
  734. ICON_CURSOR_HAND = 19,
  735. ICON_CURSOR_POINTER = 20,
  736. ICON_CURSOR_CLASSIC = 21,
  737. ICON_PENCIL = 22,
  738. ICON_PENCIL_BIG = 23,
  739. ICON_BRUSH_CLASSIC = 24,
  740. ICON_BRUSH_PAINTER = 25,
  741. ICON_WATER_DROP = 26,
  742. ICON_COLOR_PICKER = 27,
  743. ICON_RUBBER = 28,
  744. ICON_COLOR_BUCKET = 29,
  745. ICON_TEXT_T = 30,
  746. ICON_TEXT_A = 31,
  747. ICON_SCALE = 32,
  748. ICON_RESIZE = 33,
  749. ICON_FILTER_POINT = 34,
  750. ICON_FILTER_BILINEAR = 35,
  751. ICON_CROP = 36,
  752. ICON_CROP_ALPHA = 37,
  753. ICON_SQUARE_TOGGLE = 38,
  754. ICON_SYMMETRY = 39,
  755. ICON_SYMMETRY_HORIZONTAL = 40,
  756. ICON_SYMMETRY_VERTICAL = 41,
  757. ICON_LENS = 42,
  758. ICON_LENS_BIG = 43,
  759. ICON_EYE_ON = 44,
  760. ICON_EYE_OFF = 45,
  761. ICON_FILTER_TOP = 46,
  762. ICON_FILTER = 47,
  763. ICON_TARGET_POINT = 48,
  764. ICON_TARGET_SMALL = 49,
  765. ICON_TARGET_BIG = 50,
  766. ICON_TARGET_MOVE = 51,
  767. ICON_CURSOR_MOVE = 52,
  768. ICON_CURSOR_SCALE = 53,
  769. ICON_CURSOR_SCALE_RIGHT = 54,
  770. ICON_CURSOR_SCALE_LEFT = 55,
  771. ICON_UNDO = 56,
  772. ICON_REDO = 57,
  773. ICON_REREDO = 58,
  774. ICON_MUTATE = 59,
  775. ICON_ROTATE = 60,
  776. ICON_REPEAT = 61,
  777. ICON_SHUFFLE = 62,
  778. ICON_EMPTYBOX = 63,
  779. ICON_TARGET = 64,
  780. ICON_TARGET_SMALL_FILL = 65,
  781. ICON_TARGET_BIG_FILL = 66,
  782. ICON_TARGET_MOVE_FILL = 67,
  783. ICON_CURSOR_MOVE_FILL = 68,
  784. ICON_CURSOR_SCALE_FILL = 69,
  785. ICON_CURSOR_SCALE_RIGHT_FILL = 70,
  786. ICON_CURSOR_SCALE_LEFT_FILL = 71,
  787. ICON_UNDO_FILL = 72,
  788. ICON_REDO_FILL = 73,
  789. ICON_REREDO_FILL = 74,
  790. ICON_MUTATE_FILL = 75,
  791. ICON_ROTATE_FILL = 76,
  792. ICON_REPEAT_FILL = 77,
  793. ICON_SHUFFLE_FILL = 78,
  794. ICON_EMPTYBOX_SMALL = 79,
  795. ICON_BOX = 80,
  796. ICON_BOX_TOP = 81,
  797. ICON_BOX_TOP_RIGHT = 82,
  798. ICON_BOX_RIGHT = 83,
  799. ICON_BOX_BOTTOM_RIGHT = 84,
  800. ICON_BOX_BOTTOM = 85,
  801. ICON_BOX_BOTTOM_LEFT = 86,
  802. ICON_BOX_LEFT = 87,
  803. ICON_BOX_TOP_LEFT = 88,
  804. ICON_BOX_CENTER = 89,
  805. ICON_BOX_CIRCLE_MASK = 90,
  806. ICON_POT = 91,
  807. ICON_ALPHA_MULTIPLY = 92,
  808. ICON_ALPHA_CLEAR = 93,
  809. ICON_DITHERING = 94,
  810. ICON_MIPMAPS = 95,
  811. ICON_BOX_GRID = 96,
  812. ICON_GRID = 97,
  813. ICON_BOX_CORNERS_SMALL = 98,
  814. ICON_BOX_CORNERS_BIG = 99,
  815. ICON_FOUR_BOXES = 100,
  816. ICON_GRID_FILL = 101,
  817. ICON_BOX_MULTISIZE = 102,
  818. ICON_ZOOM_SMALL = 103,
  819. ICON_ZOOM_MEDIUM = 104,
  820. ICON_ZOOM_BIG = 105,
  821. ICON_ZOOM_ALL = 106,
  822. ICON_ZOOM_CENTER = 107,
  823. ICON_BOX_DOTS_SMALL = 108,
  824. ICON_BOX_DOTS_BIG = 109,
  825. ICON_BOX_CONCENTRIC = 110,
  826. ICON_BOX_GRID_BIG = 111,
  827. ICON_OK_TICK = 112,
  828. ICON_CROSS = 113,
  829. ICON_ARROW_LEFT = 114,
  830. ICON_ARROW_RIGHT = 115,
  831. ICON_ARROW_DOWN = 116,
  832. ICON_ARROW_UP = 117,
  833. ICON_ARROW_LEFT_FILL = 118,
  834. ICON_ARROW_RIGHT_FILL = 119,
  835. ICON_ARROW_DOWN_FILL = 120,
  836. ICON_ARROW_UP_FILL = 121,
  837. ICON_AUDIO = 122,
  838. ICON_FX = 123,
  839. ICON_WAVE = 124,
  840. ICON_WAVE_SINUS = 125,
  841. ICON_WAVE_SQUARE = 126,
  842. ICON_WAVE_TRIANGULAR = 127,
  843. ICON_CROSS_SMALL = 128,
  844. ICON_PLAYER_PREVIOUS = 129,
  845. ICON_PLAYER_PLAY_BACK = 130,
  846. ICON_PLAYER_PLAY = 131,
  847. ICON_PLAYER_PAUSE = 132,
  848. ICON_PLAYER_STOP = 133,
  849. ICON_PLAYER_NEXT = 134,
  850. ICON_PLAYER_RECORD = 135,
  851. ICON_MAGNET = 136,
  852. ICON_LOCK_CLOSE = 137,
  853. ICON_LOCK_OPEN = 138,
  854. ICON_CLOCK = 139,
  855. ICON_TOOLS = 140,
  856. ICON_GEAR = 141,
  857. ICON_GEAR_BIG = 142,
  858. ICON_BIN = 143,
  859. ICON_HAND_POINTER = 144,
  860. ICON_LASER = 145,
  861. ICON_COIN = 146,
  862. ICON_EXPLOSION = 147,
  863. ICON_1UP = 148,
  864. ICON_PLAYER = 149,
  865. ICON_PLAYER_JUMP = 150,
  866. ICON_KEY = 151,
  867. ICON_DEMON = 152,
  868. ICON_TEXT_POPUP = 153,
  869. ICON_GEAR_EX = 154,
  870. ICON_CRACK = 155,
  871. ICON_CRACK_POINTS = 156,
  872. ICON_STAR = 157,
  873. ICON_DOOR = 158,
  874. ICON_EXIT = 159,
  875. ICON_MODE_2D = 160,
  876. ICON_MODE_3D = 161,
  877. ICON_CUBE = 162,
  878. ICON_CUBE_FACE_TOP = 163,
  879. ICON_CUBE_FACE_LEFT = 164,
  880. ICON_CUBE_FACE_FRONT = 165,
  881. ICON_CUBE_FACE_BOTTOM = 166,
  882. ICON_CUBE_FACE_RIGHT = 167,
  883. ICON_CUBE_FACE_BACK = 168,
  884. ICON_CAMERA = 169,
  885. ICON_SPECIAL = 170,
  886. ICON_LINK_NET = 171,
  887. ICON_LINK_BOXES = 172,
  888. ICON_LINK_MULTI = 173,
  889. ICON_LINK = 174,
  890. ICON_LINK_BROKE = 175,
  891. ICON_TEXT_NOTES = 176,
  892. ICON_NOTEBOOK = 177,
  893. ICON_SUITCASE = 178,
  894. ICON_SUITCASE_ZIP = 179,
  895. ICON_MAILBOX = 180,
  896. ICON_MONITOR = 181,
  897. ICON_PRINTER = 182,
  898. ICON_PHOTO_CAMERA = 183,
  899. ICON_PHOTO_CAMERA_FLASH = 184,
  900. ICON_HOUSE = 185,
  901. ICON_HEART = 186,
  902. ICON_CORNER = 187,
  903. ICON_VERTICAL_BARS = 188,
  904. ICON_VERTICAL_BARS_FILL = 189,
  905. ICON_LIFE_BARS = 190,
  906. ICON_INFO = 191,
  907. ICON_CROSSLINE = 192,
  908. ICON_HELP = 193,
  909. ICON_FILETYPE_ALPHA = 194,
  910. ICON_FILETYPE_HOME = 195,
  911. ICON_LAYERS_VISIBLE = 196,
  912. ICON_LAYERS = 197,
  913. ICON_WINDOW = 198,
  914. ICON_HIDPI = 199,
  915. ICON_FILETYPE_BINARY = 200,
  916. ICON_HEX = 201,
  917. ICON_SHIELD = 202,
  918. ICON_FILE_NEW = 203,
  919. ICON_FOLDER_ADD = 204,
  920. ICON_ALARM = 205,
  921. ICON_CPU = 206,
  922. ICON_ROM = 207,
  923. ICON_STEP_OVER = 208,
  924. ICON_STEP_INTO = 209,
  925. ICON_STEP_OUT = 210,
  926. ICON_RESTART = 211,
  927. ICON_BREAKPOINT_ON = 212,
  928. ICON_BREAKPOINT_OFF = 213,
  929. ICON_BURGER_MENU = 214,
  930. ICON_CASE_SENSITIVE = 215,
  931. ICON_REG_EXP = 216,
  932. ICON_FOLDER = 217,
  933. ICON_FILE = 218,
  934. ICON_SAND_TIMER = 219,
  935. ICON_WARNING = 220,
  936. ICON_HELP_BOX = 221,
  937. ICON_INFO_BOX = 222,
  938. ICON_PRIORITY = 223,
  939. ICON_LAYERS_ISO = 224,
  940. ICON_LAYERS2 = 225,
  941. ICON_MLAYERS = 226,
  942. ICON_MAPS = 227,
  943. ICON_HOT = 228,
  944. ICON_229 = 229,
  945. ICON_230 = 230,
  946. ICON_231 = 231,
  947. ICON_232 = 232,
  948. ICON_233 = 233,
  949. ICON_234 = 234,
  950. ICON_235 = 235,
  951. ICON_236 = 236,
  952. ICON_237 = 237,
  953. ICON_238 = 238,
  954. ICON_239 = 239,
  955. ICON_240 = 240,
  956. ICON_241 = 241,
  957. ICON_242 = 242,
  958. ICON_243 = 243,
  959. ICON_244 = 244,
  960. ICON_245 = 245,
  961. ICON_246 = 246,
  962. ICON_247 = 247,
  963. ICON_248 = 248,
  964. ICON_249 = 249,
  965. ICON_250 = 250,
  966. ICON_251 = 251,
  967. ICON_252 = 252,
  968. ICON_253 = 253,
  969. ICON_254 = 254,
  970. ICON_255 = 255,
  971. } GuiIconName;
  972. #endif
  973. #endif
  974. #if defined(__cplusplus)
  975. } // Prevents name mangling of functions
  976. #endif
  977. #endif // RAYGUI_H
  978. /***********************************************************************************
  979. *
  980. * RAYGUI IMPLEMENTATION
  981. *
  982. ************************************************************************************/
  983. #if defined(RAYGUI_IMPLEMENTATION)
  984. #include <ctype.h> // required for: isspace() [GuiTextBox()]
  985. #include <stdio.h> // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
  986. #include <stdlib.h> // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()]
  987. #include <string.h> // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy()
  988. #include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
  989. #include <math.h> // Required for: roundf() [GuiColorPicker()]
  990. #ifdef __cplusplus
  991. #define RAYGUI_CLITERAL(name) name
  992. #else
  993. #define RAYGUI_CLITERAL(name) (name)
  994. #endif
  995. // Check if two rectangles are equal, used to validate a slider bounds as an id
  996. #ifndef CHECK_BOUNDS_ID
  997. #define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height))
  998. #endif
  999. #if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
  1000. // Embedded icons, no external file provided
  1001. #define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared)
  1002. #define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons
  1003. #define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
  1004. // Icons data is defined by bit array (every bit represents one pixel)
  1005. // Those arrays are stored as unsigned int data arrays, so,
  1006. // every array element defines 32 pixels (bits) of information
  1007. // One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels)
  1008. // NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels)
  1009. #define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32)
  1010. //----------------------------------------------------------------------------------
  1011. // Icons data for all gui possible icons (allocated on data segment by default)
  1012. //
  1013. // NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so,
  1014. // every 16x16 icon requires 8 integers (16*16/32) to be stored
  1015. //
  1016. // NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(),
  1017. // but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS
  1018. //
  1019. // guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
  1020. //----------------------------------------------------------------------------------
  1021. static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = {
  1022. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE
  1023. 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN
  1024. 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC
  1025. 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN
  1026. 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE
  1027. 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN
  1028. 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE
  1029. 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT
  1030. 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD
  1031. 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE
  1032. 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT
  1033. 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO
  1034. 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE
  1035. 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY
  1036. 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO
  1037. 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO
  1038. 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY
  1039. 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT
  1040. 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE
  1041. 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND
  1042. 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER
  1043. 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC
  1044. 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL
  1045. 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG
  1046. 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC
  1047. 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER
  1048. 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP
  1049. 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER
  1050. 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER
  1051. 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET
  1052. 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T
  1053. 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A
  1054. 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE
  1055. 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE
  1056. 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT
  1057. 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR
  1058. 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP
  1059. 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA
  1060. 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE
  1061. 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY
  1062. 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL
  1063. 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL
  1064. 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS
  1065. 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG
  1066. 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON
  1067. 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF
  1068. 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP
  1069. 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER
  1070. 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT
  1071. 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL
  1072. 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG
  1073. 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE
  1074. 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE
  1075. 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE
  1076. 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT
  1077. 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT
  1078. 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO
  1079. 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO
  1080. 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO
  1081. 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE
  1082. 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE
  1083. 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT
  1084. 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE
  1085. 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX
  1086. 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET
  1087. 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL
  1088. 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL
  1089. 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL
  1090. 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL
  1091. 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL
  1092. 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL
  1093. 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL
  1094. 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL
  1095. 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL
  1096. 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL
  1097. 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL
  1098. 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL
  1099. 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL
  1100. 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL
  1101. 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL
  1102. 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX
  1103. 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP
  1104. 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT
  1105. 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT
  1106. 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT
  1107. 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM
  1108. 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT
  1109. 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT
  1110. 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT
  1111. 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER
  1112. 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK
  1113. 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT
  1114. 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY
  1115. 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR
  1116. 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING
  1117. 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS
  1118. 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID
  1119. 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID
  1120. 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL
  1121. 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG
  1122. 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES
  1123. 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL
  1124. 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE
  1125. 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL
  1126. 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM
  1127. 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG
  1128. 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL
  1129. 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER
  1130. 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL
  1131. 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG
  1132. 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC
  1133. 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG
  1134. 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK
  1135. 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS
  1136. 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT
  1137. 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT
  1138. 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN
  1139. 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP
  1140. 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL
  1141. 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL
  1142. 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL
  1143. 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL
  1144. 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO
  1145. 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX
  1146. 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE
  1147. 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS
  1148. 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE
  1149. 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR
  1150. 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL
  1151. 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS
  1152. 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK
  1153. 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY
  1154. 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE
  1155. 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP
  1156. 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT
  1157. 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD
  1158. 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET
  1159. 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE
  1160. 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN
  1161. 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK
  1162. 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS
  1163. 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR
  1164. 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG
  1165. 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN
  1166. 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER
  1167. 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER
  1168. 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN
  1169. 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION
  1170. 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP
  1171. 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER
  1172. 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP
  1173. 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY
  1174. 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON
  1175. 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP
  1176. 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX
  1177. 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK
  1178. 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS
  1179. 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR
  1180. 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR
  1181. 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT
  1182. 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D
  1183. 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D
  1184. 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE
  1185. 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP
  1186. 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT
  1187. 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT
  1188. 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM
  1189. 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT
  1190. 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK
  1191. 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA
  1192. 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL
  1193. 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET
  1194. 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES
  1195. 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI
  1196. 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK
  1197. 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE
  1198. 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES
  1199. 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK
  1200. 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE
  1201. 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP
  1202. 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX
  1203. 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR
  1204. 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER
  1205. 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA
  1206. 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH
  1207. 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE
  1208. 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART
  1209. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER
  1210. 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS
  1211. 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL
  1212. 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS
  1213. 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO
  1214. 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE
  1215. 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP
  1216. 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA
  1217. 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME
  1218. 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE
  1219. 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS
  1220. 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW
  1221. 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI
  1222. 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY
  1223. 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX
  1224. 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD
  1225. 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW
  1226. 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD
  1227. 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM
  1228. 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU
  1229. 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM
  1230. 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER
  1231. 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO
  1232. 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT
  1233. 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART
  1234. 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON
  1235. 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF
  1236. 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU
  1237. 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE
  1238. 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP
  1239. 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER
  1240. 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE
  1241. 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER
  1242. 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING
  1243. 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX
  1244. 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX
  1245. 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY
  1246. 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO
  1247. 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2
  1248. 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS
  1249. 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS
  1250. 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT
  1251. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229
  1252. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230
  1253. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231
  1254. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_232
  1255. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_233
  1256. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234
  1257. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235
  1258. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236
  1259. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237
  1260. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238
  1261. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239
  1262. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240
  1263. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241
  1264. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242
  1265. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243
  1266. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244
  1267. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245
  1268. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246
  1269. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247
  1270. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248
  1271. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249
  1272. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250
  1273. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251
  1274. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252
  1275. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253
  1276. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254
  1277. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255
  1278. };
  1279. // NOTE: A pointer to current icons array should be defined
  1280. static unsigned int *guiIconsPtr = guiIcons;
  1281. #endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
  1282. #ifndef RAYGUI_ICON_SIZE
  1283. #define RAYGUI_ICON_SIZE 0
  1284. #endif
  1285. // WARNING: Those values define the total size of the style data array,
  1286. // if changed, previous saved styles could become incompatible
  1287. #define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls
  1288. #define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties
  1289. #define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties
  1290. //----------------------------------------------------------------------------------
  1291. // Types and Structures Definition
  1292. //----------------------------------------------------------------------------------
  1293. // Gui control property style color element
  1294. typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement;
  1295. //----------------------------------------------------------------------------------
  1296. // Global Variables Definition
  1297. //----------------------------------------------------------------------------------
  1298. static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state
  1299. static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib)
  1300. static bool guiLocked = false; // Gui lock state (no inputs processed)
  1301. static float guiAlpha = 1.0f; // Gui controls transparency
  1302. static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled)
  1303. static bool guiTooltip = false; // Tooltip enabled/disabled
  1304. static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user)
  1305. static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control)
  1306. static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier
  1307. static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*()
  1308. //static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking
  1309. static int autoCursorCooldownCounter = 0; // Cooldown frame counter for automatic cursor movement on key-down
  1310. static int autoCursorDelayCounter = 0; // Delay frame counter for automatic cursor movement
  1311. //----------------------------------------------------------------------------------
  1312. // Style data array for all gui style properties (allocated on data segment by default)
  1313. //
  1314. // NOTE 1: First set of BASE properties are generic to all controls but could be individually
  1315. // overwritten per control, first set of EXTENDED properties are generic to all controls and
  1316. // can not be overwritten individually but custom EXTENDED properties can be used by control
  1317. //
  1318. // NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(),
  1319. // but default gui style could always be recovered with GuiLoadStyleDefault()
  1320. //
  1321. // guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
  1322. //----------------------------------------------------------------------------------
  1323. static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 };
  1324. static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization
  1325. //----------------------------------------------------------------------------------
  1326. // Standalone Mode Functions Declaration
  1327. //
  1328. // NOTE: raygui depend on some raylib input and drawing functions
  1329. // To use raygui as standalone library, below functions must be defined by the user
  1330. //----------------------------------------------------------------------------------
  1331. #if defined(RAYGUI_STANDALONE)
  1332. #define KEY_RIGHT 262
  1333. #define KEY_LEFT 263
  1334. #define KEY_DOWN 264
  1335. #define KEY_UP 265
  1336. #define KEY_BACKSPACE 259
  1337. #define KEY_ENTER 257
  1338. #define MOUSE_LEFT_BUTTON 0
  1339. // Input required functions
  1340. //-------------------------------------------------------------------------------
  1341. static Vector2 GetMousePosition(void);
  1342. static float GetMouseWheelMove(void);
  1343. static bool IsMouseButtonDown(int button);
  1344. static bool IsMouseButtonPressed(int button);
  1345. static bool IsMouseButtonReleased(int button);
  1346. static bool IsKeyDown(int key);
  1347. static bool IsKeyPressed(int key);
  1348. static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
  1349. //-------------------------------------------------------------------------------
  1350. // Drawing required functions
  1351. //-------------------------------------------------------------------------------
  1352. static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
  1353. static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
  1354. //-------------------------------------------------------------------------------
  1355. // Text required functions
  1356. //-------------------------------------------------------------------------------
  1357. static Font GetFontDefault(void); // -- GuiLoadStyleDefault()
  1358. static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font
  1359. static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
  1360. static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
  1361. static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
  1362. static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
  1363. static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
  1364. static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
  1365. static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
  1366. static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
  1367. //-------------------------------------------------------------------------------
  1368. // raylib functions already implemented in raygui
  1369. //-------------------------------------------------------------------------------
  1370. static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
  1371. static int ColorToInt(Color color); // Returns hexadecimal value for a Color
  1372. static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
  1373. static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
  1374. static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
  1375. static int TextToInteger(const char *text); // Get integer value from text
  1376. static float TextToFloat(const char *text); // Get float value from text
  1377. static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text
  1378. static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter)
  1379. static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient
  1380. //-------------------------------------------------------------------------------
  1381. #endif // RAYGUI_STANDALONE
  1382. //----------------------------------------------------------------------------------
  1383. // Module specific Functions Declaration
  1384. //----------------------------------------------------------------------------------
  1385. static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only)
  1386. static int GetTextWidth(const char *text); // Gui get text width using gui font and style
  1387. static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds
  1388. static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor
  1389. static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
  1390. static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
  1391. static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
  1392. static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
  1393. static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
  1394. static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel()
  1395. static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position
  1396. static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor
  1397. //----------------------------------------------------------------------------------
  1398. // Gui Setup Functions Definition
  1399. //----------------------------------------------------------------------------------
  1400. // Enable gui global state
  1401. // NOTE: We check for STATE_DISABLED to avoid messing custom global state setups
  1402. void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; }
  1403. // Disable gui global state
  1404. // NOTE: We check for STATE_NORMAL to avoid messing custom global state setups
  1405. void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; }
  1406. // Lock gui global state
  1407. void GuiLock(void) { guiLocked = true; }
  1408. // Unlock gui global state
  1409. void GuiUnlock(void) { guiLocked = false; }
  1410. // Check if gui is locked (global state)
  1411. bool GuiIsLocked(void) { return guiLocked; }
  1412. // Set gui controls alpha global state
  1413. void GuiSetAlpha(float alpha)
  1414. {
  1415. if (alpha < 0.0f) alpha = 0.0f;
  1416. else if (alpha > 1.0f) alpha = 1.0f;
  1417. guiAlpha = alpha;
  1418. }
  1419. // Set gui state (global state)
  1420. void GuiSetState(int state) { guiState = (GuiState)state; }
  1421. // Get gui state (global state)
  1422. int GuiGetState(void) { return guiState; }
  1423. // Set custom gui font
  1424. // NOTE: Font loading/unloading is external to raygui
  1425. void GuiSetFont(Font font)
  1426. {
  1427. if (font.texture.id > 0)
  1428. {
  1429. // NOTE: If we try to setup a font but default style has not been
  1430. // lazily loaded before, it will be overwritten, so we need to force
  1431. // default style loading first
  1432. if (!guiStyleLoaded) GuiLoadStyleDefault();
  1433. guiFont = font;
  1434. }
  1435. }
  1436. // Get custom gui font
  1437. Font GuiGetFont(void)
  1438. {
  1439. return guiFont;
  1440. }
  1441. // Set control style property value
  1442. void GuiSetStyle(int control, int property, int value)
  1443. {
  1444. if (!guiStyleLoaded) GuiLoadStyleDefault();
  1445. guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
  1446. // Default properties are propagated to all controls
  1447. if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE))
  1448. {
  1449. for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
  1450. }
  1451. }
  1452. // Get control style property value
  1453. int GuiGetStyle(int control, int property)
  1454. {
  1455. if (!guiStyleLoaded) GuiLoadStyleDefault();
  1456. return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property];
  1457. }
  1458. //----------------------------------------------------------------------------------
  1459. // Gui Controls Functions Definition
  1460. //----------------------------------------------------------------------------------
  1461. // Window Box control
  1462. int GuiWindowBox(Rectangle bounds, const char *title)
  1463. {
  1464. // Window title bar height (including borders)
  1465. // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
  1466. #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
  1467. #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
  1468. #endif
  1469. int result = 0;
  1470. //GuiState state = guiState;
  1471. int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
  1472. Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight };
  1473. if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f;
  1474. Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 };
  1475. Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20,
  1476. statusBar.y + statusBarHeight/2.0f - 18.0f/2.0f, 18, 18 };
  1477. // Update control
  1478. //--------------------------------------------------------------------
  1479. // NOTE: Logic is directly managed by button
  1480. //--------------------------------------------------------------------
  1481. // Draw control
  1482. //--------------------------------------------------------------------
  1483. GuiStatusBar(statusBar, title); // Draw window header as status bar
  1484. GuiPanel(windowPanel, NULL); // Draw window base
  1485. // Draw window close button
  1486. int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  1487. int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  1488. GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  1489. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  1490. #if defined(RAYGUI_NO_ICONS)
  1491. result = GuiButton(closeButtonRec, "x");
  1492. #else
  1493. result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL));
  1494. #endif
  1495. GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  1496. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
  1497. //--------------------------------------------------------------------
  1498. return result; // Window close button clicked: result = 1
  1499. }
  1500. // Group Box control with text name
  1501. int GuiGroupBox(Rectangle bounds, const char *text)
  1502. {
  1503. #if !defined(RAYGUI_GROUPBOX_LINE_THICK)
  1504. #define RAYGUI_GROUPBOX_LINE_THICK 1
  1505. #endif
  1506. int result = 0;
  1507. GuiState state = guiState;
  1508. // Draw control
  1509. //--------------------------------------------------------------------
  1510. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
  1511. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
  1512. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
  1513. GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text);
  1514. //--------------------------------------------------------------------
  1515. return result;
  1516. }
  1517. // Line control
  1518. int GuiLine(Rectangle bounds, const char *text)
  1519. {
  1520. #if !defined(RAYGUI_LINE_ORIGIN_SIZE)
  1521. #define RAYGUI_LINE_MARGIN_TEXT 12
  1522. #endif
  1523. #if !defined(RAYGUI_LINE_TEXT_PADDING)
  1524. #define RAYGUI_LINE_TEXT_PADDING 4
  1525. #endif
  1526. int result = 0;
  1527. GuiState state = guiState;
  1528. Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR));
  1529. // Draw control
  1530. //--------------------------------------------------------------------
  1531. if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color);
  1532. else
  1533. {
  1534. Rectangle textBounds = { 0 };
  1535. textBounds.width = (float)GetTextWidth(text) + 2;
  1536. textBounds.height = bounds.height;
  1537. textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT;
  1538. textBounds.y = bounds.y;
  1539. // Draw line with embedded text label: "--- text --------------"
  1540. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color);
  1541. GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color);
  1542. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color);
  1543. }
  1544. //--------------------------------------------------------------------
  1545. return result;
  1546. }
  1547. // Panel control
  1548. int GuiPanel(Rectangle bounds, const char *text)
  1549. {
  1550. #if !defined(RAYGUI_PANEL_BORDER_WIDTH)
  1551. #define RAYGUI_PANEL_BORDER_WIDTH 1
  1552. #endif
  1553. int result = 0;
  1554. GuiState state = guiState;
  1555. // Text will be drawn as a header bar (if provided)
  1556. Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
  1557. if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
  1558. if (text != NULL)
  1559. {
  1560. // Move panel bounds after the header bar
  1561. bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
  1562. bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
  1563. }
  1564. // Draw control
  1565. //--------------------------------------------------------------------
  1566. if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
  1567. GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)),
  1568. GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)));
  1569. //--------------------------------------------------------------------
  1570. return result;
  1571. }
  1572. // Tab Bar control
  1573. // NOTE: Using GuiToggle() for the TABS
  1574. int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
  1575. {
  1576. #define RAYGUI_TABBAR_ITEM_WIDTH 160
  1577. int result = -1;
  1578. //GuiState state = guiState;
  1579. Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height };
  1580. if (*active < 0) *active = 0;
  1581. else if (*active > count - 1) *active = count - 1;
  1582. int offsetX = 0; // Required in case tabs go out of screen
  1583. offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth();
  1584. if (offsetX < 0) offsetX = 0;
  1585. bool toggle = false; // Required for individual toggles
  1586. // Draw control
  1587. //--------------------------------------------------------------------
  1588. for (int i = 0; i < count; i++)
  1589. {
  1590. tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX;
  1591. if (tabBounds.x < GetScreenWidth())
  1592. {
  1593. // Draw tabs as toggle controls
  1594. int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT);
  1595. int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING);
  1596. GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  1597. GuiSetStyle(TOGGLE, TEXT_PADDING, 8);
  1598. if (i == (*active))
  1599. {
  1600. toggle = true;
  1601. GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle);
  1602. }
  1603. else
  1604. {
  1605. toggle = false;
  1606. GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle);
  1607. if (toggle) *active = i;
  1608. }
  1609. // Close tab with middle mouse button pressed
  1610. if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;
  1611. GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);
  1612. GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
  1613. // Draw tab close button
  1614. // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds))
  1615. int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  1616. int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  1617. GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  1618. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  1619. #if defined(RAYGUI_NO_ICONS)
  1620. if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i;
  1621. #else
  1622. if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i;
  1623. #endif
  1624. GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  1625. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
  1626. }
  1627. }
  1628. // Draw tab-bar bottom line
  1629. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL)));
  1630. //--------------------------------------------------------------------
  1631. return result; // Return as result the current TAB closing requested
  1632. }
  1633. // Scroll Panel control
  1634. int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view)
  1635. {
  1636. #define RAYGUI_MIN_SCROLLBAR_WIDTH 40
  1637. #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40
  1638. #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20
  1639. int result = 0;
  1640. GuiState state = guiState;
  1641. Rectangle temp = { 0 };
  1642. if (view == NULL) view = &temp;
  1643. Vector2 scrollPos = { 0.0f, 0.0f };
  1644. if (scroll != NULL) scrollPos = *scroll;
  1645. // Text will be drawn as a header bar (if provided)
  1646. Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
  1647. if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
  1648. if (text != NULL)
  1649. {
  1650. // Move panel bounds after the header bar
  1651. bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
  1652. bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1;
  1653. }
  1654. bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
  1655. bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
  1656. // Recheck to account for the other scrollbar being visible
  1657. if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
  1658. if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
  1659. int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
  1660. int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
  1661. Rectangle horizontalScrollBar = {
  1662. (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH),
  1663. (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH),
  1664. (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH),
  1665. (float)horizontalScrollBarWidth
  1666. };
  1667. Rectangle verticalScrollBar = {
  1668. (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)),
  1669. (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH),
  1670. (float)verticalScrollBarWidth,
  1671. (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
  1672. };
  1673. // Make sure scroll bars have a minimum width/height
  1674. if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;
  1675. if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;
  1676. // Calculate view area (area without the scrollbars)
  1677. *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
  1678. RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } :
  1679. RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth };
  1680. // Clip view area to the actual content size
  1681. if (view->width > content.width) view->width = content.width;
  1682. if (view->height > content.height) view->height = content.height;
  1683. float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH);
  1684. float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH);
  1685. float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f;
  1686. float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH);
  1687. // Update control
  1688. //--------------------------------------------------------------------
  1689. if ((state != STATE_DISABLED) && !guiLocked)
  1690. {
  1691. Vector2 mousePoint = GetMousePosition();
  1692. // Check button state
  1693. if (CheckCollisionPointRec(mousePoint, bounds))
  1694. {
  1695. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1696. else state = STATE_FOCUSED;
  1697. #if defined(SUPPORT_SCROLLBAR_KEY_INPUT)
  1698. if (hasHorizontalScrollBar)
  1699. {
  1700. if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1701. if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1702. }
  1703. if (hasVerticalScrollBar)
  1704. {
  1705. if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1706. if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1707. }
  1708. #endif
  1709. float wheelMove = GetMouseWheelMove();
  1710. // Set scrolling speed with mouse wheel based on ratio between bounds and content
  1711. Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height };
  1712. if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
  1713. if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
  1714. // Horizontal and vertical scrolling with mouse wheel
  1715. if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x;
  1716. else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll
  1717. }
  1718. }
  1719. // Normalize scroll values
  1720. if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin;
  1721. if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax;
  1722. if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin;
  1723. if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax;
  1724. //--------------------------------------------------------------------
  1725. // Draw control
  1726. //--------------------------------------------------------------------
  1727. if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
  1728. GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
  1729. // Save size of the scrollbar slider
  1730. const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
  1731. // Draw horizontal scrollbar if visible
  1732. if (hasHorizontalScrollBar)
  1733. {
  1734. // Change scrollbar slider size to show the diff in size between the content width and the widget width
  1735. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)));
  1736. scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax);
  1737. }
  1738. else scrollPos.x = 0.0f;
  1739. // Draw vertical scrollbar if visible
  1740. if (hasVerticalScrollBar)
  1741. {
  1742. // Change scrollbar slider size to show the diff in size between the content height and the widget height
  1743. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)));
  1744. scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax);
  1745. }
  1746. else scrollPos.y = 0.0f;
  1747. // Draw detail corner rectangle if both scroll bars are visible
  1748. if (hasHorizontalScrollBar && hasVerticalScrollBar)
  1749. {
  1750. Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 };
  1751. GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))));
  1752. }
  1753. // Draw scrollbar lines depending on current state
  1754. GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);
  1755. // Set scrollbar slider size back to the way it was before
  1756. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
  1757. //--------------------------------------------------------------------
  1758. if (scroll != NULL) *scroll = scrollPos;
  1759. return result;
  1760. }
  1761. // Label control
  1762. int GuiLabel(Rectangle bounds, const char *text)
  1763. {
  1764. int result = 0;
  1765. GuiState state = guiState;
  1766. // Update control
  1767. //--------------------------------------------------------------------
  1768. //...
  1769. //--------------------------------------------------------------------
  1770. // Draw control
  1771. //--------------------------------------------------------------------
  1772. GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  1773. //--------------------------------------------------------------------
  1774. return result;
  1775. }
  1776. // Button control, returns true when clicked
  1777. int GuiButton(Rectangle bounds, const char *text)
  1778. {
  1779. int result = 0;
  1780. GuiState state = guiState;
  1781. // Update control
  1782. //--------------------------------------------------------------------
  1783. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  1784. {
  1785. Vector2 mousePoint = GetMousePosition();
  1786. // Check button state
  1787. if (CheckCollisionPointRec(mousePoint, bounds))
  1788. {
  1789. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1790. else state = STATE_FOCUSED;
  1791. if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1;
  1792. }
  1793. }
  1794. //--------------------------------------------------------------------
  1795. // Draw control
  1796. //--------------------------------------------------------------------
  1797. GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3))));
  1798. GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))));
  1799. if (state == STATE_FOCUSED) GuiTooltip(bounds);
  1800. //------------------------------------------------------------------
  1801. return result; // Button pressed: result = 1
  1802. }
  1803. // Label button control
  1804. int GuiLabelButton(Rectangle bounds, const char *text)
  1805. {
  1806. GuiState state = guiState;
  1807. bool pressed = false;
  1808. // NOTE: We force bounds.width to be all text
  1809. float textWidth = (float)GetTextWidth(text);
  1810. if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2;
  1811. // Update control
  1812. //--------------------------------------------------------------------
  1813. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  1814. {
  1815. Vector2 mousePoint = GetMousePosition();
  1816. // Check checkbox state
  1817. if (CheckCollisionPointRec(mousePoint, bounds))
  1818. {
  1819. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1820. else state = STATE_FOCUSED;
  1821. if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
  1822. }
  1823. }
  1824. //--------------------------------------------------------------------
  1825. // Draw control
  1826. //--------------------------------------------------------------------
  1827. GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  1828. //--------------------------------------------------------------------
  1829. return pressed;
  1830. }
  1831. // Toggle Button control
  1832. int GuiToggle(Rectangle bounds, const char *text, bool *active)
  1833. {
  1834. int result = 0;
  1835. GuiState state = guiState;
  1836. bool temp = false;
  1837. if (active == NULL) active = &temp;
  1838. // Update control
  1839. //--------------------------------------------------------------------
  1840. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  1841. {
  1842. Vector2 mousePoint = GetMousePosition();
  1843. // Check toggle button state
  1844. if (CheckCollisionPointRec(mousePoint, bounds))
  1845. {
  1846. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1847. else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  1848. {
  1849. state = STATE_NORMAL;
  1850. *active = !(*active);
  1851. }
  1852. else state = STATE_FOCUSED;
  1853. }
  1854. }
  1855. //--------------------------------------------------------------------
  1856. // Draw control
  1857. //--------------------------------------------------------------------
  1858. if (state == STATE_NORMAL)
  1859. {
  1860. GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3)))));
  1861. GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3)))));
  1862. }
  1863. else
  1864. {
  1865. GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3)));
  1866. GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)));
  1867. }
  1868. if (state == STATE_FOCUSED) GuiTooltip(bounds);
  1869. //--------------------------------------------------------------------
  1870. return result;
  1871. }
  1872. // Toggle Group control
  1873. int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
  1874. {
  1875. #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
  1876. #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32
  1877. #endif
  1878. int result = 0;
  1879. float initBoundsX = bounds.x;
  1880. int temp = 0;
  1881. if (active == NULL) active = &temp;
  1882. bool toggle = false; // Required for individual toggles
  1883. // Get substrings items from text (items pointers)
  1884. int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
  1885. int itemCount = 0;
  1886. const char **items = GuiTextSplit(text, ';', &itemCount, rows);
  1887. int prevRow = rows[0];
  1888. for (int i = 0; i < itemCount; i++)
  1889. {
  1890. if (prevRow != rows[i])
  1891. {
  1892. bounds.x = initBoundsX;
  1893. bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING));
  1894. prevRow = rows[i];
  1895. }
  1896. if (i == (*active))
  1897. {
  1898. toggle = true;
  1899. GuiToggle(bounds, items[i], &toggle);
  1900. }
  1901. else
  1902. {
  1903. toggle = false;
  1904. GuiToggle(bounds, items[i], &toggle);
  1905. if (toggle) *active = i;
  1906. }
  1907. bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING));
  1908. }
  1909. return result;
  1910. }
  1911. // Toggle Slider control extended
  1912. int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
  1913. {
  1914. int result = 0;
  1915. GuiState state = guiState;
  1916. int temp = 0;
  1917. if (active == NULL) active = &temp;
  1918. //bool toggle = false; // Required for individual toggles
  1919. // Get substrings items from text (items pointers)
  1920. int itemCount = 0;
  1921. const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
  1922. Rectangle slider = {
  1923. 0, // Calculated later depending on the active toggle
  1924. bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
  1925. (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount,
  1926. bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
  1927. // Update control
  1928. //--------------------------------------------------------------------
  1929. if ((state != STATE_DISABLED) && !guiLocked)
  1930. {
  1931. Vector2 mousePoint = GetMousePosition();
  1932. if (CheckCollisionPointRec(mousePoint, bounds))
  1933. {
  1934. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1935. else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  1936. {
  1937. state = STATE_PRESSED;
  1938. (*active)++;
  1939. result = 1;
  1940. }
  1941. else state = STATE_FOCUSED;
  1942. }
  1943. if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED;
  1944. }
  1945. if (*active >= itemCount) *active = 0;
  1946. slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width;
  1947. //--------------------------------------------------------------------
  1948. // Draw control
  1949. //--------------------------------------------------------------------
  1950. GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))),
  1951. GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL)));
  1952. // Draw internal slider
  1953. if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
  1954. else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED)));
  1955. else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
  1956. // Draw text in slider
  1957. if (text != NULL)
  1958. {
  1959. Rectangle textBounds = { 0 };
  1960. textBounds.width = (float)GetTextWidth(text);
  1961. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  1962. textBounds.x = slider.x + slider.width/2 - textBounds.width/2;
  1963. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  1964. GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha));
  1965. }
  1966. //--------------------------------------------------------------------
  1967. return result;
  1968. }
  1969. // Check Box control, returns 1 when state changed
  1970. int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
  1971. {
  1972. int result = 0;
  1973. GuiState state = guiState;
  1974. bool temp = false;
  1975. if (checked == NULL) checked = &temp;
  1976. Rectangle textBounds = { 0 };
  1977. if (text != NULL)
  1978. {
  1979. textBounds.width = (float)GetTextWidth(text) + 2;
  1980. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  1981. textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING);
  1982. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  1983. if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING);
  1984. }
  1985. // Update control
  1986. //--------------------------------------------------------------------
  1987. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  1988. {
  1989. Vector2 mousePoint = GetMousePosition();
  1990. Rectangle totalBounds = {
  1991. (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x,
  1992. bounds.y,
  1993. bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING),
  1994. bounds.height,
  1995. };
  1996. // Check checkbox state
  1997. if (CheckCollisionPointRec(mousePoint, totalBounds))
  1998. {
  1999. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2000. else state = STATE_FOCUSED;
  2001. if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  2002. {
  2003. *checked = !(*checked);
  2004. result = 1;
  2005. }
  2006. }
  2007. }
  2008. //--------------------------------------------------------------------
  2009. // Draw control
  2010. //--------------------------------------------------------------------
  2011. GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK);
  2012. if (*checked)
  2013. {
  2014. Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
  2015. bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
  2016. bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
  2017. bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) };
  2018. GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)));
  2019. }
  2020. GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  2021. //--------------------------------------------------------------------
  2022. return result;
  2023. }
  2024. // Combo Box control
  2025. int GuiComboBox(Rectangle bounds, const char *text, int *active)
  2026. {
  2027. int result = 0;
  2028. GuiState state = guiState;
  2029. int temp = 0;
  2030. if (active == NULL) active = &temp;
  2031. bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING));
  2032. Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING),
  2033. (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
  2034. // Get substrings items from text (items pointers, lengths and count)
  2035. int itemCount = 0;
  2036. const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
  2037. if (*active < 0) *active = 0;
  2038. else if (*active > (itemCount - 1)) *active = itemCount - 1;
  2039. // Update control
  2040. //--------------------------------------------------------------------
  2041. if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode)
  2042. {
  2043. Vector2 mousePoint = GetMousePosition();
  2044. if (CheckCollisionPointRec(mousePoint, bounds) ||
  2045. CheckCollisionPointRec(mousePoint, selector))
  2046. {
  2047. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2048. {
  2049. *active += 1;
  2050. if (*active >= itemCount) *active = 0; // Cyclic combobox
  2051. }
  2052. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2053. else state = STATE_FOCUSED;
  2054. }
  2055. }
  2056. //--------------------------------------------------------------------
  2057. // Draw control
  2058. //--------------------------------------------------------------------
  2059. // Draw combo box main
  2060. GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))));
  2061. GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))));
  2062. // Draw selector using a custom button
  2063. // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
  2064. int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  2065. int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  2066. GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  2067. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  2068. GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount));
  2069. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
  2070. GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  2071. //--------------------------------------------------------------------
  2072. return result;
  2073. }
  2074. // Dropdown Box control
  2075. // NOTE: Returns mouse click
  2076. int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode)
  2077. {
  2078. int result = 0;
  2079. GuiState state = guiState;
  2080. int temp = 0;
  2081. if (active == NULL) active = &temp;
  2082. int itemSelected = *active;
  2083. int itemFocused = -1;
  2084. int direction = 0; // Dropdown box open direction: down (default)
  2085. if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up
  2086. // Get substrings items from text (items pointers, lengths and count)
  2087. int itemCount = 0;
  2088. const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
  2089. Rectangle boundsOpen = bounds;
  2090. boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2091. if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING);
  2092. Rectangle itemBounds = bounds;
  2093. // Update control
  2094. //--------------------------------------------------------------------
  2095. if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode)
  2096. {
  2097. Vector2 mousePoint = GetMousePosition();
  2098. if (editMode)
  2099. {
  2100. state = STATE_PRESSED;
  2101. // Check if mouse has been pressed or released outside limits
  2102. if (!CheckCollisionPointRec(mousePoint, boundsOpen))
  2103. {
  2104. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1;
  2105. }
  2106. // Check if already selected item has been pressed again
  2107. if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
  2108. // Check focused and selected item
  2109. for (int i = 0; i < itemCount; i++)
  2110. {
  2111. // Update item rectangle y position for next item
  2112. if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2113. else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2114. if (CheckCollisionPointRec(mousePoint, itemBounds))
  2115. {
  2116. itemFocused = i;
  2117. if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  2118. {
  2119. itemSelected = i;
  2120. result = 1; // Item selected
  2121. }
  2122. break;
  2123. }
  2124. }
  2125. itemBounds = bounds;
  2126. }
  2127. else
  2128. {
  2129. if (CheckCollisionPointRec(mousePoint, bounds))
  2130. {
  2131. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2132. {
  2133. result = 1;
  2134. state = STATE_PRESSED;
  2135. }
  2136. else state = STATE_FOCUSED;
  2137. }
  2138. }
  2139. }
  2140. //--------------------------------------------------------------------
  2141. // Draw control
  2142. //--------------------------------------------------------------------
  2143. if (editMode) GuiPanel(boundsOpen, NULL);
  2144. GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)));
  2145. GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)));
  2146. if (editMode)
  2147. {
  2148. // Draw visible items
  2149. for (int i = 0; i < itemCount; i++)
  2150. {
  2151. // Update item rectangle y position for next item
  2152. if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2153. else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2154. if (i == itemSelected)
  2155. {
  2156. GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)));
  2157. GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)));
  2158. }
  2159. else if (i == itemFocused)
  2160. {
  2161. GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)));
  2162. GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)));
  2163. }
  2164. else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)));
  2165. }
  2166. }
  2167. if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN))
  2168. {
  2169. // Draw arrows (using icon if available)
  2170. #if defined(RAYGUI_NO_ICONS)
  2171. GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
  2172. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
  2173. #else
  2174. GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
  2175. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL
  2176. #endif
  2177. }
  2178. //--------------------------------------------------------------------
  2179. *active = itemSelected;
  2180. // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item...
  2181. return result; // Mouse click: result = 1
  2182. }
  2183. // Text Box control
  2184. // NOTE: Returns true on ENTER pressed (useful for data validation)
  2185. int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
  2186. {
  2187. #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)
  2188. #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 40 // Frames to wait for autocursor movement
  2189. #endif
  2190. #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY)
  2191. #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement
  2192. #endif
  2193. int result = 0;
  2194. GuiState state = guiState;
  2195. bool multiline = false; // TODO: Consider multiline text input
  2196. int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);
  2197. Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
  2198. int textLength = (int)strlen(text); // Get current text length
  2199. int thisCursorIndex = textBoxCursorIndex;
  2200. if (thisCursorIndex > textLength) thisCursorIndex = textLength;
  2201. int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex);
  2202. int textIndexOffset = 0; // Text index offset to start drawing in the box
  2203. // Cursor rectangle
  2204. // NOTE: Position X value should be updated
  2205. Rectangle cursor = {
  2206. textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING),
  2207. textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
  2208. 2,
  2209. (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
  2210. };
  2211. if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
  2212. if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH);
  2213. // Mouse cursor rectangle
  2214. // NOTE: Initialized outside of screen
  2215. Rectangle mouseCursor = cursor;
  2216. mouseCursor.x = -1;
  2217. mouseCursor.width = 1;
  2218. // Auto-cursor movement logic
  2219. // NOTE: Cursor moves automatically when key down after some time
  2220. if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCooldownCounter++;
  2221. else
  2222. {
  2223. autoCursorCooldownCounter = 0; // GLOBAL: Cursor cooldown counter
  2224. autoCursorDelayCounter = 0; // GLOBAL: Cursor delay counter
  2225. }
  2226. // Blink-cursor frame counter
  2227. //if (!autoCursorMode) blinkCursorFrameCounter++;
  2228. //else blinkCursorFrameCounter = 0;
  2229. // Update control
  2230. //--------------------------------------------------------------------
  2231. // WARNING: Text editing is only supported under certain conditions:
  2232. if ((state != STATE_DISABLED) && // Control not disabled
  2233. !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode
  2234. !guiLocked && // Gui not locked
  2235. !guiControlExclusiveMode && // No gui slider on dragging
  2236. (wrapMode == TEXT_WRAP_NONE)) // No wrap mode
  2237. {
  2238. Vector2 mousePosition = GetMousePosition();
  2239. if (editMode)
  2240. {
  2241. state = STATE_PRESSED;
  2242. if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
  2243. // If text does not fit in the textbox and current cursor position is out of bounds,
  2244. // we add an index offset to text for drawing only what requires depending on cursor
  2245. while (textWidth >= textBounds.width)
  2246. {
  2247. int nextCodepointSize = 0;
  2248. GetCodepointNext(text + textIndexOffset, &nextCodepointSize);
  2249. textIndexOffset += nextCodepointSize;
  2250. textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex);
  2251. }
  2252. int codepoint = GetCharPressed(); // Get Unicode codepoint
  2253. if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n';
  2254. // Encode codepoint as UTF-8
  2255. int codepointSize = 0;
  2256. const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
  2257. // Add codepoint to text, at current cursor position
  2258. // NOTE: Make sure we do not overflow buffer size
  2259. if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))
  2260. {
  2261. // Move forward data from cursor position
  2262. for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize];
  2263. // Add new codepoint in current cursor position
  2264. for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i];
  2265. textBoxCursorIndex += codepointSize;
  2266. textLength += codepointSize;
  2267. // Make sure text last character is EOL
  2268. text[textLength] = '\0';
  2269. }
  2270. // Move cursor to start
  2271. if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0;
  2272. // Move cursor to end
  2273. if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength;
  2274. // Delete codepoint from text, after current cursor position
  2275. if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
  2276. {
  2277. autoCursorDelayCounter++;
  2278. if (IsKeyPressed(KEY_DELETE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
  2279. {
  2280. int nextCodepointSize = 0;
  2281. GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
  2282. // Move backward text from cursor position
  2283. for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize];
  2284. textLength -= codepointSize;
  2285. if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
  2286. // Make sure text last character is EOL
  2287. text[textLength] = '\0';
  2288. }
  2289. }
  2290. // Delete related codepoints from text, before current cursor position
  2291. if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
  2292. {
  2293. int i = textBoxCursorIndex - 1;
  2294. int accCodepointSize = 0;
  2295. // Move cursor to the end of word if on space already
  2296. while ((i > 0) && isspace(text[i]))
  2297. {
  2298. int prevCodepointSize = 0;
  2299. GetCodepointPrevious(text + i, &prevCodepointSize);
  2300. i -= prevCodepointSize;
  2301. accCodepointSize += prevCodepointSize;
  2302. }
  2303. // Move cursor to the start of the word
  2304. while ((i > 0) && !isspace(text[i]))
  2305. {
  2306. int prevCodepointSize = 0;
  2307. GetCodepointPrevious(text + i, &prevCodepointSize);
  2308. i -= prevCodepointSize;
  2309. accCodepointSize += prevCodepointSize;
  2310. }
  2311. // Move forward text from cursor position
  2312. for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize];
  2313. // Prevent cursor index from decrementing past 0
  2314. if (textBoxCursorIndex > 0)
  2315. {
  2316. textBoxCursorIndex -= accCodepointSize;
  2317. textLength -= accCodepointSize;
  2318. }
  2319. // Make sure text last character is EOL
  2320. text[textLength] = '\0';
  2321. }
  2322. else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
  2323. {
  2324. autoCursorDelayCounter++;
  2325. if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
  2326. {
  2327. int prevCodepointSize = 0;
  2328. // Prevent cursor index from decrementing past 0
  2329. if (textBoxCursorIndex > 0)
  2330. {
  2331. GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
  2332. // Move backward text from cursor position
  2333. for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];
  2334. textBoxCursorIndex -= codepointSize;
  2335. textLength -= codepointSize;
  2336. }
  2337. // Make sure text last character is EOL
  2338. text[textLength] = '\0';
  2339. }
  2340. }
  2341. // Move cursor position with keys
  2342. if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))
  2343. {
  2344. autoCursorDelayCounter++;
  2345. if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
  2346. {
  2347. int prevCodepointSize = 0;
  2348. if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
  2349. if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize;
  2350. }
  2351. }
  2352. else if (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))
  2353. {
  2354. autoCursorDelayCounter++;
  2355. if (IsKeyPressed(KEY_RIGHT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
  2356. {
  2357. int nextCodepointSize = 0;
  2358. GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
  2359. if ((textBoxCursorIndex + nextCodepointSize) <= textLength) textBoxCursorIndex += nextCodepointSize;
  2360. }
  2361. }
  2362. // Move cursor position with mouse
  2363. if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text
  2364. {
  2365. float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize;
  2366. int codepointIndex = 0;
  2367. float glyphWidth = 0.0f;
  2368. float widthToMouseX = 0;
  2369. int mouseCursorIndex = 0;
  2370. for (int i = textIndexOffset; i < textLength; i++)
  2371. {
  2372. codepoint = GetCodepointNext(&text[i], &codepointSize);
  2373. codepointIndex = GetGlyphIndex(guiFont, codepoint);
  2374. if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
  2375. else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
  2376. if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2)))
  2377. {
  2378. mouseCursor.x = textBounds.x + widthToMouseX;
  2379. mouseCursorIndex = i;
  2380. break;
  2381. }
  2382. widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  2383. }
  2384. // Check if mouse cursor is at the last position
  2385. int textEndWidth = GetTextWidth(text + textIndexOffset);
  2386. if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2))
  2387. {
  2388. mouseCursor.x = textBounds.x + textEndWidth;
  2389. mouseCursorIndex = textLength;
  2390. }
  2391. // Place cursor at required index on mouse click
  2392. if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2393. {
  2394. cursor.x = mouseCursor.x;
  2395. textBoxCursorIndex = mouseCursorIndex;
  2396. }
  2397. }
  2398. else mouseCursor.x = -1;
  2399. // Recalculate cursor position.y depending on textBoxCursorIndex
  2400. cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING);
  2401. //if (multiline) cursor.y = GetTextLines()
  2402. // Finish text editing on ENTER or mouse click outside bounds
  2403. if ((!multiline && IsKeyPressed(KEY_ENTER)) ||
  2404. (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
  2405. {
  2406. textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index
  2407. result = 1;
  2408. }
  2409. }
  2410. else
  2411. {
  2412. if (CheckCollisionPointRec(mousePosition, bounds))
  2413. {
  2414. state = STATE_FOCUSED;
  2415. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2416. {
  2417. textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text
  2418. result = 1;
  2419. }
  2420. }
  2421. }
  2422. }
  2423. //--------------------------------------------------------------------
  2424. // Draw control
  2425. //--------------------------------------------------------------------
  2426. if (state == STATE_PRESSED)
  2427. {
  2428. GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)));
  2429. }
  2430. else if (state == STATE_DISABLED)
  2431. {
  2432. GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)));
  2433. }
  2434. else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK);
  2435. // Draw text considering index offset if required
  2436. // NOTE: Text index offset depends on cursor position
  2437. GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))));
  2438. // Draw cursor
  2439. if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY))
  2440. {
  2441. //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0))
  2442. GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
  2443. // Draw mouse position cursor (if required)
  2444. if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
  2445. }
  2446. else if (state == STATE_FOCUSED) GuiTooltip(bounds);
  2447. //--------------------------------------------------------------------
  2448. return result; // Mouse button pressed: result = 1
  2449. }
  2450. /*
  2451. // Text Box control with multiple lines and word-wrap
  2452. // NOTE: This text-box is readonly, no editing supported by default
  2453. bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
  2454. {
  2455. bool pressed = false;
  2456. GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
  2457. GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported
  2458. GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP);
  2459. // TODO: Implement methods to calculate cursor position properly
  2460. pressed = GuiTextBox(bounds, text, textSize, editMode);
  2461. GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);
  2462. GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
  2463. GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
  2464. return pressed;
  2465. }
  2466. */
  2467. // Spinner control, returns selected value
  2468. int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
  2469. {
  2470. int result = 1;
  2471. GuiState state = guiState;
  2472. int tempValue = *value;
  2473. Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING), bounds.y,
  2474. bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING)), bounds.height };
  2475. Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
  2476. Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
  2477. Rectangle textBounds = { 0 };
  2478. if (text != NULL)
  2479. {
  2480. textBounds.width = (float)GetTextWidth(text) + 2;
  2481. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2482. textBounds.x = bounds.x + bounds.width + GuiGetStyle(SPINNER, TEXT_PADDING);
  2483. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2484. if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING);
  2485. }
  2486. // Update control
  2487. //--------------------------------------------------------------------
  2488. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  2489. {
  2490. Vector2 mousePoint = GetMousePosition();
  2491. // Check spinner state
  2492. if (CheckCollisionPointRec(mousePoint, bounds))
  2493. {
  2494. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2495. else state = STATE_FOCUSED;
  2496. }
  2497. }
  2498. #if defined(RAYGUI_NO_ICONS)
  2499. if (GuiButton(leftButtonBound, "<")) tempValue--;
  2500. if (GuiButton(rightButtonBound, ">")) tempValue++;
  2501. #else
  2502. if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--;
  2503. if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++;
  2504. #endif
  2505. if (!editMode)
  2506. {
  2507. if (tempValue < minValue) tempValue = minValue;
  2508. if (tempValue > maxValue) tempValue = maxValue;
  2509. }
  2510. //--------------------------------------------------------------------
  2511. // Draw control
  2512. //--------------------------------------------------------------------
  2513. result = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode);
  2514. // Draw value selector custom buttons
  2515. // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
  2516. int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  2517. int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  2518. GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH));
  2519. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  2520. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
  2521. GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  2522. // Draw text label if provided
  2523. GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  2524. //--------------------------------------------------------------------
  2525. *value = tempValue;
  2526. return result;
  2527. }
  2528. // Value Box control, updates input text with numbers
  2529. // NOTE: Requires static variables: frameCounter
  2530. int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
  2531. {
  2532. #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
  2533. #define RAYGUI_VALUEBOX_MAX_CHARS 32
  2534. #endif
  2535. int result = 0;
  2536. GuiState state = guiState;
  2537. char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
  2538. sprintf(textValue, "%i", *value);
  2539. Rectangle textBounds = { 0 };
  2540. if (text != NULL)
  2541. {
  2542. textBounds.width = (float)GetTextWidth(text) + 2;
  2543. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2544. textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2545. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2546. if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2547. }
  2548. // Update control
  2549. //--------------------------------------------------------------------
  2550. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  2551. {
  2552. Vector2 mousePoint = GetMousePosition();
  2553. bool valueHasChanged = false;
  2554. if (editMode)
  2555. {
  2556. state = STATE_PRESSED;
  2557. int keyCount = (int)strlen(textValue);
  2558. // Only allow keys in range [48..57]
  2559. if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
  2560. {
  2561. if (GetTextWidth(textValue) < bounds.width)
  2562. {
  2563. int key = GetCharPressed();
  2564. if ((key >= 48) && (key <= 57))
  2565. {
  2566. textValue[keyCount] = (char)key;
  2567. keyCount++;
  2568. valueHasChanged = true;
  2569. }
  2570. }
  2571. }
  2572. // Delete text
  2573. if (keyCount > 0)
  2574. {
  2575. if (IsKeyPressed(KEY_BACKSPACE))
  2576. {
  2577. keyCount--;
  2578. textValue[keyCount] = '\0';
  2579. valueHasChanged = true;
  2580. }
  2581. }
  2582. if (valueHasChanged) *value = TextToInteger(textValue);
  2583. // NOTE: We are not clamp values until user input finishes
  2584. //if (*value > maxValue) *value = maxValue;
  2585. //else if (*value < minValue) *value = minValue;
  2586. if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
  2587. {
  2588. if (*value > maxValue) *value = maxValue;
  2589. else if (*value < minValue) *value = minValue;
  2590. result = 1;
  2591. }
  2592. }
  2593. else
  2594. {
  2595. if (*value > maxValue) *value = maxValue;
  2596. else if (*value < minValue) *value = minValue;
  2597. if (CheckCollisionPointRec(mousePoint, bounds))
  2598. {
  2599. state = STATE_FOCUSED;
  2600. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
  2601. }
  2602. }
  2603. }
  2604. //--------------------------------------------------------------------
  2605. // Draw control
  2606. //--------------------------------------------------------------------
  2607. Color baseColor = BLANK;
  2608. if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
  2609. else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
  2610. GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
  2611. GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
  2612. // Draw cursor
  2613. if (editMode)
  2614. {
  2615. // NOTE: ValueBox internal text is always centered
  2616. Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
  2617. GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
  2618. }
  2619. // Draw text label if provided
  2620. GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  2621. //--------------------------------------------------------------------
  2622. return result;
  2623. }
  2624. // Floating point Value Box control, updates input val_str with numbers
  2625. // NOTE: Requires static variables: frameCounter
  2626. int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode)
  2627. {
  2628. #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
  2629. #define RAYGUI_VALUEBOX_MAX_CHARS 32
  2630. #endif
  2631. int result = 0;
  2632. GuiState state = guiState;
  2633. //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
  2634. //sprintf(textValue, "%2.2f", *value);
  2635. Rectangle textBounds = {0};
  2636. if (text != NULL)
  2637. {
  2638. textBounds.width = (float)GetTextWidth(text) + 2;
  2639. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2640. textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2641. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2642. if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2643. }
  2644. // Update control
  2645. //--------------------------------------------------------------------
  2646. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  2647. {
  2648. Vector2 mousePoint = GetMousePosition();
  2649. bool valueHasChanged = false;
  2650. if (editMode)
  2651. {
  2652. state = STATE_PRESSED;
  2653. int keyCount = (int)strlen(textValue);
  2654. // Only allow keys in range [48..57]
  2655. if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
  2656. {
  2657. if (GetTextWidth(textValue) < bounds.width)
  2658. {
  2659. int key = GetCharPressed();
  2660. if (((key >= 48) && (key <= 57)) ||
  2661. (key == '.') ||
  2662. ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position
  2663. ((keyCount == 0) && (key == '-')))
  2664. {
  2665. textValue[keyCount] = (char)key;
  2666. keyCount++;
  2667. valueHasChanged = true;
  2668. }
  2669. }
  2670. }
  2671. // Pressed backspace
  2672. if (IsKeyPressed(KEY_BACKSPACE))
  2673. {
  2674. if (keyCount > 0)
  2675. {
  2676. keyCount--;
  2677. textValue[keyCount] = '\0';
  2678. valueHasChanged = true;
  2679. }
  2680. }
  2681. if (valueHasChanged) *value = TextToFloat(textValue);
  2682. if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;
  2683. }
  2684. else
  2685. {
  2686. if (CheckCollisionPointRec(mousePoint, bounds))
  2687. {
  2688. state = STATE_FOCUSED;
  2689. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
  2690. }
  2691. }
  2692. }
  2693. //--------------------------------------------------------------------
  2694. // Draw control
  2695. //--------------------------------------------------------------------
  2696. Color baseColor = BLANK;
  2697. if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
  2698. else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
  2699. GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
  2700. GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
  2701. // Draw cursor
  2702. if (editMode)
  2703. {
  2704. // NOTE: ValueBox internal text is always centered
  2705. Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1,
  2706. bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4,
  2707. bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};
  2708. GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
  2709. }
  2710. // Draw text label if provided
  2711. GuiDrawText(text, textBounds,
  2712. (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT,
  2713. GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
  2714. //--------------------------------------------------------------------
  2715. return result;
  2716. }
  2717. // Slider control with pro parameters
  2718. // NOTE: Other GuiSlider*() controls use this one
  2719. int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth)
  2720. {
  2721. int result = 0;
  2722. GuiState state = guiState;
  2723. float temp = (maxValue - minValue)/2.0f;
  2724. if (value == NULL) value = &temp;
  2725. float oldValue = *value;
  2726. Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
  2727. 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
  2728. // Update control
  2729. //--------------------------------------------------------------------
  2730. if ((state != STATE_DISABLED) && !guiLocked)
  2731. {
  2732. Vector2 mousePoint = GetMousePosition();
  2733. if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
  2734. {
  2735. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  2736. {
  2737. if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
  2738. {
  2739. state = STATE_PRESSED;
  2740. // Get equivalent value and slider position from mousePosition.x
  2741. *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;
  2742. }
  2743. }
  2744. else
  2745. {
  2746. guiControlExclusiveMode = false;
  2747. guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
  2748. }
  2749. }
  2750. else if (CheckCollisionPointRec(mousePoint, bounds))
  2751. {
  2752. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  2753. {
  2754. state = STATE_PRESSED;
  2755. guiControlExclusiveMode = true;
  2756. guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
  2757. if (!CheckCollisionPointRec(mousePoint, slider))
  2758. {
  2759. // Get equivalent value and slider position from mousePosition.x
  2760. *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue;
  2761. }
  2762. }
  2763. else state = STATE_FOCUSED;
  2764. }
  2765. if (*value > maxValue) *value = maxValue;
  2766. else if (*value < minValue) *value = minValue;
  2767. }
  2768. // Control value change check
  2769. if (oldValue == *value) result = 0;
  2770. else result = 1;
  2771. // Slider bar limits check
  2772. float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
  2773. if (sliderWidth > 0) // Slider
  2774. {
  2775. slider.x += sliderValue;
  2776. slider.width = (float)sliderWidth;
  2777. if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
  2778. else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
  2779. }
  2780. else if (sliderWidth == 0) // SliderBar
  2781. {
  2782. slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
  2783. slider.width = sliderValue;
  2784. if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
  2785. }
  2786. //--------------------------------------------------------------------
  2787. // Draw control
  2788. //--------------------------------------------------------------------
  2789. GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
  2790. // Draw slider internal bar (depends on state)
  2791. if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
  2792. else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)));
  2793. else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED)));
  2794. // Draw left/right text if provided
  2795. if (textLeft != NULL)
  2796. {
  2797. Rectangle textBounds = { 0 };
  2798. textBounds.width = (float)GetTextWidth(textLeft);
  2799. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2800. textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
  2801. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2802. GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
  2803. }
  2804. if (textRight != NULL)
  2805. {
  2806. Rectangle textBounds = { 0 };
  2807. textBounds.width = (float)GetTextWidth(textRight);
  2808. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2809. textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
  2810. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2811. GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
  2812. }
  2813. //--------------------------------------------------------------------
  2814. return result;
  2815. }
  2816. // Slider control extended, returns selected value and has text
  2817. int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
  2818. {
  2819. return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH));
  2820. }
  2821. // Slider Bar control extended, returns selected value
  2822. int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
  2823. {
  2824. return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0);
  2825. }
  2826. // Progress Bar control extended, shows current progress value
  2827. int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
  2828. {
  2829. int result = 0;
  2830. GuiState state = guiState;
  2831. float temp = (maxValue - minValue)/2.0f;
  2832. if (value == NULL) value = &temp;
  2833. // Progress bar
  2834. Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
  2835. bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
  2836. bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) };
  2837. // Update control
  2838. //--------------------------------------------------------------------
  2839. if (*value > maxValue) *value = maxValue;
  2840. // WARNING: Working with floats could lead to rounding issues
  2841. if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue)? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f);
  2842. //--------------------------------------------------------------------
  2843. // Draw control
  2844. //--------------------------------------------------------------------
  2845. if (state == STATE_DISABLED)
  2846. {
  2847. GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK);
  2848. }
  2849. else
  2850. {
  2851. if (*value > minValue)
  2852. {
  2853. // Draw progress bar with colored border, more visual
  2854. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
  2855. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
  2856. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
  2857. }
  2858. else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
  2859. if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + 1, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
  2860. else
  2861. {
  2862. // Draw borders not yet reached by value
  2863. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
  2864. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y + bounds.height - 1, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
  2865. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
  2866. }
  2867. // Draw slider internal progress bar (depends on state)
  2868. GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)));
  2869. }
  2870. // Draw left/right text if provided
  2871. if (textLeft != NULL)
  2872. {
  2873. Rectangle textBounds = { 0 };
  2874. textBounds.width = (float)GetTextWidth(textLeft);
  2875. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2876. textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
  2877. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2878. GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
  2879. }
  2880. if (textRight != NULL)
  2881. {
  2882. Rectangle textBounds = { 0 };
  2883. textBounds.width = (float)GetTextWidth(textRight);
  2884. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2885. textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
  2886. textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2887. GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
  2888. }
  2889. //--------------------------------------------------------------------
  2890. return result;
  2891. }
  2892. // Status Bar control
  2893. int GuiStatusBar(Rectangle bounds, const char *text)
  2894. {
  2895. int result = 0;
  2896. GuiState state = guiState;
  2897. // Draw control
  2898. //--------------------------------------------------------------------
  2899. GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3))));
  2900. GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3))));
  2901. //--------------------------------------------------------------------
  2902. return result;
  2903. }
  2904. // Dummy rectangle control, intended for placeholding
  2905. int GuiDummyRec(Rectangle bounds, const char *text)
  2906. {
  2907. int result = 0;
  2908. GuiState state = guiState;
  2909. // Update control
  2910. //--------------------------------------------------------------------
  2911. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  2912. {
  2913. Vector2 mousePoint = GetMousePosition();
  2914. // Check button state
  2915. if (CheckCollisionPointRec(mousePoint, bounds))
  2916. {
  2917. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2918. else state = STATE_FOCUSED;
  2919. }
  2920. }
  2921. //--------------------------------------------------------------------
  2922. // Draw control
  2923. //--------------------------------------------------------------------
  2924. GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
  2925. GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)));
  2926. //------------------------------------------------------------------
  2927. return result;
  2928. }
  2929. // List View control
  2930. int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active)
  2931. {
  2932. int result = 0;
  2933. int itemCount = 0;
  2934. const char **items = NULL;
  2935. if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
  2936. result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL);
  2937. return result;
  2938. }
  2939. // List View control with extended parameters
  2940. int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus)
  2941. {
  2942. int result = 0;
  2943. GuiState state = guiState;
  2944. int itemFocused = (focus == NULL)? -1 : *focus;
  2945. int itemSelected = (active == NULL)? -1 : *active;
  2946. // Check if we need a scroll bar
  2947. bool useScrollBar = false;
  2948. if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true;
  2949. // Define base item rectangle [0]
  2950. Rectangle itemBounds = { 0 };
  2951. itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING);
  2952. itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
  2953. itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
  2954. itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
  2955. if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
  2956. // Get items on the list
  2957. int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  2958. if (visibleItems > count) visibleItems = count;
  2959. int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
  2960. if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
  2961. int endIndex = startIndex + visibleItems;
  2962. // Update control
  2963. //--------------------------------------------------------------------
  2964. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  2965. {
  2966. Vector2 mousePoint = GetMousePosition();
  2967. // Check mouse inside list view
  2968. if (CheckCollisionPointRec(mousePoint, bounds))
  2969. {
  2970. state = STATE_FOCUSED;
  2971. // Check focused and selected item
  2972. for (int i = 0; i < visibleItems; i++)
  2973. {
  2974. if (CheckCollisionPointRec(mousePoint, itemBounds))
  2975. {
  2976. itemFocused = startIndex + i;
  2977. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2978. {
  2979. if (itemSelected == (startIndex + i)) itemSelected = -1;
  2980. else itemSelected = startIndex + i;
  2981. }
  2982. break;
  2983. }
  2984. // Update item rectangle y position for next item
  2985. itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  2986. }
  2987. if (useScrollBar)
  2988. {
  2989. int wheelMove = (int)GetMouseWheelMove();
  2990. startIndex -= wheelMove;
  2991. if (startIndex < 0) startIndex = 0;
  2992. else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
  2993. endIndex = startIndex + visibleItems;
  2994. if (endIndex > count) endIndex = count;
  2995. }
  2996. }
  2997. else itemFocused = -1;
  2998. // Reset item rectangle y to [0]
  2999. itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
  3000. }
  3001. //--------------------------------------------------------------------
  3002. // Draw control
  3003. //--------------------------------------------------------------------
  3004. GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
  3005. // Draw visible items
  3006. for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
  3007. {
  3008. GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);
  3009. if (state == STATE_DISABLED)
  3010. {
  3011. if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));
  3012. GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)));
  3013. }
  3014. else
  3015. {
  3016. if (((startIndex + i) == itemSelected) && (active != NULL))
  3017. {
  3018. // Draw item selected
  3019. GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)));
  3020. GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)));
  3021. }
  3022. else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned!
  3023. {
  3024. // Draw item focused
  3025. GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)));
  3026. GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)));
  3027. }
  3028. else
  3029. {
  3030. // Draw item normal
  3031. GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)));
  3032. }
  3033. }
  3034. // Update item rectangle y position for next item
  3035. itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  3036. }
  3037. if (useScrollBar)
  3038. {
  3039. Rectangle scrollBarBounds = {
  3040. bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
  3041. bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
  3042. bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
  3043. };
  3044. // Calculate percentage of visible items and apply same percentage to scrollbar
  3045. float percentVisible = (float)(endIndex - startIndex)/count;
  3046. float sliderSize = bounds.height*percentVisible;
  3047. int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size
  3048. int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
  3049. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size
  3050. GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
  3051. startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
  3052. GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
  3053. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default
  3054. }
  3055. //--------------------------------------------------------------------
  3056. if (active != NULL) *active = itemSelected;
  3057. if (focus != NULL) *focus = itemFocused;
  3058. if (scrollIndex != NULL) *scrollIndex = startIndex;
  3059. return result;
  3060. }
  3061. // Color Panel control - Color (RGBA) variant.
  3062. int GuiColorPanel(Rectangle bounds, const char *text, Color *color)
  3063. {
  3064. int result = 0;
  3065. Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f };
  3066. Vector3 hsv = ConvertRGBtoHSV(vcolor);
  3067. Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv.
  3068. GuiColorPanelHSV(bounds, text, &hsv);
  3069. // Check if the hsv was changed, only then change the color.
  3070. // This is required, because the Color->HSV->Color conversion has precision errors.
  3071. // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value.
  3072. // Otherwise GuiColorPanel would often modify it's color without user input.
  3073. // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check.
  3074. if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z)
  3075. {
  3076. Vector3 rgb = ConvertHSVtoRGB(hsv);
  3077. // NOTE: Vector3ToColor() only available on raylib 1.8.1
  3078. *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
  3079. (unsigned char)(255.0f*rgb.y),
  3080. (unsigned char)(255.0f*rgb.z),
  3081. color->a };
  3082. }
  3083. return result;
  3084. }
  3085. // Color Bar Alpha control
  3086. // NOTE: Returns alpha value normalized [0..1]
  3087. int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
  3088. {
  3089. #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE)
  3090. #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10
  3091. #endif
  3092. int result = 0;
  3093. GuiState state = guiState;
  3094. Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 };
  3095. // Update control
  3096. //--------------------------------------------------------------------
  3097. if ((state != STATE_DISABLED) && !guiLocked)
  3098. {
  3099. Vector2 mousePoint = GetMousePosition();
  3100. if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
  3101. {
  3102. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3103. {
  3104. if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
  3105. {
  3106. state = STATE_PRESSED;
  3107. *alpha = (mousePoint.x - bounds.x)/bounds.width;
  3108. if (*alpha <= 0.0f) *alpha = 0.0f;
  3109. if (*alpha >= 1.0f) *alpha = 1.0f;
  3110. }
  3111. }
  3112. else
  3113. {
  3114. guiControlExclusiveMode = false;
  3115. guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
  3116. }
  3117. }
  3118. else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
  3119. {
  3120. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3121. {
  3122. state = STATE_PRESSED;
  3123. guiControlExclusiveMode = true;
  3124. guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
  3125. *alpha = (mousePoint.x - bounds.x)/bounds.width;
  3126. if (*alpha <= 0.0f) *alpha = 0.0f;
  3127. if (*alpha >= 1.0f) *alpha = 1.0f;
  3128. //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2;
  3129. }
  3130. else state = STATE_FOCUSED;
  3131. }
  3132. }
  3133. //--------------------------------------------------------------------
  3134. // Draw control
  3135. //--------------------------------------------------------------------
  3136. // Draw alpha bar: checked background
  3137. if (state != STATE_DISABLED)
  3138. {
  3139. int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
  3140. int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
  3141. for (int x = 0; x < checksX; x++)
  3142. {
  3143. for (int y = 0; y < checksY; y++)
  3144. {
  3145. Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE };
  3146. GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f));
  3147. }
  3148. }
  3149. DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha));
  3150. }
  3151. else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
  3152. GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
  3153. // Draw alpha bar: selector
  3154. GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
  3155. //--------------------------------------------------------------------
  3156. return result;
  3157. }
  3158. // Color Bar Hue control
  3159. // Returns hue value normalized [0..1]
  3160. // NOTE: Other similar bars (for reference):
  3161. // Color GuiColorBarSat() [WHITE->color]
  3162. // Color GuiColorBarValue() [BLACK->color], HSV/HSL
  3163. // float GuiColorBarLuminance() [BLACK->WHITE]
  3164. int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
  3165. {
  3166. int result = 0;
  3167. GuiState state = guiState;
  3168. Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) };
  3169. // Update control
  3170. //--------------------------------------------------------------------
  3171. if ((state != STATE_DISABLED) && !guiLocked)
  3172. {
  3173. Vector2 mousePoint = GetMousePosition();
  3174. if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
  3175. {
  3176. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3177. {
  3178. if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
  3179. {
  3180. state = STATE_PRESSED;
  3181. *hue = (mousePoint.y - bounds.y)*360/bounds.height;
  3182. if (*hue <= 0.0f) *hue = 0.0f;
  3183. if (*hue >= 359.0f) *hue = 359.0f;
  3184. }
  3185. }
  3186. else
  3187. {
  3188. guiControlExclusiveMode = false;
  3189. guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
  3190. }
  3191. }
  3192. else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
  3193. {
  3194. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3195. {
  3196. state = STATE_PRESSED;
  3197. guiControlExclusiveMode = true;
  3198. guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
  3199. *hue = (mousePoint.y - bounds.y)*360/bounds.height;
  3200. if (*hue <= 0.0f) *hue = 0.0f;
  3201. if (*hue >= 359.0f) *hue = 359.0f;
  3202. }
  3203. else state = STATE_FOCUSED;
  3204. /*if (IsKeyDown(KEY_UP))
  3205. {
  3206. hue -= 2.0f;
  3207. if (hue <= 0.0f) hue = 0.0f;
  3208. }
  3209. else if (IsKeyDown(KEY_DOWN))
  3210. {
  3211. hue += 2.0f;
  3212. if (hue >= 360.0f) hue = 360.0f;
  3213. }*/
  3214. }
  3215. }
  3216. //--------------------------------------------------------------------
  3217. // Draw control
  3218. //--------------------------------------------------------------------
  3219. if (state != STATE_DISABLED)
  3220. {
  3221. // Draw hue bar:color bars
  3222. // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
  3223. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha));
  3224. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha));
  3225. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha));
  3226. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha));
  3227. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha));
  3228. DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha));
  3229. }
  3230. else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
  3231. GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
  3232. // Draw hue bar: selector
  3233. GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
  3234. //--------------------------------------------------------------------
  3235. return result;
  3236. }
  3237. // Color Picker control
  3238. // NOTE: It's divided in multiple controls:
  3239. // Color GuiColorPanel(Rectangle bounds, Color color)
  3240. // float GuiColorBarAlpha(Rectangle bounds, float alpha)
  3241. // float GuiColorBarHue(Rectangle bounds, float value)
  3242. // NOTE: bounds define GuiColorPanel() size
  3243. // NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead
  3244. int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
  3245. {
  3246. int result = 0;
  3247. Color temp = { 200, 0, 0, 255 };
  3248. if (color == NULL) color = &temp;
  3249. GuiColorPanel(bounds, NULL, color);
  3250. Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
  3251. //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
  3252. // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used.
  3253. Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
  3254. GuiColorBarHue(boundsHue, NULL, &hsv.x);
  3255. //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
  3256. Vector3 rgb = ConvertHSVtoRGB(hsv);
  3257. *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a };
  3258. return result;
  3259. }
  3260. // Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering.
  3261. // The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB.
  3262. // NOTE: It's divided in multiple controls:
  3263. // int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
  3264. // int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
  3265. // float GuiColorBarHue(Rectangle bounds, float value)
  3266. // NOTE: bounds define GuiColorPanelHSV() size
  3267. int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
  3268. {
  3269. int result = 0;
  3270. Vector3 tempHsv = { 0 };
  3271. if (colorHsv == NULL)
  3272. {
  3273. const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f };
  3274. tempHsv = ConvertRGBtoHSV(tempColor);
  3275. colorHsv = &tempHsv;
  3276. }
  3277. GuiColorPanelHSV(bounds, NULL, colorHsv);
  3278. const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
  3279. GuiColorBarHue(boundsHue, NULL, &colorHsv->x);
  3280. return result;
  3281. }
  3282. // Color Panel control - HSV variant
  3283. int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
  3284. {
  3285. int result = 0;
  3286. GuiState state = guiState;
  3287. Vector2 pickerSelector = { 0 };
  3288. const Color colWhite = { 255, 255, 255, 255 };
  3289. const Color colBlack = { 0, 0, 0, 255 };
  3290. pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation
  3291. pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value
  3292. Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f };
  3293. Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
  3294. Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
  3295. (unsigned char)(255.0f*rgbHue.y),
  3296. (unsigned char)(255.0f*rgbHue.z), 255 };
  3297. // Update control
  3298. //--------------------------------------------------------------------
  3299. if ((state != STATE_DISABLED) && !guiLocked)
  3300. {
  3301. Vector2 mousePoint = GetMousePosition();
  3302. if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
  3303. {
  3304. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3305. {
  3306. if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
  3307. {
  3308. pickerSelector = mousePoint;
  3309. if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x;
  3310. if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width;
  3311. if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y;
  3312. if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height;
  3313. // Calculate color from picker
  3314. Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
  3315. colorPick.x /= (float)bounds.width; // Get normalized value on x
  3316. colorPick.y /= (float)bounds.height; // Get normalized value on y
  3317. colorHsv->y = colorPick.x;
  3318. colorHsv->z = 1.0f - colorPick.y;
  3319. }
  3320. }
  3321. else
  3322. {
  3323. guiControlExclusiveMode = false;
  3324. guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
  3325. }
  3326. }
  3327. else if (CheckCollisionPointRec(mousePoint, bounds))
  3328. {
  3329. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3330. {
  3331. state = STATE_PRESSED;
  3332. guiControlExclusiveMode = true;
  3333. guiControlExclusiveRec = bounds;
  3334. pickerSelector = mousePoint;
  3335. // Calculate color from picker
  3336. Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
  3337. colorPick.x /= (float)bounds.width; // Get normalized value on x
  3338. colorPick.y /= (float)bounds.height; // Get normalized value on y
  3339. colorHsv->y = colorPick.x;
  3340. colorHsv->z = 1.0f - colorPick.y;
  3341. }
  3342. else state = STATE_FOCUSED;
  3343. }
  3344. }
  3345. //--------------------------------------------------------------------
  3346. // Draw control
  3347. //--------------------------------------------------------------------
  3348. if (state != STATE_DISABLED)
  3349. {
  3350. DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
  3351. DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
  3352. // Draw color picker: selector
  3353. Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };
  3354. GuiDrawRectangle(selector, 0, BLANK, colWhite);
  3355. }
  3356. else
  3357. {
  3358. DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
  3359. }
  3360. GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
  3361. //--------------------------------------------------------------------
  3362. return result;
  3363. }
  3364. // Message Box control
  3365. int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons)
  3366. {
  3367. #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT)
  3368. #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24
  3369. #endif
  3370. #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING)
  3371. #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12
  3372. #endif
  3373. int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
  3374. int buttonCount = 0;
  3375. const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
  3376. Rectangle buttonBounds = { 0 };
  3377. buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3378. buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3379. buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
  3380. buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
  3381. //int textWidth = GetTextWidth(message) + 2;
  3382. Rectangle textBounds = { 0 };
  3383. textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3384. textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3385. textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2;
  3386. textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
  3387. // Draw control
  3388. //--------------------------------------------------------------------
  3389. if (GuiWindowBox(bounds, title)) result = 0;
  3390. int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
  3391. GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3392. GuiLabel(textBounds, message);
  3393. GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
  3394. prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  3395. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3396. for (int i = 0; i < buttonCount; i++)
  3397. {
  3398. if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1;
  3399. buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
  3400. }
  3401. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment);
  3402. //--------------------------------------------------------------------
  3403. return result;
  3404. }
  3405. // Text Input Box control, ask for text
  3406. int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive)
  3407. {
  3408. #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT)
  3409. #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24
  3410. #endif
  3411. #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING)
  3412. #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12
  3413. #endif
  3414. #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT)
  3415. #define RAYGUI_TEXTINPUTBOX_HEIGHT 26
  3416. #endif
  3417. // Used to enable text edit mode
  3418. // WARNING: No more than one GuiTextInputBox() should be open at the same time
  3419. static bool textEditMode = false;
  3420. int result = -1;
  3421. int buttonCount = 0;
  3422. const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
  3423. Rectangle buttonBounds = { 0 };
  3424. buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3425. buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3426. buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
  3427. buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT;
  3428. int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3429. Rectangle textBounds = { 0 };
  3430. if (message != NULL)
  3431. {
  3432. int textSize = GetTextWidth(message) + 2;
  3433. textBounds.x = bounds.x + bounds.width/2 - textSize/2;
  3434. textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  3435. textBounds.width = (float)textSize;
  3436. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  3437. }
  3438. Rectangle textBoxBounds = { 0 };
  3439. textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3440. textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2;
  3441. if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3442. else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4);
  3443. textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2;
  3444. textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT;
  3445. // Draw control
  3446. //--------------------------------------------------------------------
  3447. if (GuiWindowBox(bounds, title)) result = 0;
  3448. // Draw message if available
  3449. if (message != NULL)
  3450. {
  3451. int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
  3452. GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3453. GuiLabel(textBounds, message);
  3454. GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
  3455. }
  3456. if (secretViewActive != NULL)
  3457. {
  3458. static char stars[] = "****************";
  3459. if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height },
  3460. ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode;
  3461. GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive);
  3462. }
  3463. else
  3464. {
  3465. if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode;
  3466. }
  3467. int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  3468. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3469. for (int i = 0; i < buttonCount; i++)
  3470. {
  3471. if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1;
  3472. buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
  3473. }
  3474. if (result >= 0) textEditMode = false;
  3475. GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment);
  3476. //--------------------------------------------------------------------
  3477. return result; // Result is the pressed button index
  3478. }
  3479. // Grid control
  3480. // NOTE: Returns grid mouse-hover selected cell
  3481. // About drawing lines at subpixel spacing, simple put, not easy solution:
  3482. // https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster
  3483. int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell)
  3484. {
  3485. // Grid lines alpha amount
  3486. #if !defined(RAYGUI_GRID_ALPHA)
  3487. #define RAYGUI_GRID_ALPHA 0.15f
  3488. #endif
  3489. int result = 0;
  3490. GuiState state = guiState;
  3491. Vector2 mousePoint = GetMousePosition();
  3492. Vector2 currentMouseCell = { -1, -1 };
  3493. float spaceWidth = spacing/(float)subdivs;
  3494. int linesV = (int)(bounds.width/spaceWidth) + 1;
  3495. int linesH = (int)(bounds.height/spaceWidth) + 1;
  3496. int color = GuiGetStyle(DEFAULT, LINE_COLOR);
  3497. // Update control
  3498. //--------------------------------------------------------------------
  3499. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  3500. {
  3501. if (CheckCollisionPointRec(mousePoint, bounds))
  3502. {
  3503. // NOTE: Cell values must be the upper left of the cell the mouse is in
  3504. currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing);
  3505. currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing);
  3506. }
  3507. }
  3508. //--------------------------------------------------------------------
  3509. // Draw control
  3510. //--------------------------------------------------------------------
  3511. if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED);
  3512. if (subdivs > 0)
  3513. {
  3514. // Draw vertical grid lines
  3515. for (int i = 0; i < linesV; i++)
  3516. {
  3517. Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 };
  3518. GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
  3519. }
  3520. // Draw horizontal grid lines
  3521. for (int i = 0; i < linesH; i++)
  3522. {
  3523. Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 };
  3524. GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
  3525. }
  3526. }
  3527. if (mouseCell != NULL) *mouseCell = currentMouseCell;
  3528. return result;
  3529. }
  3530. //----------------------------------------------------------------------------------
  3531. // Tooltip management functions
  3532. // NOTE: Tooltips requires some global variables: tooltipPtr
  3533. //----------------------------------------------------------------------------------
  3534. // Enable gui tooltips (global state)
  3535. void GuiEnableTooltip(void) { guiTooltip = true; }
  3536. // Disable gui tooltips (global state)
  3537. void GuiDisableTooltip(void) { guiTooltip = false; }
  3538. // Set tooltip string
  3539. void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; }
  3540. //----------------------------------------------------------------------------------
  3541. // Styles loading functions
  3542. //----------------------------------------------------------------------------------
  3543. // Load raygui style file (.rgs)
  3544. // NOTE: By default a binary file is expected, that file could contain a custom font,
  3545. // in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE)
  3546. void GuiLoadStyle(const char *fileName)
  3547. {
  3548. #define MAX_LINE_BUFFER_SIZE 256
  3549. bool tryBinary = false;
  3550. if (!guiStyleLoaded) GuiLoadStyleDefault();
  3551. // Try reading the files as text file first
  3552. FILE *rgsFile = fopen(fileName, "rt");
  3553. if (rgsFile != NULL)
  3554. {
  3555. char buffer[MAX_LINE_BUFFER_SIZE] = { 0 };
  3556. fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
  3557. if (buffer[0] == '#')
  3558. {
  3559. int controlId = 0;
  3560. int propertyId = 0;
  3561. unsigned int propertyValue = 0;
  3562. while (!feof(rgsFile))
  3563. {
  3564. switch (buffer[0])
  3565. {
  3566. case 'p':
  3567. {
  3568. // Style property: p <control_id> <property_id> <property_value> <property_name>
  3569. sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue);
  3570. GuiSetStyle(controlId, propertyId, (int)propertyValue);
  3571. } break;
  3572. case 'f':
  3573. {
  3574. // Style font: f <gen_font_size> <charmap_file> <font_file>
  3575. int fontSize = 0;
  3576. char charmapFileName[256] = { 0 };
  3577. char fontFileName[256] = { 0 };
  3578. sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName);
  3579. Font font = { 0 };
  3580. int *codepoints = NULL;
  3581. int codepointCount = 0;
  3582. if (charmapFileName[0] != '0')
  3583. {
  3584. // Load text data from file
  3585. // NOTE: Expected an UTF-8 array of codepoints, no separation
  3586. char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName));
  3587. codepoints = LoadCodepoints(textData, &codepointCount);
  3588. UnloadFileText(textData);
  3589. }
  3590. if (fontFileName[0] != '\0')
  3591. {
  3592. // In case a font is already loaded and it is not default internal font, unload it
  3593. if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
  3594. if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount);
  3595. else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints
  3596. }
  3597. // If font texture not properly loaded, revert to default font and size/spacing
  3598. if (font.texture.id == 0)
  3599. {
  3600. font = GetFontDefault();
  3601. GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
  3602. GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
  3603. }
  3604. UnloadCodepoints(codepoints);
  3605. if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font);
  3606. } break;
  3607. default: break;
  3608. }
  3609. fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
  3610. }
  3611. }
  3612. else tryBinary = true;
  3613. fclose(rgsFile);
  3614. }
  3615. if (tryBinary)
  3616. {
  3617. rgsFile = fopen(fileName, "rb");
  3618. if (rgsFile != NULL)
  3619. {
  3620. fseek(rgsFile, 0, SEEK_END);
  3621. int fileDataSize = ftell(rgsFile);
  3622. fseek(rgsFile, 0, SEEK_SET);
  3623. if (fileDataSize > 0)
  3624. {
  3625. unsigned char *fileData = (unsigned char *)RAYGUI_MALLOC(fileDataSize*sizeof(unsigned char));
  3626. fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile);
  3627. GuiLoadStyleFromMemory(fileData, fileDataSize);
  3628. RAYGUI_FREE(fileData);
  3629. }
  3630. fclose(rgsFile);
  3631. }
  3632. }
  3633. }
  3634. // Load style default over global style
  3635. void GuiLoadStyleDefault(void)
  3636. {
  3637. // We set this variable first to avoid cyclic function calls
  3638. // when calling GuiSetStyle() and GuiGetStyle()
  3639. guiStyleLoaded = true;
  3640. // Initialize default LIGHT style property values
  3641. // WARNING: Default value are applied to all controls on set but
  3642. // they can be overwritten later on for every custom control
  3643. GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff);
  3644. GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff);
  3645. GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff);
  3646. GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff);
  3647. GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff);
  3648. GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff);
  3649. GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff);
  3650. GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff);
  3651. GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff);
  3652. GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff);
  3653. GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff);
  3654. GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff);
  3655. GuiSetStyle(DEFAULT, BORDER_WIDTH, 1);
  3656. GuiSetStyle(DEFAULT, TEXT_PADDING, 0);
  3657. GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3658. // Initialize default extended property values
  3659. // NOTE: By default, extended property values are initialized to 0
  3660. GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls
  3661. GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls
  3662. GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property
  3663. GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
  3664. GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines
  3665. GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds
  3666. // Initialize control-specific property values
  3667. // NOTE: Those properties are in default list but require specific values by control type
  3668. GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3669. GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
  3670. GuiSetStyle(SLIDER, TEXT_PADDING, 4);
  3671. GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4);
  3672. GuiSetStyle(CHECKBOX, TEXT_PADDING, 4);
  3673. GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT);
  3674. GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0);
  3675. GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3676. GuiSetStyle(TEXTBOX, TEXT_PADDING, 4);
  3677. GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3678. GuiSetStyle(VALUEBOX, TEXT_PADDING, 0);
  3679. GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3680. GuiSetStyle(SPINNER, TEXT_PADDING, 0);
  3681. GuiSetStyle(SPINNER, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3682. GuiSetStyle(STATUSBAR, TEXT_PADDING, 8);
  3683. GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3684. // Initialize extended property values
  3685. // NOTE: By default, extended property values are initialized to 0
  3686. GuiSetStyle(TOGGLE, GROUP_PADDING, 2);
  3687. GuiSetStyle(SLIDER, SLIDER_WIDTH, 16);
  3688. GuiSetStyle(SLIDER, SLIDER_PADDING, 1);
  3689. GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1);
  3690. GuiSetStyle(CHECKBOX, CHECK_PADDING, 1);
  3691. GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32);
  3692. GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2);
  3693. GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
  3694. GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2);
  3695. GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24);
  3696. GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2);
  3697. GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
  3698. GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
  3699. GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6);
  3700. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0);
  3701. GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16);
  3702. GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0);
  3703. GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12);
  3704. GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28);
  3705. GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2);
  3706. GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12);
  3707. GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE);
  3708. GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8);
  3709. GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16);
  3710. GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8);
  3711. GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8);
  3712. GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2);
  3713. if (guiFont.texture.id != GetFontDefault().texture.id)
  3714. {
  3715. // Unload previous font texture
  3716. UnloadTexture(guiFont.texture);
  3717. RL_FREE(guiFont.recs);
  3718. RL_FREE(guiFont.glyphs);
  3719. guiFont.recs = NULL;
  3720. guiFont.glyphs = NULL;
  3721. // Setup default raylib font
  3722. guiFont = GetFontDefault();
  3723. // NOTE: Default raylib font character 95 is a white square
  3724. Rectangle whiteChar = guiFont.recs[95];
  3725. // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
  3726. SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 });
  3727. }
  3728. }
  3729. // Get text with icon id prepended
  3730. // NOTE: Useful to add icons by name id (enum) instead of
  3731. // a number that can change between ricon versions
  3732. const char *GuiIconText(int iconId, const char *text)
  3733. {
  3734. #if defined(RAYGUI_NO_ICONS)
  3735. return NULL;
  3736. #else
  3737. static char buffer[1024] = { 0 };
  3738. static char iconBuffer[16] = { 0 };
  3739. if (text != NULL)
  3740. {
  3741. memset(buffer, 0, 1024);
  3742. sprintf(buffer, "#%03i#", iconId);
  3743. for (int i = 5; i < 1024; i++)
  3744. {
  3745. buffer[i] = text[i - 5];
  3746. if (text[i - 5] == '\0') break;
  3747. }
  3748. return buffer;
  3749. }
  3750. else
  3751. {
  3752. sprintf(iconBuffer, "#%03i#", iconId);
  3753. return iconBuffer;
  3754. }
  3755. #endif
  3756. }
  3757. #if !defined(RAYGUI_NO_ICONS)
  3758. // Get full icons data pointer
  3759. unsigned int *GuiGetIcons(void) { return guiIconsPtr; }
  3760. // Load raygui icons file (.rgi)
  3761. // NOTE: In case nameIds are required, they can be requested with loadIconsName,
  3762. // they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH],
  3763. // WARNING: guiIconsName[]][] memory should be manually freed!
  3764. char **GuiLoadIcons(const char *fileName, bool loadIconsName)
  3765. {
  3766. // Style File Structure (.rgi)
  3767. // ------------------------------------------------------
  3768. // Offset | Size | Type | Description
  3769. // ------------------------------------------------------
  3770. // 0 | 4 | char | Signature: "rGI "
  3771. // 4 | 2 | short | Version: 100
  3772. // 6 | 2 | short | reserved
  3773. // 8 | 2 | short | Num icons (N)
  3774. // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S)
  3775. // Icons name id (32 bytes per name id)
  3776. // foreach (icon)
  3777. // {
  3778. // 12+32*i | 32 | char | Icon NameId
  3779. // }
  3780. // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size)
  3781. // S*S pixels/32bit per unsigned int = K unsigned int per icon
  3782. // foreach (icon)
  3783. // {
  3784. // ... | K | unsigned int | Icon Data
  3785. // }
  3786. FILE *rgiFile = fopen(fileName, "rb");
  3787. char **guiIconsName = NULL;
  3788. if (rgiFile != NULL)
  3789. {
  3790. char signature[5] = { 0 };
  3791. short version = 0;
  3792. short reserved = 0;
  3793. short iconCount = 0;
  3794. short iconSize = 0;
  3795. fread(signature, 1, 4, rgiFile);
  3796. fread(&version, sizeof(short), 1, rgiFile);
  3797. fread(&reserved, sizeof(short), 1, rgiFile);
  3798. fread(&iconCount, sizeof(short), 1, rgiFile);
  3799. fread(&iconSize, sizeof(short), 1, rgiFile);
  3800. if ((signature[0] == 'r') &&
  3801. (signature[1] == 'G') &&
  3802. (signature[2] == 'I') &&
  3803. (signature[3] == ' '))
  3804. {
  3805. if (loadIconsName)
  3806. {
  3807. guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **));
  3808. for (int i = 0; i < iconCount; i++)
  3809. {
  3810. guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH);
  3811. fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile);
  3812. }
  3813. }
  3814. else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR);
  3815. // Read icons data directly over internal icons array
  3816. fread(guiIconsPtr, sizeof(unsigned int), iconCount*(iconSize*iconSize/32), rgiFile);
  3817. }
  3818. fclose(rgiFile);
  3819. }
  3820. return guiIconsName;
  3821. }
  3822. // Draw selected icon using rectangles pixel-by-pixel
  3823. void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
  3824. {
  3825. #define BIT_CHECK(a,b) ((a) & (1u<<(b)))
  3826. for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++)
  3827. {
  3828. for (int k = 0; k < 32; k++)
  3829. {
  3830. if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k))
  3831. {
  3832. #if !defined(RAYGUI_STANDALONE)
  3833. GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color);
  3834. #endif
  3835. }
  3836. if ((k == 15) || (k == 31)) y++;
  3837. }
  3838. }
  3839. }
  3840. // Set icon drawing size
  3841. void GuiSetIconScale(int scale)
  3842. {
  3843. if (scale >= 1) guiIconScale = scale;
  3844. }
  3845. #endif // !RAYGUI_NO_ICONS
  3846. //----------------------------------------------------------------------------------
  3847. // Module specific Functions Definition
  3848. //----------------------------------------------------------------------------------
  3849. // Load style from memory
  3850. // WARNING: Binary files only
  3851. static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
  3852. {
  3853. unsigned char *fileDataPtr = (unsigned char *)fileData;
  3854. char signature[5] = { 0 };
  3855. short version = 0;
  3856. short reserved = 0;
  3857. int propertyCount = 0;
  3858. memcpy(signature, fileDataPtr, 4);
  3859. memcpy(&version, fileDataPtr + 4, sizeof(short));
  3860. memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short));
  3861. memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int));
  3862. fileDataPtr += 12;
  3863. if ((signature[0] == 'r') &&
  3864. (signature[1] == 'G') &&
  3865. (signature[2] == 'S') &&
  3866. (signature[3] == ' '))
  3867. {
  3868. short controlId = 0;
  3869. short propertyId = 0;
  3870. unsigned int propertyValue = 0;
  3871. for (int i = 0; i < propertyCount; i++)
  3872. {
  3873. memcpy(&controlId, fileDataPtr, sizeof(short));
  3874. memcpy(&propertyId, fileDataPtr + 2, sizeof(short));
  3875. memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int));
  3876. fileDataPtr += 8;
  3877. if (controlId == 0) // DEFAULT control
  3878. {
  3879. // If a DEFAULT property is loaded, it is propagated to all controls
  3880. // NOTE: All DEFAULT properties should be defined first in the file
  3881. GuiSetStyle(0, (int)propertyId, propertyValue);
  3882. if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue);
  3883. }
  3884. else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);
  3885. }
  3886. // Font loading is highly dependant on raylib API to load font data and image
  3887. #if !defined(RAYGUI_STANDALONE)
  3888. // Load custom font if available
  3889. int fontDataSize = 0;
  3890. memcpy(&fontDataSize, fileDataPtr, sizeof(int));
  3891. fileDataPtr += 4;
  3892. if (fontDataSize > 0)
  3893. {
  3894. Font font = { 0 };
  3895. int fontType = 0; // 0-Normal, 1-SDF
  3896. memcpy(&font.baseSize, fileDataPtr, sizeof(int));
  3897. memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int));
  3898. memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int));
  3899. fileDataPtr += 12;
  3900. // Load font white rectangle
  3901. Rectangle fontWhiteRec = { 0 };
  3902. memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle));
  3903. fileDataPtr += 16;
  3904. // Load font image parameters
  3905. int fontImageUncompSize = 0;
  3906. int fontImageCompSize = 0;
  3907. memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int));
  3908. memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int));
  3909. fileDataPtr += 8;
  3910. Image imFont = { 0 };
  3911. imFont.mipmaps = 1;
  3912. memcpy(&imFont.width, fileDataPtr, sizeof(int));
  3913. memcpy(&imFont.height, fileDataPtr + 4, sizeof(int));
  3914. memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int));
  3915. fileDataPtr += 12;
  3916. if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize))
  3917. {
  3918. // Compressed font atlas image data (DEFLATE), it requires DecompressData()
  3919. int dataUncompSize = 0;
  3920. unsigned char *compData = (unsigned char *)RAYGUI_MALLOC(fontImageCompSize);
  3921. memcpy(compData, fileDataPtr, fontImageCompSize);
  3922. fileDataPtr += fontImageCompSize;
  3923. imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize);
  3924. // Security check, dataUncompSize must match the provided fontImageUncompSize
  3925. if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted");
  3926. RAYGUI_FREE(compData);
  3927. }
  3928. else
  3929. {
  3930. // Font atlas image data is not compressed
  3931. imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageUncompSize);
  3932. memcpy(imFont.data, fileDataPtr, fontImageUncompSize);
  3933. fileDataPtr += fontImageUncompSize;
  3934. }
  3935. if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
  3936. font.texture = LoadTextureFromImage(imFont);
  3937. RAYGUI_FREE(imFont.data);
  3938. // Validate font atlas texture was loaded correctly
  3939. if (font.texture.id != 0)
  3940. {
  3941. // Load font recs data
  3942. int recsDataSize = font.glyphCount*sizeof(Rectangle);
  3943. int recsDataCompressedSize = 0;
  3944. // WARNING: Version 400 adds the compression size parameter
  3945. if (version >= 400)
  3946. {
  3947. // RGS files version 400 support compressed recs data
  3948. memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int));
  3949. fileDataPtr += sizeof(int);
  3950. }
  3951. if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize))
  3952. {
  3953. // Recs data is compressed, uncompress it
  3954. unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_MALLOC(recsDataCompressedSize);
  3955. memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize);
  3956. fileDataPtr += recsDataCompressedSize;
  3957. int recsDataUncompSize = 0;
  3958. font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize);
  3959. // Security check, data uncompressed size must match the expected original data size
  3960. if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted");
  3961. RAYGUI_FREE(recsDataCompressed);
  3962. }
  3963. else
  3964. {
  3965. // Recs data is uncompressed
  3966. font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
  3967. for (int i = 0; i < font.glyphCount; i++)
  3968. {
  3969. memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle));
  3970. fileDataPtr += sizeof(Rectangle);
  3971. }
  3972. }
  3973. // Load font glyphs info data
  3974. int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph
  3975. int glyphsDataCompressedSize = 0;
  3976. // WARNING: Version 400 adds the compression size parameter
  3977. if (version >= 400)
  3978. {
  3979. // RGS files version 400 support compressed glyphs data
  3980. memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int));
  3981. fileDataPtr += sizeof(int);
  3982. }
  3983. // Allocate required glyphs space to fill with data
  3984. font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
  3985. if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize))
  3986. {
  3987. // Glyphs data is compressed, uncompress it
  3988. unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_MALLOC(glyphsDataCompressedSize);
  3989. memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize);
  3990. fileDataPtr += glyphsDataCompressedSize;
  3991. int glyphsDataUncompSize = 0;
  3992. unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize);
  3993. // Security check, data uncompressed size must match the expected original data size
  3994. if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted");
  3995. unsigned char *glyphsDataUncompPtr = glyphsDataUncomp;
  3996. for (int i = 0; i < font.glyphCount; i++)
  3997. {
  3998. memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int));
  3999. memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int));
  4000. memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int));
  4001. memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int));
  4002. glyphsDataUncompPtr += 16;
  4003. }
  4004. RAYGUI_FREE(glypsDataCompressed);
  4005. RAYGUI_FREE(glyphsDataUncomp);
  4006. }
  4007. else
  4008. {
  4009. // Glyphs data is uncompressed
  4010. for (int i = 0; i < font.glyphCount; i++)
  4011. {
  4012. memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int));
  4013. memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int));
  4014. memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int));
  4015. memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int));
  4016. fileDataPtr += 16;
  4017. }
  4018. }
  4019. }
  4020. else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture
  4021. GuiSetFont(font);
  4022. // Set font texture source rectangle to be used as white texture to draw shapes
  4023. // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call
  4024. if ((fontWhiteRec.x > 0) &&
  4025. (fontWhiteRec.y > 0) &&
  4026. (fontWhiteRec.width > 0) &&
  4027. (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec);
  4028. }
  4029. #endif
  4030. }
  4031. }
  4032. // Gui get text width considering icon
  4033. static int GetTextWidth(const char *text)
  4034. {
  4035. #if !defined(ICON_TEXT_PADDING)
  4036. #define ICON_TEXT_PADDING 4
  4037. #endif
  4038. Vector2 textSize = { 0 };
  4039. int textIconOffset = 0;
  4040. if ((text != NULL) && (text[0] != '\0'))
  4041. {
  4042. if (text[0] == '#')
  4043. {
  4044. for (int i = 1; (i < 5) && (text[i] != '\0'); i++)
  4045. {
  4046. if (text[i] == '#')
  4047. {
  4048. textIconOffset = i;
  4049. break;
  4050. }
  4051. }
  4052. }
  4053. text += textIconOffset;
  4054. // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly
  4055. float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  4056. // Custom MeasureText() implementation
  4057. if ((guiFont.texture.id > 0) && (text != NULL))
  4058. {
  4059. // Get size in bytes of text, considering end of line and line break
  4060. int size = 0;
  4061. for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++)
  4062. {
  4063. if ((text[i] != '\0') && (text[i] != '\n')) size++;
  4064. else break;
  4065. }
  4066. float scaleFactor = fontSize/(float)guiFont.baseSize;
  4067. textSize.y = (float)guiFont.baseSize*scaleFactor;
  4068. float glyphWidth = 0.0f;
  4069. for (int i = 0, codepointSize = 0; i < size; i += codepointSize)
  4070. {
  4071. int codepoint = GetCodepointNext(&text[i], &codepointSize);
  4072. int codepointIndex = GetGlyphIndex(guiFont, codepoint);
  4073. if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
  4074. else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
  4075. textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4076. }
  4077. }
  4078. if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING);
  4079. }
  4080. return (int)textSize.x;
  4081. }
  4082. // Get text bounds considering control bounds
  4083. static Rectangle GetTextBounds(int control, Rectangle bounds)
  4084. {
  4085. Rectangle textBounds = bounds;
  4086. textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
  4087. textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING);
  4088. textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
  4089. textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line!
  4090. // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds
  4091. switch (control)
  4092. {
  4093. case COMBOBOX:
  4094. case DROPDOWNBOX:
  4095. case LISTVIEW:
  4096. // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW
  4097. case SLIDER:
  4098. case CHECKBOX:
  4099. case VALUEBOX:
  4100. case SPINNER:
  4101. // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER
  4102. default:
  4103. {
  4104. // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText()
  4105. if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING);
  4106. else textBounds.x += GuiGetStyle(control, TEXT_PADDING);
  4107. }
  4108. break;
  4109. }
  4110. return textBounds;
  4111. }
  4112. // Get text icon if provided and move text cursor
  4113. // NOTE: We support up to 999 values for iconId
  4114. static const char *GetTextIcon(const char *text, int *iconId)
  4115. {
  4116. #if !defined(RAYGUI_NO_ICONS)
  4117. *iconId = -1;
  4118. if (text[0] == '#') // Maybe we have an icon!
  4119. {
  4120. char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0'
  4121. int pos = 1;
  4122. while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9'))
  4123. {
  4124. iconValue[pos - 1] = text[pos];
  4125. pos++;
  4126. }
  4127. if (text[pos] == '#')
  4128. {
  4129. *iconId = TextToInteger(iconValue);
  4130. // Move text pointer after icon
  4131. // WARNING: If only icon provided, it could point to EOL character: '\0'
  4132. if (*iconId >= 0) text += (pos + 1);
  4133. }
  4134. }
  4135. #endif
  4136. return text;
  4137. }
  4138. // Get text divided into lines (by line-breaks '\n')
  4139. const char **GetTextLines(const char *text, int *count)
  4140. {
  4141. #define RAYGUI_MAX_TEXT_LINES 128
  4142. static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
  4143. for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
  4144. int textSize = (int)strlen(text);
  4145. lines[0] = text;
  4146. int len = 0;
  4147. *count = 1;
  4148. //int lineSize = 0; // Stores current line size, not returned
  4149. for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
  4150. {
  4151. if (text[i] == '\n')
  4152. {
  4153. //lineSize = len;
  4154. k++;
  4155. lines[k] = &text[i + 1]; // WARNING: next value is valid?
  4156. len = 0;
  4157. *count += 1;
  4158. }
  4159. else len++;
  4160. }
  4161. //lines[*count - 1].size = len;
  4162. return lines;
  4163. }
  4164. // Get text width to next space for provided string
  4165. static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex)
  4166. {
  4167. float width = 0;
  4168. int codepointByteCount = 0;
  4169. int codepoint = 0;
  4170. int index = 0;
  4171. float glyphWidth = 0;
  4172. float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
  4173. for (int i = 0; text[i] != '\0'; i++)
  4174. {
  4175. if (text[i] != ' ')
  4176. {
  4177. codepoint = GetCodepoint(&text[i], &codepointByteCount);
  4178. index = GetGlyphIndex(guiFont, codepoint);
  4179. glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor;
  4180. width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4181. }
  4182. else
  4183. {
  4184. *nextSpaceIndex = i;
  4185. break;
  4186. }
  4187. }
  4188. return width;
  4189. }
  4190. // Gui draw text using default font
  4191. static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint)
  4192. {
  4193. #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect
  4194. #if !defined(ICON_TEXT_PADDING)
  4195. #define ICON_TEXT_PADDING 4
  4196. #endif
  4197. if ((text == NULL) || (text[0] == '\0')) return; // Security check
  4198. // PROCEDURE:
  4199. // - Text is processed line per line
  4200. // - For every line, horizontal alignment is defined
  4201. // - For all text, vertical alignment is defined (multiline text only)
  4202. // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only)
  4203. // Get text lines (using '\n' as delimiter) to be processed individually
  4204. // WARNING: We can't use GuiTextSplit() function because it can be already used
  4205. // before the GuiDrawText() call and its buffer is static, it would be overriden :(
  4206. int lineCount = 0;
  4207. const char **lines = GetTextLines(text, &lineCount);
  4208. // Text style variables
  4209. //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
  4210. int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL);
  4211. int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing
  4212. // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap
  4213. float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2);
  4214. float posOffsetY = 0.0f;
  4215. for (int i = 0; i < lineCount; i++)
  4216. {
  4217. int iconId = 0;
  4218. lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor
  4219. // Get text position depending on alignment and iconId
  4220. //---------------------------------------------------------------------------------
  4221. Vector2 textBoundsPosition = { textBounds.x, textBounds.y };
  4222. float textBoundsWidthOffset = 0.0f;
  4223. // NOTE: We get text size after icon has been processed
  4224. // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?
  4225. int textSizeX = GetTextWidth(lines[i]);
  4226. // If text requires an icon, add size to measure
  4227. if (iconId >= 0)
  4228. {
  4229. textSizeX += RAYGUI_ICON_SIZE*guiIconScale;
  4230. // WARNING: If only icon provided, text could be pointing to EOF character: '\0'
  4231. #if !defined(RAYGUI_NO_ICONS)
  4232. if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING;
  4233. #endif
  4234. }
  4235. // Check guiTextAlign global variables
  4236. switch (alignment)
  4237. {
  4238. case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break;
  4239. case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break;
  4240. case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break;
  4241. default: break;
  4242. }
  4243. if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x;
  4244. switch (alignmentVertical)
  4245. {
  4246. // Only valid in case of wordWrap = 0;
  4247. case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break;
  4248. case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
  4249. case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
  4250. default: break;
  4251. }
  4252. // NOTE: Make sure we get pixel-perfect coordinates,
  4253. // In case of decimals we got weird text positioning
  4254. textBoundsPosition.x = (float)((int)textBoundsPosition.x);
  4255. textBoundsPosition.y = (float)((int)textBoundsPosition.y);
  4256. //---------------------------------------------------------------------------------
  4257. // Draw text (with icon if available)
  4258. //---------------------------------------------------------------------------------
  4259. #if !defined(RAYGUI_NO_ICONS)
  4260. if (iconId >= 0)
  4261. {
  4262. // NOTE: We consider icon height, probably different than text size
  4263. GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);
  4264. textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
  4265. textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
  4266. }
  4267. #endif
  4268. // Get size in bytes of text,
  4269. // considering end of line and line break
  4270. int lineSize = 0;
  4271. for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ }
  4272. float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
  4273. int lastSpaceIndex = 0;
  4274. bool tempWrapCharMode = false;
  4275. int textOffsetY = 0;
  4276. float textOffsetX = 0.0f;
  4277. float glyphWidth = 0;
  4278. int ellipsisWidth = GetTextWidth("...");
  4279. bool textOverflow = false;
  4280. for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize)
  4281. {
  4282. int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
  4283. int index = GetGlyphIndex(guiFont, codepoint);
  4284. // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
  4285. // but we need to draw all of the bad bytes using the '?' symbol moving one byte
  4286. if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size
  4287. // Get glyph width to check if it goes out of bounds
  4288. if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);
  4289. else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;
  4290. // Wrap mode text measuring, to validate if
  4291. // it can be drawn or a new line is required
  4292. if (wrapMode == TEXT_WRAP_CHAR)
  4293. {
  4294. // Jump to next line if current character reach end of the box limits
  4295. if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset)
  4296. {
  4297. textOffsetX = 0.0f;
  4298. textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
  4299. if (tempWrapCharMode) // Wrap at char level when too long words
  4300. {
  4301. wrapMode = TEXT_WRAP_WORD;
  4302. tempWrapCharMode = false;
  4303. }
  4304. }
  4305. }
  4306. else if (wrapMode == TEXT_WRAP_WORD)
  4307. {
  4308. if (codepoint == 32) lastSpaceIndex = c;
  4309. // Get width to next space in line
  4310. int nextSpaceIndex = 0;
  4311. float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex);
  4312. int nextSpaceIndex2 = 0;
  4313. float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2);
  4314. if (nextWordSize > textBounds.width - textBoundsWidthOffset)
  4315. {
  4316. // Considering the case the next word is longer than bounds
  4317. tempWrapCharMode = true;
  4318. wrapMode = TEXT_WRAP_CHAR;
  4319. }
  4320. else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset)
  4321. {
  4322. textOffsetX = 0.0f;
  4323. textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
  4324. }
  4325. }
  4326. if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
  4327. else
  4328. {
  4329. // TODO: There are multiple types of spaces in Unicode,
  4330. // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html
  4331. if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph
  4332. {
  4333. if (wrapMode == TEXT_WRAP_NONE)
  4334. {
  4335. // Draw only required text glyphs fitting the textBounds.width
  4336. if (textSizeX > textBounds.width)
  4337. {
  4338. if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth))
  4339. {
  4340. DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
  4341. }
  4342. else if (!textOverflow)
  4343. {
  4344. textOverflow = true;
  4345. for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3)
  4346. {
  4347. DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
  4348. }
  4349. }
  4350. }
  4351. else
  4352. {
  4353. DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
  4354. }
  4355. }
  4356. else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD))
  4357. {
  4358. // Draw only glyphs inside the bounds
  4359. if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE)))
  4360. {
  4361. DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
  4362. }
  4363. }
  4364. }
  4365. if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4366. else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4367. }
  4368. }
  4369. if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
  4370. else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING));
  4371. //---------------------------------------------------------------------------------
  4372. }
  4373. #if defined(RAYGUI_DEBUG_TEXT_BOUNDS)
  4374. GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f));
  4375. #endif
  4376. }
  4377. // Gui draw rectangle using default raygui plain style with borders
  4378. static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color)
  4379. {
  4380. if (color.a > 0)
  4381. {
  4382. // Draw rectangle filled with color
  4383. DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha));
  4384. }
  4385. if (borderWidth > 0)
  4386. {
  4387. // Draw rectangle border lines with color
  4388. DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
  4389. DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
  4390. DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
  4391. DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
  4392. }
  4393. #if defined(RAYGUI_DEBUG_RECS_BOUNDS)
  4394. DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f));
  4395. #endif
  4396. }
  4397. // Draw tooltip using control bounds
  4398. static void GuiTooltip(Rectangle controlRec)
  4399. {
  4400. if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode)
  4401. {
  4402. Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4403. if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width);
  4404. GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, NULL);
  4405. int textPadding = GuiGetStyle(LABEL, TEXT_PADDING);
  4406. int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
  4407. GuiSetStyle(LABEL, TEXT_PADDING, 0);
  4408. GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  4409. GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, guiTooltipPtr);
  4410. GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment);
  4411. GuiSetStyle(LABEL, TEXT_PADDING, textPadding);
  4412. }
  4413. }
  4414. // Split controls text into multiple strings
  4415. // Also check for multiple columns (required by GuiToggleGroup())
  4416. static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
  4417. {
  4418. // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
  4419. // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
  4420. // all used memory is static... it has some limitations:
  4421. // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
  4422. // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
  4423. // NOTE: Those definitions could be externally provided if required
  4424. // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user
  4425. // textRow is an externally provided array of integers that stores row number for every splitted string
  4426. #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
  4427. #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
  4428. #endif
  4429. #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
  4430. #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
  4431. #endif
  4432. static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
  4433. static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
  4434. memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
  4435. result[0] = buffer;
  4436. int counter = 1;
  4437. if (textRow != NULL) textRow[0] = 0;
  4438. // Count how many substrings we have on text and point to every one
  4439. for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
  4440. {
  4441. buffer[i] = text[i];
  4442. if (buffer[i] == '\0') break;
  4443. else if ((buffer[i] == delimiter) || (buffer[i] == '\n'))
  4444. {
  4445. result[counter] = buffer + i + 1;
  4446. if (textRow != NULL)
  4447. {
  4448. if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1;
  4449. else textRow[counter] = textRow[counter - 1];
  4450. }
  4451. buffer[i] = '\0'; // Set an end of string at this point
  4452. counter++;
  4453. if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
  4454. }
  4455. }
  4456. *count = counter;
  4457. return result;
  4458. }
  4459. // Convert color data from RGB to HSV
  4460. // NOTE: Color data should be passed normalized
  4461. static Vector3 ConvertRGBtoHSV(Vector3 rgb)
  4462. {
  4463. Vector3 hsv = { 0 };
  4464. float min = 0.0f;
  4465. float max = 0.0f;
  4466. float delta = 0.0f;
  4467. min = (rgb.x < rgb.y)? rgb.x : rgb.y;
  4468. min = (min < rgb.z)? min : rgb.z;
  4469. max = (rgb.x > rgb.y)? rgb.x : rgb.y;
  4470. max = (max > rgb.z)? max : rgb.z;
  4471. hsv.z = max; // Value
  4472. delta = max - min;
  4473. if (delta < 0.00001f)
  4474. {
  4475. hsv.y = 0.0f;
  4476. hsv.x = 0.0f; // Undefined, maybe NAN?
  4477. return hsv;
  4478. }
  4479. if (max > 0.0f)
  4480. {
  4481. // NOTE: If max is 0, this divide would cause a crash
  4482. hsv.y = (delta/max); // Saturation
  4483. }
  4484. else
  4485. {
  4486. // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
  4487. hsv.y = 0.0f;
  4488. hsv.x = 0.0f; // Undefined, maybe NAN?
  4489. return hsv;
  4490. }
  4491. // NOTE: Comparing float values could not work properly
  4492. if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
  4493. else
  4494. {
  4495. if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
  4496. else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
  4497. }
  4498. hsv.x *= 60.0f; // Convert to degrees
  4499. if (hsv.x < 0.0f) hsv.x += 360.0f;
  4500. return hsv;
  4501. }
  4502. // Convert color data from HSV to RGB
  4503. // NOTE: Color data should be passed normalized
  4504. static Vector3 ConvertHSVtoRGB(Vector3 hsv)
  4505. {
  4506. Vector3 rgb = { 0 };
  4507. float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
  4508. long i = 0;
  4509. // NOTE: Comparing float values could not work properly
  4510. if (hsv.y <= 0.0f)
  4511. {
  4512. rgb.x = hsv.z;
  4513. rgb.y = hsv.z;
  4514. rgb.z = hsv.z;
  4515. return rgb;
  4516. }
  4517. hh = hsv.x;
  4518. if (hh >= 360.0f) hh = 0.0f;
  4519. hh /= 60.0f;
  4520. i = (long)hh;
  4521. ff = hh - i;
  4522. p = hsv.z*(1.0f - hsv.y);
  4523. q = hsv.z*(1.0f - (hsv.y*ff));
  4524. t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
  4525. switch (i)
  4526. {
  4527. case 0:
  4528. {
  4529. rgb.x = hsv.z;
  4530. rgb.y = t;
  4531. rgb.z = p;
  4532. } break;
  4533. case 1:
  4534. {
  4535. rgb.x = q;
  4536. rgb.y = hsv.z;
  4537. rgb.z = p;
  4538. } break;
  4539. case 2:
  4540. {
  4541. rgb.x = p;
  4542. rgb.y = hsv.z;
  4543. rgb.z = t;
  4544. } break;
  4545. case 3:
  4546. {
  4547. rgb.x = p;
  4548. rgb.y = q;
  4549. rgb.z = hsv.z;
  4550. } break;
  4551. case 4:
  4552. {
  4553. rgb.x = t;
  4554. rgb.y = p;
  4555. rgb.z = hsv.z;
  4556. } break;
  4557. case 5:
  4558. default:
  4559. {
  4560. rgb.x = hsv.z;
  4561. rgb.y = p;
  4562. rgb.z = q;
  4563. } break;
  4564. }
  4565. return rgb;
  4566. }
  4567. // Scroll bar control (used by GuiScrollPanel())
  4568. static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
  4569. {
  4570. GuiState state = guiState;
  4571. // Is the scrollbar horizontal or vertical?
  4572. bool isVertical = (bounds.width > bounds.height)? false : true;
  4573. // The size (width or height depending on scrollbar type) of the spinner buttons
  4574. const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)?
  4575. (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) :
  4576. (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0;
  4577. // Arrow buttons [<] [>] [∧] [∨]
  4578. Rectangle arrowUpLeft = { 0 };
  4579. Rectangle arrowDownRight = { 0 };
  4580. // Actual area of the scrollbar excluding the arrow buttons
  4581. Rectangle scrollbar = { 0 };
  4582. // Slider bar that moves --[///]-----
  4583. Rectangle slider = { 0 };
  4584. // Normalize value
  4585. if (value > maxValue) value = maxValue;
  4586. if (value < minValue) value = minValue;
  4587. int valueRange = maxValue - minValue;
  4588. if (valueRange <= 0) valueRange = 1;
  4589. int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
  4590. if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size
  4591. // Calculate rectangles for all of the components
  4592. arrowUpLeft = RAYGUI_CLITERAL(Rectangle){
  4593. (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH),
  4594. (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH),
  4595. (float)spinnerSize, (float)spinnerSize };
  4596. if (isVertical)
  4597. {
  4598. arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize };
  4599. scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) };
  4600. // Make sure the slider won't get outside of the scrollbar
  4601. sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize;
  4602. slider = RAYGUI_CLITERAL(Rectangle){
  4603. bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING),
  4604. scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)),
  4605. bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)),
  4606. (float)sliderSize };
  4607. }
  4608. else // horizontal
  4609. {
  4610. arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize };
  4611. scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) };
  4612. // Make sure the slider won't get outside of the scrollbar
  4613. sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize;
  4614. slider = RAYGUI_CLITERAL(Rectangle){
  4615. scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)),
  4616. bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING),
  4617. (float)sliderSize,
  4618. bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) };
  4619. }
  4620. // Update control
  4621. //--------------------------------------------------------------------
  4622. if ((state != STATE_DISABLED) && !guiLocked)
  4623. {
  4624. Vector2 mousePoint = GetMousePosition();
  4625. if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
  4626. {
  4627. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) &&
  4628. !CheckCollisionPointRec(mousePoint, arrowUpLeft) &&
  4629. !CheckCollisionPointRec(mousePoint, arrowDownRight))
  4630. {
  4631. if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
  4632. {
  4633. state = STATE_PRESSED;
  4634. if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue);
  4635. else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue);
  4636. }
  4637. }
  4638. else
  4639. {
  4640. guiControlExclusiveMode = false;
  4641. guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
  4642. }
  4643. }
  4644. else if (CheckCollisionPointRec(mousePoint, bounds))
  4645. {
  4646. state = STATE_FOCUSED;
  4647. // Handle mouse wheel
  4648. int wheel = (int)GetMouseWheelMove();
  4649. if (wheel != 0) value += wheel;
  4650. // Handle mouse button down
  4651. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  4652. {
  4653. guiControlExclusiveMode = true;
  4654. guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
  4655. // Check arrows click
  4656. if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  4657. else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  4658. else if (!CheckCollisionPointRec(mousePoint, slider))
  4659. {
  4660. // If click on scrollbar position but not on slider, place slider directly on that position
  4661. if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue);
  4662. else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue);
  4663. }
  4664. state = STATE_PRESSED;
  4665. }
  4666. // Keyboard control on mouse hover scrollbar
  4667. /*
  4668. if (isVertical)
  4669. {
  4670. if (IsKeyDown(KEY_DOWN)) value += 5;
  4671. else if (IsKeyDown(KEY_UP)) value -= 5;
  4672. }
  4673. else
  4674. {
  4675. if (IsKeyDown(KEY_RIGHT)) value += 5;
  4676. else if (IsKeyDown(KEY_LEFT)) value -= 5;
  4677. }
  4678. */
  4679. }
  4680. // Normalize value
  4681. if (value > maxValue) value = maxValue;
  4682. if (value < minValue) value = minValue;
  4683. }
  4684. //--------------------------------------------------------------------
  4685. // Draw control
  4686. //--------------------------------------------------------------------
  4687. GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background
  4688. GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background
  4689. GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar
  4690. // Draw arrows (using icon if available)
  4691. if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE))
  4692. {
  4693. #if defined(RAYGUI_NO_ICONS)
  4694. GuiDrawText(isVertical? "^" : "<",
  4695. RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4696. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
  4697. GuiDrawText(isVertical? "v" : ">",
  4698. RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4699. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
  4700. #else
  4701. GuiDrawText(isVertical? "#121#" : "#118#",
  4702. RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4703. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
  4704. GuiDrawText(isVertical? "#120#" : "#119#",
  4705. RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4706. TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
  4707. #endif
  4708. }
  4709. //--------------------------------------------------------------------
  4710. return value;
  4711. }
  4712. // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
  4713. // WARNING: It multiplies current alpha by alpha scale factor
  4714. static Color GuiFade(Color color, float alpha)
  4715. {
  4716. if (alpha < 0.0f) alpha = 0.0f;
  4717. else if (alpha > 1.0f) alpha = 1.0f;
  4718. Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) };
  4719. return result;
  4720. }
  4721. #if defined(RAYGUI_STANDALONE)
  4722. // Returns a Color struct from hexadecimal value
  4723. static Color GetColor(int hexValue)
  4724. {
  4725. Color color;
  4726. color.r = (unsigned char)(hexValue >> 24) & 0xFF;
  4727. color.g = (unsigned char)(hexValue >> 16) & 0xFF;
  4728. color.b = (unsigned char)(hexValue >> 8) & 0xFF;
  4729. color.a = (unsigned char)hexValue & 0xFF;
  4730. return color;
  4731. }
  4732. // Returns hexadecimal value for a Color
  4733. static int ColorToInt(Color color)
  4734. {
  4735. return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
  4736. }
  4737. // Check if point is inside rectangle
  4738. static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
  4739. {
  4740. bool collision = false;
  4741. if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) &&
  4742. (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
  4743. return collision;
  4744. }
  4745. // Formatting of text with variables to 'embed'
  4746. static const char *TextFormat(const char *text, ...)
  4747. {
  4748. #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE)
  4749. #define RAYGUI_TEXTFORMAT_MAX_SIZE 256
  4750. #endif
  4751. static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE];
  4752. va_list args;
  4753. va_start(args, text);
  4754. vsprintf(buffer, text, args);
  4755. va_end(args);
  4756. return buffer;
  4757. }
  4758. // Draw rectangle with vertical gradient fill color
  4759. // NOTE: This function is only used by GuiColorPicker()
  4760. static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
  4761. {
  4762. Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height };
  4763. DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
  4764. }
  4765. // Split string into multiple strings
  4766. const char **TextSplit(const char *text, char delimiter, int *count)
  4767. {
  4768. // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
  4769. // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
  4770. // all used memory is static... it has some limitations:
  4771. // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
  4772. // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
  4773. #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
  4774. #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
  4775. #endif
  4776. #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
  4777. #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
  4778. #endif
  4779. static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL };
  4780. static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 };
  4781. memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
  4782. result[0] = buffer;
  4783. int counter = 0;
  4784. if (text != NULL)
  4785. {
  4786. counter = 1;
  4787. // Count how many substrings we have on text and point to every one
  4788. for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
  4789. {
  4790. buffer[i] = text[i];
  4791. if (buffer[i] == '\0') break;
  4792. else if (buffer[i] == delimiter)
  4793. {
  4794. buffer[i] = '\0'; // Set an end of string at this point
  4795. result[counter] = buffer + i + 1;
  4796. counter++;
  4797. if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
  4798. }
  4799. }
  4800. }
  4801. *count = counter;
  4802. return result;
  4803. }
  4804. // Get integer value from text
  4805. // NOTE: This function replaces atoi() [stdlib.h]
  4806. static int TextToInteger(const char *text)
  4807. {
  4808. int value = 0;
  4809. int sign = 1;
  4810. if ((text[0] == '+') || (text[0] == '-'))
  4811. {
  4812. if (text[0] == '-') sign = -1;
  4813. text++;
  4814. }
  4815. for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0');
  4816. return value*sign;
  4817. }
  4818. // Get float value from text
  4819. // NOTE: This function replaces atof() [stdlib.h]
  4820. // WARNING: Only '.' character is understood as decimal point
  4821. static float TextToFloat(const char *text)
  4822. {
  4823. float value = 0.0f;
  4824. float sign = 1.0f;
  4825. if ((text[0] == '+') || (text[0] == '-'))
  4826. {
  4827. if (text[0] == '-') sign = -1.0f;
  4828. text++;
  4829. }
  4830. int i = 0;
  4831. for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
  4832. if (text[i++] != '.') value *= sign;
  4833. else
  4834. {
  4835. float divisor = 10.0f;
  4836. for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
  4837. {
  4838. value += ((float)(text[i] - '0'))/divisor;
  4839. divisor = divisor*10.0f;
  4840. }
  4841. }
  4842. return value;
  4843. }
  4844. // Encode codepoint into UTF-8 text (char array size returned as parameter)
  4845. static const char *CodepointToUTF8(int codepoint, int *byteSize)
  4846. {
  4847. static char utf8[6] = { 0 };
  4848. int size = 0;
  4849. if (codepoint <= 0x7f)
  4850. {
  4851. utf8[0] = (char)codepoint;
  4852. size = 1;
  4853. }
  4854. else if (codepoint <= 0x7ff)
  4855. {
  4856. utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
  4857. utf8[1] = (char)((codepoint & 0x3f) | 0x80);
  4858. size = 2;
  4859. }
  4860. else if (codepoint <= 0xffff)
  4861. {
  4862. utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
  4863. utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
  4864. utf8[2] = (char)((codepoint & 0x3f) | 0x80);
  4865. size = 3;
  4866. }
  4867. else if (codepoint <= 0x10ffff)
  4868. {
  4869. utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0);
  4870. utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
  4871. utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
  4872. utf8[3] = (char)((codepoint & 0x3f) | 0x80);
  4873. size = 4;
  4874. }
  4875. *byteSize = size;
  4876. return utf8;
  4877. }
  4878. // Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
  4879. // When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
  4880. // Total number of bytes processed are returned as a parameter
  4881. // NOTE: the standard says U+FFFD should be returned in case of errors
  4882. // but that character is not supported by the default font in raylib
  4883. static int GetCodepointNext(const char *text, int *codepointSize)
  4884. {
  4885. const char *ptr = text;
  4886. int codepoint = 0x3f; // Codepoint (defaults to '?')
  4887. *codepointSize = 1;
  4888. // Get current codepoint and bytes processed
  4889. if (0xf0 == (0xf8 & ptr[0]))
  4890. {
  4891. // 4 byte UTF-8 codepoint
  4892. if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
  4893. codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
  4894. *codepointSize = 4;
  4895. }
  4896. else if (0xe0 == (0xf0 & ptr[0]))
  4897. {
  4898. // 3 byte UTF-8 codepoint */
  4899. if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
  4900. codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
  4901. *codepointSize = 3;
  4902. }
  4903. else if (0xc0 == (0xe0 & ptr[0]))
  4904. {
  4905. // 2 byte UTF-8 codepoint
  4906. if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
  4907. codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
  4908. *codepointSize = 2;
  4909. }
  4910. else if (0x00 == (0x80 & ptr[0]))
  4911. {
  4912. // 1 byte UTF-8 codepoint
  4913. codepoint = ptr[0];
  4914. *codepointSize = 1;
  4915. }
  4916. return codepoint;
  4917. }
  4918. #endif // RAYGUI_STANDALONE
  4919. #endif // RAYGUI_IMPLEMENTATION