OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4GameOverDlg.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2008-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // game over dialog showing winners and losers
17 
18 #include "C4Include.h"
19 #include "gui/C4GameOverDlg.h"
20 
21 #include "game/C4Application.h"
22 #include "object/C4Def.h"
23 #include "object/C4DefList.h"
24 #include "game/C4Game.h"
25 #include "game/C4FullScreen.h"
26 #include "player/C4Player.h"
28 #include "player/C4PlayerList.h"
29 #include "object/C4GameObjects.h"
30 #include "control/C4GameControl.h"
32 
33 
34 // ---------------------------------------------------
35 // C4GoalDisplay
36 
37 C4GoalDisplay::GoalPicture::GoalPicture(const C4Rect &rcBounds, C4ID idGoal, bool fFulfilled)
38  : C4GUI::Window(), idGoal(idGoal), fFulfilled(fFulfilled)
39 {
40  // bounds
41  SetBounds(rcBounds);
42  // can't get specialized desc from object at the moment because of potential script callbacks!
43  StdStrBuf strGoalName;
44  // just get desc from def
45  C4Def *pGoalDef = ::Definitions.ID2Def(idGoal);
46  if (pGoalDef)
47  {
48  strGoalName.Copy(pGoalDef->GetName());
49  // strGoalDesc.Copy(pGoalDef->GetDesc());
50  }
51  // get tooltip
52  StdStrBuf sToolTip;
53  if (fFulfilled)
54  sToolTip.Format(LoadResStr("IDS_DESC_GOALFULFILLED"), strGoalName.getData());
55  else
56  sToolTip.Format(LoadResStr("IDS_DESC_GOALNOTFULFILLED"), strGoalName.getData());
57  SetToolTip(sToolTip.getData());
58  // create buffered picture of goal definition
59  C4Def *pDrawDef = ::Definitions.ID2Def(idGoal);
60  if (pDrawDef)
61  {
62  Picture.Create(C4PictureSize, C4PictureSize);
63  // get an object instance to draw (optional; may be zero)
64  C4Object *pGoalObj = ::Objects.Find(pDrawDef);
65  // draw goal def!
66  pDrawDef->Draw(Picture, false, 0, pGoalObj);
67  }
68  // unfulfilled goal: grey out picture
69  if (!fFulfilled)
70  Picture.Grayscale(30);
71 }
72 
73 void C4GoalDisplay::GoalPicture::DrawElement(C4TargetFacet &cgo)
74 {
75  // draw area
76  C4Facet cgoDraw;
77  cgoDraw.Set(cgo.Surface, cgo.X+rcBounds.x+cgo.TargetX, cgo.Y+rcBounds.y+cgo.TargetY, rcBounds.Wdt, rcBounds.Hgt);
78  // draw buffered picture
79  Picture.Draw(cgoDraw);
80  // draw star symbol if fulfilled
81  if (fFulfilled)
82  {
83  cgoDraw.Set(cgoDraw.Surface, cgoDraw.X+cgoDraw.Wdt*1/2, cgoDraw.Y+cgoDraw.Hgt*1/2, cgoDraw.Wdt/2, cgoDraw.Hgt/2);
85  }
86 }
87 
88 void C4GoalDisplay::SetGoals(const C4IDList &rAllGoals, const C4IDList &rFulfilledGoals, int32_t iGoalSymbolHeight)
89 {
90  // clear previous
91  ClearChildren();
92  // determine goal display area by goal count
93  int32_t iGoalSymbolMargin = C4GUI_DefDlgSmallIndent;
94  int32_t iGoalSymbolAreaHeight = 2*iGoalSymbolMargin + iGoalSymbolHeight;
95  int32_t iGoalAreaWdt = GetClientRect().Wdt;
96  int32_t iGoalsPerRow = std::max<int32_t>(1, iGoalAreaWdt / iGoalSymbolAreaHeight);
97  int32_t iGoalCount = rAllGoals.GetNumberOfIDs();
98  int32_t iRowCount = (iGoalCount-1) / iGoalsPerRow + 1;
99  C4Rect rcNewBounds = GetBounds();
100  rcNewBounds.Hgt = GetMarginTop()+GetMarginBottom()+iRowCount*iGoalSymbolAreaHeight;
101  SetBounds(rcNewBounds);
102  C4GUI::ComponentAligner caAll(GetClientRect(), 0,0, true);
103  // place goal symbols in this area
104  int32_t iGoal = 0;
105  for (int32_t iRow=0; iRow<iRowCount; ++iRow)
106  {
107  int32_t iColCount = std::min<int32_t>(iGoalCount - iGoal, iGoalsPerRow);
108  C4GUI::ComponentAligner caGoalArea(caAll.GetFromTop(iGoalSymbolAreaHeight, iColCount*iGoalSymbolAreaHeight), iGoalSymbolMargin,iGoalSymbolMargin, false);
109  for (int32_t iCol=0; iCol<iColCount; ++iCol,++iGoal)
110  {
111  C4ID idGoal = rAllGoals.GetID(iGoal);
112  bool fFulfilled = !!rFulfilledGoals.GetIDCount(idGoal, 1);
113  AddElement(new GoalPicture(caGoalArea.GetGridCell(iCol, iColCount, iRow, iRowCount), idGoal, fFulfilled));
114  }
115  }
116 }
117 
118 // ---------------------------------------------------
119 // C4GameOverDlg
120 
121 bool C4GameOverDlg::is_shown = false;
122 
123 C4GameOverDlg::C4GameOverDlg() : C4GUI::Dialog( (C4GUI::GetScreenWdt() < 800) ? (C4GUI::GetScreenWdt()-10) : std::min<int32_t>(C4GUI::GetScreenWdt()-150, 800),
124  (C4GUI::GetScreenHgt() < 600) ? (C4GUI::GetScreenHgt()-10) : std::min<int32_t>(C4GUI::GetScreenHgt()-150, 600),
125  LoadResStr("IDS_TEXT_EVALUATION"),
126  false), pNetResultLabel(nullptr), fIsNetDone(false), fHasNextMissionButton(false)
127 {
128  is_shown = true; // assume dlg will be shown, soon
129  UpdateOwnPos();
130  // indents / sizes
131  int32_t iDefBtnHeight = 32;
132  int32_t iIndentX1=10;
133  int32_t iIndentY1=6, iIndentY2=0;
134  // main screen components
135  C4GUI::ComponentAligner caMain(GetClientRect(), 0,iIndentY1,true);
136  int32_t iMainTextWidth = caMain.GetWidth() - 6*iIndentX1;
137  caMain.GetFromBottom(iIndentY2);
138  // lower button-area
139  C4GUI::ComponentAligner caBottom(caMain.GetFromBottom(iDefBtnHeight+iIndentY1*2), iIndentX1,0);
140  int32_t iBottomButtonSize = caBottom.GetInnerWidth();
141  iBottomButtonSize = std::min<int32_t>(iBottomButtonSize/2-2*iIndentX1, ::GraphicsResource.CaptionFont.GetTextWidth("Quit it, baby! And some.")*2);
142  // goal display
143  const C4IDList &rGoals = Game.RoundResults.GetGoals();
144  const C4IDList &rFulfilledGoals = Game.RoundResults.GetFulfilledGoals();
145  if (rGoals.GetNumberOfIDs())
146  {
147  C4GoalDisplay *pGoalDisplay = new C4GoalDisplay(caMain.GetFromTop(C4GUI_IconExHgt));
148  pGoalDisplay->SetGoals(rGoals, rFulfilledGoals, C4GUI_IconExHgt);
149  AddElement(pGoalDisplay);
150  // goal display may have resized itself; adjust component aligner
151  caMain.ExpandTop(C4GUI_IconExHgt - pGoalDisplay->GetBounds().Hgt);
152  }
153  // league/network result, present or pending
154  fIsNetDone = false;
155  bool fHasNetResult = Game.RoundResults.HasNetResult();
156  const char *szNetResult = nullptr;
157  if (Game.Parameters.isLeague() || fHasNetResult)
158  {
159  if (fHasNetResult)
160  szNetResult = Game.RoundResults.GetNetResultString();
161  else
162  szNetResult = LoadResStr("IDS_TEXT_LEAGUEWAITINGFOREVALUATIO");
163  pNetResultLabel = new C4GUI::Label(szNetResult, caMain.GetFromTop(::GraphicsResource.TextFont.GetLineHeight()*2, iMainTextWidth), ACenter, C4GUI_Caption2FontClr, nullptr, false, false, true);
164  AddElement(pNetResultLabel);
165  // only add label - contents and fIsNetDone will be set in next update
166  }
167  else
168  {
169  // otherwise, network is always done
170  fIsNetDone = true;
171  }
172  // extra evaluation string area
173  const char *szCustomEvaluationStrings = Game.RoundResults.GetCustomEvaluationStrings();
174  if (szCustomEvaluationStrings && *szCustomEvaluationStrings)
175  {
176  int32_t iMaxHgt = caMain.GetInnerHeight() / 3; // max 1/3rd of height for extra data
177  C4GUI::MultilineLabel *pCustomStrings = new C4GUI::MultilineLabel(caMain.GetFromTop(0 /* resized later*/, iMainTextWidth), 0,0, " ", true, true);
178  pCustomStrings->AddLine(szCustomEvaluationStrings, &::GraphicsResource.TextFont, C4GUI_MessageFontClr, true, false, nullptr);
179  C4Rect rcCustomStringBounds = pCustomStrings->GetBounds();
180  if (rcCustomStringBounds.Hgt > iMaxHgt)
181  {
182  // Buffer too large: Use a scrollbox instead
183  delete pCustomStrings;
184  rcCustomStringBounds.Hgt = iMaxHgt;
185  C4GUI::TextWindow *pCustomStringsWin = new C4GUI::TextWindow(rcCustomStringBounds, 0,0,0, 0,0," ",true, nullptr,0, true);
186  pCustomStringsWin->SetDecoration(false, false, nullptr, false);
187  pCustomStringsWin->AddTextLine(szCustomEvaluationStrings, &::GraphicsResource.TextFont, C4GUI_MessageFontClr, true, false, nullptr);
188  caMain.ExpandTop(-iMaxHgt);
189  AddElement(pCustomStringsWin);
190  }
191  else
192  {
193  // buffer size OK: Reserve required space
194  caMain.ExpandTop(-rcCustomStringBounds.Hgt);
195  AddElement(pCustomStrings);
196  }
197  }
198  // player list area
199  C4GUI::ComponentAligner caPlayerArea(caMain.GetAll(), iIndentX1,0);
200  iPlrListCount = 1; bool fSepTeamLists = false;
202  {
203  // exactly two predefined teams: Use two player list boxes; one for each team
204  iPlrListCount = 2;
205  fSepTeamLists = true;
206  }
207  ppPlayerLists = new C4PlayerInfoListBox *[iPlrListCount];
208  for (int32_t i=0; i<iPlrListCount; ++i)
209  {
210  ppPlayerLists[i] = new C4PlayerInfoListBox(caPlayerArea.GetGridCell(i,iPlrListCount,0,1), C4PlayerInfoListBox::PILBM_Evaluation, fSepTeamLists ? Game.Teams.GetTeamByIndex(i)->GetID() : 0);
211  ppPlayerLists[i]->SetSelectionDiabled(true);
212  ppPlayerLists[i]->SetDecoration(false, nullptr, true, false);
213  AddElement(ppPlayerLists[i]);
214  }
215  // add buttons
217  pBtnExit = btnExit = new C4GUI::CallbackButton<C4GameOverDlg>(LoadResStr("IDS_BTN_ENDROUND"), caBottom.GetGridCell(0,2, 0,1, iBottomButtonSize, -1, true), &C4GameOverDlg::OnExitBtn);
218  btnExit->SetToolTip(LoadResStr("IDS_DESC_ENDTHEROUND"));
219  AddElement(btnExit);
221  pBtnContinue = btnContinue = new C4GUI::CallbackButton<C4GameOverDlg>(LoadResStr("IDS_BTN_CONTINUEGAME"), caBottom.GetGridCell(1,2, 0,1, iBottomButtonSize, -1, true), &C4GameOverDlg::OnContinueBtn);
222  btnContinue->SetToolTip(LoadResStr("IDS_DESC_CONTINUETHEROUNDWITHNOFUR"));
223  AddElement(btnContinue);
224  // convert continue button to "next mission" button if available
225  if (Game.NextMission)
226  {
227  // not available for regular replay and network clients, obviously
228  // it is available for films though, so you can create cinematics for adventures
229  if (::Control.isCtrlHost() || (Game.C4S.Head.Film == 2))
230  {
231  fHasNextMissionButton = true;
232  btnContinue->SetText(Game.NextMissionText.getData());
233  btnContinue->SetToolTip(Game.NextMissionDesc.getData());
234  }
235  }
236  fIsQuitBtnVisible = fIsNetDone || !::Network.isHost();
237  // updates
238  Application.Add(this);
239  Update();
240  // initial focus on quit button if visible, so space/enter/low gamepad buttons quit
241  if (fIsQuitBtnVisible) SetFocus(btnExit, false);
242 }
243 
245 {
246  Application.Remove(this);
247  delete ppPlayerLists;
248  is_shown = false;
249 }
250 
251 void C4GameOverDlg::Update()
252 {
253  for (int32_t i=0; i<iPlrListCount; ++i) ppPlayerLists[i]->Update();
254  if (pNetResultLabel)
255  {
257  }
258  // exit/continue button only visible for host if league streaming finished
259  bool fBtnsVisible = fIsNetDone || !::Network.isHost();
260  if (fBtnsVisible != fIsQuitBtnVisible)
261  {
262  fIsQuitBtnVisible = fBtnsVisible;
263  pBtnExit->SetVisibility(fBtnsVisible);
264  pBtnContinue->SetVisibility(fBtnsVisible);
265  if (fIsQuitBtnVisible) SetFocus(pBtnExit, false);
266  }
267 }
268 
269 void C4GameOverDlg::SetNetResult(const char *szResultString, C4RoundResults::NetResult eResultType, size_t iPendingStreamingData, bool fIsStreaming)
270 {
271  // add info about pending streaming data
272  StdStrBuf sResult(szResultString);
273  if (fIsStreaming)
274  {
275  sResult.AppendChar('|');
276  sResult.AppendFormat("[!]Transmitting record to league server... (%d kb remaining)", int(iPendingStreamingData/1024));
277  }
278  // message linebreak into box
279  StdStrBuf sBrokenResult;
280  ::GraphicsResource.TextFont.BreakMessage(sResult.getData(), pNetResultLabel->GetBounds().Wdt, &sBrokenResult, true);
281  pNetResultLabel->SetText(sBrokenResult.getData(), false);
282  // all done?
283  if (eResultType != C4RoundResults::NR_None && !fIsStreaming)
284  {
285  // a final result is determined and all streaming data has been transmitted
286  fIsNetDone = true;
287  }
288  // network error?
289  if (eResultType == C4RoundResults::NR_NetError)
290  {
291  // disconnected. Do not show winners/losers
292  for (int32_t i=0; i<iPlrListCount; ++i) ppPlayerLists[i]->SetMode(C4PlayerInfoListBox::PILBM_EvaluationNoWinners);
293  }
294 }
295 
296 void C4GameOverDlg::OnExitBtn(C4GUI::Control *btn)
297 {
298  // callback: exit button pressed.
300  Close(false);
301 }
302 
303 void C4GameOverDlg::OnContinueBtn(C4GUI::Control *btn)
304 {
305  // callback: continue button pressed
306  if (fHasNextMissionButton)
307  {
308  // switch to next mission if next mission button is pressed
311  }
312  Close(true); // unpauses and deletes this object
313 }
314 
316 {
317  // close some other dialogs
320  for (C4Player *plr = ::Players.First; plr; plr = plr->Next)
321  plr->CloseMenu();
322  // pause game when round results dlg is shown
323  Game.Pause();
324 }
325 
327 {
328  Game.Unpause();
329  typedef C4GUI::Dialog BaseClass;
330  BaseClass::OnClosed(fOK); // deletes this object!
331 }
const char * getData() const
Definition: StdBuf.h:450
C4Def * ID2Def(C4ID id)
int32_t GetIDCount(C4ID c_id, int32_t iZeroDefVal=0) const
Definition: stub-handle.cpp:67
int32_t GetID() const
Definition: C4Teams.h:66
void ExpandTop(int32_t iByHgt)
Definition: C4Gui.h:2808
int GetLineHeight() const
Definition: C4FontLoader.h:132
float Y
Definition: C4Facet.h:120
void GetAll(C4Rect &rcOut)
Definition: C4Gui.cpp:1128
virtual const char * GetName() const
Definition: C4PropList.cpp:267
StdCopyStrBuf NextMission
Definition: C4Game.h:148
void SetDecoration(bool fDrawBG, bool fDrawFrame, ScrollBarFacets *pToGfx, bool fAutoScroll)
Definition: C4Gui.h:1752
bool isHost() const
Definition: C4Network2.h:209
#define C4GUI_MessageFontClr
Definition: C4Gui.h:43
int32_t GetInnerHeight() const
Definition: C4Gui.h:2806
bool isCtrlHost() const
Definition: C4GameControl.h:99
C4Game Game
Definition: C4Globals.cpp:52
C4Scenario C4S
Definition: C4Game.h:76
void Draw(C4TargetFacet &cgo, int32_t iByPlayer=-1, DrawMode eDrawMode=ODM_Normal, float offX=0, float offY=0)
Definition: C4Object.cpp:1800
#define C4GUI_IconExHgt
Definition: C4Gui.h:96
bool IsAutoGenerateTeams() const
Definition: C4Teams.h:173
bool HasNetResult() const
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:410
#define C4GUI_DefDlgSmallIndent
Definition: C4Gui.h:133
bool isStreaming() const
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
void Close(bool fOK)
Definition: C4Rect.h:29
int32_t GetScreenWdt()
Definition: C4Gui.h:2821
NetResult GetNetResult() const
C4Player * First
Definition: C4PlayerList.h:31
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:864
void AddElement(Element *pChild)
virtual void OnShown()
C4Scoreboard Scoreboard
Definition: C4Game.h:96
const C4IDList & GetFulfilledGoals() const
int32_t GetTextWidth(const char *szText, bool fCheckMarkup=true)
Definition: C4FontLoader.h:147
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
C4GraphicsResource GraphicsResource
void SetDecoration(bool fDrawBG, ScrollBarFacets *pToGfx, bool fAutoScroll, bool fDrawBorder=false)
Definition: C4Gui.h:1566
void SetGoals(const C4IDList &rAllGoals, const C4IDList &rFulfilledGoals, int32_t iGoalSymbolHeight)
C4GameParameters & Parameters
Definition: C4Game.h:69
void Add(StdSchedulerProc *pProc)
C4TeamList & Teams
Definition: C4Game.h:72
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool Pause()
Definition: C4Game.cpp:954
virtual void SetVisibility(bool fToValue)
StdCopyStrBuf NextMissionDesc
Definition: C4Game.h:148
const char * GetNetResultString() const
virtual int32_t GetMarginTop()
Definition: C4Gui.h:873
int32_t Wdt
Definition: C4Rect.h:32
C4Network2 Network
Definition: C4Globals.cpp:53
bool GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1062
int32_t y
Definition: C4Rect.h:32
const int ACenter
Definition: C4Surface.h:43
C4GameControl Control
size_t getPendingStreamData() const
Definition: C4Network2.h:300
C4Team * GetTeamByIndex(int32_t iIndex) const
Definition: C4Teams.cpp:405
bool Unpause()
Definition: C4Game.cpp:980
C4PlayerList Players
void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true)
Definition: C4Facet.cpp:154
Definition: C4Def.h:100
StdCopyStrBuf NextMissionText
Definition: C4Game.h:148
const char * GetCustomEvaluationStrings() const
Definition: C4Id.h:28
int32_t GetScreenHgt()
Definition: C4Gui.h:2822
C4RoundResults & RoundResults
Definition: C4Game.h:75
C4Rect & GetBounds()
Definition: C4Gui.h:445
int32_t GetWidth() const
Definition: C4Gui.h:2800
void AddLine(const char *szLine, CStdFont *pFont, DWORD dwClr, bool fDoUpdate, bool fMakeReadableOnBlack, CStdFont *pCaptionFont)
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
int32_t x
Definition: C4Rect.h:32
virtual void UpdateOwnPos()
void Remove(StdSchedulerProc *pProc)
const int C4PictureSize
Definition: C4Constants.h:60
float TargetX
Definition: C4Facet.h:167
void SetFocus(Control *pCtrl, bool fByMouse)
C4Object * Find(C4Def *def, int iOwner=ANY_OWNER, DWORD dwOCF=OCF_All)
float Hgt
Definition: C4Facet.h:120
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
#define C4GUI_Caption2FontClr
Definition: C4Gui.h:38
C4Player * Next
Definition: C4Player.h:144
bool isLeague() const
const C4IDList & GetGoals() const
void AddTextLine(const char *szText, CStdFont *pFont, DWORD dwClr, bool fDoUpdate, bool fMakeReadableOnBlack, CStdFont *pCaptionFont=nullptr)
Definition: C4Gui.h:1740
int32_t GetTeamCount() const
Definition: C4Teams.h:159
C4DefList Definitions
Definition: C4Globals.cpp:49
int32_t Hgt
Definition: C4Rect.h:32
C4SHead Head
Definition: C4Scenario.h:230
C4Surface * Surface
Definition: C4Facet.h:119
float TargetY
Definition: C4Facet.h:167
virtual void OnClosed(bool fOK)
C4ID GetID(size_t index, int32_t *ipCount=nullptr) const
Definition: C4IDList.cpp:99
void SetNextMission(const char *szMissionFilename)
int32_t GetNumberOfIDs() const
Definition: C4IDList.cpp:197
void Copy()
Definition: StdBuf.h:475
float Wdt
Definition: C4Facet.h:120
float X
Definition: C4Facet.h:120
C4Application Application
Definition: C4Globals.cpp:44
static C4Facet GetIconFacet(Icons icoIconIndex)
bool GetFromBottom(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1112
void SetSelectionDiabled(bool fToVal=true)
Definition: C4Gui.h:1568
int32_t GetInnerWidth() const
Definition: C4Gui.h:2805
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
int32_t Film
Definition: C4Scenario.h:73
C4GameObjects Objects
Definition: C4Globals.cpp:48
virtual int32_t GetMarginBottom()
Definition: C4Gui.h:876