OpenClonk
C4GraphicsResource.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 /* Loads all standard graphics from Graphics.ocg */
19 
20 #include "C4Include.h"
23 
24 #include "c4group/C4Components.h"
25 #include "graphics/C4FontLoader.h"
26 #include "graphics/C4DrawGL.h"
27 #include "object/C4DefList.h"
28 
29 /* C4GraphicsResource */
30 
32  CaptionFont(FontCaption), TitleFont(FontTitle), TextFont(FontRegular), MiniFont(FontTiny), TooltipFont(FontTooltip)
33 {
34  Default();
35 }
36 
38 {
39  Clear();
40 }
41 
43 {
44  fInitialized = false;
45 
47  idSfcControl = 0;
49  idSfcClonkSkins = 0;
50 
52  fctFlag.Default();
54  fctCrew.Default();
56  fctRank.Default();
57  fctFire.Default();
62  fctMenu.Default();
64  fctLogo.Default();
67  fctArrow.Default();
68  fctExit.Default();
69  fctHand.Default();
71  fctBuild.Default();
72 
76 
80  fctKey.Default();
82  fctMouse.Default();
83 
85 
86  iNumRanks=1;
88 }
89 
91 {
92  fInitialized = false;
93 
94  sfcControl.Clear();
95  idSfcControl = 0;
97  idSfcClonkSkins = 0;
98 
99  fctCrewClr.Clear();
100  fctFlagClr.Clear();
102 
103  fctPlayer.Clear();
104  fctFlag.Clear();
105  fctCrew.Clear();
106  fctWealth.Clear();
107  fctRank.Clear();
108  fctFire.Clear();
110  fctCaptain.Clear();
113  fctMenu.Clear();
115  fctLogo.Clear();
117  fctEnergy.Clear();
118  fctOptions.Clear();
119  fctArrow.Clear();
120  fctExit.Clear();
121  fctHand.Clear();
122  fctGamepad.Clear();
123  fctBuild.Clear();
125  // GUI data
132  fctSubmenu.Clear();
133  fctCheckbox.Clear();
137 
138 
139  // unhook deflist from font
140  FontRegular.SetCustomImages(nullptr);
141 
143 
144  // closing the group set will also close the graphics.ocg
145  // this is just for games that failed to init
146  // normally, this is done after successful init anyway
147  CloseFiles();
148 }
149 
151 {
152  // this regards scenario-specific fonts or overloads in Extra.ocg
153  const char *szFont;
154  if (!Game.C4S.Head.Font.empty()) szFont = Game.C4S.Head.Font.c_str(); else szFont = Config.General.RXFontName;
163  if (!::FontLoader.InitFont(&FontTooltip, szFont, C4FontLoader::C4FT_Main, Config.General.RXFontSize, &Files, false)) return false;
165  // assign def list as custom image source
167  return true;
168 }
169 
171 {
172  FontRegular.Clear();
173  FontTitle.Clear();
174  FontCaption.Clear();
175  FontTiny.Clear();
176  FontTooltip.Clear();
177 }
178 
180 {
181  if (!RegisterGlobalGraphics())
182  return false;
183  // update group set
184  if (!RegisterMainGroups())
185  {
186  LogFatal(LoadResStr("IDS_ERR_GFX_REGISTERMAIN"));
187  return false;
188  }
189 
190 #ifndef USE_CONSOLE
191  // Pre-load all shader files
193  if (!pGL->InitShaders(&Files))
194  {
195  LogFatal(LoadResStr("IDS_ERR_GFX_INITSHADERS"));
196  return false;
197  }
198 #endif
199 
200  Game.SetInitProgress(11.0f);
201  ProgressStart = 12.0f; ProgressIncrement = 0.35f; // TODO: This should be changed so that it stops at 25%, no matter how many graphics we load.
202  // The progress bar is the only graphic besides the background that is
203  // used during startup, so load it early
204  if (!LoadFile(fctProgressBar, "GUIProgress", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
206 
207  if (!InitFonts()) return false;
208 
209  // load GUI files
210  if (!LoadFile(sfcCaption, "GUICaption", Files, idSfcCaption, 0)) return false;
212  if (!LoadFile(sfcButton, "GUIButton", Files, idSfcButton, 0)) return false;
214  if (!LoadFile(sfcButtonD, "GUIButtonDown", Files, idSfcButtonD, 0)) return false;
216  if (!LoadFile(fctButtonHighlight, "GUIButtonHighlight", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
217  if (!LoadFile(fctButtonHighlightRound, "GUIButtonHighlightRound", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
218  if (!LoadFile(fctIcons, "GUIIcons", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
220  if (!LoadFile(fctIconsEx, "GUIIcons2", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
222  if (!LoadFile(fctControllerIcons, "ControllerIcons", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
224  if (!LoadFile(sfcScroll, "GUIScroll", Files, idSfcScroll, 0)) return false;
225  sfctScroll.Set(C4Facet(&sfcScroll,0,0,32,32));
226  if (!LoadFile(sfcContext, "GUIContext", Files, idSfcContext, 0)) return false;
227  fctContext.Set(&sfcContext,0,0,16,16);
228  if (!LoadFile(fctSubmenu, "GUISubmenu", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
229  if (!LoadFile(fctCheckbox, "GUICheckbox", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
231  if (!LoadFile(fctBigArrows, "GUIBigArrows", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
233 
234  // Control
235  if (!LoadFile(sfcControl, "Control", Files, idSfcControl, 0)) return false;
236  fctKeyboard.Set(&sfcControl,0,0,80,36);
237  fctCommand.Set(&sfcControl,0,36,32,32);
238  fctKey.Set(&sfcControl,0,100,64,64);
239  fctOKCancel.Set(&sfcControl,128,100,32,32);
240  fctMouse.Set(&sfcControl,198,100,32,32);
241 
242  // Clonk style selection
243  if (!LoadFile(sfcClonkSkins, "ClonkSkins", Files, idSfcClonkSkins, 0)) return false;
244  fctClonkSkin.Set(&sfcClonkSkins,0,0,64,64);
245 
246  // Facet bitmap resources
247  if (!LoadFile(fctFire, "Fire", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
248  if (!LoadFile(fctBackground, "Background", Files, C4FCT_Full, C4FCT_Full, false, C4SF_Tileable)) return false; // tileable
249  if (!LoadFile(fctFlag, "Flag", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new format)
250  if (!LoadFile(fctCrew, "Crew", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new format)
251  if (!LoadFile(fctWealth, "Wealth", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new)
252  if (!LoadFile(fctPlayer, "Player", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new format)
253  if (!LoadFile(fctRank, "Rank", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
254  if (!LoadFile(fctCaptain, "Captain", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
255  if (!LoadCursorGfx()) return false;
256  if (!LoadFile(fctSelectMark, "SelectMark", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
257  if (!LoadFile(fctMenu, "Menu", Files, 35, 35, false, 0)) return false;
258  if (!LoadFile(fctLogo, "Logo", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
259  if (!LoadFile(fctConstruction,"Construction", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new)
260  if (!LoadFile(fctEnergy, "Energy", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false; // (new)
261  if (!LoadFile(fctOptions, "Options", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
262  if (!LoadFile(fctUpperBoard, "UpperBoard", Files, C4FCT_Full, C4FCT_Full, false, C4SF_Tileable)) return false; // tileable
263  if (!LoadFile(fctArrow, "Arrow", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
264  if (!LoadFile(fctExit, "Exit", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
265  if (!LoadFile(fctHand, "Hand", Files, C4FCT_Height, C4FCT_Full, false, 0)) return false;
266  if (!LoadFile(fctGamepad, "Gamepad", Files, 80, C4FCT_Full, false, 0)) return false;
267  if (!LoadFile(fctBuild, "Build", Files, C4FCT_Full, C4FCT_Full, false, 0)) return false;
268  if (!LoadFile(fctTransformKnob,"TransformKnob",Files,C4FCT_Full, C4FCT_Full, false, 0)) return false;
269 
270  // achievements
271  if (!Achievements.Init(Files)) return false;
272 
273  // create ColorByOwner overlay surfaces
275  {
276  if (!fctCrewClr.CreateClrByOwner(fctCrew.Surface)) { LogFatal("ClrByOwner error! (1)"); return false; }
280  }
282  {
283  if (!fctFlagClr.CreateClrByOwner(fctFlag.Surface)) { LogFatal("ClrByOwner error! (1)"); return false; }
287  }
289  {
290  if (!fctPlayerClr.CreateClrByOwner(fctPlayer.Surface)) { LogFatal("ClrByOwner error! (1)"); return false; }
294  }
295 
296  // get number of ranks
297  int32_t Q; fctRank.GetPhaseNum(iNumRanks, Q);
298  if (!iNumRanks) iNumRanks=1;
299 
300  // CloseFiles() must not be called now:
301  // The sky still needs to be loaded from the global graphics
302  // group in C4Game::InitGame -> C4Sky::Init so we need to keep the group(s) open.
303  // In activated NETWORK2, the files mustn't be closed either, because there will be
304  // multiple calls to this function to allow overloadings
305 
306  // mark initialized
307  fInitialized = true;
308 
309  return true;
310 }
311 
313 {
314  // Determine appropriate GFX file by screen resolution
315  const char *szCursorFilename;
316  szCursorFilename = "Cursor";
317  if (!LoadFile(fctMouseCursor, szCursorFilename, Files, C4FCT_Height, C4FCT_Full, false, 0))
318  return false;
319  return true;
320 }
321 
323 {
324  // Create main gfx group - register with fixed ID 1, to prevent unnecessary font reloading.
325  // FontLoader-initializations always check whether the font has already been initialized
326  // with the same parameters. If the game is simply reloaded in console-mode, this means
327  // that fonts are not reinitialized. This will also apply for InGame-scenario switches yet
328  // to be implemented.
329  // Bitmap fonts from other groups are always reloaded, because the group indices of the gfx
330  // group set are not reset, and will then differ for subsequent group registrations.
331  // Resetting the group index of the gfx group set at game reset would cause problems if a
332  // scenario with its own font face is being closed, and then another scenario with another,
333  // overloaded font face is opened. The group indices could match and the old font would
334  // then be kept.
335  // The cleanest alternative would be to reinit all the fonts whenever a scenario is reloaded
336  // FIXME: Test whether vector fonts from a scenario are correctly reloaded
337  auto *pMainGfxGrp = new C4Group();
338  if (!Reloc.Open(*pMainGfxGrp, C4CFN_Graphics) || !Files.RegisterGroup(*pMainGfxGrp, true, C4GSPrio_Base, C4GSCnt_Graphics, true))
339  {
340  // error
341  LogFatal(FormatString(LoadResStr("IDS_PRC_NOGFXFILE"),C4CFN_Graphics,pMainGfxGrp->GetError()).getData());
342  delete pMainGfxGrp;
343  return false;
344  }
345  return true;
346 }
347 
349 {
350  // register main groups
353  return true;
354 }
355 
357 {
358  // closes main gfx group; releases dependencies into game group set
359  Files.Clear();
361 }
362 
363 static C4Group *FindSuitableFile(const char *szName, C4GroupSet &rGfxSet, char *szFileName, int32_t * pID)
364 {
365  const char * const extensions[] = { "bmp", "jpeg", "jpg", "png", nullptr };
366 
367  return rGfxSet.FindSuitableFile(szName, extensions, szFileName, pID);
368 }
369 
370 bool C4GraphicsResource::LoadFile(C4FacetID &fct, const char *szName, C4GroupSet &rGfxSet, int32_t iWdt, int32_t iHgt, bool fNoWarnIfNotFound, int iFlags)
371 {
372  char FileName[_MAX_FNAME]; int32_t ID = 0;
373  C4Group *pGrp = FindSuitableFile(szName, rGfxSet, FileName, &ID);
374  if (!pGrp)
375  {
376  // FIXME: Use LogFatal here
377  if (!fNoWarnIfNotFound)
378  {
379  LogF(LoadResStr("IDS_PRC_NOGFXFILE"), szName, LoadResStr("IDS_PRC_FILENOTFOUND"));
380  }
381  return false;
382  }
383  // check group
384  if (fct.idSourceGroup == ID)
385  // already up-to-date
386  return true;
387  // load
388  if (!fct.Load(*pGrp, FileName, iWdt, iHgt, false, iFlags))
389  {
390  LogF(LoadResStr("IDS_PRC_NOGFXFILE"), FileName, LoadResStr("IDS_ERR_NOFILE"));
391  return false;
392  }
393  fct.idSourceGroup = ID;
396  return true;
397 }
398 
399 bool C4GraphicsResource::LoadFile(C4Surface& sfc, const char *szName, C4GroupSet &rGfxSet, int32_t &ridCurrSfc, int iFlags)
400 {
401  // find
402  char FileName[_MAX_FNAME]; int32_t ID = 0;
403  C4Group *pGrp = FindSuitableFile(szName, rGfxSet, FileName, &ID);
404  if (!pGrp)
405  {
406  LogF(LoadResStr("IDS_PRC_NOGFXFILE"), szName, LoadResStr("IDS_PRC_FILENOTFOUND"));
407  return false;
408  }
409  // check group
410  if (ID == ridCurrSfc)
411  // already up-to-date
412  return true;
413  // load
414  if (!sfc.Load(*pGrp, FileName, false, false, iFlags))
415  {
416  LogF(LoadResStr("IDS_PRC_NOGFXFILE"), FileName, LoadResStr("IDS_ERR_NOFILE"));
417  return false;
418  }
419  ridCurrSfc = ID;
422  return true;
423 }
424 
425 CStdFont &C4GraphicsResource::GetFontByHeight(int32_t iHgt, float *pfZoom)
426 {
427  // get optimal font for given control size
428  CStdFont *pUseFont;
429  if (iHgt <= MiniFont.GetLineHeight()) pUseFont = &MiniFont;
430  else if (iHgt <= TextFont.GetLineHeight()) pUseFont = &TextFont;
431  else if (iHgt <= CaptionFont.GetLineHeight()) pUseFont = &CaptionFont;
432  else pUseFont = &TitleFont;
433  // determine zoom
434  if (pfZoom)
435  {
436  int32_t iLineHgt = pUseFont->GetLineHeight();
437  if (iLineHgt)
438  *pfZoom = (float) iHgt / (float) iLineHgt;
439  else
440  *pfZoom = 1.0f; // error
441  }
442  return *pUseFont;
443 }
444 
446 {
447  if(!fInitialized) return false;
448  // reload any files that depend on the current resolution
449  // reloads the cursor
450 
451  // Re-open the graphics files if they are not open anymore -- this
452  // happens when the game is running.
453  // Note also that at the moment there are no resolution dependent
454  // graphics files...
455  const bool hadGroupsRegistered = (idRegisteredMainGroupSetFiles != -1);
456  if(!hadGroupsRegistered)
457  {
460  }
461 
463  const bool result = true;
464 
465  if(!hadGroupsRegistered)
466  CloseFiles();
467 
468  return result;
469 }
470 
#define C4CFN_Graphics
Definition: C4Components.h:28
#define C4CFN_ShaderFiles
Definition: C4Components.h:183
C4Config Config
Definition: C4Config.cpp:930
CStdGL * pGL
Definition: C4DrawGL.cpp:907
const int C4FCT_Full
Definition: C4FacetEx.h:26
const int C4FCT_Height
Definition: C4FacetEx.h:27
C4FontLoader FontLoader
C4Game Game
Definition: C4Globals.cpp:52
C4DefList Definitions
Definition: C4Globals.cpp:49
C4GraphicsResource GraphicsResource
#define C4GSPrio_Base
Definition: C4GroupSet.h:23
#define C4GSCnt_Graphics
Definition: C4GroupSet.h:34
#define C4GUI_IconHgt
Definition: C4Gui.h:94
#define C4GUI_ControllerIconHgt
Definition: C4Gui.h:98
#define C4GUI_ControllerIconWdt
Definition: C4Gui.h:97
#define C4GUI_IconExHgt
Definition: C4Gui.h:96
#define C4GUI_IconWdt
Definition: C4Gui.h:93
#define C4GUI_IconExWdt
Definition: C4Gui.h:95
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
bool LogFatal(const char *szMessage)
Definition: C4Log.cpp:239
C4Reloc Reloc
Definition: C4Reloc.cpp:21
const int C4SF_Tileable
Definition: C4Surface.h:49
#define _MAX_FNAME
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool Init(C4Group &File)
char RXFontName[CFG_MaxString+1]
Definition: C4Config.h:42
int32_t RXFontSize
Definition: C4Config.h:43
C4ConfigGeneral General
Definition: C4Config.h:255
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
C4Surface * Surface
Definition: C4Facet.h:117
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
void Default()
Definition: C4Facet.cpp:31
bool GetPhaseNum(int32_t &rX, int32_t &rY)
Definition: C4Facet.cpp:472
void Clear()
Definition: C4FacetEx.h:76
int32_t idSourceGroup
Definition: C4FacetEx.h:71
void Default()
Definition: C4FacetEx.h:75
bool Load(C4Group &hGroup, const char *szName, int iWdt, int iHgt, bool fNoErrIfNotFound, int iFlags)
Definition: C4FacetEx.cpp:84
bool CreateClrByOwner(C4Surface *pBySurface)
Definition: C4FacetEx.cpp:73
void Set(const C4Facet &cpy)
Definition: C4FacetEx.h:46
bool InitFont(CStdFont *Font, const char *szFontName, FontType eType, int32_t iSize, C4GroupSet *pGfxGroups, bool fDoShadow=true)
C4Scenario C4S
Definition: C4Game.h:74
void SetInitProgress(float to_progress)
Definition: C4Game.cpp:4207
C4GroupSet GroupSet
Definition: C4Game.h:87
int32_t idRegisteredMainGroupSetFiles
CStdFont & GetFontByHeight(int32_t iHgt, float *pfZoom=nullptr)
C4AchievementGraphics Achievements
C4GUI::DynBarFacet barButton
C4FacetID fctButtonHighlightRound
bool LoadFile(C4FacetID &fct, const char *szName, C4GroupSet &rGfxSet, int32_t iWdt, int32_t iHgt, bool fNoWarnIfNotFound, int iFlags)
C4GUI::ScrollBarFacets sfctScroll
C4GUI::DynBarFacet barButtonD
C4GUI::DynBarFacet barCaption
void Clear()
Definition: C4GroupSet.cpp:50
int32_t GetLastID()
Definition: C4GroupSet.h:105
bool RegisterGroup(C4Group &rGroup, bool fOwnGrp, int32_t Priority, int32_t Contents, bool fCheckContent=true)
Definition: C4GroupSet.cpp:88
int32_t PreCacheEntries(const char *szEntryMask)
Definition: C4GroupSet.cpp:375
C4Group * FindSuitableFile(const char *szName, const char *const extensions[], char *szFileName, int32_t *pID=nullptr)
Definition: C4GroupSet.cpp:191
bool RegisterGroups(const C4GroupSet &rCopy, int32_t Contents, const char *szFilename=nullptr, int32_t iMaxSkipID=0)
Definition: C4GroupSet.cpp:128
bool Open(C4Group &group, const char *filename) const
Definition: C4Reloc.cpp:156
std::string Font
Definition: C4Scenario.h:66
C4SHead Head
Definition: C4Scenario.h:232
bool Load(C4Group &hGroup, const char *szFilename, bool fOwnPal, bool fNoErrIfNotFound, int iFlags)
void Clear()
Definition: C4Surface.cpp:126
int Hgt
Definition: C4Surface.h:65
void Default()
Definition: C4Surface.cpp:71
int GetLineHeight() const
Definition: C4FontLoader.h:125
void Clear()
void SetCustomImages(CustomImages *pHandler)
Definition: C4FontLoader.h:186
bool InitShaders(C4GroupSet *pGroups)
Definition: C4DrawGL.cpp:714
const char * getData() const
Definition: StdBuf.h:442
void SetHorizontal(C4Surface &rBySfc, int iHeight=0, int iBorderWidth=0)
Definition: C4Gui.cpp:119
void Clear()
Definition: C4Gui.h:355
void Set(const C4Facet &rByFct, int32_t iPinIndex=0)
Definition: C4Gui.cpp:136