Window.cpp 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "DeviceContext.h"
  23. #include "Window.h"
  24. #include "UserInterfaceLocal.h"
  25. #include "EditWindow.h"
  26. #include "ChoiceWindow.h"
  27. #include "SliderWindow.h"
  28. #include "BindWindow.h"
  29. #include "ListWindow.h"
  30. #include "RenderWindow.h"
  31. #include "MarkerWindow.h"
  32. #include "FieldWindow.h"
  33. #include "GameSSDWindow.h"
  34. #include "GameBearShootWindow.h"
  35. #include "GameBustOutWindow.h"
  36. //
  37. // gui editor is more integrated into the window now
  38. #include "../tools/guied/GEWindowWrapper.h"
  39. bool idWindow::registerIsTemporary[MAX_EXPRESSION_REGISTERS]; // statics to assist during parsing
  40. //float idWindow::shaderRegisters[MAX_EXPRESSION_REGISTERS];
  41. //wexpOp_t idWindow::shaderOps[MAX_EXPRESSION_OPS];
  42. idCVar idWindow::gui_debug( "gui_debug", "0", CVAR_GUI | CVAR_BOOL, "" );
  43. idCVar idWindow::gui_edit( "gui_edit", "0", CVAR_GUI | CVAR_BOOL, "" );
  44. extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces
  45. // made RegisterVars a member of idWindow
  46. const idRegEntry idWindow::RegisterVars[] = {
  47. { "forecolor", idRegister::VEC4 },
  48. { "hovercolor", idRegister::VEC4 },
  49. { "backcolor", idRegister::VEC4 },
  50. { "bordercolor", idRegister::VEC4 },
  51. { "rect", idRegister::RECTANGLE },
  52. { "matcolor", idRegister::VEC4 },
  53. { "scale", idRegister::VEC2 },
  54. { "translate", idRegister::VEC2 },
  55. { "rotate", idRegister::FLOAT },
  56. { "textscale", idRegister::FLOAT },
  57. { "visible", idRegister::BOOL },
  58. { "noevents", idRegister::BOOL },
  59. { "text", idRegister::STRING },
  60. { "background", idRegister::STRING },
  61. { "runscript", idRegister::STRING },
  62. { "varbackground", idRegister::STRING },
  63. { "cvar", idRegister::STRING },
  64. { "choices", idRegister::STRING },
  65. { "choiceVar", idRegister::STRING },
  66. { "bind", idRegister::STRING },
  67. { "modelRotate", idRegister::VEC4 },
  68. { "modelOrigin", idRegister::VEC4 },
  69. { "lightOrigin", idRegister::VEC4 },
  70. { "lightColor", idRegister::VEC4 },
  71. { "viewOffset", idRegister::VEC4 },
  72. { "hideCursor", idRegister::BOOL}
  73. };
  74. const int idWindow::NumRegisterVars = sizeof(RegisterVars) / sizeof(idRegEntry);
  75. const char *idWindow::ScriptNames[] = {
  76. "onMouseEnter",
  77. "onMouseExit",
  78. "onAction",
  79. "onActivate",
  80. "onDeactivate",
  81. "onESC",
  82. "onEvent",
  83. "onTrigger",
  84. "onActionRelease",
  85. "onEnter",
  86. "onEnterRelease"
  87. };
  88. /*
  89. ================
  90. idWindow::CommonInit
  91. ================
  92. */
  93. void idWindow::CommonInit() {
  94. childID = 0;
  95. flags = 0;
  96. lastTimeRun = 0;
  97. origin.Zero();
  98. fontNum = 0;
  99. timeLine = -1;
  100. xOffset = yOffset = 0.0;
  101. cursor = 0;
  102. forceAspectWidth = 640;
  103. forceAspectHeight = 480;
  104. matScalex = 1;
  105. matScaley = 1;
  106. borderSize = 0;
  107. noTime = false;
  108. visible = true;
  109. textAlign = 0;
  110. textAlignx = 0;
  111. textAligny = 0;
  112. noEvents = false;
  113. rotate = 0;
  114. shear.Zero();
  115. textScale = 0.35f;
  116. backColor.Zero();
  117. foreColor = idVec4(1, 1, 1, 1);
  118. hoverColor = idVec4(1, 1, 1, 1);
  119. matColor = idVec4(1, 1, 1, 1);
  120. borderColor.Zero();
  121. background = NULL;
  122. backGroundName = "";
  123. focusedChild = NULL;
  124. captureChild = NULL;
  125. overChild = NULL;
  126. parent = NULL;
  127. saveOps = NULL;
  128. saveRegs = NULL;
  129. timeLine = -1;
  130. textShadow = 0;
  131. hover = false;
  132. for (int i = 0; i < SCRIPT_COUNT; i++) {
  133. scripts[i] = NULL;
  134. }
  135. hideCursor = false;
  136. }
  137. /*
  138. ================
  139. idWindow::Size
  140. ================
  141. */
  142. size_t idWindow::Size() {
  143. int c = children.Num();
  144. int sz = 0;
  145. for (int i = 0; i < c; i++) {
  146. sz += children[i]->Size();
  147. }
  148. sz += sizeof(*this) + Allocated();
  149. return sz;
  150. }
  151. /*
  152. ================
  153. idWindow::Allocated
  154. ================
  155. */
  156. size_t idWindow::Allocated() {
  157. int i, c;
  158. int sz = name.Allocated();
  159. sz += text.Size();
  160. sz += backGroundName.Size();
  161. c = definedVars.Num();
  162. for (i = 0; i < c; i++) {
  163. sz += definedVars[i]->Size();
  164. }
  165. for (i = 0; i < SCRIPT_COUNT; i++) {
  166. if (scripts[i]) {
  167. sz += scripts[i]->Size();
  168. }
  169. }
  170. c = timeLineEvents.Num();
  171. for (i = 0; i < c; i++) {
  172. sz += timeLineEvents[i]->Size();
  173. }
  174. c = namedEvents.Num();
  175. for (i = 0; i < c; i++) {
  176. sz += namedEvents[i]->Size();
  177. }
  178. c = drawWindows.Num();
  179. for (i = 0; i < c; i++) {
  180. if (drawWindows[i].simp) {
  181. sz += drawWindows[i].simp->Size();
  182. }
  183. }
  184. return sz;
  185. }
  186. /*
  187. ================
  188. idWindow::idWindow
  189. ================
  190. */
  191. idWindow::idWindow(idUserInterfaceLocal *ui) {
  192. dc = NULL;
  193. gui = ui;
  194. CommonInit();
  195. }
  196. /*
  197. ================
  198. idWindow::idWindow
  199. ================
  200. */
  201. idWindow::idWindow(idDeviceContext *d, idUserInterfaceLocal *ui) {
  202. dc = d;
  203. gui = ui;
  204. CommonInit();
  205. }
  206. /*
  207. ================
  208. idWindow::CleanUp
  209. ================
  210. */
  211. void idWindow::CleanUp() {
  212. int i, c = drawWindows.Num();
  213. for (i = 0; i < c; i++) {
  214. delete drawWindows[i].simp;
  215. }
  216. // ensure the register list gets cleaned up
  217. regList.Reset ( );
  218. // Cleanup the named events
  219. namedEvents.DeleteContents(true);
  220. drawWindows.Clear();
  221. children.DeleteContents(true);
  222. definedVars.DeleteContents(true);
  223. timeLineEvents.DeleteContents(true);
  224. for (i = 0; i < SCRIPT_COUNT; i++) {
  225. delete scripts[i];
  226. }
  227. CommonInit();
  228. }
  229. /*
  230. ================
  231. idWindow::~idWindow
  232. ================
  233. */
  234. idWindow::~idWindow() {
  235. CleanUp();
  236. }
  237. /*
  238. ================
  239. idWindow::Move
  240. ================
  241. */
  242. void idWindow::Move(float x, float y) {
  243. idRectangle rct = rect;
  244. rct.x = x;
  245. rct.y = y;
  246. idRegister *reg = RegList()->FindReg("rect");
  247. if (reg) {
  248. reg->Enable(false);
  249. }
  250. rect = rct;
  251. }
  252. /*
  253. ================
  254. idWindow::SetFont
  255. ================
  256. */
  257. void idWindow::SetFont() {
  258. dc->SetFont(fontNum);
  259. }
  260. /*
  261. ================
  262. idWindow::GetMaxCharHeight
  263. ================
  264. */
  265. float idWindow::GetMaxCharHeight() {
  266. SetFont();
  267. return dc->MaxCharHeight(textScale);
  268. }
  269. /*
  270. ================
  271. idWindow::GetMaxCharWidth
  272. ================
  273. */
  274. float idWindow::GetMaxCharWidth() {
  275. SetFont();
  276. return dc->MaxCharWidth(textScale);
  277. }
  278. /*
  279. ================
  280. idWindow::Draw
  281. ================
  282. */
  283. void idWindow::Draw( int time, float x, float y ) {
  284. if ( text.Length() == 0 ) {
  285. return;
  286. }
  287. if ( textShadow ) {
  288. idStr shadowText = text;
  289. idRectangle shadowRect = textRect;
  290. shadowText.RemoveColors();
  291. shadowRect.x += textShadow;
  292. shadowRect.y += textShadow;
  293. dc->DrawText( shadowText, textScale, textAlign, colorBlack, shadowRect, !( flags & WIN_NOWRAP ), -1 );
  294. }
  295. dc->DrawText( text, textScale, textAlign, foreColor, textRect, !( flags & WIN_NOWRAP ), -1 );
  296. if ( gui_edit.GetBool() ) {
  297. dc->EnableClipping( false );
  298. dc->DrawText( va( "x: %i y: %i", ( int )rect.x(), ( int )rect.y() ), 0.25, 0, dc->colorWhite, idRectangle( rect.x(), rect.y() - 15, 100, 20 ), false );
  299. dc->DrawText( va( "w: %i h: %i", ( int )rect.w(), ( int )rect.h() ), 0.25, 0, dc->colorWhite, idRectangle( rect.x() + rect.w(), rect.w() + rect.h() + 5, 100, 20 ), false );
  300. dc->EnableClipping( true );
  301. }
  302. }
  303. /*
  304. ================
  305. idWindow::BringToTop
  306. ================
  307. */
  308. void idWindow::BringToTop(idWindow *w) {
  309. if (w && !(w->flags & WIN_MODAL)) {
  310. return;
  311. }
  312. int c = children.Num();
  313. for (int i = 0; i < c; i++) {
  314. if (children[i] == w) {
  315. // this is it move from i - 1 to 0 to i to 1 then shove this one into 0
  316. for (int j = i+1; j < c; j++) {
  317. children[j-1] = children[j];
  318. }
  319. children[c-1] = w;
  320. break;
  321. }
  322. }
  323. }
  324. /*
  325. ================
  326. idWindow::Size
  327. ================
  328. */
  329. void idWindow::Size(float x, float y, float w, float h) {
  330. idRectangle rct = rect;
  331. rct.x = x;
  332. rct.y = y;
  333. rct.w = w;
  334. rct.h = h;
  335. rect = rct;
  336. CalcClientRect(0,0);
  337. }
  338. /*
  339. ================
  340. idWindow::MouseEnter
  341. ================
  342. */
  343. void idWindow::MouseEnter() {
  344. if (noEvents) {
  345. return;
  346. }
  347. RunScript(ON_MOUSEENTER);
  348. }
  349. /*
  350. ================
  351. idWindow::MouseExit
  352. ================
  353. */
  354. void idWindow::MouseExit() {
  355. if (noEvents) {
  356. return;
  357. }
  358. RunScript(ON_MOUSEEXIT);
  359. }
  360. /*
  361. ================
  362. idWindow::RouteMouseCoords
  363. ================
  364. */
  365. const char *idWindow::RouteMouseCoords(float xd, float yd) {
  366. idStr str;
  367. if (GetCaptureChild()) {
  368. //FIXME: unkludge this whole mechanism
  369. return GetCaptureChild()->RouteMouseCoords(xd, yd);
  370. }
  371. if (xd == -2000 || yd == -2000) {
  372. return "";
  373. }
  374. int c = children.Num();
  375. while (c > 0) {
  376. idWindow *child = children[--c];
  377. if (child->visible && !child->noEvents && child->Contains(child->drawRect, gui->CursorX(), gui->CursorY())) {
  378. dc->SetCursor(child->cursor);
  379. child->hover = true;
  380. if (overChild != child) {
  381. if (overChild) {
  382. overChild->MouseExit();
  383. str = overChild->cmd;
  384. if (str.Length()) {
  385. gui->GetDesktop()->AddCommand(str);
  386. overChild->cmd = "";
  387. }
  388. }
  389. overChild = child;
  390. overChild->MouseEnter();
  391. str = overChild->cmd;
  392. if (str.Length()) {
  393. gui->GetDesktop()->AddCommand(str);
  394. overChild->cmd = "";
  395. }
  396. } else {
  397. if (!(child->flags & WIN_HOLDCAPTURE)) {
  398. child->RouteMouseCoords(xd, yd);
  399. }
  400. }
  401. return "";
  402. }
  403. }
  404. if (overChild) {
  405. overChild->MouseExit();
  406. str = overChild->cmd;
  407. if (str.Length()) {
  408. gui->GetDesktop()->AddCommand(str);
  409. overChild->cmd = "";
  410. }
  411. overChild = NULL;
  412. }
  413. return "";
  414. }
  415. /*
  416. ================
  417. idWindow::Activate
  418. ================
  419. */
  420. void idWindow::Activate( bool activate, idStr &act ) {
  421. int n = (activate) ? ON_ACTIVATE : ON_DEACTIVATE;
  422. // make sure win vars are updated before activation
  423. UpdateWinVars ( );
  424. RunScript(n);
  425. int c = children.Num();
  426. for (int i = 0; i < c; i++) {
  427. children[i]->Activate( activate, act );
  428. }
  429. if ( act.Length() ) {
  430. act += " ; ";
  431. }
  432. }
  433. /*
  434. ================
  435. idWindow::Trigger
  436. ================
  437. */
  438. void idWindow::Trigger() {
  439. RunScript( ON_TRIGGER );
  440. int c = children.Num();
  441. for ( int i = 0; i < c; i++ ) {
  442. children[i]->Trigger();
  443. }
  444. StateChanged( true );
  445. }
  446. /*
  447. ================
  448. idWindow::StateChanged
  449. ================
  450. */
  451. void idWindow::StateChanged( bool redraw ) {
  452. UpdateWinVars();
  453. if (expressionRegisters.Num() && ops.Num()) {
  454. EvalRegs();
  455. }
  456. int c = drawWindows.Num();
  457. for ( int i = 0; i < c; i++ ) {
  458. if ( drawWindows[i].win ) {
  459. drawWindows[i].win->StateChanged( redraw );
  460. } else {
  461. drawWindows[i].simp->StateChanged( redraw );
  462. }
  463. }
  464. if ( redraw ) {
  465. if ( flags & WIN_DESKTOP ) {
  466. Redraw( 0.0f, 0.0f );
  467. }
  468. if ( background && background->CinematicLength() ) {
  469. background->UpdateCinematic( gui->GetTime() );
  470. }
  471. }
  472. }
  473. /*
  474. ================
  475. idWindow::SetCapture
  476. ================
  477. */
  478. idWindow *idWindow::SetCapture(idWindow *w) {
  479. // only one child can have the focus
  480. idWindow *last = NULL;
  481. int c = children.Num();
  482. for (int i = 0; i < c; i++) {
  483. if ( children[i]->flags & WIN_CAPTURE ) {
  484. last = children[i];
  485. //last->flags &= ~WIN_CAPTURE;
  486. last->LoseCapture();
  487. break;
  488. }
  489. }
  490. w->flags |= WIN_CAPTURE;
  491. w->GainCapture();
  492. gui->GetDesktop()->captureChild = w;
  493. return last;
  494. }
  495. /*
  496. ================
  497. idWindow::AddUpdateVar
  498. ================
  499. */
  500. void idWindow::AddUpdateVar(idWinVar *var) {
  501. updateVars.AddUnique(var);
  502. }
  503. /*
  504. ================
  505. idWindow::UpdateWinVars
  506. ================
  507. */
  508. void idWindow::UpdateWinVars() {
  509. int c = updateVars.Num();
  510. for (int i = 0; i < c; i++) {
  511. updateVars[i]->Update();
  512. }
  513. }
  514. /*
  515. ================
  516. idWindow::RunTimeEvents
  517. ================
  518. */
  519. bool idWindow::RunTimeEvents(int time) {
  520. if ( time - lastTimeRun < USERCMD_MSEC ) {
  521. //common->Printf("Skipping gui time events at %i\n", time);
  522. return false;
  523. }
  524. lastTimeRun = time;
  525. UpdateWinVars();
  526. if (expressionRegisters.Num() && ops.Num()) {
  527. EvalRegs();
  528. }
  529. if ( flags & WIN_INTRANSITION ) {
  530. Transition();
  531. }
  532. Time();
  533. // renamed ON_EVENT to ON_FRAME
  534. RunScript(ON_FRAME);
  535. int c = children.Num();
  536. for (int i = 0; i < c; i++) {
  537. children[i]->RunTimeEvents(time);
  538. }
  539. return true;
  540. }
  541. /*
  542. ================
  543. idWindow::RunNamedEvent
  544. ================
  545. */
  546. void idWindow::RunNamedEvent ( const char* eventName )
  547. {
  548. int i;
  549. int c;
  550. // Find and run the event
  551. c = namedEvents.Num( );
  552. for ( i = 0; i < c; i ++ ) {
  553. if ( namedEvents[i]->mName.Icmp( eventName ) ) {
  554. continue;
  555. }
  556. UpdateWinVars();
  557. // Make sure we got all the current values for stuff
  558. if (expressionRegisters.Num() && ops.Num()) {
  559. EvalRegs(-1, true);
  560. }
  561. RunScriptList( namedEvents[i]->mEvent );
  562. break;
  563. }
  564. // Run the event in all the children as well
  565. c = children.Num();
  566. for ( i = 0; i < c; i++ ) {
  567. children[i]->RunNamedEvent ( eventName );
  568. }
  569. }
  570. /*
  571. ================
  572. idWindow::Contains
  573. ================
  574. */
  575. bool idWindow::Contains(const idRectangle &sr, float x, float y) {
  576. idRectangle r = sr;
  577. r.x += actualX - drawRect.x;
  578. r.y += actualY - drawRect.y;
  579. return r.Contains(x, y);
  580. }
  581. /*
  582. ================
  583. idWindow::Contains
  584. ================
  585. */
  586. bool idWindow::Contains(float x, float y) {
  587. idRectangle r = drawRect;
  588. r.x = actualX;
  589. r.y = actualY;
  590. return r.Contains(x, y);
  591. }
  592. /*
  593. ================
  594. idWindow::AddCommand
  595. ================
  596. */
  597. void idWindow::AddCommand(const char *_cmd) {
  598. idStr str = cmd;
  599. if (str.Length()) {
  600. str += " ; ";
  601. str += _cmd;
  602. } else {
  603. str = _cmd;
  604. }
  605. cmd = str;
  606. }
  607. /*
  608. ================
  609. idWindow::HandleEvent
  610. ================
  611. */
  612. const char *idWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) {
  613. static bool actionDownRun;
  614. static bool actionUpRun;
  615. cmd = "";
  616. if ( flags & WIN_DESKTOP ) {
  617. actionDownRun = false;
  618. actionUpRun = false;
  619. if (expressionRegisters.Num() && ops.Num()) {
  620. EvalRegs();
  621. }
  622. RunTimeEvents(gui->GetTime());
  623. CalcRects(0,0);
  624. dc->SetCursor( idDeviceContext::CURSOR_ARROW );
  625. }
  626. if (visible && !noEvents) {
  627. if (event->evType == SE_KEY) {
  628. EvalRegs(-1, true);
  629. if (updateVisuals) {
  630. *updateVisuals = true;
  631. }
  632. if (event->evValue == K_MOUSE1) {
  633. if (!event->evValue2 && GetCaptureChild()) {
  634. GetCaptureChild()->LoseCapture();
  635. gui->GetDesktop()->captureChild = NULL;
  636. return "";
  637. }
  638. int c = children.Num();
  639. while (--c >= 0) {
  640. if (children[c]->visible && children[c]->Contains(children[c]->drawRect, gui->CursorX(), gui->CursorY()) && !(children[c]->noEvents)) {
  641. idWindow *child = children[c];
  642. if (event->evValue2) {
  643. BringToTop(child);
  644. SetFocus(child);
  645. if (child->flags & WIN_HOLDCAPTURE) {
  646. SetCapture(child);
  647. }
  648. }
  649. if (child->Contains(child->clientRect, gui->CursorX(), gui->CursorY())) {
  650. //if ((gui_edit.GetBool() && (child->flags & WIN_SELECTED)) || (!gui_edit.GetBool() && (child->flags & WIN_MOVABLE))) {
  651. // SetCapture(child);
  652. //}
  653. SetFocus(child);
  654. const char *childRet = child->HandleEvent(event, updateVisuals);
  655. if (childRet && *childRet) {
  656. return childRet;
  657. }
  658. if (child->flags & WIN_MODAL) {
  659. return "";
  660. }
  661. } else {
  662. if (event->evValue2) {
  663. SetFocus(child);
  664. bool capture = true;
  665. if (capture && ((child->flags & WIN_MOVABLE) || gui_edit.GetBool())) {
  666. SetCapture(child);
  667. }
  668. return "";
  669. } else {
  670. }
  671. }
  672. }
  673. }
  674. if (event->evValue2 && !actionDownRun) {
  675. actionDownRun = RunScript( ON_ACTION );
  676. } else if (!actionUpRun) {
  677. actionUpRun = RunScript( ON_ACTIONRELEASE );
  678. }
  679. } else if (event->evValue == K_MOUSE2) {
  680. if (!event->evValue2 && GetCaptureChild()) {
  681. GetCaptureChild()->LoseCapture();
  682. gui->GetDesktop()->captureChild = NULL;
  683. return "";
  684. }
  685. int c = children.Num();
  686. while (--c >= 0) {
  687. if (children[c]->visible && children[c]->Contains(children[c]->drawRect, gui->CursorX(), gui->CursorY()) && !(children[c]->noEvents)) {
  688. idWindow *child = children[c];
  689. if (event->evValue2) {
  690. BringToTop(child);
  691. SetFocus(child);
  692. }
  693. if (child->Contains(child->clientRect,gui->CursorX(), gui->CursorY()) || GetCaptureChild() == child) {
  694. if ((gui_edit.GetBool() && (child->flags & WIN_SELECTED)) || (!gui_edit.GetBool() && (child->flags & WIN_MOVABLE))) {
  695. SetCapture(child);
  696. }
  697. const char *childRet = child->HandleEvent(event, updateVisuals);
  698. if (childRet && *childRet) {
  699. return childRet;
  700. }
  701. if (child->flags & WIN_MODAL) {
  702. return "";
  703. }
  704. }
  705. }
  706. }
  707. } else if (event->evValue == K_MOUSE3) {
  708. if (gui_edit.GetBool()) {
  709. int c = children.Num();
  710. for (int i = 0; i < c; i++) {
  711. if (children[i]->drawRect.Contains(gui->CursorX(), gui->CursorY())) {
  712. if (event->evValue2) {
  713. children[i]->flags ^= WIN_SELECTED;
  714. if (children[i]->flags & WIN_SELECTED) {
  715. flags &= ~WIN_SELECTED;
  716. return "childsel";
  717. }
  718. }
  719. }
  720. }
  721. }
  722. } else if (event->evValue == K_TAB && event->evValue2) {
  723. if (GetFocusedChild()) {
  724. const char *childRet = GetFocusedChild()->HandleEvent(event, updateVisuals);
  725. if (childRet && *childRet) {
  726. return childRet;
  727. }
  728. // If the window didn't handle the tab, then move the focus to the next window
  729. // or the previous window if shift is held down
  730. int direction = 1;
  731. if ( idKeyInput::IsDown( K_SHIFT ) ) {
  732. direction = -1;
  733. }
  734. idWindow *currentFocus = GetFocusedChild();
  735. idWindow *child = GetFocusedChild();
  736. idWindow *parent = child->GetParent();
  737. while ( parent ) {
  738. bool foundFocus = false;
  739. bool recurse = false;
  740. int index = 0;
  741. if ( child ) {
  742. index = parent->GetChildIndex( child ) + direction;
  743. } else if ( direction < 0 ) {
  744. index = parent->GetChildCount() - 1;
  745. }
  746. while ( index < parent->GetChildCount() && index >= 0) {
  747. idWindow *testWindow = parent->GetChild( index );
  748. if ( testWindow == currentFocus ) {
  749. // we managed to wrap around and get back to our starting window
  750. foundFocus = true;
  751. break;
  752. }
  753. if ( testWindow && !testWindow->noEvents && testWindow->visible ) {
  754. if ( testWindow->flags & WIN_CANFOCUS ) {
  755. SetFocus( testWindow );
  756. foundFocus = true;
  757. break;
  758. } else if ( testWindow->GetChildCount() > 0 ) {
  759. parent = testWindow;
  760. child = NULL;
  761. recurse = true;
  762. break;
  763. }
  764. }
  765. index += direction;
  766. }
  767. if ( foundFocus ) {
  768. // We found a child to focus on
  769. break;
  770. } else if ( recurse ) {
  771. // We found a child with children
  772. continue;
  773. } else {
  774. // We didn't find anything, so go back up to our parent
  775. child = parent;
  776. parent = child->GetParent();
  777. if ( parent == gui->GetDesktop() ) {
  778. // We got back to the desktop, so wrap around but don't actually go to the desktop
  779. parent = NULL;
  780. child = NULL;
  781. }
  782. }
  783. }
  784. }
  785. } else if (event->evValue == K_ESCAPE && event->evValue2) {
  786. if (GetFocusedChild()) {
  787. const char *childRet = GetFocusedChild()->HandleEvent(event, updateVisuals);
  788. if (childRet && *childRet) {
  789. return childRet;
  790. }
  791. }
  792. RunScript( ON_ESC );
  793. } else if (event->evValue == K_ENTER ) {
  794. if (GetFocusedChild()) {
  795. const char *childRet = GetFocusedChild()->HandleEvent(event, updateVisuals);
  796. if (childRet && *childRet) {
  797. return childRet;
  798. }
  799. }
  800. if ( flags & WIN_WANTENTER ) {
  801. if ( event->evValue2 ) {
  802. RunScript( ON_ACTION );
  803. } else {
  804. RunScript( ON_ACTIONRELEASE );
  805. }
  806. }
  807. } else {
  808. if (GetFocusedChild()) {
  809. const char *childRet = GetFocusedChild()->HandleEvent(event, updateVisuals);
  810. if (childRet && *childRet) {
  811. return childRet;
  812. }
  813. }
  814. }
  815. } else if (event->evType == SE_MOUSE) {
  816. if (updateVisuals) {
  817. *updateVisuals = true;
  818. }
  819. const char *mouseRet = RouteMouseCoords(event->evValue, event->evValue2);
  820. if (mouseRet && *mouseRet) {
  821. return mouseRet;
  822. }
  823. } else if (event->evType == SE_NONE) {
  824. } else if (event->evType == SE_CHAR) {
  825. if (GetFocusedChild()) {
  826. const char *childRet = GetFocusedChild()->HandleEvent(event, updateVisuals);
  827. if (childRet && *childRet) {
  828. return childRet;
  829. }
  830. }
  831. }
  832. }
  833. gui->GetReturnCmd() = cmd;
  834. if ( gui->GetPendingCmd().Length() ) {
  835. gui->GetReturnCmd() += " ; ";
  836. gui->GetReturnCmd() += gui->GetPendingCmd();
  837. gui->GetPendingCmd().Clear();
  838. }
  839. cmd = "";
  840. return gui->GetReturnCmd();
  841. }
  842. /*
  843. ================
  844. idWindow::DebugDraw
  845. ================
  846. */
  847. void idWindow::DebugDraw(int time, float x, float y) {
  848. static char buff[16384];
  849. if (dc) {
  850. dc->EnableClipping(false);
  851. if (gui_debug.GetInteger() == 1) {
  852. dc->DrawRect(drawRect.x, drawRect.y, drawRect.w, drawRect.h, 1, idDeviceContext::colorRed);
  853. } else if (gui_debug.GetInteger() == 2) {
  854. char out[1024];
  855. idStr str;
  856. str = text.c_str();
  857. if (str.Length()) {
  858. sprintf(buff, "%s\n", str.c_str());
  859. }
  860. sprintf(out, "Rect: %0.1f, %0.1f, %0.1f, %0.1f\n", rect.x(), rect.y(), rect.w(), rect.h());
  861. strcat(buff, out);
  862. sprintf(out, "Draw Rect: %0.1f, %0.1f, %0.1f, %0.1f\n", drawRect.x, drawRect.y, drawRect.w, drawRect.h);
  863. strcat(buff, out);
  864. sprintf(out, "Client Rect: %0.1f, %0.1f, %0.1f, %0.1f\n", clientRect.x, clientRect.y, clientRect.w, clientRect.h);
  865. strcat(buff, out);
  866. sprintf(out, "Cursor: %0.1f : %0.1f\n", gui->CursorX(), gui->CursorY());
  867. strcat(buff, out);
  868. //idRectangle tempRect = textRect;
  869. //tempRect.x += offsetX;
  870. //drawRect.y += offsetY;
  871. dc->DrawText(buff, textScale, textAlign, foreColor, textRect, true);
  872. }
  873. dc->EnableClipping(true);
  874. }
  875. }
  876. /*
  877. ================
  878. idWindow::Transition
  879. ================
  880. */
  881. void idWindow::Transition() {
  882. int i, c = transitions.Num();
  883. bool clear = true;
  884. for ( i = 0; i < c; i++ ) {
  885. idTransitionData *data = &transitions[i];
  886. idWinRectangle *r = NULL;
  887. idWinVec4 *v4 = dynamic_cast<idWinVec4*>(data->data);
  888. idWinFloat* val = NULL;
  889. if (v4 == NULL) {
  890. r = dynamic_cast<idWinRectangle*>(data->data);
  891. if ( !r ) {
  892. val = dynamic_cast<idWinFloat*>(data->data);
  893. }
  894. }
  895. if ( data->interp.IsDone( gui->GetTime() ) && data->data) {
  896. if (v4) {
  897. *v4 = data->interp.GetEndValue();
  898. } else if ( val ) {
  899. *val = data->interp.GetEndValue()[0];
  900. } else {
  901. *r = data->interp.GetEndValue();
  902. }
  903. } else {
  904. clear = false;
  905. if (data->data) {
  906. if (v4) {
  907. *v4 = data->interp.GetCurrentValue( gui->GetTime() );
  908. } else if ( val ) {
  909. *val = data->interp.GetCurrentValue( gui->GetTime() )[0];
  910. } else {
  911. *r = data->interp.GetCurrentValue( gui->GetTime() );
  912. }
  913. } else {
  914. common->Warning("Invalid transitional data for window %s in gui %s", GetName(), gui->GetSourceFile());
  915. }
  916. }
  917. }
  918. if ( clear ) {
  919. transitions.SetNum( 0, false );
  920. flags &= ~WIN_INTRANSITION;
  921. }
  922. }
  923. /*
  924. ================
  925. idWindow::Time
  926. ================
  927. */
  928. void idWindow::Time() {
  929. if ( noTime ) {
  930. return;
  931. }
  932. if ( timeLine == -1 ) {
  933. timeLine = gui->GetTime();
  934. }
  935. cmd = "";
  936. int c = timeLineEvents.Num();
  937. if ( c > 0 ) {
  938. for (int i = 0; i < c; i++) {
  939. if ( timeLineEvents[i]->pending && gui->GetTime() - timeLine >= timeLineEvents[i]->time ) {
  940. timeLineEvents[i]->pending = false;
  941. RunScriptList( timeLineEvents[i]->event );
  942. }
  943. }
  944. }
  945. if ( gui->Active() ) {
  946. gui->GetPendingCmd() += cmd;
  947. }
  948. }
  949. /*
  950. ================
  951. idWindow::EvalRegs
  952. ================
  953. */
  954. float idWindow::EvalRegs(int test, bool force) {
  955. static float regs[MAX_EXPRESSION_REGISTERS];
  956. static idWindow *lastEval = NULL;
  957. if (!force && test >= 0 && test < MAX_EXPRESSION_REGISTERS && lastEval == this) {
  958. return regs[test];
  959. }
  960. lastEval = this;
  961. if (expressionRegisters.Num()) {
  962. regList.SetToRegs(regs);
  963. EvaluateRegisters(regs);
  964. regList.GetFromRegs(regs);
  965. }
  966. if (test >= 0 && test < MAX_EXPRESSION_REGISTERS) {
  967. return regs[test];
  968. }
  969. return 0.0;
  970. }
  971. /*
  972. ================
  973. idWindow::DrawBackground
  974. ================
  975. */
  976. void idWindow::DrawBackground(const idRectangle &drawRect) {
  977. if ( backColor.w() ) {
  978. dc->DrawFilledRect(drawRect.x, drawRect.y, drawRect.w, drawRect.h, backColor);
  979. }
  980. if ( background && matColor.w() ) {
  981. float scalex, scaley;
  982. if ( flags & WIN_NATURALMAT ) {
  983. scalex = drawRect.w / background->GetImageWidth();
  984. scaley = drawRect.h / background->GetImageHeight();
  985. } else {
  986. scalex = matScalex;
  987. scaley = matScaley;
  988. }
  989. dc->DrawMaterial(drawRect.x, drawRect.y, drawRect.w, drawRect.h, background, matColor, scalex, scaley);
  990. }
  991. }
  992. /*
  993. ================
  994. idWindow::DrawBorderAndCaption
  995. ================
  996. */
  997. void idWindow::DrawBorderAndCaption(const idRectangle &drawRect) {
  998. if ( flags & WIN_BORDER && borderSize && borderColor.w() ) {
  999. dc->DrawRect(drawRect.x, drawRect.y, drawRect.w, drawRect.h, borderSize, borderColor);
  1000. }
  1001. }
  1002. /*
  1003. ================
  1004. idWindow::SetupTransforms
  1005. ================
  1006. */
  1007. void idWindow::SetupTransforms(float x, float y) {
  1008. static idMat3 trans;
  1009. static idVec3 org;
  1010. trans.Identity();
  1011. org.Set( origin.x + x, origin.y + y, 0 );
  1012. if ( rotate ) {
  1013. static idRotation rot;
  1014. static idVec3 vec(0, 0, 1);
  1015. rot.Set( org, vec, rotate );
  1016. trans = rot.ToMat3();
  1017. }
  1018. if ( shear.x || shear.y ) {
  1019. static idMat3 smat;
  1020. smat.Identity();
  1021. smat[0][1] = shear.x;
  1022. smat[1][0] = shear.y;
  1023. trans *= smat;
  1024. }
  1025. if ( !trans.IsIdentity() ) {
  1026. dc->SetTransformInfo( org, trans );
  1027. }
  1028. }
  1029. /*
  1030. ================
  1031. idWindow::CalcRects
  1032. ================
  1033. */
  1034. void idWindow::CalcRects(float x, float y) {
  1035. CalcClientRect(0, 0);
  1036. drawRect.Offset(x, y);
  1037. clientRect.Offset(x, y);
  1038. actualX = drawRect.x;
  1039. actualY = drawRect.y;
  1040. int c = drawWindows.Num();
  1041. for (int i = 0; i < c; i++) {
  1042. if (drawWindows[i].win) {
  1043. drawWindows[i].win->CalcRects(clientRect.x + xOffset, clientRect.y + yOffset);
  1044. }
  1045. }
  1046. drawRect.Offset(-x, -y);
  1047. clientRect.Offset(-x, -y);
  1048. }
  1049. /*
  1050. ================
  1051. idWindow::Redraw
  1052. ================
  1053. */
  1054. void idWindow::Redraw(float x, float y) {
  1055. idStr str;
  1056. if (r_skipGuiShaders.GetInteger() == 1 || dc == NULL ) {
  1057. return;
  1058. }
  1059. int time = gui->GetTime();
  1060. if ( flags & WIN_DESKTOP && r_skipGuiShaders.GetInteger() != 3 ) {
  1061. RunTimeEvents( time );
  1062. }
  1063. if ( r_skipGuiShaders.GetInteger() == 2 ) {
  1064. return;
  1065. }
  1066. if ( flags & WIN_SHOWTIME ) {
  1067. dc->DrawText(va(" %0.1f seconds\n%s", (float)(time - timeLine) / 1000, gui->State().GetString("name")), 0.35f, 0, dc->colorWhite, idRectangle(100, 0, 80, 80), false);
  1068. }
  1069. if ( flags & WIN_SHOWCOORDS ) {
  1070. dc->EnableClipping(false);
  1071. sprintf(str, "x: %i y: %i cursorx: %i cursory: %i", (int)rect.x(), (int)rect.y(), (int)gui->CursorX(), (int)gui->CursorY());
  1072. dc->DrawText(str, 0.25f, 0, dc->colorWhite, idRectangle(0, 0, 100, 20), false);
  1073. dc->EnableClipping(true);
  1074. }
  1075. if (!visible) {
  1076. return;
  1077. }
  1078. CalcClientRect(0, 0);
  1079. SetFont();
  1080. //if (flags & WIN_DESKTOP) {
  1081. // see if this window forces a new aspect ratio
  1082. dc->SetSize(forceAspectWidth, forceAspectHeight);
  1083. //}
  1084. //FIXME: go to screen coord tracking
  1085. drawRect.Offset(x, y);
  1086. clientRect.Offset(x, y);
  1087. textRect.Offset(x, y);
  1088. actualX = drawRect.x;
  1089. actualY = drawRect.y;
  1090. idVec3 oldOrg;
  1091. idMat3 oldTrans;
  1092. dc->GetTransformInfo( oldOrg, oldTrans );
  1093. SetupTransforms(x, y);
  1094. DrawBackground(drawRect);
  1095. DrawBorderAndCaption(drawRect);
  1096. if ( !( flags & WIN_NOCLIP) ) {
  1097. dc->PushClipRect(clientRect);
  1098. }
  1099. if ( r_skipGuiShaders.GetInteger() < 5 ) {
  1100. Draw(time, x, y);
  1101. }
  1102. if ( gui_debug.GetInteger() ) {
  1103. DebugDraw(time, x, y);
  1104. }
  1105. int c = drawWindows.Num();
  1106. for ( int i = 0; i < c; i++ ) {
  1107. if ( drawWindows[i].win ) {
  1108. drawWindows[i].win->Redraw( clientRect.x + xOffset, clientRect.y + yOffset );
  1109. } else {
  1110. drawWindows[i].simp->Redraw( clientRect.x + xOffset, clientRect.y + yOffset );
  1111. }
  1112. }
  1113. // Put transforms back to what they were before the children were processed
  1114. dc->SetTransformInfo(oldOrg, oldTrans);
  1115. if ( ! ( flags & WIN_NOCLIP ) ) {
  1116. dc->PopClipRect();
  1117. }
  1118. if (gui_edit.GetBool() || (flags & WIN_DESKTOP && !( flags & WIN_NOCURSOR ) && !hideCursor && (gui->Active() || ( flags & WIN_MENUGUI ) ))) {
  1119. dc->SetTransformInfo(vec3_origin, mat3_identity);
  1120. gui->DrawCursor();
  1121. }
  1122. if (gui_debug.GetInteger() && flags & WIN_DESKTOP) {
  1123. dc->EnableClipping(false);
  1124. sprintf(str, "x: %1.f y: %1.f", gui->CursorX(), gui->CursorY());
  1125. dc->DrawText(str, 0.25, 0, dc->colorWhite, idRectangle(0, 0, 100, 20), false);
  1126. dc->DrawText(gui->GetSourceFile(), 0.25, 0, dc->colorWhite, idRectangle(0, 20, 300, 20), false);
  1127. dc->EnableClipping(true);
  1128. }
  1129. drawRect.Offset(-x, -y);
  1130. clientRect.Offset(-x, -y);
  1131. textRect.Offset(-x, -y);
  1132. }
  1133. /*
  1134. ================
  1135. idWindow::SetDC
  1136. ================
  1137. */
  1138. void idWindow::SetDC(idDeviceContext *d) {
  1139. dc = d;
  1140. //if (flags & WIN_DESKTOP) {
  1141. dc->SetSize(forceAspectWidth, forceAspectHeight);
  1142. //}
  1143. int c = children.Num();
  1144. for (int i = 0; i < c; i++) {
  1145. children[i]->SetDC(d);
  1146. }
  1147. }
  1148. /*
  1149. ================
  1150. idWindow::ArchiveToDictionary
  1151. ================
  1152. */
  1153. void idWindow::ArchiveToDictionary(idDict *dict, bool useNames) {
  1154. //FIXME: rewrite without state
  1155. int c = children.Num();
  1156. for (int i = 0; i < c; i++) {
  1157. children[i]->ArchiveToDictionary(dict);
  1158. }
  1159. }
  1160. /*
  1161. ================
  1162. idWindow::InitFromDictionary
  1163. ================
  1164. */
  1165. void idWindow::InitFromDictionary(idDict *dict, bool byName) {
  1166. //FIXME: rewrite without state
  1167. int c = children.Num();
  1168. for (int i = 0; i < c; i++) {
  1169. children[i]->InitFromDictionary(dict);
  1170. }
  1171. }
  1172. /*
  1173. ================
  1174. idWindow::CalcClientRect
  1175. ================
  1176. */
  1177. void idWindow::CalcClientRect(float xofs, float yofs) {
  1178. drawRect = rect;
  1179. if ( flags & WIN_INVERTRECT ) {
  1180. drawRect.x = rect.x() - rect.w();
  1181. drawRect.y = rect.y() - rect.h();
  1182. }
  1183. if (flags & (WIN_HCENTER | WIN_VCENTER) && parent) {
  1184. // in this case treat xofs and yofs as absolute top left coords
  1185. // and ignore the original positioning
  1186. if (flags & WIN_HCENTER) {
  1187. drawRect.x = (parent->rect.w() - rect.w()) / 2;
  1188. } else {
  1189. drawRect.y = (parent->rect.h() - rect.h()) / 2;
  1190. }
  1191. }
  1192. drawRect.x += xofs;
  1193. drawRect.y += yofs;
  1194. clientRect = drawRect;
  1195. if (rect.h() > 0.0 && rect.w() > 0.0) {
  1196. if (flags & WIN_BORDER && borderSize != 0.0) {
  1197. clientRect.x += borderSize;
  1198. clientRect.y += borderSize;
  1199. clientRect.w -= borderSize;
  1200. clientRect.h -= borderSize;
  1201. }
  1202. textRect = clientRect;
  1203. textRect.x += 2.0;
  1204. textRect.w -= 2.0;
  1205. textRect.y += 2.0;
  1206. textRect.h -= 2.0;
  1207. textRect.x += textAlignx;
  1208. textRect.y += textAligny;
  1209. }
  1210. origin.Set( rect.x() + (rect.w() / 2 ), rect.y() + ( rect.h() / 2 ) );
  1211. }
  1212. /*
  1213. ================
  1214. idWindow::SetupBackground
  1215. ================
  1216. */
  1217. void idWindow::SetupBackground() {
  1218. if (backGroundName.Length()) {
  1219. background = declManager->FindMaterial(backGroundName);
  1220. background->SetImageClassifications( 1 ); // just for resource tracking
  1221. if ( background && !background->TestMaterialFlag( MF_DEFAULTED ) ) {
  1222. background->SetSort(SS_GUI );
  1223. }
  1224. }
  1225. backGroundName.SetMaterialPtr(&background);
  1226. }
  1227. /*
  1228. ================
  1229. idWindow::SetupFromState
  1230. ================
  1231. */
  1232. void idWindow::SetupFromState() {
  1233. idStr str;
  1234. background = NULL;
  1235. SetupBackground();
  1236. if (borderSize) {
  1237. flags |= WIN_BORDER;
  1238. }
  1239. if (regList.FindReg("rotate") || regList.FindReg("shear")) {
  1240. flags |= WIN_TRANSFORM;
  1241. }
  1242. CalcClientRect(0,0);
  1243. if ( scripts[ ON_ACTION ] ) {
  1244. cursor = idDeviceContext::CURSOR_HAND;
  1245. flags |= WIN_CANFOCUS;
  1246. }
  1247. }
  1248. /*
  1249. ================
  1250. idWindow::Moved
  1251. ================
  1252. */
  1253. void idWindow::Moved() {
  1254. }
  1255. /*
  1256. ================
  1257. idWindow::Sized
  1258. ================
  1259. */
  1260. void idWindow::Sized() {
  1261. }
  1262. /*
  1263. ================
  1264. idWindow::GainFocus
  1265. ================
  1266. */
  1267. void idWindow::GainFocus() {
  1268. }
  1269. /*
  1270. ================
  1271. idWindow::LoseFocus
  1272. ================
  1273. */
  1274. void idWindow::LoseFocus() {
  1275. }
  1276. /*
  1277. ================
  1278. idWindow::GainCapture
  1279. ================
  1280. */
  1281. void idWindow::GainCapture() {
  1282. }
  1283. /*
  1284. ================
  1285. idWindow::LoseCapture
  1286. ================
  1287. */
  1288. void idWindow::LoseCapture() {
  1289. flags &= ~WIN_CAPTURE;
  1290. }
  1291. /*
  1292. ================
  1293. idWindow::SetFlag
  1294. ================
  1295. */
  1296. void idWindow::SetFlag(unsigned int f) {
  1297. flags |= f;
  1298. }
  1299. /*
  1300. ================
  1301. idWindow::ClearFlag
  1302. ================
  1303. */
  1304. void idWindow::ClearFlag(unsigned int f) {
  1305. flags &= ~f;
  1306. }
  1307. /*
  1308. ================
  1309. idWindow::SetParent
  1310. ================
  1311. */
  1312. void idWindow::SetParent(idWindow *w) {
  1313. parent = w;
  1314. }
  1315. /*
  1316. ================
  1317. idWindow::GetCaptureChild
  1318. ================
  1319. */
  1320. idWindow *idWindow::GetCaptureChild() {
  1321. if (flags & WIN_DESKTOP) {
  1322. return gui->GetDesktop()->captureChild;
  1323. }
  1324. return NULL;
  1325. }
  1326. /*
  1327. ================
  1328. idWindow::GetFocusedChild
  1329. ================
  1330. */
  1331. idWindow *idWindow::GetFocusedChild() {
  1332. if (flags & WIN_DESKTOP) {
  1333. return gui->GetDesktop()->focusedChild;
  1334. }
  1335. return NULL;
  1336. }
  1337. /*
  1338. ================
  1339. idWindow::SetFocus
  1340. ================
  1341. */
  1342. idWindow *idWindow::SetFocus(idWindow *w, bool scripts) {
  1343. // only one child can have the focus
  1344. idWindow *lastFocus = NULL;
  1345. if (w->flags & WIN_CANFOCUS) {
  1346. lastFocus = gui->GetDesktop()->focusedChild;
  1347. if ( lastFocus ) {
  1348. lastFocus->flags &= ~WIN_FOCUS;
  1349. lastFocus->LoseFocus();
  1350. }
  1351. // call on lose focus
  1352. if ( scripts && lastFocus ) {
  1353. // calling this broke all sorts of guis
  1354. // lastFocus->RunScript(ON_MOUSEEXIT);
  1355. }
  1356. // call on gain focus
  1357. if ( scripts && w ) {
  1358. // calling this broke all sorts of guis
  1359. // w->RunScript(ON_MOUSEENTER);
  1360. }
  1361. w->flags |= WIN_FOCUS;
  1362. w->GainFocus();
  1363. gui->GetDesktop()->focusedChild = w;
  1364. }
  1365. return lastFocus;
  1366. }
  1367. /*
  1368. ================
  1369. idWindow::ParseScript
  1370. ================
  1371. */
  1372. bool idWindow::ParseScript(idParser *src, idGuiScriptList &list, int *timeParm, bool elseBlock ) {
  1373. bool ifElseBlock = false;
  1374. idToken token;
  1375. // scripts start with { ( unless parm is true ) and have ; separated command lists.. commands are command,
  1376. // arg.. basically we want everything between the { } as it will be interpreted at
  1377. // run time
  1378. if ( elseBlock ) {
  1379. src->ReadToken ( &token );
  1380. if ( !token.Icmp ( "if" ) ) {
  1381. ifElseBlock = true;
  1382. }
  1383. src->UnreadToken ( &token );
  1384. if ( !ifElseBlock && !src->ExpectTokenString( "{" ) ) {
  1385. return false;
  1386. }
  1387. }
  1388. else if ( !src->ExpectTokenString( "{" ) ) {
  1389. return false;
  1390. }
  1391. int nest = 0;
  1392. while (1) {
  1393. if ( !src->ReadToken(&token) ) {
  1394. src->Error( "Unexpected end of file" );
  1395. return false;
  1396. }
  1397. if ( token == "{" ) {
  1398. nest++;
  1399. }
  1400. if ( token == "}" ) {
  1401. if (nest-- <= 0) {
  1402. return true;
  1403. }
  1404. }
  1405. idGuiScript *gs = new idGuiScript();
  1406. if (token.Icmp("if") == 0) {
  1407. gs->conditionReg = ParseExpression(src);
  1408. gs->ifList = new idGuiScriptList();
  1409. ParseScript(src, *gs->ifList, NULL);
  1410. if (src->ReadToken(&token)) {
  1411. if (token == "else") {
  1412. gs->elseList = new idGuiScriptList();
  1413. // pass true to indicate we are parsing an else condition
  1414. ParseScript(src, *gs->elseList, NULL, true );
  1415. } else {
  1416. src->UnreadToken(&token);
  1417. }
  1418. }
  1419. list.Append(gs);
  1420. // if we are parsing an else if then return out so
  1421. // the initial "if" parser can handle the rest of the tokens
  1422. if ( ifElseBlock ) {
  1423. return true;
  1424. }
  1425. continue;
  1426. } else {
  1427. src->UnreadToken(&token);
  1428. }
  1429. // empty { } is not allowed
  1430. if ( token == "{" ) {
  1431. src->Error ( "Unexpected {" );
  1432. delete gs;
  1433. return false;
  1434. }
  1435. gs->Parse(src);
  1436. list.Append(gs);
  1437. }
  1438. }
  1439. /*
  1440. ================
  1441. idWindow::SaveExpressionParseState
  1442. ================
  1443. */
  1444. void idWindow::SaveExpressionParseState() {
  1445. saveTemps = (bool*)Mem_Alloc(MAX_EXPRESSION_REGISTERS * sizeof(bool));
  1446. memcpy(saveTemps, registerIsTemporary, MAX_EXPRESSION_REGISTERS * sizeof(bool));
  1447. }
  1448. /*
  1449. ================
  1450. idWindow::RestoreExpressionParseState
  1451. ================
  1452. */
  1453. void idWindow::RestoreExpressionParseState() {
  1454. memcpy(registerIsTemporary, saveTemps, MAX_EXPRESSION_REGISTERS * sizeof(bool));
  1455. Mem_Free(saveTemps);
  1456. }
  1457. /*
  1458. ================
  1459. idWindow::ParseScriptEntry
  1460. ================
  1461. */
  1462. bool idWindow::ParseScriptEntry(const char *name, idParser *src) {
  1463. for (int i = 0; i < SCRIPT_COUNT; i++) {
  1464. if (idStr::Icmp(name, ScriptNames[i]) == 0) {
  1465. delete scripts[i];
  1466. scripts[i] = new idGuiScriptList;
  1467. return ParseScript(src, *scripts[i]);
  1468. }
  1469. }
  1470. return false;
  1471. }
  1472. /*
  1473. ================
  1474. idWindow::DisableRegister
  1475. ================
  1476. */
  1477. void idWindow::DisableRegister(const char *_name) {
  1478. idRegister *reg = RegList()->FindReg(_name);
  1479. if (reg) {
  1480. reg->Enable(false);
  1481. }
  1482. }
  1483. /*
  1484. ================
  1485. idWindow::PostParse
  1486. ================
  1487. */
  1488. void idWindow::PostParse() {
  1489. }
  1490. /*
  1491. ================
  1492. idWindow::GetWinVarOffset
  1493. ================
  1494. */
  1495. int idWindow::GetWinVarOffset( idWinVar *wv, drawWin_t* owner) {
  1496. int ret = -1;
  1497. if ( wv == &rect ) {
  1498. ret = (int)&( ( idWindow * ) 0 )->rect;
  1499. }
  1500. if ( wv == &backColor ) {
  1501. ret = (int)&( ( idWindow * ) 0 )->backColor;
  1502. }
  1503. if ( wv == &matColor ) {
  1504. ret = (int)&( ( idWindow * ) 0 )->matColor;
  1505. }
  1506. if ( wv == &foreColor ) {
  1507. ret = (int)&( ( idWindow * ) 0 )->foreColor;
  1508. }
  1509. if ( wv == &hoverColor ) {
  1510. ret = (int)&( ( idWindow * ) 0 )->hoverColor;
  1511. }
  1512. if ( wv == &borderColor ) {
  1513. ret = (int)&( ( idWindow * ) 0 )->borderColor;
  1514. }
  1515. if ( wv == &textScale ) {
  1516. ret = (int)&( ( idWindow * ) 0 )->textScale;
  1517. }
  1518. if ( wv == &rotate ) {
  1519. ret = (int)&( ( idWindow * ) 0 )->rotate;
  1520. }
  1521. if ( ret != -1 ) {
  1522. owner->win = this;
  1523. return ret;
  1524. }
  1525. for ( int i = 0; i < drawWindows.Num(); i++ ) {
  1526. if ( drawWindows[i].win ) {
  1527. ret = drawWindows[i].win->GetWinVarOffset( wv, owner );
  1528. } else {
  1529. ret = drawWindows[i].simp->GetWinVarOffset( wv, owner );
  1530. }
  1531. if ( ret != -1 ) {
  1532. break;
  1533. }
  1534. }
  1535. return ret;
  1536. }
  1537. /*
  1538. ================
  1539. idWindow::GetWinVarByName
  1540. ================
  1541. */
  1542. idWinVar *idWindow::GetWinVarByName(const char *_name, bool fixup, drawWin_t** owner) {
  1543. idWinVar *retVar = NULL;
  1544. if ( owner ) {
  1545. *owner = NULL;
  1546. }
  1547. if (idStr::Icmp(_name, "notime") == 0) {
  1548. retVar = &noTime;
  1549. }
  1550. if (idStr::Icmp(_name, "background") == 0) {
  1551. retVar = &backGroundName;
  1552. }
  1553. if (idStr::Icmp(_name, "visible") == 0) {
  1554. retVar = &visible;
  1555. }
  1556. if (idStr::Icmp(_name, "rect") == 0) {
  1557. retVar = &rect;
  1558. }
  1559. if (idStr::Icmp(_name, "backColor") == 0) {
  1560. retVar = &backColor;
  1561. }
  1562. if (idStr::Icmp(_name, "matColor") == 0) {
  1563. retVar = &matColor;
  1564. }
  1565. if (idStr::Icmp(_name, "foreColor") == 0) {
  1566. retVar = &foreColor;
  1567. }
  1568. if (idStr::Icmp(_name, "hoverColor") == 0) {
  1569. retVar = &hoverColor;
  1570. }
  1571. if (idStr::Icmp(_name, "borderColor") == 0) {
  1572. retVar = &borderColor;
  1573. }
  1574. if (idStr::Icmp(_name, "textScale") == 0) {
  1575. retVar = &textScale;
  1576. }
  1577. if (idStr::Icmp(_name, "rotate") == 0) {
  1578. retVar = &rotate;
  1579. }
  1580. if (idStr::Icmp(_name, "noEvents") == 0) {
  1581. retVar = &noEvents;
  1582. }
  1583. if (idStr::Icmp(_name, "text") == 0) {
  1584. retVar = &text;
  1585. }
  1586. if (idStr::Icmp(_name, "backGroundName") == 0) {
  1587. retVar = &backGroundName;
  1588. }
  1589. if (idStr::Icmp(_name, "hidecursor") == 0) {
  1590. retVar = &hideCursor;
  1591. }
  1592. idStr key = _name;
  1593. bool guiVar = (key.Find(VAR_GUIPREFIX) >= 0);
  1594. int c = definedVars.Num();
  1595. for (int i = 0; i < c; i++) {
  1596. if (idStr::Icmp(_name, (guiVar) ? va("%s",definedVars[i]->GetName()) : definedVars[i]->GetName()) == 0) {
  1597. retVar = definedVars[i];
  1598. break;
  1599. }
  1600. }
  1601. if (retVar) {
  1602. if (fixup && *_name != '$') {
  1603. DisableRegister(_name);
  1604. }
  1605. if ( owner && parent ) {
  1606. *owner = parent->FindChildByName ( name );
  1607. }
  1608. return retVar;
  1609. }
  1610. int len = key.Length();
  1611. if ( len > 5 && guiVar ) {
  1612. idWinVar *var = new idWinStr;
  1613. var->Init(_name, this);
  1614. definedVars.Append(var);
  1615. return var;
  1616. } else if (fixup) {
  1617. int n = key.Find("::");
  1618. if (n > 0) {
  1619. idStr winName = key.Left(n);
  1620. idStr var = key.Right(key.Length() - n - 2);
  1621. drawWin_t *win = GetGui()->GetDesktop()->FindChildByName(winName);
  1622. if (win) {
  1623. if (win->win) {
  1624. return win->win->GetWinVarByName(var, false, owner);
  1625. } else {
  1626. if ( owner ) {
  1627. *owner = win;
  1628. }
  1629. return win->simp->GetWinVarByName(var);
  1630. }
  1631. }
  1632. }
  1633. }
  1634. return NULL;
  1635. }
  1636. /*
  1637. ================
  1638. idWindow::ParseString
  1639. ================
  1640. */
  1641. void idWindow::ParseString(idParser *src, idStr &out) {
  1642. idToken tok;
  1643. if (src->ReadToken(&tok)) {
  1644. out = tok;
  1645. }
  1646. }
  1647. /*
  1648. ================
  1649. idWindow::ParseVec4
  1650. ================
  1651. */
  1652. void idWindow::ParseVec4(idParser *src, idVec4 &out) {
  1653. idToken tok;
  1654. src->ReadToken(&tok);
  1655. out.x = atof(tok);
  1656. src->ExpectTokenString(",");
  1657. src->ReadToken(&tok);
  1658. out.y = atof(tok);
  1659. src->ExpectTokenString(",");
  1660. src->ReadToken(&tok);
  1661. out.z = atof(tok);
  1662. src->ExpectTokenString(",");
  1663. src->ReadToken(&tok);
  1664. out.w = atof(tok);
  1665. }
  1666. /*
  1667. ================
  1668. idWindow::ParseInternalVar
  1669. ================
  1670. */
  1671. bool idWindow::ParseInternalVar(const char *_name, idParser *src) {
  1672. if (idStr::Icmp(_name, "showtime") == 0) {
  1673. if ( src->ParseBool() ) {
  1674. flags |= WIN_SHOWTIME;
  1675. }
  1676. return true;
  1677. }
  1678. if (idStr::Icmp(_name, "showcoords") == 0) {
  1679. if ( src->ParseBool() ) {
  1680. flags |= WIN_SHOWCOORDS;
  1681. }
  1682. return true;
  1683. }
  1684. if (idStr::Icmp(_name, "forceaspectwidth") == 0) {
  1685. forceAspectWidth = src->ParseFloat();
  1686. return true;
  1687. }
  1688. if (idStr::Icmp(_name, "forceaspectheight") == 0) {
  1689. forceAspectHeight = src->ParseFloat();
  1690. return true;
  1691. }
  1692. if (idStr::Icmp(_name, "matscalex") == 0) {
  1693. matScalex = src->ParseFloat();
  1694. return true;
  1695. }
  1696. if (idStr::Icmp(_name, "matscaley") == 0) {
  1697. matScaley = src->ParseFloat();
  1698. return true;
  1699. }
  1700. if (idStr::Icmp(_name, "bordersize") == 0) {
  1701. borderSize = src->ParseFloat();
  1702. return true;
  1703. }
  1704. if (idStr::Icmp(_name, "nowrap") == 0) {
  1705. if ( src->ParseBool() ) {
  1706. flags |= WIN_NOWRAP;
  1707. }
  1708. return true;
  1709. }
  1710. if (idStr::Icmp(_name, "shadow") == 0) {
  1711. textShadow = src->ParseInt();
  1712. return true;
  1713. }
  1714. if (idStr::Icmp(_name, "textalign") == 0) {
  1715. textAlign = src->ParseInt();
  1716. return true;
  1717. }
  1718. if (idStr::Icmp(_name, "textalignx") == 0) {
  1719. textAlignx = src->ParseFloat();
  1720. return true;
  1721. }
  1722. if (idStr::Icmp(_name, "textaligny") == 0) {
  1723. textAligny = src->ParseFloat();
  1724. return true;
  1725. }
  1726. if (idStr::Icmp(_name, "shear") == 0) {
  1727. shear.x = src->ParseFloat();
  1728. idToken tok;
  1729. src->ReadToken( &tok );
  1730. if ( tok.Icmp( "," ) ) {
  1731. src->Error( "Expected comma in shear definiation" );
  1732. return false;
  1733. }
  1734. shear.y = src->ParseFloat();
  1735. return true;
  1736. }
  1737. if (idStr::Icmp(_name, "wantenter") == 0) {
  1738. if ( src->ParseBool() ) {
  1739. flags |= WIN_WANTENTER;
  1740. }
  1741. return true;
  1742. }
  1743. if (idStr::Icmp(_name, "naturalmatscale") == 0) {
  1744. if ( src->ParseBool() ) {
  1745. flags |= WIN_NATURALMAT;
  1746. }
  1747. return true;
  1748. }
  1749. if (idStr::Icmp(_name, "noclip") == 0) {
  1750. if ( src->ParseBool() ) {
  1751. flags |= WIN_NOCLIP;
  1752. }
  1753. return true;
  1754. }
  1755. if (idStr::Icmp(_name, "nocursor") == 0) {
  1756. if ( src->ParseBool() ) {
  1757. flags |= WIN_NOCURSOR;
  1758. }
  1759. return true;
  1760. }
  1761. if (idStr::Icmp(_name, "menugui") == 0) {
  1762. if ( src->ParseBool() ) {
  1763. flags |= WIN_MENUGUI;
  1764. }
  1765. return true;
  1766. }
  1767. if (idStr::Icmp(_name, "modal") == 0) {
  1768. if ( src->ParseBool() ) {
  1769. flags |= WIN_MODAL;
  1770. }
  1771. return true;
  1772. }
  1773. if (idStr::Icmp(_name, "invertrect") == 0) {
  1774. if ( src->ParseBool() ) {
  1775. flags |= WIN_INVERTRECT;
  1776. }
  1777. return true;
  1778. }
  1779. if (idStr::Icmp(_name, "name") == 0) {
  1780. ParseString(src, name);
  1781. return true;
  1782. }
  1783. if (idStr::Icmp(_name, "play") == 0) {
  1784. common->Warning( "play encountered during gui parse.. see Robert\n" );
  1785. idStr playStr;
  1786. ParseString(src, playStr);
  1787. return true;
  1788. }
  1789. if (idStr::Icmp(_name, "comment") == 0) {
  1790. ParseString(src, comment);
  1791. return true;
  1792. }
  1793. if ( idStr::Icmp( _name, "font" ) == 0 ) {
  1794. idStr fontStr;
  1795. ParseString( src, fontStr );
  1796. fontNum = dc->FindFont( fontStr );
  1797. return true;
  1798. }
  1799. return false;
  1800. }
  1801. /*
  1802. ================
  1803. idWindow::ParseRegEntry
  1804. ================
  1805. */
  1806. bool idWindow::ParseRegEntry(const char *name, idParser *src) {
  1807. idStr work;
  1808. work = name;
  1809. work.ToLower();
  1810. idWinVar *var = GetWinVarByName(work, NULL);
  1811. if ( var ) {
  1812. for (int i = 0; i < NumRegisterVars; i++) {
  1813. if (idStr::Icmp(work, RegisterVars[i].name) == 0) {
  1814. regList.AddReg(work, RegisterVars[i].type, src, this, var);
  1815. return true;
  1816. }
  1817. }
  1818. }
  1819. // not predefined so just read the next token and add it to the state
  1820. idToken tok;
  1821. idVec4 v;
  1822. idWinInt *vari;
  1823. idWinFloat *varf;
  1824. idWinStr *vars;
  1825. if (src->ReadToken(&tok)) {
  1826. if (var) {
  1827. var->Set(tok);
  1828. return true;
  1829. }
  1830. switch (tok.type) {
  1831. case TT_NUMBER :
  1832. if (tok.subtype & TT_INTEGER) {
  1833. vari = new idWinInt();
  1834. *vari = atoi(tok);
  1835. vari->SetName(work);
  1836. definedVars.Append(vari);
  1837. } else if (tok.subtype & TT_FLOAT) {
  1838. varf = new idWinFloat();
  1839. *varf = atof(tok);
  1840. varf->SetName(work);
  1841. definedVars.Append(varf);
  1842. } else {
  1843. vars = new idWinStr();
  1844. *vars = tok;
  1845. vars->SetName(work);
  1846. definedVars.Append(vars);
  1847. }
  1848. break;
  1849. default :
  1850. vars = new idWinStr();
  1851. *vars = tok;
  1852. vars->SetName(work);
  1853. definedVars.Append(vars);
  1854. break;
  1855. }
  1856. }
  1857. return true;
  1858. }
  1859. /*
  1860. ================
  1861. idWindow::SetInitialState
  1862. ================
  1863. */
  1864. void idWindow::SetInitialState(const char *_name) {
  1865. name = _name;
  1866. matScalex = 1.0;
  1867. matScaley = 1.0;
  1868. forceAspectWidth = 640.0;
  1869. forceAspectHeight = 480.0;
  1870. noTime = false;
  1871. visible = true;
  1872. flags = 0;
  1873. }
  1874. /*
  1875. ================
  1876. idWindow::Parse
  1877. ================
  1878. */
  1879. bool idWindow::Parse( idParser *src, bool rebuild) {
  1880. idToken token, token2, token3, token4, token5, token6, token7;
  1881. idStr work;
  1882. if (rebuild) {
  1883. CleanUp();
  1884. }
  1885. drawWin_t dwt;
  1886. timeLineEvents.Clear();
  1887. transitions.Clear();
  1888. namedEvents.DeleteContents( true );
  1889. src->ExpectTokenType( TT_NAME, 0, &token );
  1890. SetInitialState(token);
  1891. src->ExpectTokenString( "{" );
  1892. src->ExpectAnyToken( &token );
  1893. bool ret = true;
  1894. // attach a window wrapper to the window if the gui editor is running
  1895. #ifdef ID_ALLOW_TOOLS
  1896. if ( com_editors & EDITOR_GUI ) {
  1897. new rvGEWindowWrapper ( this, rvGEWindowWrapper::WT_NORMAL );
  1898. }
  1899. #endif
  1900. while( token != "}" ) {
  1901. // track what was parsed so we can maintain it for the guieditor
  1902. src->SetMarker ( );
  1903. if ( token == "windowDef" || token == "animationDef" ) {
  1904. if (token == "animationDef") {
  1905. visible = false;
  1906. rect = idRectangle(0,0,0,0);
  1907. }
  1908. src->ExpectTokenType( TT_NAME, 0, &token );
  1909. token2 = token;
  1910. src->UnreadToken(&token);
  1911. drawWin_t *dw = FindChildByName(token2.c_str());
  1912. if (dw && dw->win) {
  1913. SaveExpressionParseState();
  1914. dw->win->Parse(src, rebuild);
  1915. RestoreExpressionParseState();
  1916. } else {
  1917. idWindow *win = new idWindow(dc, gui);
  1918. SaveExpressionParseState();
  1919. win->Parse(src, rebuild);
  1920. RestoreExpressionParseState();
  1921. win->SetParent(this);
  1922. dwt.simp = NULL;
  1923. dwt.win = NULL;
  1924. if (win->IsSimple()) {
  1925. idSimpleWindow *simple = new idSimpleWindow(win);
  1926. dwt.simp = simple;
  1927. drawWindows.Append(dwt);
  1928. delete win;
  1929. } else {
  1930. AddChild(win);
  1931. SetFocus(win,false);
  1932. dwt.win = win;
  1933. drawWindows.Append(dwt);
  1934. }
  1935. }
  1936. }
  1937. else if ( token == "editDef" ) {
  1938. idEditWindow *win = new idEditWindow(dc, gui);
  1939. SaveExpressionParseState();
  1940. win->Parse(src, rebuild);
  1941. RestoreExpressionParseState();
  1942. AddChild(win);
  1943. win->SetParent(this);
  1944. dwt.simp = NULL;
  1945. dwt.win = win;
  1946. drawWindows.Append(dwt);
  1947. }
  1948. else if ( token == "choiceDef" ) {
  1949. idChoiceWindow *win = new idChoiceWindow(dc, gui);
  1950. SaveExpressionParseState();
  1951. win->Parse(src, rebuild);
  1952. RestoreExpressionParseState();
  1953. AddChild(win);
  1954. win->SetParent(this);
  1955. dwt.simp = NULL;
  1956. dwt.win = win;
  1957. drawWindows.Append(dwt);
  1958. }
  1959. else if ( token == "sliderDef" ) {
  1960. idSliderWindow *win = new idSliderWindow(dc, gui);
  1961. SaveExpressionParseState();
  1962. win->Parse(src, rebuild);
  1963. RestoreExpressionParseState();
  1964. AddChild(win);
  1965. win->SetParent(this);
  1966. dwt.simp = NULL;
  1967. dwt.win = win;
  1968. drawWindows.Append(dwt);
  1969. }
  1970. else if ( token == "markerDef" ) {
  1971. idMarkerWindow *win = new idMarkerWindow(dc, gui);
  1972. SaveExpressionParseState();
  1973. win->Parse(src, rebuild);
  1974. RestoreExpressionParseState();
  1975. AddChild(win);
  1976. win->SetParent(this);
  1977. dwt.simp = NULL;
  1978. dwt.win = win;
  1979. drawWindows.Append(dwt);
  1980. }
  1981. else if ( token == "bindDef" ) {
  1982. idBindWindow *win = new idBindWindow(dc, gui);
  1983. SaveExpressionParseState();
  1984. win->Parse(src, rebuild);
  1985. RestoreExpressionParseState();
  1986. AddChild(win);
  1987. win->SetParent(this);
  1988. dwt.simp = NULL;
  1989. dwt.win = win;
  1990. drawWindows.Append(dwt);
  1991. }
  1992. else if ( token == "listDef" ) {
  1993. idListWindow *win = new idListWindow(dc, gui);
  1994. SaveExpressionParseState();
  1995. win->Parse(src, rebuild);
  1996. RestoreExpressionParseState();
  1997. AddChild(win);
  1998. win->SetParent(this);
  1999. dwt.simp = NULL;
  2000. dwt.win = win;
  2001. drawWindows.Append(dwt);
  2002. }
  2003. else if ( token == "fieldDef" ) {
  2004. idFieldWindow *win = new idFieldWindow(dc, gui);
  2005. SaveExpressionParseState();
  2006. win->Parse(src, rebuild);
  2007. RestoreExpressionParseState();
  2008. AddChild(win);
  2009. win->SetParent(this);
  2010. dwt.simp = NULL;
  2011. dwt.win = win;
  2012. drawWindows.Append(dwt);
  2013. }
  2014. else if ( token == "renderDef" ) {
  2015. idRenderWindow *win = new idRenderWindow(dc, gui);
  2016. SaveExpressionParseState();
  2017. win->Parse(src, rebuild);
  2018. RestoreExpressionParseState();
  2019. AddChild(win);
  2020. win->SetParent(this);
  2021. dwt.simp = NULL;
  2022. dwt.win = win;
  2023. drawWindows.Append(dwt);
  2024. }
  2025. else if ( token == "gameSSDDef" ) {
  2026. idGameSSDWindow *win = new idGameSSDWindow(dc, gui);
  2027. SaveExpressionParseState();
  2028. win->Parse(src, rebuild);
  2029. RestoreExpressionParseState();
  2030. AddChild(win);
  2031. win->SetParent(this);
  2032. dwt.simp = NULL;
  2033. dwt.win = win;
  2034. drawWindows.Append(dwt);
  2035. }
  2036. else if ( token == "gameBearShootDef" ) {
  2037. idGameBearShootWindow *win = new idGameBearShootWindow(dc, gui);
  2038. SaveExpressionParseState();
  2039. win->Parse(src, rebuild);
  2040. RestoreExpressionParseState();
  2041. AddChild(win);
  2042. win->SetParent(this);
  2043. dwt.simp = NULL;
  2044. dwt.win = win;
  2045. drawWindows.Append(dwt);
  2046. }
  2047. else if ( token == "gameBustOutDef" ) {
  2048. idGameBustOutWindow *win = new idGameBustOutWindow(dc, gui);
  2049. SaveExpressionParseState();
  2050. win->Parse(src, rebuild);
  2051. RestoreExpressionParseState();
  2052. AddChild(win);
  2053. win->SetParent(this);
  2054. dwt.simp = NULL;
  2055. dwt.win = win;
  2056. drawWindows.Append(dwt);
  2057. }
  2058. //
  2059. // added new onEvent
  2060. else if ( token == "onNamedEvent" ) {
  2061. // Read the event name
  2062. if ( !src->ReadToken(&token) ) {
  2063. src->Error( "Expected event name" );
  2064. return false;
  2065. }
  2066. rvNamedEvent* ev = new rvNamedEvent ( token );
  2067. src->SetMarker ( );
  2068. if ( !ParseScript ( src, *ev->mEvent ) ) {
  2069. ret = false;
  2070. break;
  2071. }
  2072. // If we are in the gui editor then add the internal var to the
  2073. // the wrapper
  2074. #ifdef ID_ALLOW_TOOLS
  2075. if ( com_editors & EDITOR_GUI ) {
  2076. idStr str;
  2077. idStr out;
  2078. // Grab the string from the last marker
  2079. src->GetStringFromMarker ( str, false );
  2080. // Parse it one more time to knock unwanted tabs out
  2081. idLexer src2( str, str.Length(), "", src->GetFlags() );
  2082. src2.ParseBracedSectionExact ( out, 1);
  2083. // Save the script
  2084. rvGEWindowWrapper::GetWrapper ( this )->GetScriptDict().Set ( va("onEvent %s", token.c_str()), out );
  2085. }
  2086. #endif
  2087. namedEvents.Append(ev);
  2088. }
  2089. else if ( token == "onTime" ) {
  2090. idTimeLineEvent *ev = new idTimeLineEvent;
  2091. if ( !src->ReadToken(&token) ) {
  2092. src->Error( "Unexpected end of file" );
  2093. return false;
  2094. }
  2095. ev->time = atoi(token.c_str());
  2096. // reset the mark since we dont want it to include the time
  2097. src->SetMarker ( );
  2098. if (!ParseScript(src, *ev->event, &ev->time)) {
  2099. ret = false;
  2100. break;
  2101. }
  2102. // add the script to the wrappers script list
  2103. // If we are in the gui editor then add the internal var to the
  2104. // the wrapper
  2105. #ifdef ID_ALLOW_TOOLS
  2106. if ( com_editors & EDITOR_GUI ) {
  2107. idStr str;
  2108. idStr out;
  2109. // Grab the string from the last marker
  2110. src->GetStringFromMarker ( str, false );
  2111. // Parse it one more time to knock unwanted tabs out
  2112. idLexer src2( str, str.Length(), "", src->GetFlags() );
  2113. src2.ParseBracedSectionExact ( out, 1);
  2114. // Save the script
  2115. rvGEWindowWrapper::GetWrapper ( this )->GetScriptDict().Set ( va("onTime %d", ev->time), out );
  2116. }
  2117. #endif
  2118. // this is a timeline event
  2119. ev->pending = true;
  2120. timeLineEvents.Append(ev);
  2121. }
  2122. else if ( token == "definefloat" ) {
  2123. src->ReadToken(&token);
  2124. work = token;
  2125. work.ToLower();
  2126. idWinFloat *varf = new idWinFloat();
  2127. varf->SetName(work);
  2128. definedVars.Append(varf);
  2129. // add the float to the editors wrapper dict
  2130. // Set the marker after the float name
  2131. src->SetMarker ( );
  2132. // Read in the float
  2133. regList.AddReg(work, idRegister::FLOAT, src, this, varf);
  2134. // If we are in the gui editor then add the float to the defines
  2135. #ifdef ID_ALLOW_TOOLS
  2136. if ( com_editors & EDITOR_GUI ) {
  2137. idStr str;
  2138. // Grab the string from the last marker and save it in the wrapper
  2139. src->GetStringFromMarker ( str, true );
  2140. rvGEWindowWrapper::GetWrapper ( this )->GetVariableDict().Set ( va("definefloat\t\"%s\"",token.c_str()), str );
  2141. }
  2142. #endif
  2143. }
  2144. else if ( token == "definevec4" ) {
  2145. src->ReadToken(&token);
  2146. work = token;
  2147. work.ToLower();
  2148. idWinVec4 *var = new idWinVec4();
  2149. var->SetName(work);
  2150. // set the marker so we can determine what was parsed
  2151. // set the marker after the vec4 name
  2152. src->SetMarker ( );
  2153. // FIXME: how about we add the var to the desktop instead of this window so it won't get deleted
  2154. // when this window is destoyed which even happens during parsing with simple windows ?
  2155. //definedVars.Append(var);
  2156. gui->GetDesktop()->definedVars.Append( var );
  2157. gui->GetDesktop()->regList.AddReg( work, idRegister::VEC4, src, gui->GetDesktop(), var );
  2158. // store the original vec4 for the editor
  2159. // If we are in the gui editor then add the float to the defines
  2160. #ifdef ID_ALLOW_TOOLS
  2161. if ( com_editors & EDITOR_GUI ) {
  2162. idStr str;
  2163. // Grab the string from the last marker and save it in the wrapper
  2164. src->GetStringFromMarker ( str, true );
  2165. rvGEWindowWrapper::GetWrapper ( this )->GetVariableDict().Set ( va("definevec4\t\"%s\"",token.c_str()), str );
  2166. }
  2167. #endif
  2168. }
  2169. else if ( token == "float" ) {
  2170. src->ReadToken(&token);
  2171. work = token;
  2172. work.ToLower();
  2173. idWinFloat *varf = new idWinFloat();
  2174. varf->SetName(work);
  2175. definedVars.Append(varf);
  2176. // add the float to the editors wrapper dict
  2177. // set the marker to after the float name
  2178. src->SetMarker ( );
  2179. // Parse the float
  2180. regList.AddReg(work, idRegister::FLOAT, src, this, varf);
  2181. // If we are in the gui editor then add the float to the defines
  2182. #ifdef ID_ALLOW_TOOLS
  2183. if ( com_editors & EDITOR_GUI ) {
  2184. idStr str;
  2185. // Grab the string from the last marker and save it in the wrapper
  2186. src->GetStringFromMarker ( str, true );
  2187. rvGEWindowWrapper::GetWrapper ( this )->GetVariableDict().Set ( va("float\t\"%s\"",token.c_str()), str );
  2188. }
  2189. #endif
  2190. }
  2191. else if (ParseScriptEntry(token, src)) {
  2192. // add the script to the wrappers script list
  2193. // If we are in the gui editor then add the internal var to the
  2194. // the wrapper
  2195. #ifdef ID_ALLOW_TOOLS
  2196. if ( com_editors & EDITOR_GUI ) {
  2197. idStr str;
  2198. idStr out;
  2199. // Grab the string from the last marker
  2200. src->GetStringFromMarker ( str, false );
  2201. // Parse it one more time to knock unwanted tabs out
  2202. idLexer src2( str, str.Length(), "", src->GetFlags() );
  2203. src2.ParseBracedSectionExact ( out, 1);
  2204. // Save the script
  2205. rvGEWindowWrapper::GetWrapper ( this )->GetScriptDict().Set ( token, out );
  2206. }
  2207. #endif
  2208. } else if (ParseInternalVar(token, src)) {
  2209. // gui editor support
  2210. // If we are in the gui editor then add the internal var to the
  2211. // the wrapper
  2212. #ifdef ID_ALLOW_TOOLS
  2213. if ( com_editors & EDITOR_GUI ) {
  2214. idStr str;
  2215. src->GetStringFromMarker ( str );
  2216. rvGEWindowWrapper::GetWrapper ( this )->SetStateKey ( token, str, false );
  2217. }
  2218. #endif
  2219. }
  2220. else {
  2221. ParseRegEntry(token, src);
  2222. // hook into the main window parsing for the gui editor
  2223. // If we are in the gui editor then add the internal var to the
  2224. // the wrapper
  2225. #ifdef ID_ALLOW_TOOLS
  2226. if ( com_editors & EDITOR_GUI ) {
  2227. idStr str;
  2228. src->GetStringFromMarker ( str );
  2229. rvGEWindowWrapper::GetWrapper ( this )->SetStateKey ( token, str, false );
  2230. }
  2231. #endif
  2232. }
  2233. if ( !src->ReadToken( &token ) ) {
  2234. src->Error( "Unexpected end of file" );
  2235. ret = false;
  2236. break;
  2237. }
  2238. }
  2239. if (ret) {
  2240. EvalRegs(-1, true);
  2241. }
  2242. SetupFromState();
  2243. PostParse();
  2244. // hook into the main window parsing for the gui editor
  2245. // If we are in the gui editor then add the internal var to the
  2246. // the wrapper
  2247. #ifdef ID_ALLOW_TOOLS
  2248. if ( com_editors & EDITOR_GUI ) {
  2249. rvGEWindowWrapper::GetWrapper ( this )->Finish ( );
  2250. }
  2251. #endif
  2252. return ret;
  2253. }
  2254. /*
  2255. ================
  2256. idWindow::FindSimpleWinByName
  2257. ================
  2258. */
  2259. idSimpleWindow *idWindow::FindSimpleWinByName(const char *_name) {
  2260. int c = drawWindows.Num();
  2261. for (int i = 0; i < c; i++) {
  2262. if (drawWindows[i].simp == NULL) {
  2263. continue;
  2264. }
  2265. if ( idStr::Icmp(drawWindows[i].simp->name, _name) == 0 ) {
  2266. return drawWindows[i].simp;
  2267. }
  2268. }
  2269. return NULL;
  2270. }
  2271. /*
  2272. ================
  2273. idWindow::FindChildByName
  2274. ================
  2275. */
  2276. drawWin_t *idWindow::FindChildByName(const char *_name) {
  2277. static drawWin_t dw;
  2278. if (idStr::Icmp(name,_name) == 0) {
  2279. dw.simp = NULL;
  2280. dw.win = this;
  2281. return &dw;
  2282. }
  2283. int c = drawWindows.Num();
  2284. for (int i = 0; i < c; i++) {
  2285. if (drawWindows[i].win) {
  2286. if (idStr::Icmp(drawWindows[i].win->name, _name) == 0) {
  2287. return &drawWindows[i];
  2288. }
  2289. drawWin_t *win = drawWindows[i].win->FindChildByName(_name);
  2290. if (win) {
  2291. return win;
  2292. }
  2293. } else {
  2294. if (idStr::Icmp(drawWindows[i].simp->name, _name) == 0) {
  2295. return &drawWindows[i];
  2296. }
  2297. }
  2298. }
  2299. return NULL;
  2300. }
  2301. /*
  2302. ================
  2303. idWindow::GetStrPtrByName
  2304. ================
  2305. */
  2306. idStr* idWindow::GetStrPtrByName(const char *_name) {
  2307. return NULL;
  2308. }
  2309. /*
  2310. ================
  2311. idWindow::AddTransition
  2312. ================
  2313. */
  2314. void idWindow::AddTransition(idWinVar *dest, idVec4 from, idVec4 to, int time, float accelTime, float decelTime) {
  2315. idTransitionData data;
  2316. data.data = dest;
  2317. data.interp.Init(gui->GetTime(), accelTime * time, decelTime * time, time, from, to);
  2318. transitions.Append(data);
  2319. }
  2320. /*
  2321. ================
  2322. idWindow::StartTransition
  2323. ================
  2324. */
  2325. void idWindow::StartTransition() {
  2326. flags |= WIN_INTRANSITION;
  2327. }
  2328. /*
  2329. ================
  2330. idWindow::ResetCinematics
  2331. ================
  2332. */
  2333. void idWindow::ResetCinematics() {
  2334. if ( background ) {
  2335. background->ResetCinematicTime( gui->GetTime() );
  2336. }
  2337. }
  2338. /*
  2339. ================
  2340. idWindow::ResetTime
  2341. ================
  2342. */
  2343. void idWindow::ResetTime(int t) {
  2344. timeLine = gui->GetTime() - t;
  2345. int i, c = timeLineEvents.Num();
  2346. for ( i = 0; i < c; i++ ) {
  2347. if ( timeLineEvents[i]->time >= t ) {
  2348. timeLineEvents[i]->pending = true;
  2349. }
  2350. }
  2351. noTime = false;
  2352. c = transitions.Num();
  2353. for ( i = 0; i < c; i++ ) {
  2354. idTransitionData *data = &transitions[i];
  2355. if ( data->interp.IsDone( gui->GetTime() ) && data->data ) {
  2356. transitions.RemoveIndex( i );
  2357. i--;
  2358. c--;
  2359. }
  2360. }
  2361. }
  2362. /*
  2363. ================
  2364. idWindow::RunScriptList
  2365. ================
  2366. */
  2367. bool idWindow::RunScriptList(idGuiScriptList *src) {
  2368. if (src == NULL) {
  2369. return false;
  2370. }
  2371. src->Execute(this);
  2372. return true;
  2373. }
  2374. /*
  2375. ================
  2376. idWindow::RunScript
  2377. ================
  2378. */
  2379. bool idWindow::RunScript(int n) {
  2380. if (n >= ON_MOUSEENTER && n < SCRIPT_COUNT) {
  2381. return RunScriptList(scripts[n]);
  2382. }
  2383. return false;
  2384. }
  2385. /*
  2386. ================
  2387. idWindow::ExpressionConstant
  2388. ================
  2389. */
  2390. int idWindow::ExpressionConstant(float f) {
  2391. int i;
  2392. for ( i = WEXP_REG_NUM_PREDEFINED ; i < expressionRegisters.Num() ; i++ ) {
  2393. if ( !registerIsTemporary[i] && expressionRegisters[i] == f ) {
  2394. return i;
  2395. }
  2396. }
  2397. if ( expressionRegisters.Num() == MAX_EXPRESSION_REGISTERS ) {
  2398. common->Warning( "expressionConstant: gui %s hit MAX_EXPRESSION_REGISTERS", gui->GetSourceFile() );
  2399. return 0;
  2400. }
  2401. int c = expressionRegisters.Num();
  2402. if (i > c) {
  2403. while (i > c) {
  2404. expressionRegisters.Append(-9999999);
  2405. i--;
  2406. }
  2407. }
  2408. i = expressionRegisters.Append(f);
  2409. registerIsTemporary[i] = false;
  2410. return i;
  2411. }
  2412. /*
  2413. ================
  2414. idWindow::ExpressionTemporary
  2415. ================
  2416. */
  2417. int idWindow::ExpressionTemporary() {
  2418. if ( expressionRegisters.Num() == MAX_EXPRESSION_REGISTERS ) {
  2419. common->Warning( "expressionTemporary: gui %s hit MAX_EXPRESSION_REGISTERS", gui->GetSourceFile());
  2420. return 0;
  2421. }
  2422. int i = expressionRegisters.Num();
  2423. registerIsTemporary[i] = true;
  2424. i = expressionRegisters.Append(0);
  2425. return i;
  2426. }
  2427. /*
  2428. ================
  2429. idWindow::ExpressionOp
  2430. ================
  2431. */
  2432. wexpOp_t *idWindow::ExpressionOp() {
  2433. if ( ops.Num() == MAX_EXPRESSION_OPS ) {
  2434. common->Warning( "expressionOp: gui %s hit MAX_EXPRESSION_OPS", gui->GetSourceFile());
  2435. return &ops[0];
  2436. }
  2437. wexpOp_t wop;
  2438. memset(&wop, 0, sizeof(wexpOp_t));
  2439. int i = ops.Append(wop);
  2440. return &ops[i];
  2441. }
  2442. /*
  2443. ================
  2444. idWindow::EmitOp
  2445. ================
  2446. */
  2447. int idWindow::EmitOp( int a, int b, wexpOpType_t opType, wexpOp_t **opp ) {
  2448. wexpOp_t *op;
  2449. /*
  2450. // optimize away identity operations
  2451. if ( opType == WOP_TYPE_ADD ) {
  2452. if ( !registerIsTemporary[a] && shaderRegisters[a] == 0 ) {
  2453. return b;
  2454. }
  2455. if ( !registerIsTemporary[b] && shaderRegisters[b] == 0 ) {
  2456. return a;
  2457. }
  2458. if ( !registerIsTemporary[a] && !registerIsTemporary[b] ) {
  2459. return ExpressionConstant( shaderRegisters[a] + shaderRegisters[b] );
  2460. }
  2461. }
  2462. if ( opType == WOP_TYPE_MULTIPLY ) {
  2463. if ( !registerIsTemporary[a] && shaderRegisters[a] == 1 ) {
  2464. return b;
  2465. }
  2466. if ( !registerIsTemporary[a] && shaderRegisters[a] == 0 ) {
  2467. return a;
  2468. }
  2469. if ( !registerIsTemporary[b] && shaderRegisters[b] == 1 ) {
  2470. return a;
  2471. }
  2472. if ( !registerIsTemporary[b] && shaderRegisters[b] == 0 ) {
  2473. return b;
  2474. }
  2475. if ( !registerIsTemporary[a] && !registerIsTemporary[b] ) {
  2476. return ExpressionConstant( shaderRegisters[a] * shaderRegisters[b] );
  2477. }
  2478. }
  2479. */
  2480. op = ExpressionOp();
  2481. op->opType = opType;
  2482. op->a = a;
  2483. op->b = b;
  2484. op->c = ExpressionTemporary();
  2485. if (opp) {
  2486. *opp = op;
  2487. }
  2488. return op->c;
  2489. }
  2490. /*
  2491. ================
  2492. idWindow::ParseEmitOp
  2493. ================
  2494. */
  2495. int idWindow::ParseEmitOp( idParser *src, int a, wexpOpType_t opType, int priority, wexpOp_t **opp ) {
  2496. int b = ParseExpressionPriority( src, priority );
  2497. return EmitOp( a, b, opType, opp );
  2498. }
  2499. /*
  2500. ================
  2501. idWindow::ParseTerm
  2502. Returns a register index
  2503. =================
  2504. */
  2505. int idWindow::ParseTerm( idParser *src, idWinVar *var, int component ) {
  2506. idToken token;
  2507. int a, b;
  2508. src->ReadToken( &token );
  2509. if ( token == "(" ) {
  2510. a = ParseExpression( src );
  2511. src->ExpectTokenString(")");
  2512. return a;
  2513. }
  2514. if ( !token.Icmp( "time" ) ) {
  2515. return WEXP_REG_TIME;
  2516. }
  2517. // parse negative numbers
  2518. if ( token == "-" ) {
  2519. src->ReadToken( &token );
  2520. if ( token.type == TT_NUMBER || token == "." ) {
  2521. return ExpressionConstant( -(float) token.GetFloatValue() );
  2522. }
  2523. src->Warning( "Bad negative number '%s'", token.c_str() );
  2524. return 0;
  2525. }
  2526. if ( token.type == TT_NUMBER || token == "." || token == "-" ) {
  2527. return ExpressionConstant( (float) token.GetFloatValue() );
  2528. }
  2529. // see if it is a table name
  2530. const idDeclTable *table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, token.c_str(), false ) );
  2531. if ( table ) {
  2532. a = table->Index();
  2533. // parse a table expression
  2534. src->ExpectTokenString("[");
  2535. b = ParseExpression(src);
  2536. src->ExpectTokenString("]");
  2537. return EmitOp( a, b, WOP_TYPE_TABLE );
  2538. }
  2539. if (var == NULL) {
  2540. var = GetWinVarByName(token, true);
  2541. }
  2542. if (var) {
  2543. a = (int)var;
  2544. //assert(dynamic_cast<idWinVec4*>(var));
  2545. var->Init(token, this);
  2546. b = component;
  2547. if (dynamic_cast<idWinVec4*>(var)) {
  2548. if (src->ReadToken(&token)) {
  2549. if (token == "[") {
  2550. b = ParseExpression(src);
  2551. src->ExpectTokenString("]");
  2552. } else {
  2553. src->UnreadToken(&token);
  2554. }
  2555. }
  2556. return EmitOp(a, b, WOP_TYPE_VAR);
  2557. } else if (dynamic_cast<idWinFloat*>(var)) {
  2558. return EmitOp(a, b, WOP_TYPE_VARF);
  2559. } else if (dynamic_cast<idWinInt*>(var)) {
  2560. return EmitOp(a, b, WOP_TYPE_VARI);
  2561. } else if (dynamic_cast<idWinBool*>(var)) {
  2562. return EmitOp(a, b, WOP_TYPE_VARB);
  2563. } else if (dynamic_cast<idWinStr*>(var)) {
  2564. return EmitOp(a, b, WOP_TYPE_VARS);
  2565. } else {
  2566. src->Warning("Var expression not vec4, float or int '%s'", token.c_str());
  2567. }
  2568. return 0;
  2569. } else {
  2570. // ugly but used for post parsing to fixup named vars
  2571. char *p = new char[token.Length()+1];
  2572. strcpy(p, token);
  2573. a = (int)p;
  2574. b = -2;
  2575. return EmitOp(a, b, WOP_TYPE_VAR);
  2576. }
  2577. }
  2578. /*
  2579. =================
  2580. idWindow::ParseExpressionPriority
  2581. Returns a register index
  2582. =================
  2583. */
  2584. #define TOP_PRIORITY 4
  2585. int idWindow::ParseExpressionPriority( idParser *src, int priority, idWinVar *var, int component ) {
  2586. idToken token;
  2587. int a;
  2588. if ( priority == 0 ) {
  2589. return ParseTerm( src, var, component );
  2590. }
  2591. a = ParseExpressionPriority( src, priority - 1, var, component );
  2592. if ( !src->ReadToken( &token ) ) {
  2593. // we won't get EOF in a real file, but we can
  2594. // when parsing from generated strings
  2595. return a;
  2596. }
  2597. if ( priority == 1 && token == "*" ) {
  2598. return ParseEmitOp( src, a, WOP_TYPE_MULTIPLY, priority );
  2599. }
  2600. if ( priority == 1 && token == "/" ) {
  2601. return ParseEmitOp( src, a, WOP_TYPE_DIVIDE, priority );
  2602. }
  2603. if ( priority == 1 && token == "%" ) { // implied truncate both to integer
  2604. return ParseEmitOp( src, a, WOP_TYPE_MOD, priority );
  2605. }
  2606. if ( priority == 2 && token == "+" ) {
  2607. return ParseEmitOp( src, a, WOP_TYPE_ADD, priority );
  2608. }
  2609. if ( priority == 2 && token == "-" ) {
  2610. return ParseEmitOp( src, a, WOP_TYPE_SUBTRACT, priority );
  2611. }
  2612. if ( priority == 3 && token == ">" ) {
  2613. return ParseEmitOp( src, a, WOP_TYPE_GT, priority );
  2614. }
  2615. if ( priority == 3 && token == ">=" ) {
  2616. return ParseEmitOp( src, a, WOP_TYPE_GE, priority );
  2617. }
  2618. if ( priority == 3 && token == "<" ) {
  2619. return ParseEmitOp( src, a, WOP_TYPE_LT, priority );
  2620. }
  2621. if ( priority == 3 && token == "<=" ) {
  2622. return ParseEmitOp( src, a, WOP_TYPE_LE, priority );
  2623. }
  2624. if ( priority == 3 && token == "==" ) {
  2625. return ParseEmitOp( src, a, WOP_TYPE_EQ, priority );
  2626. }
  2627. if ( priority == 3 && token == "!=" ) {
  2628. return ParseEmitOp( src, a, WOP_TYPE_NE, priority );
  2629. }
  2630. if ( priority == 4 && token == "&&" ) {
  2631. return ParseEmitOp( src, a, WOP_TYPE_AND, priority );
  2632. }
  2633. if ( priority == 4 && token == "||" ) {
  2634. return ParseEmitOp( src, a, WOP_TYPE_OR, priority );
  2635. }
  2636. if ( priority == 4 && token == "?" ) {
  2637. wexpOp_t *oop = NULL;
  2638. int o = ParseEmitOp( src, a, WOP_TYPE_COND, priority, &oop );
  2639. if ( !src->ReadToken( &token ) ) {
  2640. return o;
  2641. }
  2642. if (token == ":") {
  2643. a = ParseExpressionPriority( src, priority - 1, var );
  2644. oop->d = a;
  2645. }
  2646. return o;
  2647. }
  2648. // assume that anything else terminates the expression
  2649. // not too robust error checking...
  2650. src->UnreadToken( &token );
  2651. return a;
  2652. }
  2653. /*
  2654. ================
  2655. idWindow::ParseExpression
  2656. Returns a register index
  2657. ================
  2658. */
  2659. int idWindow::ParseExpression(idParser *src, idWinVar *var, int component) {
  2660. return ParseExpressionPriority( src, TOP_PRIORITY, var );
  2661. }
  2662. /*
  2663. ================
  2664. idWindow::ParseBracedExpression
  2665. ================
  2666. */
  2667. void idWindow::ParseBracedExpression(idParser *src) {
  2668. src->ExpectTokenString("{");
  2669. ParseExpression(src);
  2670. src->ExpectTokenString("}");
  2671. }
  2672. /*
  2673. ===============
  2674. idWindow::EvaluateRegisters
  2675. Parameters are taken from the localSpace and the renderView,
  2676. then all expressions are evaluated, leaving the shader registers
  2677. set to their apropriate values.
  2678. ===============
  2679. */
  2680. void idWindow::EvaluateRegisters(float *registers) {
  2681. int i, b;
  2682. wexpOp_t *op;
  2683. idVec4 v;
  2684. int erc = expressionRegisters.Num();
  2685. int oc = ops.Num();
  2686. // copy the constants
  2687. for ( i = WEXP_REG_NUM_PREDEFINED ; i < erc ; i++ ) {
  2688. registers[i] = expressionRegisters[i];
  2689. }
  2690. // copy the local and global parameters
  2691. registers[WEXP_REG_TIME] = gui->GetTime();
  2692. for ( i = 0 ; i < oc ; i++ ) {
  2693. op = &ops[i];
  2694. if (op->b == -2) {
  2695. continue;
  2696. }
  2697. switch( op->opType ) {
  2698. case WOP_TYPE_ADD:
  2699. registers[op->c] = registers[op->a] + registers[op->b];
  2700. break;
  2701. case WOP_TYPE_SUBTRACT:
  2702. registers[op->c] = registers[op->a] - registers[op->b];
  2703. break;
  2704. case WOP_TYPE_MULTIPLY:
  2705. registers[op->c] = registers[op->a] * registers[op->b];
  2706. break;
  2707. case WOP_TYPE_DIVIDE:
  2708. if ( registers[op->b] == 0.0f ) {
  2709. common->Warning( "Divide by zero in window '%s' in %s", GetName(), gui->GetSourceFile() );
  2710. registers[op->c] = registers[op->a];
  2711. } else {
  2712. registers[op->c] = registers[op->a] / registers[op->b];
  2713. }
  2714. break;
  2715. case WOP_TYPE_MOD:
  2716. b = (int)registers[op->b];
  2717. b = b != 0 ? b : 1;
  2718. registers[op->c] = (int)registers[op->a] % b;
  2719. break;
  2720. case WOP_TYPE_TABLE:
  2721. {
  2722. const idDeclTable *table = static_cast<const idDeclTable *>( declManager->DeclByIndex( DECL_TABLE, op->a ) );
  2723. registers[op->c] = table->TableLookup( registers[op->b] );
  2724. }
  2725. break;
  2726. case WOP_TYPE_GT:
  2727. registers[op->c] = registers[ op->a ] > registers[op->b];
  2728. break;
  2729. case WOP_TYPE_GE:
  2730. registers[op->c] = registers[ op->a ] >= registers[op->b];
  2731. break;
  2732. case WOP_TYPE_LT:
  2733. registers[op->c] = registers[ op->a ] < registers[op->b];
  2734. break;
  2735. case WOP_TYPE_LE:
  2736. registers[op->c] = registers[ op->a ] <= registers[op->b];
  2737. break;
  2738. case WOP_TYPE_EQ:
  2739. registers[op->c] = registers[ op->a ] == registers[op->b];
  2740. break;
  2741. case WOP_TYPE_NE:
  2742. registers[op->c] = registers[ op->a ] != registers[op->b];
  2743. break;
  2744. case WOP_TYPE_COND:
  2745. registers[op->c] = (registers[ op->a ]) ? registers[op->b] : registers[op->d];
  2746. break;
  2747. case WOP_TYPE_AND:
  2748. registers[op->c] = registers[ op->a ] && registers[op->b];
  2749. break;
  2750. case WOP_TYPE_OR:
  2751. registers[op->c] = registers[ op->a ] || registers[op->b];
  2752. break;
  2753. case WOP_TYPE_VAR:
  2754. if ( !op->a ) {
  2755. registers[op->c] = 0.0f;
  2756. break;
  2757. }
  2758. if ( op->b >= 0 && registers[op->b] >= 0 && registers[op->b] < 4 ) {
  2759. // grabs vector components
  2760. idWinVec4 *var = (idWinVec4 *)( op->a );
  2761. registers[op->c] = ((idVec4&)var)[registers[op->b]];
  2762. } else {
  2763. registers[op->c] = ((idWinVar*)(op->a))->x();
  2764. }
  2765. break;
  2766. case WOP_TYPE_VARS:
  2767. if (op->a) {
  2768. idWinStr *var = (idWinStr*)(op->a);
  2769. registers[op->c] = atof(var->c_str());
  2770. } else {
  2771. registers[op->c] = 0;
  2772. }
  2773. break;
  2774. case WOP_TYPE_VARF:
  2775. if (op->a) {
  2776. idWinFloat *var = (idWinFloat*)(op->a);
  2777. registers[op->c] = *var;
  2778. } else {
  2779. registers[op->c] = 0;
  2780. }
  2781. break;
  2782. case WOP_TYPE_VARI:
  2783. if (op->a) {
  2784. idWinInt *var = (idWinInt*)(op->a);
  2785. registers[op->c] = *var;
  2786. } else {
  2787. registers[op->c] = 0;
  2788. }
  2789. break;
  2790. case WOP_TYPE_VARB:
  2791. if (op->a) {
  2792. idWinBool *var = (idWinBool*)(op->a);
  2793. registers[op->c] = *var;
  2794. } else {
  2795. registers[op->c] = 0;
  2796. }
  2797. break;
  2798. default:
  2799. common->FatalError( "R_EvaluateExpression: bad opcode" );
  2800. }
  2801. }
  2802. }
  2803. /*
  2804. ================
  2805. idWindow::ReadFromDemoFile
  2806. ================
  2807. */
  2808. void idWindow::ReadFromDemoFile( class idDemoFile *f, bool rebuild ) {
  2809. // should never hit unless we re-enable WRITE_GUIS
  2810. #ifndef WRITE_GUIS
  2811. assert( false );
  2812. #else
  2813. if (rebuild) {
  2814. CommonInit();
  2815. }
  2816. f->SetLog(true, "window1");
  2817. backGroundName = f->ReadHashString();
  2818. f->SetLog(true, backGroundName);
  2819. if ( backGroundName[0] ) {
  2820. background = declManager->FindMaterial(backGroundName);
  2821. } else {
  2822. background = NULL;
  2823. }
  2824. f->ReadUnsignedChar( cursor );
  2825. f->ReadUnsignedInt( flags );
  2826. f->ReadInt( timeLine );
  2827. f->ReadInt( lastTimeRun );
  2828. idRectangle rct = rect;
  2829. f->ReadFloat( rct.x );
  2830. f->ReadFloat( rct.y );
  2831. f->ReadFloat( rct.w );
  2832. f->ReadFloat( rct.h );
  2833. f->ReadFloat( drawRect.x );
  2834. f->ReadFloat( drawRect.y );
  2835. f->ReadFloat( drawRect.w );
  2836. f->ReadFloat( drawRect.h );
  2837. f->ReadFloat( clientRect.x );
  2838. f->ReadFloat( clientRect.y );
  2839. f->ReadFloat( clientRect.w );
  2840. f->ReadFloat( clientRect.h );
  2841. f->ReadFloat( textRect.x );
  2842. f->ReadFloat( textRect.y );
  2843. f->ReadFloat( textRect.w );
  2844. f->ReadFloat( textRect.h );
  2845. f->ReadFloat( xOffset);
  2846. f->ReadFloat( yOffset);
  2847. int i, c;
  2848. idStr work;
  2849. if (rebuild) {
  2850. f->SetLog(true, (work + "-scripts"));
  2851. for (i = 0; i < SCRIPT_COUNT; i++) {
  2852. bool b;
  2853. f->ReadBool( b );
  2854. if (b) {
  2855. delete scripts[i];
  2856. scripts[i] = new idGuiScriptList;
  2857. scripts[i]->ReadFromDemoFile(f);
  2858. }
  2859. }
  2860. f->SetLog(true, (work + "-timelines"));
  2861. f->ReadInt( c );
  2862. for (i = 0; i < c; i++) {
  2863. idTimeLineEvent *tl = new idTimeLineEvent;
  2864. f->ReadInt( tl->time );
  2865. f->ReadBool( tl->pending );
  2866. tl->event->ReadFromDemoFile(f);
  2867. if (rebuild) {
  2868. timeLineEvents.Append(tl);
  2869. } else {
  2870. assert(i < timeLineEvents.Num());
  2871. timeLineEvents[i]->time = tl->time;
  2872. timeLineEvents[i]->pending = tl->pending;
  2873. }
  2874. }
  2875. }
  2876. f->SetLog(true, (work + "-transitions"));
  2877. f->ReadInt( c );
  2878. for (i = 0; i < c; i++) {
  2879. idTransitionData td;
  2880. td.data = NULL;
  2881. f->ReadInt ( td.offset );
  2882. float startTime, accelTime, linearTime, decelTime;
  2883. idVec4 startValue, endValue;
  2884. f->ReadFloat( startTime );
  2885. f->ReadFloat( accelTime );
  2886. f->ReadFloat( linearTime );
  2887. f->ReadFloat( decelTime );
  2888. f->ReadVec4( startValue );
  2889. f->ReadVec4( endValue );
  2890. td.interp.Init( startTime, accelTime, decelTime, accelTime + linearTime + decelTime, startValue, endValue );
  2891. // read this for correct data padding with the win32 savegames
  2892. // the extrapolate is correctly initialized through the above Init call
  2893. int extrapolationType;
  2894. float duration;
  2895. idVec4 baseSpeed, speed;
  2896. float currentTime;
  2897. idVec4 currentValue;
  2898. f->ReadInt( extrapolationType );
  2899. f->ReadFloat( startTime );
  2900. f->ReadFloat( duration );
  2901. f->ReadVec4( startValue );
  2902. f->ReadVec4( baseSpeed );
  2903. f->ReadVec4( speed );
  2904. f->ReadFloat( currentTime );
  2905. f->ReadVec4( currentValue );
  2906. transitions.Append(td);
  2907. }
  2908. f->SetLog(true, (work + "-regstuff"));
  2909. if (rebuild) {
  2910. f->ReadInt( c );
  2911. for (i = 0; i < c; i++) {
  2912. wexpOp_t w;
  2913. f->ReadInt( (int&)w.opType );
  2914. f->ReadInt( w.a );
  2915. f->ReadInt( w.b );
  2916. f->ReadInt( w.c );
  2917. f->ReadInt( w.d );
  2918. ops.Append(w);
  2919. }
  2920. f->ReadInt( c );
  2921. for (i = 0; i < c; i++) {
  2922. float ff;
  2923. f->ReadFloat( ff );
  2924. expressionRegisters.Append(ff);
  2925. }
  2926. regList.ReadFromDemoFile(f);
  2927. }
  2928. f->SetLog(true, (work + "-children"));
  2929. f->ReadInt( c );
  2930. for (i = 0; i < c; i++) {
  2931. if (rebuild) {
  2932. idWindow *win = new idWindow(dc, gui);
  2933. win->ReadFromDemoFile(f);
  2934. AddChild(win);
  2935. } else {
  2936. for (int j = 0; j < c; j++) {
  2937. if (children[j]->childID == i) {
  2938. children[j]->ReadFromDemoFile(f,rebuild);
  2939. break;
  2940. } else {
  2941. continue;
  2942. }
  2943. }
  2944. }
  2945. }
  2946. #endif /* WRITE_GUIS */
  2947. }
  2948. /*
  2949. ================
  2950. idWindow::WriteToDemoFile
  2951. ================
  2952. */
  2953. void idWindow::WriteToDemoFile( class idDemoFile *f ) {
  2954. // should never hit unless we re-enable WRITE_GUIS
  2955. #ifndef WRITE_GUIS
  2956. assert( false );
  2957. #else
  2958. f->SetLog(true, "window");
  2959. f->WriteHashString(backGroundName);
  2960. f->SetLog(true, backGroundName);
  2961. f->WriteUnsignedChar( cursor );
  2962. f->WriteUnsignedInt( flags );
  2963. f->WriteInt( timeLine );
  2964. f->WriteInt( lastTimeRun );
  2965. idRectangle rct = rect;
  2966. f->WriteFloat( rct.x );
  2967. f->WriteFloat( rct.y );
  2968. f->WriteFloat( rct.w );
  2969. f->WriteFloat( rct.h );
  2970. f->WriteFloat( drawRect.x );
  2971. f->WriteFloat( drawRect.y );
  2972. f->WriteFloat( drawRect.w );
  2973. f->WriteFloat( drawRect.h );
  2974. f->WriteFloat( clientRect.x );
  2975. f->WriteFloat( clientRect.y );
  2976. f->WriteFloat( clientRect.w );
  2977. f->WriteFloat( clientRect.h );
  2978. f->WriteFloat( textRect.x );
  2979. f->WriteFloat( textRect.y );
  2980. f->WriteFloat( textRect.w );
  2981. f->WriteFloat( textRect.h );
  2982. f->WriteFloat( xOffset );
  2983. f->WriteFloat( yOffset );
  2984. idStr work;
  2985. f->SetLog(true, work);
  2986. int i, c;
  2987. f->SetLog(true, (work + "-transitions"));
  2988. c = transitions.Num();
  2989. f->WriteInt( c );
  2990. for (i = 0; i < c; i++) {
  2991. f->WriteInt( 0 );
  2992. f->WriteInt( transitions[i].offset );
  2993. f->WriteFloat( transitions[i].interp.GetStartTime() );
  2994. f->WriteFloat( transitions[i].interp.GetAccelTime() );
  2995. f->WriteFloat( transitions[i].interp.GetLinearTime() );
  2996. f->WriteFloat( transitions[i].interp.GetDecelTime() );
  2997. f->WriteVec4( transitions[i].interp.GetStartValue() );
  2998. f->WriteVec4( transitions[i].interp.GetEndValue() );
  2999. // write to keep win32 render demo format compatiblity - we don't actually read them back anymore
  3000. f->WriteInt( transitions[i].interp.GetExtrapolate()->GetExtrapolationType() );
  3001. f->WriteFloat( transitions[i].interp.GetExtrapolate()->GetStartTime() );
  3002. f->WriteFloat( transitions[i].interp.GetExtrapolate()->GetDuration() );
  3003. f->WriteVec4( transitions[i].interp.GetExtrapolate()->GetStartValue() );
  3004. f->WriteVec4( transitions[i].interp.GetExtrapolate()->GetBaseSpeed() );
  3005. f->WriteVec4( transitions[i].interp.GetExtrapolate()->GetSpeed() );
  3006. f->WriteFloat( transitions[i].interp.GetExtrapolate()->GetCurrentTime() );
  3007. f->WriteVec4( transitions[i].interp.GetExtrapolate()->GetCurrentValue() );
  3008. }
  3009. f->SetLog(true, (work + "-regstuff"));
  3010. f->SetLog(true, (work + "-children"));
  3011. c = children.Num();
  3012. f->WriteInt( c );
  3013. for (i = 0; i < c; i++) {
  3014. for (int j = 0; j < c; j++) {
  3015. if (children[j]->childID == i) {
  3016. children[j]->WriteToDemoFile(f);
  3017. break;
  3018. } else {
  3019. continue;
  3020. }
  3021. }
  3022. }
  3023. #endif /* WRITE_GUIS */
  3024. }
  3025. /*
  3026. ===============
  3027. idWindow::WriteString
  3028. ===============
  3029. */
  3030. void idWindow::WriteSaveGameString( const char *string, idFile *savefile ) {
  3031. int len = strlen( string );
  3032. savefile->Write( &len, sizeof( len ) );
  3033. savefile->Write( string, len );
  3034. }
  3035. /*
  3036. ===============
  3037. idWindow::WriteSaveGameTransition
  3038. ===============
  3039. */
  3040. void idWindow::WriteSaveGameTransition( idTransitionData &trans, idFile *savefile ) {
  3041. drawWin_t dw, *fdw;
  3042. idStr winName("");
  3043. dw.simp = NULL;
  3044. dw.win = NULL;
  3045. int offset = gui->GetDesktop()->GetWinVarOffset( trans.data, &dw );
  3046. if ( dw.win || dw.simp ) {
  3047. winName = ( dw.win ) ? dw.win->GetName() : dw.simp->name.c_str();
  3048. }
  3049. fdw = gui->GetDesktop()->FindChildByName( winName );
  3050. if ( offset != -1 && fdw && ( fdw->win || fdw->simp ) ) {
  3051. savefile->Write( &offset, sizeof( offset ) );
  3052. WriteSaveGameString( winName, savefile );
  3053. savefile->Write( &trans.interp, sizeof( trans.interp ) );
  3054. } else {
  3055. offset = -1;
  3056. savefile->Write( &offset, sizeof( offset ) );
  3057. }
  3058. }
  3059. /*
  3060. ===============
  3061. idWindow::ReadSaveGameTransition
  3062. ===============
  3063. */
  3064. void idWindow::ReadSaveGameTransition( idTransitionData &trans, idFile *savefile ) {
  3065. int offset;
  3066. savefile->Read( &offset, sizeof( offset ) );
  3067. if ( offset != -1 ) {
  3068. idStr winName;
  3069. ReadSaveGameString( winName, savefile );
  3070. savefile->Read( &trans.interp, sizeof( trans.interp ) );
  3071. trans.data = NULL;
  3072. trans.offset = offset;
  3073. if ( winName.Length() ) {
  3074. idWinStr *strVar = new idWinStr();
  3075. strVar->Set( winName );
  3076. trans.data = dynamic_cast< idWinVar* >( strVar );
  3077. }
  3078. }
  3079. }
  3080. /*
  3081. ===============
  3082. idWindow::WriteToSaveGame
  3083. ===============
  3084. */
  3085. void idWindow::WriteToSaveGame( idFile *savefile ) {
  3086. int i;
  3087. WriteSaveGameString( cmd, savefile );
  3088. savefile->Write( &actualX, sizeof( actualX ) );
  3089. savefile->Write( &actualY, sizeof( actualY ) );
  3090. savefile->Write( &childID, sizeof( childID ) );
  3091. savefile->Write( &flags, sizeof( flags ) );
  3092. savefile->Write( &lastTimeRun, sizeof( lastTimeRun ) );
  3093. savefile->Write( &drawRect, sizeof( drawRect ) );
  3094. savefile->Write( &clientRect, sizeof( clientRect ) );
  3095. savefile->Write( &origin, sizeof( origin ) );
  3096. savefile->Write( &fontNum, sizeof( fontNum ) );
  3097. savefile->Write( &timeLine, sizeof( timeLine ) );
  3098. savefile->Write( &xOffset, sizeof( xOffset ) );
  3099. savefile->Write( &yOffset, sizeof( yOffset ) );
  3100. savefile->Write( &cursor, sizeof( cursor ) );
  3101. savefile->Write( &forceAspectWidth, sizeof( forceAspectWidth ) );
  3102. savefile->Write( &forceAspectHeight, sizeof( forceAspectHeight ) );
  3103. savefile->Write( &matScalex, sizeof( matScalex ) );
  3104. savefile->Write( &matScaley, sizeof( matScaley ) );
  3105. savefile->Write( &borderSize, sizeof( borderSize ) );
  3106. savefile->Write( &textAlign, sizeof( textAlign ) );
  3107. savefile->Write( &textAlignx, sizeof( textAlignx ) );
  3108. savefile->Write( &textAligny, sizeof( textAligny ) );
  3109. savefile->Write( &textShadow, sizeof( textShadow ) );
  3110. savefile->Write( &shear, sizeof( shear ) );
  3111. WriteSaveGameString( name, savefile );
  3112. WriteSaveGameString( comment, savefile );
  3113. // WinVars
  3114. noTime.WriteToSaveGame( savefile );
  3115. visible.WriteToSaveGame( savefile );
  3116. rect.WriteToSaveGame( savefile );
  3117. backColor.WriteToSaveGame( savefile );
  3118. matColor.WriteToSaveGame( savefile );
  3119. foreColor.WriteToSaveGame( savefile );
  3120. hoverColor.WriteToSaveGame( savefile );
  3121. borderColor.WriteToSaveGame( savefile );
  3122. textScale.WriteToSaveGame( savefile );
  3123. noEvents.WriteToSaveGame( savefile );
  3124. rotate.WriteToSaveGame( savefile );
  3125. text.WriteToSaveGame( savefile );
  3126. backGroundName.WriteToSaveGame( savefile );
  3127. hideCursor.WriteToSaveGame(savefile);
  3128. // Defined Vars
  3129. for ( i = 0; i < definedVars.Num(); i++ ) {
  3130. definedVars[i]->WriteToSaveGame( savefile );
  3131. }
  3132. savefile->Write( &textRect, sizeof( textRect ) );
  3133. // Window pointers saved as the child ID of the window
  3134. int winID;
  3135. winID = focusedChild ? focusedChild->childID : -1 ;
  3136. savefile->Write( &winID, sizeof( winID ) );
  3137. winID = captureChild ? captureChild->childID : -1 ;
  3138. savefile->Write( &winID, sizeof( winID ) );
  3139. winID = overChild ? overChild->childID : -1 ;
  3140. savefile->Write( &winID, sizeof( winID ) );
  3141. // Scripts
  3142. for ( i = 0; i < SCRIPT_COUNT; i++ ) {
  3143. if ( scripts[i] ) {
  3144. scripts[i]->WriteToSaveGame( savefile );
  3145. }
  3146. }
  3147. // TimeLine Events
  3148. for ( i = 0; i < timeLineEvents.Num(); i++ ) {
  3149. if ( timeLineEvents[i] ) {
  3150. savefile->Write( &timeLineEvents[i]->pending, sizeof( timeLineEvents[i]->pending ) );
  3151. savefile->Write( &timeLineEvents[i]->time, sizeof( timeLineEvents[i]->time ) );
  3152. if ( timeLineEvents[i]->event ) {
  3153. timeLineEvents[i]->event->WriteToSaveGame( savefile );
  3154. }
  3155. }
  3156. }
  3157. // Transitions
  3158. int num = transitions.Num();
  3159. savefile->Write( &num, sizeof( num ) );
  3160. for ( i = 0; i < transitions.Num(); i++ ) {
  3161. WriteSaveGameTransition( transitions[ i ], savefile );
  3162. }
  3163. // Named Events
  3164. for ( i = 0; i < namedEvents.Num(); i++ ) {
  3165. if ( namedEvents[i] ) {
  3166. WriteSaveGameString( namedEvents[i]->mName, savefile );
  3167. if ( namedEvents[i]->mEvent ) {
  3168. namedEvents[i]->mEvent->WriteToSaveGame( savefile );
  3169. }
  3170. }
  3171. }
  3172. // regList
  3173. regList.WriteToSaveGame( savefile );
  3174. // Save children
  3175. for ( i = 0; i < drawWindows.Num(); i++ ) {
  3176. drawWin_t window = drawWindows[i];
  3177. if ( window.simp ) {
  3178. window.simp->WriteToSaveGame( savefile );
  3179. } else if ( window.win ) {
  3180. window.win->WriteToSaveGame( savefile );
  3181. }
  3182. }
  3183. }
  3184. /*
  3185. ===============
  3186. idWindow::ReadSaveGameString
  3187. ===============
  3188. */
  3189. void idWindow::ReadSaveGameString( idStr &string, idFile *savefile ) {
  3190. int len;
  3191. savefile->Read( &len, sizeof( len ) );
  3192. if ( len < 0 ) {
  3193. common->Warning( "idWindow::ReadSaveGameString: invalid length" );
  3194. }
  3195. string.Fill( ' ', len );
  3196. savefile->Read( &string[0], len );
  3197. }
  3198. /*
  3199. ===============
  3200. idWindow::ReadFromSaveGame
  3201. ===============
  3202. */
  3203. void idWindow::ReadFromSaveGame( idFile *savefile ) {
  3204. int i;
  3205. transitions.Clear();
  3206. ReadSaveGameString( cmd, savefile );
  3207. savefile->Read( &actualX, sizeof( actualX ) );
  3208. savefile->Read( &actualY, sizeof( actualY ) );
  3209. savefile->Read( &childID, sizeof( childID ) );
  3210. savefile->Read( &flags, sizeof( flags ) );
  3211. savefile->Read( &lastTimeRun, sizeof( lastTimeRun ) );
  3212. savefile->Read( &drawRect, sizeof( drawRect ) );
  3213. savefile->Read( &clientRect, sizeof( clientRect ) );
  3214. savefile->Read( &origin, sizeof( origin ) );
  3215. savefile->Read( &fontNum, sizeof( fontNum ) );
  3216. savefile->Read( &timeLine, sizeof( timeLine ) );
  3217. savefile->Read( &xOffset, sizeof( xOffset ) );
  3218. savefile->Read( &yOffset, sizeof( yOffset ) );
  3219. savefile->Read( &cursor, sizeof( cursor ) );
  3220. savefile->Read( &forceAspectWidth, sizeof( forceAspectWidth ) );
  3221. savefile->Read( &forceAspectHeight, sizeof( forceAspectHeight ) );
  3222. savefile->Read( &matScalex, sizeof( matScalex ) );
  3223. savefile->Read( &matScaley, sizeof( matScaley ) );
  3224. savefile->Read( &borderSize, sizeof( borderSize ) );
  3225. savefile->Read( &textAlign, sizeof( textAlign ) );
  3226. savefile->Read( &textAlignx, sizeof( textAlignx ) );
  3227. savefile->Read( &textAligny, sizeof( textAligny ) );
  3228. savefile->Read( &textShadow, sizeof( textShadow ) );
  3229. savefile->Read( &shear, sizeof( shear ) );
  3230. ReadSaveGameString( name, savefile );
  3231. ReadSaveGameString( comment, savefile );
  3232. // WinVars
  3233. noTime.ReadFromSaveGame( savefile );
  3234. visible.ReadFromSaveGame( savefile );
  3235. rect.ReadFromSaveGame( savefile );
  3236. backColor.ReadFromSaveGame( savefile );
  3237. matColor.ReadFromSaveGame( savefile );
  3238. foreColor.ReadFromSaveGame( savefile );
  3239. hoverColor.ReadFromSaveGame( savefile );
  3240. borderColor.ReadFromSaveGame( savefile );
  3241. textScale.ReadFromSaveGame( savefile );
  3242. noEvents.ReadFromSaveGame( savefile );
  3243. rotate.ReadFromSaveGame( savefile );
  3244. text.ReadFromSaveGame( savefile );
  3245. backGroundName.ReadFromSaveGame( savefile );
  3246. if ( session->GetSaveGameVersion() >= 17 ) {
  3247. hideCursor.ReadFromSaveGame(savefile);
  3248. } else {
  3249. hideCursor = false;
  3250. }
  3251. // Defined Vars
  3252. for ( i = 0; i < definedVars.Num(); i++ ) {
  3253. definedVars[i]->ReadFromSaveGame( savefile );
  3254. }
  3255. savefile->Read( &textRect, sizeof( textRect ) );
  3256. // Window pointers saved as the child ID of the window
  3257. int winID = -1;
  3258. savefile->Read( &winID, sizeof( winID ) );
  3259. for ( i = 0; i < children.Num(); i++ ) {
  3260. if ( children[i]->childID == winID ) {
  3261. focusedChild = children[i];
  3262. }
  3263. }
  3264. savefile->Read( &winID, sizeof( winID ) );
  3265. for ( i = 0; i < children.Num(); i++ ) {
  3266. if ( children[i]->childID == winID ) {
  3267. captureChild = children[i];
  3268. }
  3269. }
  3270. savefile->Read( &winID, sizeof( winID ) );
  3271. for ( i = 0; i < children.Num(); i++ ) {
  3272. if ( children[i]->childID == winID ) {
  3273. overChild = children[i];
  3274. }
  3275. }
  3276. // Scripts
  3277. for ( i = 0; i < SCRIPT_COUNT; i++ ) {
  3278. if ( scripts[i] ) {
  3279. scripts[i]->ReadFromSaveGame( savefile );
  3280. }
  3281. }
  3282. // TimeLine Events
  3283. for ( i = 0; i < timeLineEvents.Num(); i++ ) {
  3284. if ( timeLineEvents[i] ) {
  3285. savefile->Read( &timeLineEvents[i]->pending, sizeof( timeLineEvents[i]->pending ) );
  3286. savefile->Read( &timeLineEvents[i]->time, sizeof( timeLineEvents[i]->time ) );
  3287. if ( timeLineEvents[i]->event ) {
  3288. timeLineEvents[i]->event->ReadFromSaveGame( savefile );
  3289. }
  3290. }
  3291. }
  3292. // Transitions
  3293. int num;
  3294. savefile->Read( &num, sizeof( num ) );
  3295. for ( i = 0; i < num; i++ ) {
  3296. idTransitionData trans;
  3297. trans.data = NULL;
  3298. ReadSaveGameTransition( trans, savefile );
  3299. if ( trans.data ) {
  3300. transitions.Append( trans );
  3301. }
  3302. }
  3303. // Named Events
  3304. for ( i = 0; i < namedEvents.Num(); i++ ) {
  3305. if ( namedEvents[i] ) {
  3306. ReadSaveGameString( namedEvents[i]->mName, savefile );
  3307. if ( namedEvents[i]->mEvent ) {
  3308. namedEvents[i]->mEvent->ReadFromSaveGame( savefile );
  3309. }
  3310. }
  3311. }
  3312. // regList
  3313. regList.ReadFromSaveGame( savefile );
  3314. // Read children
  3315. for ( i = 0; i < drawWindows.Num(); i++ ) {
  3316. drawWin_t window = drawWindows[i];
  3317. if ( window.simp ) {
  3318. window.simp->ReadFromSaveGame( savefile );
  3319. } else if ( window.win ) {
  3320. window.win->ReadFromSaveGame( savefile );
  3321. }
  3322. }
  3323. if ( flags & WIN_DESKTOP ) {
  3324. FixupTransitions();
  3325. }
  3326. }
  3327. /*
  3328. ===============
  3329. idWindow::NumTransitions
  3330. ===============
  3331. */
  3332. int idWindow::NumTransitions() {
  3333. int c = transitions.Num();
  3334. for ( int i = 0; i < children.Num(); i++ ) {
  3335. c += children[i]->NumTransitions();
  3336. }
  3337. return c;
  3338. }
  3339. /*
  3340. ===============
  3341. idWindow::FixupTransitions
  3342. ===============
  3343. */
  3344. void idWindow::FixupTransitions() {
  3345. int i, c = transitions.Num();
  3346. for ( i = 0; i < c; i++ ) {
  3347. drawWin_t *dw = gui->GetDesktop()->FindChildByName( ( ( idWinStr* )transitions[i].data )->c_str() );
  3348. delete transitions[i].data;
  3349. transitions[i].data = NULL;
  3350. if ( dw && ( dw->win || dw->simp ) ){
  3351. if ( dw->win ) {
  3352. if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->rect ) {
  3353. transitions[i].data = &dw->win->rect;
  3354. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->backColor ) {
  3355. transitions[i].data = &dw->win->backColor;
  3356. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->matColor ) {
  3357. transitions[i].data = &dw->win->matColor;
  3358. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->foreColor ) {
  3359. transitions[i].data = &dw->win->foreColor;
  3360. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->borderColor ) {
  3361. transitions[i].data = &dw->win->borderColor;
  3362. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->textScale ) {
  3363. transitions[i].data = &dw->win->textScale;
  3364. } else if ( transitions[i].offset == (int)&( ( idWindow * ) 0 )->rotate ) {
  3365. transitions[i].data = &dw->win->rotate;
  3366. }
  3367. } else {
  3368. if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->rect ) {
  3369. transitions[i].data = &dw->simp->rect;
  3370. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->backColor ) {
  3371. transitions[i].data = &dw->simp->backColor;
  3372. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->matColor ) {
  3373. transitions[i].data = &dw->simp->matColor;
  3374. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->foreColor ) {
  3375. transitions[i].data = &dw->simp->foreColor;
  3376. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->borderColor ) {
  3377. transitions[i].data = &dw->simp->borderColor;
  3378. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->textScale ) {
  3379. transitions[i].data = &dw->simp->textScale;
  3380. } else if ( transitions[i].offset == (int)&( ( idSimpleWindow * ) 0 )->rotate ) {
  3381. transitions[i].data = &dw->simp->rotate;
  3382. }
  3383. }
  3384. }
  3385. if ( transitions[i].data == NULL ) {
  3386. transitions.RemoveIndex( i );
  3387. i--;
  3388. c--;
  3389. }
  3390. }
  3391. for ( c = 0; c < children.Num(); c++ ) {
  3392. children[c]->FixupTransitions();
  3393. }
  3394. }
  3395. /*
  3396. ===============
  3397. idWindow::AddChild
  3398. ===============
  3399. */
  3400. void idWindow::AddChild(idWindow *win) {
  3401. win->childID = children.Append(win);
  3402. }
  3403. /*
  3404. ================
  3405. idWindow::FixupParms
  3406. ================
  3407. */
  3408. void idWindow::FixupParms() {
  3409. int i;
  3410. int c = children.Num();
  3411. for (i = 0; i < c; i++) {
  3412. children[i]->FixupParms();
  3413. }
  3414. for (i = 0; i < SCRIPT_COUNT; i++) {
  3415. if (scripts[i]) {
  3416. scripts[i]->FixupParms(this);
  3417. }
  3418. }
  3419. c = timeLineEvents.Num();
  3420. for (i = 0; i < c; i++) {
  3421. timeLineEvents[i]->event->FixupParms(this);
  3422. }
  3423. c = namedEvents.Num();
  3424. for (i = 0; i < c; i++) {
  3425. namedEvents[i]->mEvent->FixupParms(this);
  3426. }
  3427. c = ops.Num();
  3428. for (i = 0; i < c; i++) {
  3429. if (ops[i].b == -2) {
  3430. // need to fix this up
  3431. const char *p = (const char*)(ops[i].a);
  3432. idWinVar *var = GetWinVarByName(p, true);
  3433. delete []p;
  3434. ops[i].a = (int)var;
  3435. ops[i].b = -1;
  3436. }
  3437. }
  3438. if (flags & WIN_DESKTOP) {
  3439. CalcRects(0,0);
  3440. }
  3441. }
  3442. /*
  3443. ================
  3444. idWindow::IsSimple
  3445. ================
  3446. */
  3447. bool idWindow::IsSimple() {
  3448. // dont do simple windows when in gui editor
  3449. if ( com_editors & EDITOR_GUI ) {
  3450. return false;
  3451. }
  3452. if (ops.Num()) {
  3453. return false;
  3454. }
  3455. if (flags & (WIN_HCENTER | WIN_VCENTER)) {
  3456. return false;
  3457. }
  3458. if (children.Num() || drawWindows.Num()) {
  3459. return false;
  3460. }
  3461. for (int i = 0; i < SCRIPT_COUNT; i++) {
  3462. if (scripts[i]) {
  3463. return false;
  3464. }
  3465. }
  3466. if (timeLineEvents.Num()) {
  3467. return false;
  3468. }
  3469. if ( namedEvents.Num() ) {
  3470. return false;
  3471. }
  3472. return true;
  3473. }
  3474. /*
  3475. ================
  3476. idWindow::ContainsStateVars
  3477. ================
  3478. */
  3479. bool idWindow::ContainsStateVars() {
  3480. if ( updateVars.Num() ) {
  3481. return true;
  3482. }
  3483. int c = children.Num();
  3484. for (int i = 0; i < c; i++) {
  3485. if ( children[i]->ContainsStateVars() ) {
  3486. return true;
  3487. }
  3488. }
  3489. return false;
  3490. }
  3491. /*
  3492. ================
  3493. idWindow::Interactive
  3494. ================
  3495. */
  3496. bool idWindow::Interactive() {
  3497. if ( scripts[ ON_ACTION ] ) {
  3498. return true;
  3499. }
  3500. int c = children.Num();
  3501. for (int i = 0; i < c; i++) {
  3502. if (children[i]->Interactive()) {
  3503. return true;
  3504. }
  3505. }
  3506. return false;
  3507. }
  3508. /*
  3509. ================
  3510. idWindow::SetChildWinVarVal
  3511. ================
  3512. */
  3513. void idWindow::SetChildWinVarVal(const char *name, const char *var, const char *val) {
  3514. drawWin_t *dw = FindChildByName(name);
  3515. idWinVar *wv = NULL;
  3516. if (dw && dw->simp) {
  3517. wv = dw->simp->GetWinVarByName(var);
  3518. } else if (dw && dw->win) {
  3519. wv = dw->win->GetWinVarByName(var);
  3520. }
  3521. if (wv) {
  3522. wv->Set(val);
  3523. wv->SetEval(false);
  3524. }
  3525. }
  3526. /*
  3527. ================
  3528. idWindow::FindChildByPoint
  3529. Finds the window under the given point
  3530. ================
  3531. */
  3532. idWindow* idWindow::FindChildByPoint ( float x, float y, idWindow** below ) {
  3533. int c = children.Num();
  3534. // If we are looking for a window below this one then
  3535. // the next window should be good, but this one wasnt it
  3536. if ( *below == this ) {
  3537. *below = NULL;
  3538. return NULL;
  3539. }
  3540. if ( !Contains ( drawRect, x, y ) ) {
  3541. return NULL;
  3542. }
  3543. for (int i = c - 1; i >= 0 ; i-- ) {
  3544. idWindow* found = children[i]->FindChildByPoint ( x, y, below );
  3545. if ( found ) {
  3546. if ( *below ) {
  3547. continue;
  3548. }
  3549. return found;
  3550. }
  3551. }
  3552. return this;
  3553. }
  3554. /*
  3555. ================
  3556. idWindow::FindChildByPoint
  3557. ================
  3558. */
  3559. idWindow* idWindow::FindChildByPoint ( float x, float y, idWindow* below )
  3560. {
  3561. return FindChildByPoint ( x, y, &below );
  3562. }
  3563. /*
  3564. ================
  3565. idWindow::GetChildCount
  3566. Returns the number of children
  3567. ================
  3568. */
  3569. int idWindow::GetChildCount ( void )
  3570. {
  3571. return drawWindows.Num ( );
  3572. }
  3573. /*
  3574. ================
  3575. idWindow::GetChild
  3576. Returns the child window at the given index
  3577. ================
  3578. */
  3579. idWindow* idWindow::GetChild ( int index )
  3580. {
  3581. return drawWindows[index].win;
  3582. }
  3583. /*
  3584. ================
  3585. idWindow::GetChildIndex
  3586. Returns the index of the given child window
  3587. ================
  3588. */
  3589. int idWindow::GetChildIndex ( idWindow* window ) {
  3590. int find;
  3591. for ( find = 0; find < drawWindows.Num(); find ++ ) {
  3592. if ( drawWindows[find].win == window ) {
  3593. return find;
  3594. }
  3595. }
  3596. return -1;
  3597. }
  3598. /*
  3599. ================
  3600. idWindow::RemoveChild
  3601. Removes the child from the list of children. Note that the child window being
  3602. removed must still be deallocated by the caller
  3603. ================
  3604. */
  3605. void idWindow::RemoveChild ( idWindow *win ) {
  3606. int find;
  3607. // Remove the child window
  3608. children.Remove ( win );
  3609. for ( find = 0; find < drawWindows.Num(); find ++ )
  3610. {
  3611. if ( drawWindows[find].win == win )
  3612. {
  3613. drawWindows.RemoveIndex ( find );
  3614. break;
  3615. }
  3616. }
  3617. }
  3618. /*
  3619. ================
  3620. idWindow::InsertChild
  3621. Inserts the given window as a child into the given location in the zorder.
  3622. ================
  3623. */
  3624. bool idWindow::InsertChild ( idWindow *win, idWindow* before )
  3625. {
  3626. AddChild ( win );
  3627. win->parent = this;
  3628. drawWin_t dwt;
  3629. dwt.simp = NULL;
  3630. dwt.win = win;
  3631. // If not inserting before anything then just add it at the end
  3632. if ( before ) {
  3633. int index;
  3634. index = GetChildIndex ( before );
  3635. if ( index != -1 ) {
  3636. drawWindows.Insert ( dwt, index );
  3637. return true;
  3638. }
  3639. }
  3640. drawWindows.Append ( dwt );
  3641. return true;
  3642. }
  3643. /*
  3644. ================
  3645. idWindow::ScreenToClient
  3646. ================
  3647. */
  3648. void idWindow::ScreenToClient ( idRectangle* r ) {
  3649. int x;
  3650. int y;
  3651. idWindow* p;
  3652. for ( p = this, x = 0, y = 0; p; p = p->parent ) {
  3653. x += p->rect.x();
  3654. y += p->rect.y();
  3655. }
  3656. r->x -= x;
  3657. r->y -= y;
  3658. }
  3659. /*
  3660. ================
  3661. idWindow::ClientToScreen
  3662. ================
  3663. */
  3664. void idWindow::ClientToScreen ( idRectangle* r ) {
  3665. int x;
  3666. int y;
  3667. idWindow* p;
  3668. for ( p = this, x = 0, y = 0; p; p = p->parent ) {
  3669. x += p->rect.x();
  3670. y += p->rect.y();
  3671. }
  3672. r->x += x;
  3673. r->y += y;
  3674. }
  3675. /*
  3676. ================
  3677. idWindow::SetDefaults
  3678. Set the window do a default window with no text, no background and
  3679. default colors, etc..
  3680. ================
  3681. */
  3682. void idWindow::SetDefaults ( void ) {
  3683. forceAspectWidth = 640.0f;
  3684. forceAspectHeight = 480.0f;
  3685. matScalex = 1;
  3686. matScaley = 1;
  3687. borderSize = 0;
  3688. noTime = false;
  3689. visible = true;
  3690. textAlign = 0;
  3691. textAlignx = 0;
  3692. textAligny = 0;
  3693. noEvents = false;
  3694. rotate = 0;
  3695. shear.Zero();
  3696. textScale = 0.35f;
  3697. backColor.Zero();
  3698. foreColor = idVec4(1, 1, 1, 1);
  3699. hoverColor = idVec4(1, 1, 1, 1);
  3700. matColor = idVec4(1, 1, 1, 1);
  3701. borderColor.Zero();
  3702. text = "";
  3703. background = NULL;
  3704. backGroundName = "";
  3705. }
  3706. /*
  3707. ================
  3708. idWindow::UpdateFromDictionary
  3709. The editor only has a dictionary to work with so the easiest way to push the
  3710. values of the dictionary onto the window is for the window to interpret the
  3711. dictionary as if were a file being parsed.
  3712. ================
  3713. */
  3714. bool idWindow::UpdateFromDictionary ( idDict& dict ) {
  3715. const idKeyValue* kv;
  3716. int i;
  3717. SetDefaults ( );
  3718. // Clear all registers since they will get recreated
  3719. regList.Reset ( );
  3720. expressionRegisters.Clear ( );
  3721. ops.Clear ( );
  3722. for ( i = 0; i < dict.GetNumKeyVals(); i ++ ) {
  3723. kv = dict.GetKeyVal ( i );
  3724. // Special case name
  3725. if ( !kv->GetKey().Icmp ( "name" ) ) {
  3726. name = kv->GetValue();
  3727. continue;
  3728. }
  3729. idParser src( kv->GetValue().c_str(), kv->GetValue().Length(), "",
  3730. LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
  3731. if ( !ParseInternalVar ( kv->GetKey(), &src ) ) {
  3732. // Kill the old register since the parse reg entry will add a new one
  3733. if ( !ParseRegEntry ( kv->GetKey(), &src ) ) {
  3734. continue;
  3735. }
  3736. }
  3737. }
  3738. EvalRegs(-1, true);
  3739. SetupFromState();
  3740. PostParse();
  3741. return true;
  3742. }