00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <ctype.h>
00040 #include <vector>
00041 #include <sstream>
00042
00043 #include "stratagus.h"
00044
00045 #include "unit.h"
00046 #include "unittype.h"
00047 #include "upgrade.h"
00048 #include "interface.h"
00049 #include "ui.h"
00050 #include "player.h"
00051 #include "spells.h"
00052 #include "sound.h"
00053 #include "map.h"
00054 #include "commands.h"
00055 #include "video.h"
00056 #include "font.h"
00057 #include "guichan/key.h"
00058 #include "guichan/sdl/sdlinput.h"
00059
00060
00061
00062
00063
00064
00065
00066
00067
00069 int CurrentButtonLevel;
00071 std::vector<ButtonAction *> UnitButtonTable;
00073 ButtonAction *CurrentButtons;
00074
00075
00076
00077
00078
00082 void InitButtons(void)
00083 {
00084
00085 for (int z = 0; z < (int)UnitButtonTable.size(); ++z) {
00086 UnitButtonTable[z]->Icon.Load();
00087 }
00088 delete[] CurrentButtons;
00089 CurrentButtons = NULL;
00090 }
00091
00092
00093
00094
00095
00099 int AddButton(int pos, int level, const std::string &icon_ident,
00100 ButtonCmd action, const std::string &value, const ButtonCheckFunc func,
00101 const std::string &allow, const std::string &hint, const std::string &umask)
00102 {
00103 std::string buf;
00104 ButtonAction *ba;
00105
00106 ba = new ButtonAction;
00107 Assert(ba);
00108
00109 ba->Pos = pos;
00110 ba->Level = level;
00111 ba->Icon.Name = icon_ident;
00112
00113
00114 ba->Action = action;
00115 if (!value.empty()) {
00116 ba->ValueStr = value;
00117 switch (action) {
00118 case ButtonSpellCast:
00119 ba->Value = SpellTypeByIdent(value)->Slot;
00120 #ifdef DEBUG
00121 if (ba->Value < 0) {
00122 DebugPrint("Spell %s does not exist?\n" _C_ value.c_str());
00123 Assert(ba->Value >= 0);
00124 }
00125 #endif
00126 break;
00127 case ButtonTrain:
00128 ba->Value = UnitTypeIdByIdent(value);
00129 break;
00130 case ButtonBuild:
00131 ba->Value = UnitTypeIdByIdent(value);
00132 break;
00133 default:
00134 ba->Value = atoi(value.c_str());
00135 break;
00136 }
00137 } else {
00138 ba->ValueStr.clear();
00139 ba->Value = 0;
00140 }
00141
00142 ba->Allowed = func;
00143 ba->AllowStr = allow;
00144 int key = GetHotKey(hint);
00145 if (isascii(key) && isupper(key)) {
00146 key = tolower(key);
00147 }
00148 ba->Key = key;
00149 ba->Hint = hint;
00150
00151
00152 ba->UnitMask = umask;
00153 UnitButtonTable.push_back(ba);
00154
00155
00156 return 1;
00157 }
00158
00159
00163 void CleanButtons(void)
00164 {
00165
00166 for (int z = 0; z < (int)UnitButtonTable.size(); ++z) {
00167 Assert(UnitButtonTable[z]);
00168 delete UnitButtonTable[z];
00169 }
00170 UnitButtonTable.clear();
00171
00172 CurrentButtonLevel = 0;
00173 delete[] CurrentButtons;
00174 CurrentButtons = NULL;
00175 }
00176
00188 static int GetButtonStatus(const ButtonAction *button)
00189 {
00190 int res;
00191 int action;
00192 int i;
00193
00194 Assert(button);
00195 Assert(NumSelected);
00196
00197 res = 0;
00198
00199 if (ButtonAreaUnderCursor == ButtonAreaButton && ButtonUnderCursor == button->Pos - 1) {
00200 res |= IconActive;
00201 if (MouseButtons & LeftButton) {
00202
00203 res = IconClicked;
00204 }
00205 }
00206
00207 action = UnitActionNone;
00208 switch (button->Action) {
00209 case ButtonStop:
00210 action = UnitActionStill;
00211 break;
00212 case ButtonStandGround:
00213 action = UnitActionStandGround;
00214 break;
00215 case ButtonAttack:
00216 action = UnitActionAttack;
00217 break;
00218 case ButtonAttackGround:
00219 action = UnitActionAttackGround;
00220 break;
00221 case ButtonPatrol:
00222 action = UnitActionPatrol;
00223 break;
00224 case ButtonHarvest:
00225 action = UnitActionResource;
00226 break;
00227 default:
00228 break;
00229 }
00230
00231 if (action != UnitActionNone) {
00232 for (i = 0; i < NumSelected; ++i) {
00233 if (Selected[i]->Orders[0]->Action != action) {
00234 break;
00235 }
00236 }
00237 if (i == NumSelected) {
00238 res |= IconSelected;
00239 }
00240 return res;
00241 }
00242
00243 switch (button->Action) {
00244 case ButtonMove:
00245 for (i = 0; i < NumSelected; ++i) {
00246 if (Selected[i]->Orders[0]->Action != UnitActionMove &&
00247 Selected[i]->Orders[0]->Action != UnitActionBuild &&
00248 Selected[i]->Orders[0]->Action != UnitActionFollow) {
00249 break;
00250 }
00251 }
00252 if (i == NumSelected) {
00253 res |= IconSelected;
00254 }
00255 break;
00256 case ButtonSpellCast:
00257
00258
00259
00260 for (i = 0; i < NumSelected; ++i) {
00261 Assert(Selected[i]->AutoCastSpell);
00262 if (Selected[i]->AutoCastSpell[button->Value] != 1) {
00263 break;
00264 }
00265 }
00266 if (i == NumSelected) {
00267 res |= IconAutoCast;
00268 }
00269 break;
00270 case ButtonRepair:
00271 for (i = 0; i < NumSelected; ++i) {
00272 if (Selected[i]->Orders[0]->Action != UnitActionRepair) {
00273 break;
00274 }
00275 }
00276 if (i == NumSelected) {
00277 res |= IconSelected;
00278 }
00279
00280 for (i = 0; i < NumSelected; ++i) {
00281 if (Selected[i]->AutoRepair != 1) {
00282 break;
00283 }
00284 }
00285 if (i == NumSelected) {
00286 res |= IconAutoCast;
00287 }
00288 break;
00289
00290 default:
00291 break;
00292 }
00293 return res;
00294 }
00295
00299 static void DrawPopup()
00300 {
00301 ButtonAction *button = &CurrentButtons[ButtonUnderCursor];
00302 CUIButton *uibutton = &UI.ButtonPanel.Buttons[ButtonUnderCursor];
00303 Uint32 backgroundColor = Video.MapRGB(TheScreen->format, 255, 255, 200);
00304
00305
00306 if (button->Action != ButtonBuild && button->Action != ButtonTrain) {
00307 int popupWidth = SmallFont->Width(button->Hint) + 10;
00308 int popupHeight = 19;
00309 int x = std::min(uibutton->X, Video.Width - 1 - popupWidth);
00310 int y = uibutton->Y - popupHeight - 10;
00311 std::string nc, rc;
00312
00313 GetDefaultTextColors(nc, rc);
00314 SetDefaultTextColors("black", "red");
00315
00316
00317 Video.FillRectangle(backgroundColor, x, y, popupWidth, popupHeight);
00318 Video.DrawRectangle(ColorBlack, x, y, popupWidth, popupHeight);
00319
00320
00321 VideoDrawText(x + 5, y + 3, SmallFont, button->Hint);
00322
00323 SetDefaultTextColors(nc, rc);
00324 return;
00325 }
00326
00327 int popupWidth = 140;
00328 int popupHeight = 115;
00329 std::string nc, rc;
00330 CUnitType *type;
00331
00332 int x = std::min(uibutton->X, Video.Width - 1 - popupWidth);
00333 int y = uibutton->Y - popupHeight - 10;
00334 type = UnitTypes[button->Value];
00335
00336 GetDefaultTextColors(nc, rc);
00337 SetDefaultTextColors("black", "red");
00338
00339
00340 Video.FillRectangle(backgroundColor, x, y, popupWidth, popupHeight);
00341 Video.DrawRectangle(ColorBlack, x, y, popupWidth, popupHeight);
00342
00343
00344 VideoDrawText(x + 5, y + 3, SmallFont, type->Name);
00345 Video.DrawHLine(ColorBlack, x, y + 15, popupWidth);
00346
00347 y += 20;
00348
00349
00350 for (int i = 0; i < MaxCosts; ++i) {
00351 if (type->ProductionCosts[i]) {
00352 if (UI.Resources[i].G) {
00353 UI.Resources[i].G->DrawFrameClip(UI.Resources[i].IconFrame,
00354 x + 5 + 60 * i, y);
00355 }
00356 VideoDrawNumber(x + 20 + 60 * i, y, SmallFont, type->ProductionCosts[i] / CYCLES_PER_SECOND);
00357 }
00358 }
00359 y += 15;
00360
00361
00362 std::ostringstream hitPoints;
00363 hitPoints << "Hit Points: " << type->Variable[HP_INDEX].Value;
00364 VideoDrawText(x + 5, y, SmallFont, hitPoints.str());
00365 y += 15;
00366
00367 if (type->CanAttack) {
00368
00369 int min_damage = std::max(1, type->Variable[PIERCINGDAMAGE_INDEX].Value / 2);
00370 int max_damage = type->Variable[PIERCINGDAMAGE_INDEX].Value + type->Variable[BASICDAMAGE_INDEX].Value;
00371 std::ostringstream damage;
00372 damage << "Damage: " << min_damage << "-" << max_damage;
00373 VideoDrawText(x + 5, y, SmallFont, damage.str());
00374 y += 15;
00375
00376
00377 std::ostringstream attackRange;
00378 attackRange << "Attack Range: " << type->Variable[ATTACKRANGE_INDEX].Value;
00379 VideoDrawText(x + 5, y, SmallFont, attackRange.str());
00380 y += 15;
00381 }
00382
00383
00384 std::ostringstream armor;
00385 armor << "Armor: " << type->Variable[ARMOR_INDEX].Value;
00386 VideoDrawText(x + 5, y, SmallFont, armor.str());
00387 y += 15;
00388
00389 if (type->Variable[RADAR_INDEX].Value) {
00390
00391 std::ostringstream radarRange;
00392 radarRange << "Radar Range: " << type->Variable[RADAR_INDEX].Value;
00393 VideoDrawText(x + 5, y, SmallFont, radarRange.str());
00394 } else {
00395
00396 std::ostringstream sightRange;
00397 sightRange << "Sight Range: " << type->Variable[SIGHTRANGE_INDEX].Value;
00398 VideoDrawText(x + 5, y, SmallFont, sightRange.str());
00399 }
00400 y += 15;
00401
00402 SetDefaultTextColors(nc, rc);
00403 }
00404
00410 void CButtonPanel::Draw(void)
00411 {
00412 CPlayer *player;
00413 const ButtonAction *buttons;
00414 char buf[8];
00415
00416
00417
00418
00419 if (UI.ButtonPanel.G) {
00420 UI.ButtonPanel.G->DrawClip(UI.ButtonPanel.X, UI.ButtonPanel.Y);
00421 }
00422
00423
00424 if (!(buttons = CurrentButtons)) {
00425 return;
00426 }
00427
00428 Assert(NumSelected > 0);
00429 player = Selected[0]->Player;
00430
00431
00432
00433
00434 for (int i = 0; i < (int)UI.ButtonPanel.Buttons.size(); ++i) {
00435 if (buttons[i].Pos == -1) {
00436 continue;
00437 }
00438 Assert(buttons[i].Pos == i + 1);
00439
00440
00441
00442
00443 if (ShowCommandKey) {
00444 if (CurrentButtons[i].Key == gcn::Key::ESCAPE) {
00445 strcpy_s(buf, sizeof(buf), "ESC");
00446 } else {
00447 buf[0] = toupper(CurrentButtons[i].Key);
00448 buf[1] = '\0';
00449 }
00450 } else {
00451 buf[0] = '\0';
00452 }
00453
00454
00455
00456
00457 buttons[i].Icon.Icon->DrawUnitIcon(player, UI.ButtonPanel.Buttons[i].Style,
00458 GetButtonStatus(&buttons[i]),
00459 UI.ButtonPanel.Buttons[i].X, UI.ButtonPanel.Buttons[i].Y, buf);
00460
00461
00462
00463
00464 if (ButtonAreaUnderCursor == ButtonAreaButton &&
00465 ButtonUnderCursor == i && KeyState != KeyStateInput) {
00466 DrawPopup();
00467 UpdateStatusLineForButton(&buttons[i]);
00468 }
00469 }
00470 }
00471
00477 void UpdateStatusLineForButton(const ButtonAction *button)
00478 {
00479 Assert(button);
00480 UI.StatusLine.Set(button->Hint);
00481
00482 switch (button->Action) {
00483 case ButtonBuild:
00484 case ButtonTrain:
00485 SetCosts(0, UnitTypes[button->Value]->ProductionCosts);
00486 break;
00487 case ButtonSpellCast:
00488 SetCosts(SpellTypeTable[button->Value]->ManaCost, NULL);
00489 break;
00490 default:
00491 ClearCosts();
00492 break;
00493 }
00494 }
00495
00496
00497
00498
00499
00510 static bool IsButtonAllowed(const CUnit *unit, const ButtonAction *buttonaction)
00511 {
00512 bool res;
00513
00514 Assert(unit);
00515 Assert(buttonaction);
00516
00517 if (buttonaction->Allowed) {
00518 return buttonaction->Allowed(unit, buttonaction);
00519 }
00520
00521 res = false;
00522
00523
00524
00525 switch (buttonaction->Action) {
00526 case ButtonStop:
00527 case ButtonStandGround:
00528 case ButtonButton:
00529 case ButtonMove:
00530 case ButtonHarvest:
00531 res = true;
00532 break;
00533 case ButtonRepair:
00534 res = unit->Type->RepairRange > 0;
00535 break;
00536 case ButtonPatrol:
00537 res = CanMove(unit);
00538 break;
00539 case ButtonAttack:
00540 res = ButtonCheckAttack(unit, buttonaction);
00541 break;
00542 case ButtonAttackGround:
00543 if (unit->Type->GroundAttack) {
00544 res = true;
00545 }
00546 break;
00547 case ButtonTrain:
00548 case ButtonBuild:
00549 res = true;
00550 break;
00551 case ButtonSpellCast:
00552 res = SpellIsAvailable(unit->Player, buttonaction->Value);
00553 break;
00554 case ButtonUnload:
00555 res = (Selected[0]->Type->CanTransport && Selected[0]->BoardCount);
00556 break;
00557 case ButtonCancel:
00558 res = true;
00559 break;
00560 case ButtonCancelTrain:
00561 res = unit->Orders[0]->Action == UnitActionTrain;
00562 break;
00563 case ButtonCancelBuild:
00564 res = unit->Orders[0]->Action == UnitActionBuilt;
00565 break;
00566 }
00567 #if 0
00568
00569 if (res && buttonaction->Disabled) {
00570 return buttonaction->Disabled(unit, buttonaction);
00571 }
00572 #endif
00573 return res;
00574 }
00575
00584 static ButtonAction *UpdateButtonPanelMultipleUnits(void)
00585 {
00586 std::string unit_ident;
00587 int z;
00588 ButtonAction *res;
00589 bool allow;
00590
00591 res = new ButtonAction[UI.ButtonPanel.Buttons.size()];
00592 for (z = 0; z < (int)UI.ButtonPanel.Buttons.size(); ++z) {
00593 res[z].Pos = -1;
00594 }
00595
00596
00597 unit_ident = ",elites-group,";
00598
00599 for (z = 0; z < (int)UnitButtonTable.size(); ++z) {
00600 if (UnitButtonTable[z]->Level != CurrentButtonLevel) {
00601 continue;
00602 }
00603
00604
00605 if (UnitButtonTable[z]->UnitMask[0] != '*' &&
00606 UnitButtonTable[z]->UnitMask.find(unit_ident) == std::string::npos) {
00607 continue;
00608 }
00609 allow = true;
00610 for (int i = 0; i < NumSelected; i++) {
00611 if (!IsButtonAllowed(Selected[i], UnitButtonTable[z])) {
00612 allow = false;
00613 break;
00614 }
00615 }
00616 Assert(1 <= UnitButtonTable[z]->Pos);
00617 Assert(UnitButtonTable[z]->Pos <= (int)UI.ButtonPanel.Buttons.size());
00618
00619
00620 if (allow) {
00621
00622 res[UnitButtonTable[z]->Pos - 1] = *UnitButtonTable[z];
00623 }
00624 }
00625 return res;
00626 }
00627
00638 static ButtonAction *UpdateButtonPanelSingleUnit(const CUnit *unit)
00639 {
00640 int allow;
00641 std::string unit_ident;
00642 ButtonAction *buttonaction;
00643 ButtonAction *res;
00644 int z;
00645
00646 Assert(unit);
00647
00648 res = new ButtonAction[UI.ButtonPanel.Buttons.size()];
00649 for (z = 0; z < (int)UI.ButtonPanel.Buttons.size(); ++z) {
00650 res[z].Pos = -1;
00651 }
00652
00653
00654
00655
00656 if (unit->Orders[0]->Action == UnitActionBuilt) {
00657
00658 unit_ident = ",cancel-build,";
00659 } else {
00660 unit_ident = "," + unit->Type->Ident + ",";
00661 }
00662
00663 for (z = 0; z < (int)UnitButtonTable.size(); ++z) {
00664 int pos;
00665
00666 buttonaction = UnitButtonTable[z];
00667 Assert(0 < buttonaction->Pos && buttonaction->Pos <= (int)UI.ButtonPanel.Buttons.size());
00668
00669
00670 if (buttonaction->Level != CurrentButtonLevel) {
00671 continue;
00672 }
00673
00674
00675 if (buttonaction->UnitMask[0] != '*' &&
00676 buttonaction->UnitMask.find(unit_ident) == std::string::npos) {
00677 continue;
00678 }
00679 allow = IsButtonAllowed(unit, buttonaction);
00680
00681 pos = buttonaction->Pos;
00682
00683
00684 if (allow) {
00685
00686 res[pos - 1] = *buttonaction;
00687 }
00688 }
00689 return res;
00690 }
00691
00697 void CButtonPanel::Update(void)
00698 {
00699 CUnit *unit;
00700 bool sameType;
00701
00702
00703 delete[] CurrentButtons;
00704 CurrentButtons = NULL;
00705
00706 if (!NumSelected) {
00707 return;
00708 }
00709
00710 unit = Selected[0];
00711
00712 if (unit->Player != ThisPlayer && !ThisPlayer->IsTeamed(unit)) {
00713 return;
00714 }
00715
00716 sameType = true;
00717
00718 for (int i = 1; i < NumSelected; ++i) {
00719 if (Selected[i]->Type != unit->Type) {
00720 sameType = false;
00721 break;
00722 }
00723 }
00724
00725
00726 if (!sameType) {
00727 CurrentButtons = UpdateButtonPanelMultipleUnits();
00728 } else {
00729
00730
00731 CurrentButtons = UpdateButtonPanelSingleUnit(unit);
00732 }
00733 }
00734
00740 void CButtonPanel::DoClicked(int button)
00741 {
00742 int i;
00743 CUnitType *type;
00744
00745 Assert(0 <= button && button < (int)UI.ButtonPanel.Buttons.size());
00746
00747 if (!CurrentButtons) {
00748 return;
00749 }
00750
00751
00752
00753
00754 if (CurrentButtons[button].Pos == -1 ||
00755 !ThisPlayer->IsTeamed(Selected[0])) {
00756 return;
00757 }
00758
00759 PlayGameSound(GameSounds.Click.Sound, MaxSampleVolume);
00760
00761
00762
00763
00764 switch (CurrentButtons[button].Action) {
00765 case ButtonUnload:
00766
00767
00768
00769
00770 if ((NumSelected == 1 && Selected[0]->Orders[0]->Action == UnitActionStill &&
00771 Map.CoastOnMap(Selected[0]->X, Selected[0]->Y)) || !CanMove(Selected[0])) {
00772 SendCommandUnload(Selected[0],
00773 Selected[0]->X, Selected[0]->Y, NoUnitP,
00774 !(KeyModifiers & ModifierShift));
00775 break;
00776 }
00777 CursorState = CursorStateSelect;
00778 GameCursor = UI.YellowHair.Cursor;
00779 CursorAction = CurrentButtons[button].Action;
00780 CursorValue = CurrentButtons[button].Value;
00781 CurrentButtonLevel = 9;
00782 UI.ButtonPanel.Update();
00783 UI.StatusLine.Set(_("Select Target"));
00784 break;
00785 case ButtonSpellCast:
00786 if (KeyModifiers & ModifierControl) {
00787 int autocast;
00788 int spellId;
00789
00790 spellId = CurrentButtons[button].Value;
00791 if (!SpellTypeTable[spellId]->AutoCast) {
00792 PlayGameSound(GameSounds.PlacementError.Sound,
00793 MaxSampleVolume);
00794 break;
00795 }
00796
00797 autocast = 0;
00798
00799
00800 for (i = 0; i < NumSelected; ++i) {
00801 if (Selected[i]->AutoCastSpell[spellId] == 0) {
00802 autocast = 1;
00803 break;
00804 }
00805 }
00806 for (i = 0; i < NumSelected; ++i) {
00807 if (Selected[i]->AutoCastSpell[spellId] != autocast) {
00808 SendCommandAutoSpellCast(Selected[i],
00809 spellId, autocast);
00810 }
00811 }
00812 break;
00813 }
00814
00815 case ButtonRepair:
00816 if (KeyModifiers & ModifierControl) {
00817 unsigned autorepair;
00818
00819 autorepair = 0;
00820
00821
00822 for (i = 0; i < NumSelected; ++i) {
00823 if (Selected[i]->AutoRepair == 0) {
00824 autorepair = 1;
00825 break;
00826 }
00827 }
00828 for (i = 0; i < NumSelected; ++i) {
00829 if (Selected[i]->AutoRepair != autorepair) {
00830 SendCommandAutoRepair(Selected[i], autorepair);
00831 }
00832 }
00833 break;
00834 }
00835
00836 case ButtonMove:
00837 case ButtonPatrol:
00838 case ButtonHarvest:
00839 case ButtonAttack:
00840 case ButtonAttackGround:
00841
00842 CursorState = CursorStateSelect;
00843 GameCursor = UI.YellowHair.Cursor;
00844 CursorAction = CurrentButtons[button].Action;
00845 CursorValue = CurrentButtons[button].Value;
00846 CurrentButtonLevel = 9;
00847 UI.ButtonPanel.Update();
00848 UI.StatusLine.Set(_("Select Target"));
00849 break;
00850 case ButtonStop:
00851 for (i = 0; i < NumSelected; ++i) {
00852 SendCommandStopUnit(Selected[i]);
00853 }
00854 break;
00855 case ButtonStandGround:
00856 for (i = 0; i < NumSelected; ++i) {
00857 SendCommandStandGround(Selected[i],
00858 !(KeyModifiers & ModifierShift));
00859 }
00860 break;
00861 case ButtonButton:
00862 CurrentButtonLevel = CurrentButtons[button].Value;
00863 UI.ButtonPanel.Update();
00864 break;
00865
00866 case ButtonCancel:
00867 UI.StatusLine.Clear();
00868 ClearCosts();
00869 CurrentButtonLevel = 0;
00870 UI.ButtonPanel.Update();
00871 GameCursor = UI.Point.Cursor;
00872 CursorBuilding = NULL;
00873 CursorState = CursorStatePoint;
00874 break;
00875
00876 case ButtonCancelTrain:
00877 Assert(Selected[0]->Orders[0]->Action == UnitActionTrain);
00878 SendCommandCancelTraining(Selected[0], -1, NULL);
00879 UI.StatusLine.Clear();
00880 ClearCosts();
00881 break;
00882
00883 case ButtonCancelBuild:
00884
00885 Assert(Selected[0]->Orders[0]->Action == UnitActionBuilt);
00886 if (NumSelected == 1) {
00887 SendCommandDismiss(Selected[0]);
00888 }
00889 UI.StatusLine.Clear();
00890 ClearCosts();
00891 break;
00892
00893 case ButtonBuild:
00894
00895 type = UnitTypes[CurrentButtons[button].Value];
00896 UI.StatusLine.Set(_("Select Location"));
00897 ClearCosts();
00898 CursorBuilding = type;
00899
00900 CurrentButtonLevel = 9;
00901 UI.ButtonPanel.Update();
00902 break;
00903
00904 case ButtonTrain:
00905
00906 type = UnitTypes[CurrentButtons[button].Value];
00907
00908
00909
00910 if (Selected[0]->Player->CheckLimits(type) >= 0) {
00911 SendCommandTrainUnit(Selected[0], type,
00912 !(KeyModifiers & ModifierShift));
00913 UI.StatusLine.Clear();
00914 ClearCosts();
00915 }
00916 break;
00917 }
00918 }
00919
00920
00928 int CButtonPanel::DoKey(int key)
00929 {
00930 SDL_keysym keysym;
00931 memset(&keysym, 0, sizeof(keysym));
00932 keysym.sym = (SDLKey)key;
00933 gcn::Key k = gcn::SDLInput::convertKeyCharacter(keysym);
00934 key = k.getValue();
00935
00936 if (CurrentButtons) {
00937
00938 if (isascii(key) && isupper(key)) {
00939 key = tolower(key);
00940 }
00941
00942 for (int i = 0; i < (int)UI.ButtonPanel.Buttons.size(); ++i) {
00943 if (CurrentButtons[i].Pos != -1 && key == CurrentButtons[i].Key) {
00944 UI.ButtonPanel.DoClicked(i);
00945 return 1;
00946 }
00947 }
00948 }
00949 return 0;
00950 }
00951