raygui.h 284 KB

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