1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef GAME_CLIENT_COMPONENTS_SKINS7_H
4#define GAME_CLIENT_COMPONENTS_SKINS7_H
5
6#include <base/color.h>
7#include <base/vmath.h>
8
9#include <engine/client/enums.h>
10#include <engine/graphics.h>
11
12#include <generated/protocol.h>
13#include <generated/protocol7.h>
14
15#include <game/client/component.h>
16#include <game/client/render.h>
17
18#include <chrono>
19#include <vector>
20
21class CSkins7 : public CComponent
22{
23public:
24 enum
25 {
26 SKINFLAG_SPECIAL = 1 << 0,
27 SKINFLAG_STANDARD = 1 << 1,
28
29 NUM_COLOR_COMPONENTS = 4,
30
31 HAT_NUM = 2,
32 HAT_OFFSET_SIDE = 2,
33 };
34
35 typedef std::function<void()> TSkinLoadedCallback;
36
37 class CSkinPart
38 {
39 public:
40 int m_Type;
41 int m_Flags;
42 char m_aName[24];
43 IGraphics::CTextureHandle m_OriginalTexture;
44 IGraphics::CTextureHandle m_ColorableTexture;
45 ColorRGBA m_BloodColor;
46
47 void ApplyTo(CTeeRenderInfo::CSixup &SixupRenderInfo) const;
48
49 bool operator<(const CSkinPart &Other) const;
50 };
51
52 class CSkin
53 {
54 public:
55 int m_Flags;
56 char m_aName[24];
57 const CSkinPart *m_apParts[protocol7::NUM_SKINPARTS];
58 int m_aUseCustomColors[protocol7::NUM_SKINPARTS];
59 unsigned m_aPartColors[protocol7::NUM_SKINPARTS];
60
61 bool operator<(const CSkin &Other) const;
62 bool operator==(const CSkin &Other) const;
63 };
64
65 static const char *const ms_apSkinPartNames[protocol7::NUM_SKINPARTS];
66 static const char *const ms_apSkinPartNamesLocalized[protocol7::NUM_SKINPARTS];
67 static const char *const ms_apColorComponents[NUM_COLOR_COMPONENTS];
68
69 static char *ms_apSkinNameVariables[NUM_DUMMIES];
70 static char *ms_apSkinVariables[NUM_DUMMIES][protocol7::NUM_SKINPARTS];
71 static int *ms_apUCCVariables[NUM_DUMMIES][protocol7::NUM_SKINPARTS]; // use custom color
72 static unsigned *ms_apColorVariables[NUM_DUMMIES][protocol7::NUM_SKINPARTS];
73
74 int Sizeof() const override { return sizeof(*this); }
75 void OnInit() override;
76
77 void Refresh(TSkinLoadedCallback &&SkinLoadedCallback);
78 std::chrono::nanoseconds LastRefreshTime() const { return m_LastRefreshTime; }
79
80 const std::vector<CSkin> &GetSkins() const;
81 const std::vector<CSkinPart> &GetSkinParts(int Part) const;
82 const CSkinPart *FindSkinPartOrNullptr(int Part, const char *pName, bool AllowSpecialPart) const;
83 const CSkinPart *FindDefaultSkinPart(int Part) const;
84 const CSkinPart *FindSkinPart(int Part, const char *pName, bool AllowSpecialPart) const;
85 void RandomizeSkin(int Dummy) const;
86
87 ColorRGBA GetColor(int Value, bool UseAlpha) const;
88 void ApplyColorTo(CTeeRenderInfo::CSixup &SixupRenderInfo, bool UseCustomColors, int Value, int Part) const;
89 ColorRGBA GetTeamColor(int UseCustomColors, int PartColor, int Team, int Part) const;
90
91 // returns true if everything was valid and nothing changed
92 bool ValidateSkinParts(char *apPartNames[protocol7::NUM_SKINPARTS], int *pUseCustomColors, int *pPartColors, int GameFlags) const;
93
94 bool SaveSkinfile(const char *pName, int Dummy);
95 bool RemoveSkin(const CSkin *pSkin);
96
97 IGraphics::CTextureHandle XmasHatTexture() const { return m_XmasHatTexture; }
98 IGraphics::CTextureHandle BotDecorationTexture() const { return m_BotTexture; }
99
100 static bool IsSpecialSkin(const char *pName);
101
102private:
103 std::chrono::nanoseconds m_LastRefreshTime;
104
105 std::vector<CSkinPart> m_avSkinParts[protocol7::NUM_SKINPARTS];
106 CSkinPart m_aPlaceholderSkinParts[protocol7::NUM_SKINPARTS];
107 std::vector<CSkin> m_vSkins;
108
109 IGraphics::CTextureHandle m_XmasHatTexture;
110 IGraphics::CTextureHandle m_BotTexture;
111
112 static int SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser);
113 bool LoadSkinPart(int PartType, const char *pName, int DirType);
114 static int SkinScan(const char *pName, int IsDir, int DirType, void *pUser);
115 bool LoadSkin(const char *pName, int DirType);
116
117 void InitPlaceholderSkinParts();
118 void LoadXmasHat();
119 void LoadBotDecoration();
120
121 void AddSkinFromConfigVariables(const char *pName, int Dummy);
122};
123
124#endif
125