raygui.h 272 KB

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