C4Viewport *C4Menu::GetViewport() { // ask all viewports for (C4Viewport *pVP = ::Viewports.GetFirstViewport(); pVP; pVP = pVP->GetNext()) if (pVP->IsViewportMenu(this)) return pVP; // none matching return NULL; }
static gboolean OnConfigureDareaStatic(GtkWidget* widget, GdkEventConfigure* event, gpointer user_data) { C4ViewportWindow* window = static_cast<C4ViewportWindow*>(user_data); C4Viewport* cvp = window->cvp; cvp->UpdateOutputSize(); return false; }
bool C4FullScreen::ViewportCheck() { int iPlrNum; C4Player *pPlr; // Not active if (!Active) return false; // Determine film mode bool fFilm = (Game.C4S.Head.Replay && Game.C4S.Head.Film); // Check viewports switch (::Viewports.GetViewportCount()) { // No viewports: create no-owner viewport case 0: iPlrNum = NO_OWNER; // Film mode: create viewport for first player (instead of no-owner) if (fFilm) if ((pPlr = ::Players.First)) iPlrNum = pPlr->Number; // Create viewport ::Viewports.CreateViewport(iPlrNum, iPlrNum==NO_OWNER); // Non-film (observer mode) if (!fFilm) { // Activate mouse control ::MouseControl.Init(iPlrNum); // Display message for how to open observer menu (this message will be cleared if any owned viewport opens) StdStrBuf sKey; sKey.Format("<c ffff00><%s></c>", Game.KeyboardInput.GetKeyCodeNameByKeyName("FullscreenMenuOpen", false).getData()); ::GraphicsSystem.FlashMessage(FormatString(LoadResStr("IDS_MSG_PRESSORPUSHANYGAMEPADBUTT"), sKey.getData()).getData()); } break; // One viewport: do nothing case 1: break; // More than one viewport: remove all no-owner viewports default: ::Viewports.CloseViewport(NO_OWNER, true); break; } // Look for no-owner viewport C4Viewport *pNoOwnerVp = ::Viewports.GetViewport(NO_OWNER); // No no-owner viewport found if (!pNoOwnerVp) { // Close any open fullscreen menu CloseMenu(); } // No-owner viewport present else { // movie mode: player present, and no valid viewport assigned? if (Game.C4S.Head.Replay && Game.C4S.Head.Film && (pPlr = ::Players.First)) // assign viewport to joined player pNoOwnerVp->Init(pPlr->Number, true); } // Done return true; }
bool C4GraphicsSystem::ViewportNextPlayer() { // safety: switch valid? if ((!Game.C4S.Head.Film || !Game.C4S.Head.Replay) && !Game.GraphicsSystem.GetViewport(NO_OWNER)) return false; // do switch then C4Viewport *vp = GetFirstViewport(); if (!vp) return false; vp->NextPlayer(); return true; }
bool C4Video::AdjustPosition() { // Get source player & viewport C4Viewport *pViewport = Game.GraphicsSystem.GetFirstViewport(); if (!pViewport) return false; C4Player *pPlr = Game.Players.Get(pViewport->GetPlayer()); if (!pPlr) return false; // Set camera position X = pPlr->ViewX - pViewport->ViewX + pViewport->DrawX - Width/2; X = BoundBy( X, 0, pViewport->ViewWdt - Width ); Y = pPlr->ViewY - pViewport->ViewY + pViewport->DrawY - Height/2; Y = BoundBy( Y, 0, pViewport->ViewHgt - Height ); // Success return true; }
BOOL C4GraphicsSystem::CreateViewport(int32_t iPlayer, bool fSilent) { // Create and init new viewport, add to viewport list int32_t iLastCount = GetViewportCount(); C4Viewport *nvp = new C4Viewport; BOOL fOkay = FALSE; if (Application.isFullScreen) fOkay = nvp->Init(iPlayer, false); else fOkay = nvp->Init(&Console,&Application,iPlayer); if (!fOkay) { delete nvp; return FALSE; } C4Viewport *pLast; for (pLast=FirstViewport; pLast && pLast->Next; pLast=pLast->Next); if (pLast) pLast->Next=nvp; else FirstViewport=nvp; // Recalculate viewports RecalculateViewports(); // Viewports start off at centered position nvp->CenterPosition(); // Action sound if (GetViewportCount()!=iLastCount) if (!fSilent) StartSoundEffect("CloseViewport"); return TRUE; }
void C4GraphicsSystem::RecalculateViewports() { // Fullscreen only if (!Application.isFullScreen) return; // Sort viewports SortViewportsByPlayerControl(); // Viewport area int32_t iBorderTop = 0, iBorderBottom = 0; if (Config.Graphics.UpperBoard) iBorderTop = C4UpperBoardHeight; iBorderBottom = MessageBoard.Output.Hgt; ViewportArea.Set(Application.DDraw->lpBack,0,iBorderTop, Config.Graphics.ResX, Config.Graphics.ResY-iBorderTop-iBorderBottom); // Redraw flag InvalidateBg(); #ifdef _WIN32 // reset mouse clipping ClipCursor(NULL); #else // StdWindow handles this. #endif // reset GUI dlg pos if (Game.pGUI) Game.pGUI->SetPreferredDlgRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt)); // fullscreen background: First, cover all of screen BackgroundAreas.Clear(); BackgroundAreas.AddRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt)); // Viewports C4Viewport *cvp; int32_t iViews = 0; for (cvp=FirstViewport; cvp; cvp=cvp->Next) iViews++; if (!iViews) return; int32_t iViewsH = (int32_t) sqrt(float(iViews)); int32_t iViewsX = iViews / iViewsH; int32_t iViewsL = iViews % iViewsH; int32_t cViewH,cViewX,ciViewsX; int32_t cViewWdt,cViewHgt,cOffWdt,cOffHgt,cOffX,cOffY; cvp=FirstViewport; for (cViewH=0; cViewH<iViewsH; cViewH++) { ciViewsX = iViewsX; if (cViewH<iViewsL) ciViewsX++; for (cViewX=0; cViewX<ciViewsX; cViewX++) { cViewWdt = ViewportArea.Wdt/ciViewsX; cViewHgt = ViewportArea.Hgt/iViewsH; cOffX = ViewportArea.X; cOffY = ViewportArea.Y; cOffWdt=cOffHgt=0; int32_t ViewportScrollBorder = Application.isFullScreen ? C4ViewportScrollBorder : 0; if (ciViewsX*Min<int32_t>(cViewWdt, GBackWdt+2*ViewportScrollBorder)<ViewportArea.Wdt) cOffX=(ViewportArea.Wdt-ciViewsX*Min<int32_t>(cViewWdt, GBackWdt+2*ViewportScrollBorder))/2; if (iViewsH*Min<int32_t>(cViewHgt, GBackHgt+2*ViewportScrollBorder)<ViewportArea.Hgt) cOffY=(ViewportArea.Hgt-iViewsH*Min<int32_t>(cViewHgt, GBackHgt+2*ViewportScrollBorder))/2 + ViewportArea.Y; if (Config.Graphics.SplitscreenDividers) { if (cViewX<ciViewsX-1) cOffWdt=4; if (cViewH<iViewsH-1) cOffHgt=4; } int32_t coViewWdt=cViewWdt-cOffWdt; if (coViewWdt>GBackWdt+2*ViewportScrollBorder) { coViewWdt=GBackWdt+2*ViewportScrollBorder; } int32_t coViewHgt=cViewHgt-cOffHgt; if (coViewHgt>GBackHgt+2*ViewportScrollBorder) { coViewHgt=GBackHgt+2*ViewportScrollBorder; } C4Rect rcOut(cOffX+cViewX*cViewWdt, cOffY+cViewH*cViewHgt, coViewWdt, coViewHgt); cvp->SetOutputSize(rcOut.x,rcOut.y,rcOut.x,rcOut.y,rcOut.Wdt,rcOut.Hgt); cvp=cvp->Next; // clip down area avaiable for background drawing BackgroundAreas.ClipByRect(rcOut); } } }
static gboolean OnExposeStatic(GtkWidget* widget, void *, gpointer user_data) { C4Viewport* cvp = static_cast<C4ViewportWindow*>(user_data)->cvp; cvp->Execute(); return true; }
bool Screen::MouseInput(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, Dialog *pForDlg, class C4Viewport *pForVP) { // help mode and button pressed: Abort help and discard button if (Game.MouseControl.IsHelp()) { switch (iButton) { case C4MC_Button_None: // just movement break; case C4MC_Button_LeftDown: case C4MC_Button_RightDown: // special for left/right down: Just ignore them, but don't stop help yet // help should be stopped on button-up, so these won't be processed iButton = C4MC_Button_None; break; default: // buttons stop help Game.MouseControl.AbortHelp(); iButton = C4MC_Button_None; break; } } // forward to mouse Mouse.Input(iButton, iX, iY, dwKeyParam); // dragging if (Mouse.pDragElement) { int32_t iX2=iX, iY2=iY; Mouse.pDragElement->ScreenPos2ClientPos(iX2, iY2); if (!Mouse.IsLDown()) { // stop dragging Mouse.pDragElement->StopDragging(Mouse, iX2, iY2, dwKeyParam); Mouse.pDragElement = NULL; } else { // continue dragging Mouse.pDragElement->DoDragging(Mouse, iX2, iY2, dwKeyParam); } } // backup previous MouseOver-element Mouse.pPrevMouseOverElement = Mouse.pMouseOverElement; Mouse.pMouseOverElement = NULL; bool fProcessed = false; // active context menu? if (!pForVP && pContext && pContext->CtxMouseInput(Mouse, iButton, iX, iY, dwKeyParam)) { // processed by context menu: OK! } // otherwise: active dlg and inside screen? (or direct forward to specific dlg/viewport dlg) else if (rcBounds.Contains(iX, iY) || pForDlg || pForVP) { // context menu open but mouse down command issued? close context then if (pContext && (iButton == C4MC_Button_LeftDown || iButton == C4MC_Button_RightDown)) AbortContext(true); // get client pos if (!pForDlg && !pForVP) { C4Rect &rcClientArea = GetClientRect(); iX -= rcClientArea.x; iY -= rcClientArea.y; } // exclusive mode: process active dialog only if (IsExclusive() && !pForDlg && !pForVP) { if (pActiveDlg && pActiveDlg->IsVisible() && !pActiveDlg->IsFading()) { // bounds check to dlg: only if not dragging C4Rect &rcDlgBounds = pActiveDlg->GetBounds(); if (Mouse.IsLDown() || rcDlgBounds.Contains(iX, iY)) // forward to active dialog pActiveDlg->MouseInput(Mouse, iButton, iX - rcDlgBounds.x, iY - rcDlgBounds.y, dwKeyParam); else Mouse.pMouseOverElement = NULL; } else // outside dialog: own handling (for screen context menu) Window::MouseInput(Mouse, iButton, iX, iY, dwKeyParam); } else { // non-exclusive mode: process all dialogs; make them active on left-click Dialog *pDlg; for (Element *pEl = pLast; pEl; pEl = pEl->GetPrev()) if (pDlg = pEl->GetDlg()) if (pDlg->IsShown()) { // if specified: process specified dlg only if (pForDlg && pDlg != pForDlg) continue; // if specified: process specified viewport only bool fIsExternalDrawDialog = pDlg->IsExternalDrawDialog(); C4Viewport *pVP = fIsExternalDrawDialog ? pDlg->GetViewport() : NULL; if (pForVP && pForVP != pVP) continue; // calc offset C4Rect &rcDlgBounds = pDlg->GetBounds(); int32_t iOffX=0, iOffY=0; // special handling for viewport dialogs if (fIsExternalDrawDialog) { // ignore external drawing dialogs without a viepwort assigned if (!pVP) continue; // always clip to viewport bounds C4Rect rcOut(pVP->GetOutputRect()); if (!rcOut.Contains(iX + rcBounds.x, iY + rcBounds.y)) continue; // viewport dialogs: Offset determined by viewport position iOffX = rcOut.x; iOffY = rcOut.y; } // hit test; or special: dragging possible outside active dialog if (rcDlgBounds.Contains(iX-iOffX, iY-iOffY) || (pDlg == pActiveDlg && Mouse.pDragElement)) { // Okay; do input pDlg->MouseInput(Mouse, iButton, iX - rcDlgBounds.x - iOffX, iY - rcDlgBounds.y - iOffY, dwKeyParam); // dlgs may destroy GUI if (!IsGUIValid()) return false; // CAUTION: pDlg may be invalid now! // set processed-flag manually fProcessed = true; // inactive dialogs get activated by clicks if (Mouse.IsLDown() && pDlg != pActiveDlg) // but not viewport dialogs! if (!pDlg->IsExternalDrawDialog()) ActivateDialog(pDlg); // one dlg only; break loop here break; } } } // check valid GUI; might be destroyed by mouse input if (!IsGUIValid()) return false; } // check if MouseOver has changed if (Mouse.pPrevMouseOverElement != Mouse.pMouseOverElement) { // send events if (Mouse.pPrevMouseOverElement) Mouse.pPrevMouseOverElement->MouseLeave(Mouse); if (Mouse.pMouseOverElement) Mouse.pMouseOverElement->MouseEnter(Mouse); } // return whether anything processed it return fProcessed || Mouse.pDragElement || (Mouse.pMouseOverElement && Mouse.pMouseOverElement!=this) || pContext; }
bool C4MainMenu::MenuCommand(const char *szCommand, bool fIsCloseCommand) { // Determine player C4Player *pPlr = ::Players.Get(Player); // Activate if (SEqual2(szCommand,"ActivateMenu:")) { if (C4GameOverDlg::IsShown()) return false; // no new menus during game over dlg if (SEqual(szCommand+13,"Main")) return ActivateMain(Player); if (SEqual(szCommand+13,"Hostility")) return ActivateHostility(Player); if (SEqual(szCommand+13,"NewPlayer")) return ActivateNewPlayer(Player); if (SEqual(szCommand+13,"Goals")) { ::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::ActivateGoalMenu(::Players.Get(Player)), CDT_Queue); return true; } if (SEqual(szCommand+13,"Rules")) return ActivateRules(Player); if (SEqual(szCommand+13,"Host")) return ActivateHost(Player); if (SEqual(szCommand+13,"Client")) return ActivateClient(Player); if (SEqual(szCommand+13,"Options")) return ActivateOptions(Player); if (SEqual(szCommand+13,"Display")) return ActivateDisplay(Player); if (SEqual(szCommand+13,"Save:Game")) return ActivateSavegame(Player); if (SEqual(szCommand+13,"TeamSel")) return pPlr ? pPlr->ActivateMenuTeamSelection(true) : false; if (SEqual(szCommand+13,"Surrender")) return ActivateSurrender(Player); if (SEqual(szCommand+13,"Observer")) return ActivateObserver(); } // JoinPlayer if (SEqual2(szCommand,"JoinPlayer:")) { // not in league or replay mode if (Game.Parameters.isLeague() || Game.C4S.Head.Replay) return false; // join player // 2do: not for observers and such? Players.JoinNew(szCommand+11); return true; } // SetHostility if (SEqual2(szCommand,"SetHostility:")) { // only if allowed if (!Game.Teams.IsHostilityChangeAllowed()) return false; int32_t iOpponent; sscanf(szCommand+13,"%i",&iOpponent); C4Player *pOpponent = ::Players.Get(iOpponent); if (!pOpponent || pOpponent->GetType() != C4PT_User) return false; ::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::SetHostility(::Players.Get(Player), pOpponent, !::Players.HostilityDeclared(Player, pOpponent->Number)), CDT_Queue); return true; } // Abort if (SEqual2(szCommand,"Abort")) { FullScreen.ShowAbortDlg(); return true; } // Surrender if (SEqual2(szCommand,"Surrender")) { ::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::Surrender(::Players.Get(Player)), CDT_Queue); return true; } // Save game if (SEqual2(szCommand, "Save:Game:")) { char strFilename[_MAX_PATH + 1]; SCopySegment(szCommand, 2, strFilename, ':', _MAX_PATH); char strTitle[_MAX_PATH + 1]; SCopy(szCommand + SCharPos(':', szCommand, 2) + 1, strTitle, _MAX_PATH); Game.QuickSave(strFilename, strTitle); ActivateSavegame(Player); return true; } // Kick if (SEqual2(szCommand,"Host:Kick:")) { int iClientID = atoi(szCommand+10); if (iClientID && ::Network.isEnabled()) { if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID)) ::Network.Vote(VT_Kick, true, iClientID); else { C4Client *pClient = Game.Clients.getClientByID(iClientID); if (pClient) Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKBYMENU")); Close(true); } } return true; } // Part if (SEqual2(szCommand,"Part")) { if (::Network.isEnabled()) { if (Game.Parameters.isLeague() && ::Players.GetLocalByIndex(0)) ::Network.Vote(VT_Kick, true, ::Control.ClientID()); else { Game.RoundResults.EvaluateNetwork(C4RoundResults::NR_NetError, LoadResStr("IDS_ERR_GAMELEFTVIAPLAYERMENU")); ::Network.Clear(); } } return true; } // Options if (SEqual2(szCommand,"Options:")) { // Music if (SEqual(szCommand + 8, "Music")) { Application.MusicSystem.ToggleOnOff(); } // Sound if (SEqual(szCommand + 8, "Sound")) { if (Config.Sound.RXSound) { Application.SoundSystem.Clear(); Config.Sound.RXSound = false; } else { Config.Sound.RXSound = true; if (!Application.SoundSystem.Init()) { Log(LoadResStr("IDS_PRC_NOSND")); } } } // Reopen with updated options ActivateOptions(Player, GetSelection()); return true; } // Display if (SEqual2(szCommand,"Display:")) { // Upper board if (SEqual(szCommand + 8, "UpperBoard")) { Config.Graphics.UpperBoard = !Config.Graphics.UpperBoard; ::Viewports.RecalculateViewports(); } // FPS if (SEqual(szCommand + 8, "FPS")) Config.General.FPS = !Config.General.FPS; // Player names if (SEqual(szCommand + 8, "PlayerNames")) Config.Graphics.ShowCrewNames = !Config.Graphics.ShowCrewNames; // Clonk names if (SEqual(szCommand + 8, "ClonkNames")) Config.Graphics.ShowCrewCNames = !Config.Graphics.ShowCrewCNames; // Clock if (SEqual(szCommand + 8, "Clock")) Config.Graphics.ShowClock = !Config.Graphics.ShowClock; // Reopen with updated options ActivateDisplay(Player, GetSelection()); return true; } // Goal info if (SEqual2(szCommand,"Player:Goal:") || SEqual2(szCommand,"Player:Rule:")) { if (!ValidPlr(Player)) return false; // observers may not look at goal/rule info, because it requires queue activation Close(true); C4Object *pObj; C4ID idItem(szCommand+12); C4Def * pDef = C4Id2Def(idItem); if (pDef && (pObj = ::Objects.Find(pDef))) ::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::ActivateGoal(::Players.Get(Player), pObj), CDT_Queue); else return false; return true; } // Team selection if (SEqual2(szCommand, "TeamSel:")) { Close(true); int32_t idTeam = atoi(szCommand+8); // OK, join this team if (pPlr) pPlr->DoTeamSelection(idTeam); return true; } // Team switch if (SEqual2(szCommand, "TeamSwitch:")) { Close(true); int32_t idTeam = atoi(szCommand+11); // check if it's still allowed if (!Game.Teams.IsTeamSwitchAllowed()) return false; // OK, join this team ::Control.DoInput(CID_PlrAction, C4ControlPlayerAction::SetTeam(::Players.Get(Player), idTeam), CDT_Queue); return true; } // Observe if (SEqual2(szCommand, "Observe:")) { const char *szObserverTarget = szCommand+8; C4Viewport *pVP = ::Viewports.GetViewport(NO_OWNER); if (pVP) // viewport may have closed meanwhile { if (SEqual(szObserverTarget, "Free")) { // free view pVP->Init(NO_OWNER, true); return true; } else { // view following player int32_t iPlr = atoi(szObserverTarget); if (ValidPlr(iPlr)) { pVP->Init(iPlr, true); return true; } } } return false; } // No valid command return false; }
bool C4MainMenu::DoRefillInternal(bool &rfRefilled) { // Variables C4FacetSurface fctSymbol; C4Player *pPlayer; C4IDList ListItems; C4Facet fctTarget; bool fWasEmpty = !GetItemCount(); // Refill switch (Identification) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_Hostility: { // Clear items ClearItems(); // Refill player if (!(pPlayer = ::Players.Get(Player))) return false; // Refill items C4Player *pPlr; int32_t iIndex; for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++) // Ignore player self and invisible if (pPlr != pPlayer) if (!pPlr->IsInvisible()) { // Symbol fctSymbol.Create(C4SymbolSize,C4SymbolSize); pPlayer->DrawHostility(fctSymbol,iIndex); // Message StdStrBuf sMsg; bool isFriendly = pPlayer->Hostility.find(pPlr) == pPlayer->Hostility.end(); if (isFriendly) sMsg.Format(LoadResStr("IDS_MENU_ATTACK"),pPlr->GetName()); else sMsg.Format(LoadResStr("IDS_MENU_NOATTACK"),pPlr->GetName()); // Command char szCommand[1000]; sprintf(szCommand,"SetHostility:%i",pPlr->Number); // Info caption char szInfoCaption[C4MaxTitle+1],szFriendly[50],szNot[30]=""; SCopy(LoadResStr(isFriendly ? "IDS_MENU_ATTACKHOSTILE" : "IDS_MENU_ATTACKFRIENDLY"),szFriendly); if (!isFriendly) SCopy(LoadResStr("IDS_MENU_ATTACKNOT"),szNot); sprintf(szInfoCaption,LoadResStr("IDS_MENU_ATTACKINFO"),pPlr->GetName(),szFriendly,szNot); if (iIndex==pPlayer->Number) SCopy(LoadResStr("IDS_MENU_ATTACKSELF"),szInfoCaption); // Add item Add(sMsg.getData(),fctSymbol,szCommand,C4MN_Item_NoCount,NULL,szInfoCaption); fctSymbol.Default(); } break; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_TeamSelection: case C4MN_TeamSwitch: { // Clear items ClearItems(); // add all teams as menu items // 2do: Icon C4Team *pTeam; int32_t i=0; bool fAddNewTeam=Game.Teams.IsAutoGenerateTeams(); for (;;) { pTeam = Game.Teams.GetTeamByIndex(i); if (pTeam) { // next regular team ++i; // do not add a new team if an empty team exists if (!pTeam->GetPlayerCount()) fAddNewTeam = false; } else if (fAddNewTeam) { // join new team fAddNewTeam = false; } else { // all teams done break; } // create team symbol: Icon spec if specified; otherwise flag for empty and crew for nonempty team fctSymbol.Create(C4SymbolSize,C4SymbolSize); const char *szIconSpec = pTeam ? pTeam->GetIconSpec() : NULL; bool fHasIcon = false; if (szIconSpec && *szIconSpec) { fHasIcon = Game.DrawTextSpecImage(fctSymbol, szIconSpec, NULL, pTeam->GetColor()); } if (!fHasIcon) { if (pTeam && pTeam->GetPlayerCount()) ::GraphicsResource.fctCrewClr.DrawClr(fctSymbol, true, pTeam->GetColor()); else C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team).Draw(fctSymbol, true); } StdStrBuf sTeamName; if (pTeam) { sTeamName.Take(pTeam->GetNameWithParticipants()); } else sTeamName.Ref(LoadResStr("IDS_PRC_NEWTEAM")); const char *szOperation = (Identification == C4MN_TeamSwitch) ? "TeamSwitch" : "TeamSel"; Add(sTeamName.getData(), fctSymbol,FormatString("%s:%d", szOperation, pTeam ? pTeam->GetID() : TEAMID_New).getData(), C4MN_Item_NoCount,NULL,FormatString(LoadResStr("IDS_MSG_JOINTEAM"), sTeamName.getData()).getData(), C4ID(pTeam ? pTeam->GetID() : 0)); fctSymbol.Default(); } break; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_Observer: // observer menu { // Clear items ClearItems(); // Check validity C4Viewport *pVP = ::Viewports.GetViewport(NO_OWNER); if (!pVP) return false; int32_t iInitialSelection = 0; // Add free view AddRefSym(LoadResStr("IDS_MSG_FREEVIEW"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Star), "Observe:Free", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MSG_FREELYSCROLLAROUNDTHEMAP")); // Add players C4Player *pPlr; int32_t iIndex; for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++) { // Ignore invisible if (!pPlr->IsInvisible()) { // Symbol fctSymbol.Create(C4SymbolSize,C4SymbolSize); ::GraphicsResource.fctPlayerClr.DrawClr(fctSymbol, true, pPlr->ColorDw); // Message StdStrBuf sMsg; DWORD dwClr = pPlr->ColorDw; sMsg.Format("<c %x>%s</c>", (unsigned int)C4GUI::MakeColorReadableOnBlack(dwClr), pPlr->GetName()); // Command StdStrBuf sCommand; sCommand.Format("Observe:%d", (int)pPlr->Number); // Info caption StdStrBuf sInfo; sInfo.Format(LoadResStr("IDS_TEXT_FOLLOWVIEWOFPLAYER"), pPlr->GetName()); // Add item Add(sMsg.getData(),fctSymbol,sCommand.getData(),C4MN_Item_NoCount,NULL,sInfo.getData()); fctSymbol.Default(); // check if this is the currently selected player if (pVP->GetPlayer() == pPlr->Number) iInitialSelection = GetItemCount()-1; } // Initial selection on followed player if (fWasEmpty) SetSelection(iInitialSelection, false, true); } } break; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default: // No internal refill needed return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } // Successfull internal refill rfRefilled = true; return true; }