OpenClonk
C4MessageBoard.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Fullscreen startup log and chat type-in */
19 
20 #include "C4Include.h"
21 #include "gui/C4MessageBoard.h"
22 
23 #include "game/C4Application.h"
24 #include "game/C4FullScreen.h"
25 #include "game/C4GraphicsSystem.h"
26 #include "graphics/C4Draw.h"
28 #include "gui/C4Gui.h"
29 #include "gui/C4LoaderScreen.h"
30 #include "gui/C4MessageInput.h"
31 #include "lib/StdColors.h"
32 #include "player/C4Player.h"
33 #include "player/C4PlayerList.h"
34 
35 const int C4LogSize=30000, C4LogMaxLines=1000;
36 
38 {
39  Delay = -1;
40  Fader = 0;
41  Speed = 2;
42  Output.Default();
43  Startup = false;
44  ScreenFader = 0;
45  iBackScroll = -1;
46  ScrollUpBinding = nullptr;
47  ScrollDownBinding = nullptr;
48  iLineHgt = 1; // Prevent unitialized access with USE_CONSOLE
49 }
50 
52 {
53  LogBuffer.Clear();
54  LogBuffer.SetLBWidth(0);
55 }
56 
58 {
59  // Startup? draw only
60  if (Startup) { Draw(Output); return; }
61 
62  // typein or messages waiting? fade in
63  if (::MessageInput.IsTypeIn() || iBackScroll >= 0)
64  ScreenFader = std::max(ScreenFader - 0.20f, -1.0f);
65 
66  // no curr msg?
67  if (iBackScroll<0)
68  {
69  // draw anyway
70  Draw(Output);
71  if (!::MessageInput.IsTypeIn())
72  ScreenFader = std::min(ScreenFader + 0.05f, 1.0f);
73  return;
74  }
75 
76  // recalc fade/delay speed
77  Speed = std::max(1, iBackScroll / 5);
78  // fade msg in?
79  if (Fader > 0)
80  Fader = std::max(Fader - Speed, 0);
81  // hold curr msg? (delay)
82  if (Fader <= 0)
83  {
84  // no delay set yet?
85  if (Delay == -1)
86  {
87  // set delay based on msg length
88  const char *szCurrMsg = LogBuffer.GetLine(std::min(-iBackScroll, -1), nullptr, nullptr, nullptr);
89  if (szCurrMsg) Delay = strlen(szCurrMsg); else Delay = 0;
90  }
91  // wait...
92  if (Delay > 0) Delay = std::max(Delay - Speed, 0);
93  // end of delay
94  if (Delay == 0)
95  {
96  // set cursor to next msg (or at end of log)
97  iBackScroll = std::max(iBackScroll - 1, -1);
98  // reset fade
99  Fader = iLineHgt;
100  Delay = -1;
101  }
102  }
103 
104  // Draw
105  Draw(Output);
106 }
107 
108 void C4MessageBoard::Init(C4Facet &cgo, bool fStartup)
109 {
110  Output=cgo;
111  Startup=fStartup;
113  LogBuffer.SetLBWidth(Output.Wdt);
114 
115  if (!Startup)
116  {
117  // set cursor to end of log
118  iBackScroll = -1;
119  Fader = 0;
120  Speed = 2;
121  ScreenFader = 1.0f; // msgs faded out
122 
123  LogBuffer.SetLBWidth(Output.Wdt);
124  }
125 
126  // messageboard
127  ScrollUpBinding = std::make_unique<C4KeyBinding>(C4KeyCodeEx(K_UP, KEYS_Shift), "MsgBoardScrollUp", KEYSCOPE_Fullscreen, new C4KeyCB <C4MessageBoard>(*GraphicsSystem.MessageBoard, &C4MessageBoard::ControlScrollUp));
128  ScrollDownBinding = std::make_unique<C4KeyBinding>(C4KeyCodeEx(K_DOWN, KEYS_Shift), "MsgBoardScrollDown", KEYSCOPE_Fullscreen, new C4KeyCB <C4MessageBoard>(*GraphicsSystem.MessageBoard, &C4MessageBoard::ControlScrollDown));
129 }
130 
132 {
133  if (!Application.Active) return;
134 
135  // Startup: draw Loader
136  if (Startup)
137  {
139  ::GraphicsSystem.pLoaderScreen->Draw(cgo, C4LoaderScreen::Flag::ALL, Game.InitProgress, &LogBuffer);
140  else
141  // loader not yet loaded: black BG
142  pDraw->DrawBoxDw(cgo.Surface, 0,0, cgo.Wdt, cgo.Hgt, 0x00000000);
143  return;
144  }
145 
146  // Game running: message fader
147 
148  // draw messages
149  // how many "extra" messages should be shown?
150  int iMsgFader = C4MSGB_MaxMsgFading;
151  // check screenfader range
152  if (ScreenFader >= 1.0f)
153  {
154  return;
155  }
157  // show msgs
158  for (int iMsg = -iMsgFader; iMsg < 0; iMsg++)
159  {
160  // get message at pos
161  if (iMsg-iBackScroll >= 0) break;
162  const char *Message = LogBuffer.GetLine(iMsg-iBackScroll, nullptr, nullptr, nullptr);
163  if (!Message || !*Message) continue;
164  // calc target position (y)
165  int iMsgY = cgo.Y + cgo.Hgt + iMsg * iLineHgt + Fader;
166 
167  // player message color?
168  C4Player *pPlr = GetMessagePlayer(Message);
169 
170  DWORD dwColor;
171  if (pPlr)
172  dwColor = PlrClr2TxtClr(pPlr->ColorDw) & 0xffffff;
173  else
174  dwColor = 0xffffff;
175  // fade out (msg fade)
176  float fade = std::max(ScreenFader, 0.0f) + ((iMsg + 2.0f + float(Fader) / iLineHgt) / std::min(2-iMsgFader, -1));
177  DWORD dwFade = (0xff - Clamp(int(fade * 0xff), 0, 0xff)) << 24;
178  dwColor |= dwFade;
179  // Draw
180  pDraw->StringOut(Message,::GraphicsResource.FontRegular,1.0,cgo.Surface,cgo.X,iMsgY,dwColor);
181  }
182 }
183 
185 {
186  // Ingore if startup or typein
187  if (Startup) return;
188  // scroll until end of log
189  for (int i = 0; i < 100; i++)
190  {
192  Execute();
193  if (iBackScroll < 0) break;
194  Delay=0;
195  }
196 }
197 
198 void C4MessageBoard::AddLog(const char *szMessage)
199 {
200  // safety
201  if (!szMessage || !*szMessage) return;
202  // make sure new message will be drawn
203  ++iBackScroll;
204  // register message in standard messageboard font
205  LogBuffer.AppendLines(szMessage, &::GraphicsResource.FontRegular, 0, nullptr);
206 }
207 
209 {
210  LogBuffer.Clear();
211 }
212 
214 {
215  // do not show startup board if GUI is active
216  if (::pGUI->IsActive()) return;
217  // Reset
218  iBackScroll=0;
219  // Draw
220  if (pDraw)
221  {
222  Draw(Output);
223  // startup: Draw message board only and do page flip
224  if (Startup) FullScreen.pSurface->PageFlip();
225  }
226 }
227 
229 {
230  // Scan message text for heading player name
231  if (SEqual2(szMessage, "* "))
232  {
233  StdStrBuf str;
234  str.CopyUntil(szMessage + 2,' ');
236  }
237  if (SCharCount(':',szMessage))
238  {
239  StdStrBuf str;
240  str.CopyUntil(szMessage + 2,':');
242  }
243  return nullptr;
244 }
245 
247 {
248  Delay=-1; Fader=0;
249  iBackScroll++;
250  return true;
251 }
252 
254 {
255  Delay=-1; Fader=0;
256  if (iBackScroll > -1) iBackScroll--;
257  return true;
258 }
C4Draw * pDraw
Definition: C4Draw.cpp:42
C4Game Game
Definition: C4Globals.cpp:52
C4Application Application
Definition: C4Globals.cpp:44
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
C4GraphicsResource GraphicsResource
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
@ KEYSCOPE_Fullscreen
@ KEYS_Shift
const int C4LogSize
const int C4LogMaxLines
const int C4MSGB_MaxMsgFading
C4MessageInput MessageInput
C4PlayerList Players
uint32_t DWORD
unsigned int SCharCount(char cTarget, const char *szInStr, const char *cpUntil)
Definition: Standard.cpp:326
bool SEqual2(const char *szStr1, const char *szStr2)
Definition: Standard.cpp:204
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:44
DWORD PlrClr2TxtClr(DWORD dwClr)
Definition: StdColors.h:104
bool Active
Definition: C4App.h:63
bool StringOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:570
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:840
C4Surface * Surface
Definition: C4Facet.h:117
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
void Default()
Definition: C4Facet.cpp:31
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
bool IsActive()
Definition: C4Gui.h:2633
int32_t InitProgress
Definition: C4Game.h:134
std::unique_ptr< C4MessageBoard > MessageBoard
C4LoaderScreen * pLoaderScreen
void Draw(C4Facet &cgo, Flag options=Flag::ALL, int iProgress=0, class C4LogBuffer *pLog=nullptr, int Process=0)
void Clear()
Definition: C4LogBuf.cpp:308
const char * GetLine(int iLineIndex, CStdFont **ppFont, DWORD *pdwClr, bool *pNewParagraph) const
Definition: C4LogBuf.cpp:280
void SetLBWidth(int iToWidth)
Definition: C4LogBuf.cpp:314
void AppendLines(const char *szLine, CStdFont *pFont, DWORD dwClr, CStdFont *pFirstLineFont=nullptr)
Definition: C4LogBuf.cpp:170
C4Player * GetMessagePlayer(const char *szMessage)
void Draw(C4Facet &cgo)
void Init(C4Facet &cgo, bool fStartup)
void AddLog(const char *szMessage)
uint32_t ColorDw
Definition: C4Player.h:89
C4Player * GetByName(const char *szName, int iExcluding=NO_OWNER) const
bool PageFlip(C4Rect *pSrcRt=nullptr, C4Rect *pDstRt=nullptr)
Definition: C4Surface.cpp:310
C4Surface * pSurface
Definition: C4Window.h:275
int GetLineHeight() const
Definition: C4FontLoader.h:125
void CopyUntil(const char *szString, char cUntil)
Definition: StdBuf.h:613
const char * getData() const
Definition: StdBuf.h:442