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