1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2004-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 // graphics used by object definitions (object and portraits)
17 
18 #ifndef INC_C4DefGraphics
19 #define INC_C4DefGraphics
20 
21 #include "graphics/C4Facet.h"
22 #include "lib/C4InputValidation.h"
23 #include "lib/StdMeshUpdate.h"
24 #include "object/C4Id.h"
25 #include "object/C4ObjectPtr.h"
26 
27 // defintion graphics
28 class C4AdditionalDefGraphics;
29 class C4DefGraphicsPtrBackup;
30 
31 class C4DefGraphics
32 {
33 public:
34 	C4Def *pDef;                    // underlying definition
35 
36 protected:
37 	C4AdditionalDefGraphics *pNext; // next graphics
38 
39 	C4DefGraphics *GetLast(); // get last graphics in list
40 public:
41 	enum GraphicsType
42 	{
43 		TYPE_None,
44 		TYPE_Bitmap,
45 		TYPE_Mesh
46 	};
47 
48 	GraphicsType Type;
49 
50 	union
51 	{
52 		struct
53 		{
54 			C4Surface *Bitmap, *BitmapClr, *BitmapNormal;
55 		} Bmp;
56 		StdMesh *Mesh;
57 	};
58 
59 	bool fColorBitmapAutoCreated;  // if set, the color-by-owner-bitmap has been created automatically by all blue shades of the bitmap
60 
61 	C4Surface *GetBitmap(DWORD dwClr=0);
62 
63 	C4DefGraphics(C4Def *pOwnDef=nullptr);  // ctor
~C4DefGraphics()64 	virtual ~C4DefGraphics() { Clear(); }; // dtor
65 
66 	bool LoadBitmap(C4Group &hGroup, const char *szFilenamePNG, const char *szOverlayPNG, const char *szNormal, bool fColorByOwner); // load specified graphics from group
67 	bool LoadBitmaps(C4Group &hGroup, bool fColorByOwner); // load graphics from group
68 	bool LoadMesh(C4Group &hGroup, const char* szFilename, StdMeshSkeletonLoader& loader);
69 	bool LoadSkeleton(C4Group &hGroup, const char* szFilename, StdMeshSkeletonLoader& loader);
70 	bool Load(C4Group &hGroup, StdMeshSkeletonLoader &loader, bool fColorByOwner); // load graphics from group
71 	C4DefGraphics *Get(const char *szGrpName); // get graphics by name
72 	void Clear(); // clear fields; delete additional graphics
IsMesh()73 	bool IsMesh() const { return Type == TYPE_Mesh; }
IsColorByOwner()74 	bool IsColorByOwner() // returns whether ColorByOwner-surfaces have been created
75 	{ return Type == TYPE_Mesh || (Type == TYPE_Bitmap && !!Bmp.BitmapClr); } // Mesh can always apply PlayerColor (if used in its material)
76 
77 	void Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans);
78 
GetName()79 	virtual const char *GetName() { return nullptr; } // return name to be stored in safe game files
80 
GetNext()81 	C4AdditionalDefGraphics *GetNext() { return pNext; }
82 
83 	void DrawClr(C4Facet &cgo, bool fAspect=true, DWORD dwClr=0); // set surface color and draw
84 
85 	void CompileFunc(StdCompiler *pComp);
86 
87 	friend class C4DefGraphicsPtrBackup;
88 };
89 
90 // additional definition graphics
91 class C4AdditionalDefGraphics : public C4DefGraphics
92 {
93 protected:
94 	char Name[C4MaxName+1];   // graphics name
95 
96 public:
97 	C4AdditionalDefGraphics(C4Def *pOwnDef, const char *szName);  // ctor
GetName()98 	const char *GetName() override { return Name; }
99 };
100 
101 // backup class holding dead graphics pointers and names
102 class C4DefGraphicsPtrBackupEntry
103 {
104 protected:
105 	C4DefGraphics *pGraphicsPtr; // dead graphics ptr
106 	C4Def *pDef;                 // definition of dead graphics
107 	char Name[C4MaxName+1];        // name of graphics
108 	StdMeshUpdate* pMeshUpdate;    // Dead mesh
109 
110 public:
111 	C4DefGraphicsPtrBackupEntry(C4DefGraphics *pSourceGraphics); // ctor
112 	~C4DefGraphicsPtrBackupEntry();                              // dtor
113 
114 	void AssignUpdate();   // update all game objects with new graphics pointers
115 	void AssignRemoval();  // remove graphics of this def from all game objects
116 
117 private:
118 	void UpdateAttachedMeshes();
119 	void UpdateAttachedMesh(StdMeshInstance* instance);
120 };
121 
122 // On definition reload, all graphics updates need to be performed in one
123 // batch using this class.
124 class C4DefGraphicsPtrBackup
125 {
126 public:
127 	C4DefGraphicsPtrBackup();
128 	~C4DefGraphicsPtrBackup();
129 
130 	// Add a def graphics to the list of graphics to be updated.
131 	// Also adds additional graphics linked from pGraphics.
132 	void Add(C4DefGraphics *pGraphics);
133 
134 	void AssignUpdate();   // update all game objects with new graphics pointers
135 	void AssignRemoval();  // remove graphics of all defs from all game objects
136 
GetUpdater()137 	StdMeshMaterialUpdate &GetUpdater() { return MeshMaterialUpdate; }
138 
139 private:
140 	void UpdateMesh(StdMeshInstance* instance);
141 
142 	StdMeshMaterialUpdate MeshMaterialUpdate; // Backup of dead mesh materials
143 	StdMeshAnimationUpdate MeshAnimationUpdate; // Backup of animation names in the animation tree
144 
145 	std::list<C4DefGraphicsPtrBackupEntry*> Entries;
146 
147 	bool fApplied{false};
148 };
149 
150 // Helper to compile C4DefGraphics-Pointer
151 class C4DefGraphicsAdapt
152 {
153 protected:
154 	C4DefGraphics *&pDefGraphics;
155 public:
C4DefGraphicsAdapt(C4DefGraphics * & pDefGraphics)156 	C4DefGraphicsAdapt(C4DefGraphics *&pDefGraphics) : pDefGraphics(pDefGraphics) { }
157 	void CompileFunc(StdCompiler *pComp);
158 	// Default checking / setting
159 	bool operator == (C4DefGraphics *pDef2) { return pDefGraphics == pDef2; }
160 	void operator = (C4DefGraphics *pDef2) { pDefGraphics = pDef2; }
161 };
162 
163 // graphics overlay used to attach additional graphics to objects
164 class C4GraphicsOverlay
165 {
166 	friend class C4DefGraphicsPtrBackupEntry;
167 	friend class C4DefGraphicsPtrBackup;
168 public:
169 	enum Mode
170 	{
171 		MODE_None=0,
172 		MODE_Base=1,     // display base facet
173 		MODE_Action=2,   // display action facet specified in Action
174 		MODE_Picture=3,  // overlay picture to this picture only
175 		MODE_IngamePicture=4, // draw picture of source def
176 		MODE_Object=5,        // draw another object gfx
177 		MODE_ExtraGraphics=6,       // draw like this were a ClrByOwner-surface
178 		MODE_Rank=7,                 // draw rank symbol
179 		MODE_ObjectPicture=8    // draw the picture of source object
180 	};
181 protected:
182 	Mode eMode{MODE_None};                // overlay mode
183 
184 	C4DefGraphics *pSourceGfx{nullptr}; // source graphics - used for savegame saving and comparisons in ReloadDef
185 	char Action[C4MaxName+1];  // action used as overlay in source gfx
186 	C4TargetFacet fctBlit; // current blit data for bitmap graphics
187 	StdMeshInstance* pMeshInstance{nullptr}; // NoSave // - current blit data for mesh graphics
188 	uint32_t dwBlitMode{0};          // extra parameters for additive blits, etc.
189 	uint32_t dwClrModulation{0xffffff};        // colormod for this overlay
190 	C4ObjectPtr OverlayObj; // object to be drawn as overlay in MODE_Object
191 	C4DrawTransform Transform; // drawing transformation: Rotation, zoom, etc.
192 	int32_t iPhase{0};                // action face for MODE_Action
193 	bool fZoomToShape{false};             // if true, overlay will be zoomed to match the target object shape
194 
195 	int32_t iID{0}; // identification number for Z-ordering and script identification
196 
197 	C4GraphicsOverlay *pNext{nullptr}; // singly linked list
198 
199 	void UpdateFacet();       // update fctBlit to reflect current data
200 	void Set(Mode aMode, C4DefGraphics *pGfx, const char *szAction, DWORD dwBMode, C4Object *pOvrlObj);
201 
202 public:
C4GraphicsOverlay()203 	C4GraphicsOverlay() : fctBlit(),
204 			OverlayObj(nullptr), Transform(+1) { *Action=0; } // std ctor
205 	~C4GraphicsOverlay(); // dtor
206 
207 	void CompileFunc(StdCompiler *pComp);
208 
209 	// object pointer management
210 	void DenumeratePointers();
211 
SetAsBase(C4DefGraphics * pBaseGfx,DWORD dwBMode)212 	void SetAsBase(C4DefGraphics *pBaseGfx, DWORD dwBMode) // set in MODE_Base
213 	{ Set(MODE_Base, pBaseGfx, nullptr, dwBMode, nullptr); }
SetAsAction(C4DefGraphics * pBaseGfx,const char * szAction,DWORD dwBMode)214 	void SetAsAction(C4DefGraphics *pBaseGfx, const char *szAction, DWORD dwBMode)
215 	{ Set(MODE_Action, pBaseGfx, szAction, dwBMode, nullptr); }
SetAsPicture(C4DefGraphics * pBaseGfx,DWORD dwBMode)216 	void SetAsPicture(C4DefGraphics *pBaseGfx, DWORD dwBMode)
217 	{ Set(MODE_Picture, pBaseGfx, nullptr, dwBMode, nullptr); }
SetAsIngamePicture(C4DefGraphics * pBaseGfx,DWORD dwBMode)218 	void SetAsIngamePicture(C4DefGraphics *pBaseGfx, DWORD dwBMode)
219 	{ Set(MODE_IngamePicture, pBaseGfx, nullptr, dwBMode, nullptr); }
SetAsObject(C4Object * pOverlayObj,DWORD dwBMode)220 	void SetAsObject(C4Object *pOverlayObj, DWORD dwBMode)
221 	{ Set(MODE_Object, nullptr, nullptr, dwBMode, pOverlayObj); }
SetAsObjectPicture(C4Object * pOverlayObj,DWORD dwBMode)222 	void SetAsObjectPicture(C4Object *pOverlayObj, DWORD dwBMode)
223 	{ Set(MODE_ObjectPicture, nullptr, nullptr, dwBMode, pOverlayObj); }
SetAsExtraGraphics(C4DefGraphics * pGfx,DWORD dwBMode)224 	void SetAsExtraGraphics(C4DefGraphics *pGfx, DWORD dwBMode)
225 	{ Set(MODE_ExtraGraphics, pGfx, nullptr, dwBMode, nullptr); }
SetAsRank(DWORD dwBMode,C4Object * rank_obj)226 	void SetAsRank(DWORD dwBMode, C4Object *rank_obj)
227 	{ Set(MODE_Rank, nullptr, nullptr, dwBMode, rank_obj); }
228 
229 	bool IsValid(const C4Object *pForObj) const;
230 
GetTransform()231 	C4DrawTransform *GetTransform() { return &Transform; }
GetOverlayObject()232 	C4Object *GetOverlayObject() const { return OverlayObj; }
GetID()233 	int32_t GetID() const { return iID; }
SetID(int32_t aID)234 	void SetID(int32_t aID) { iID = aID; }
235 	void SetPhase(int32_t iToPhase);
GetNext()236 	C4GraphicsOverlay *GetNext() const { return pNext; }
SetNext(C4GraphicsOverlay * paNext)237 	void SetNext(C4GraphicsOverlay *paNext) { pNext = paNext; }
IsPicture()238 	bool IsPicture() { return eMode == MODE_Picture; }
GetGfx()239 	C4DefGraphics *GetGfx() const { return pSourceGfx; }
240 
241 	void Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByPlayer);
242 	void DrawPicture(C4Facet &cgo, C4Object *pForObj, C4DrawTransform* trans);
243 	void DrawRankSymbol(C4Facet &cgo, C4Object *rank_obj);
244 
245 	bool operator == (const C4GraphicsOverlay &rCmp) const; // comparison operator
246 
GetClrModulation()247 	uint32_t GetClrModulation() const { return dwClrModulation; }
SetClrModulation(uint32_t dwToMod)248 	void SetClrModulation(uint32_t dwToMod) { dwClrModulation = dwToMod; }
249 
GetBlitMode()250 	uint32_t GetBlitMode() const { return dwBlitMode; }
SetBlitMode(uint32_t dwToMode)251 	void SetBlitMode(uint32_t dwToMode) { dwBlitMode = dwToMode; }
252 
253 };
254 
255 // Helper to compile lists of C4GraphicsOverlay
256 class C4GraphicsOverlayListAdapt
257 {
258 protected:
259 	C4GraphicsOverlay *&pOverlay;
260 public:
C4GraphicsOverlayListAdapt(C4GraphicsOverlay * & pOverlay)261 	C4GraphicsOverlayListAdapt(C4GraphicsOverlay *&pOverlay) : pOverlay(pOverlay) { }
262 	void CompileFunc(StdCompiler *pComp);
263 	// Default checking / setting
264 	bool operator == (C4GraphicsOverlay *pDefault) { return pOverlay == pDefault; }
265 	void operator = (C4GraphicsOverlay *pDefault) { delete pOverlay; pOverlay = pDefault; }
266 };
267 
268 #endif // INC_C4DefGraphics
269