1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2004, Sven2
6 * Copyright (c) 2017-2022, The LegacyClonk 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// graphics used by object definitions (object and portraits)
19
20#pragma once
21
22#include <C4EnumeratedObjectPtr.h>
23#include <C4FacetEx.h>
24#include "C4ForwardDeclarations.h"
25#include <C4Material.h>
26#include <C4Surface.h>
27
28#define C4Portrait_None "none"
29#define C4Portrait_Random "random"
30#define C4Portrait_Custom "custom"
31
32// defintion graphics
33class C4AdditionalDefGraphics;
34class C4DefGraphicsPtrBackup;
35class C4PortraitGraphics;
36
37class C4DefGraphics
38{
39public:
40 C4Def *pDef; // underlying definition
41
42protected:
43 C4AdditionalDefGraphics *pNext; // next graphics
44
45public:
46 C4Surface *Bitmap, *BitmapClr;
47 bool fColorBitmapAutoCreated; // if set, the color-by-owner-bitmap has been created automatically by all blue shades of the bitmap
48
49 inline C4Surface *GetBitmap(uint32_t dwClr = 0) { if (BitmapClr) { BitmapClr->SetClr(dwClr); return BitmapClr; } else return Bitmap; }
50
51 C4DefGraphics(C4Def *pOwnDef = nullptr);
52 virtual ~C4DefGraphics() { Clear(); }
53
54 bool LoadGraphics(C4Group &hGroup, const char *szFilename, const char *szFilenamePNG, const char *szOverlayPNG, bool fColorByOwner); // load specified graphics from group
55 bool LoadAllGraphics(C4Group &hGroup, bool fColorByOwner); // load graphics from group
56 bool ColorizeByMaterial(int32_t iMat, C4MaterialMap &rMats, uint8_t bGBM); // colorize all graphics by material
57 C4DefGraphics *Get(const char *szGrpName); // get graphics by name
58 void Clear(); // clear fields; delete additional graphics
59
60 bool IsColorByOwner() // returns whether ColorByOwner-surfaces have been created
61 {
62 return !!BitmapClr;
63 }
64
65 bool CopyGraphicsFrom(C4DefGraphics &rSource); // copy bitmaps from source graphics
66
67 virtual const char *GetName() { return nullptr; } // return name to be stored in safe game files
68
69 C4AdditionalDefGraphics *GetNext() { return pNext; }
70 virtual C4PortraitGraphics *IsPortrait() { return nullptr; }
71
72 void DrawClr(C4Facet &cgo, bool fAspect = true, uint32_t dwClr = 0); // set surface color and draw
73
74 friend class C4DefGraphicsPtrBackup;
75};
76
77// additional definition graphics
78class C4AdditionalDefGraphics : public C4DefGraphics
79{
80protected:
81 char Name[C4MaxName + 1]; // graphics name
82
83public:
84 C4AdditionalDefGraphics(C4Def *pOwnDef, const char *szName);
85 virtual const char *GetName() override { return Name; }
86};
87
88// portrait graphics within object definition
89class C4PortraitGraphics : public C4AdditionalDefGraphics
90{
91public:
92 C4PortraitGraphics(C4Def *pOwnDef, const char *szName)
93 : C4AdditionalDefGraphics(pOwnDef, szName) {}
94
95 virtual C4PortraitGraphics *IsPortrait() override { return this; }
96 C4PortraitGraphics *GetByIndex(int32_t iIndex);
97 C4PortraitGraphics *Get(const char *szGrpName); // get portrait graphics by name
98};
99
100// backup class holding dead graphics pointers and names
101class C4DefGraphicsPtrBackup
102{
103protected:
104 C4DefGraphics *pGraphicsPtr; // dead graphics ptr
105 C4Surface *BitmapPtr; // dead bitmap ptr
106 C4Def *pDef; // definition of dead graphics
107 char Name[C4MaxName + 1]; // name of graphics
108 C4DefGraphicsPtrBackup *pNext; // next member of linked list
109
110public:
111 C4DefGraphicsPtrBackup(C4DefGraphics *pSourceGraphics);
112 ~C4DefGraphicsPtrBackup();
113
114 void AssignUpdate(C4DefGraphics *pNewGraphics); // update all game objects with new graphics pointers
115 void AssignRemoval(); // remove graphics of this def from all game objects
116};
117
118// Helper to compile C4DefGraphics-Pointer
119class C4DefGraphicsAdapt
120{
121protected:
122 C4DefGraphics *&pDefGraphics;
123
124public:
125 C4DefGraphicsAdapt(C4DefGraphics *&pDefGraphics) : pDefGraphics(pDefGraphics) {}
126 void CompileFunc(StdCompiler *pComp);
127
128 // Default checking / setting
129 bool operator==(C4DefGraphics *pDef2) { return pDefGraphics == pDef2; }
130 void operator=(C4DefGraphics *pDef2) { pDefGraphics = pDef2; }
131};
132
133// portrait link class
134class C4Portrait
135{
136protected:
137 C4DefGraphics *pGfxPortrait; // the portrait graphics
138 bool fGraphicsOwned; // if true, the portrait graphics are owned (and deleted upon destruction)
139
140public:
141 C4Portrait() : pGfxPortrait(nullptr), fGraphicsOwned(false) {}
142 ~C4Portrait() { if (fGraphicsOwned) delete pGfxPortrait; }
143 void Default() { pGfxPortrait = nullptr; fGraphicsOwned = false; }
144 void Clear() { if (fGraphicsOwned) { delete pGfxPortrait; fGraphicsOwned = false; } pGfxPortrait = nullptr; }
145
146 bool CopyFrom(C4DefGraphics &rCopyGfx); // copy portrait from graphics
147 bool CopyFrom(C4Portrait &rCopy); // copy portrait
148
149 bool Load(C4Group &rGrp, const char *szFilename, const char *szFilenamePNG, const char *szOverlayPNG); // load own portrait from group
150 bool Link(C4DefGraphics *pGfxPortrait); // link with a present portrait surface
151 bool SavePNG(C4Group &rGroup, const char *szFilename, const char *szOverlayFN); // store portrait gfx to file (including overlay)
152
153 C4DefGraphics *GetGfx() { return pGfxPortrait; }
154 bool IsOwnedGfx() { return fGraphicsOwned; } // return if it's a custom portrait
155
156 static const char *EvaluatePortraitString(const char *szPortrait, C4ID &rIDOut, C4ID idDefaultID, uint32_t *pdwClrOut); // get portrait source and def from string
157};
158
159// graphics overlay used to attach additional graphics to objects
160class C4GraphicsOverlay
161{
162public:
163 enum Mode
164 {
165 MODE_None = 0,
166 MODE_Base = 1, // display base facet
167 MODE_Action = 2, // display action facet specified in Action
168 MODE_Picture = 3, // overlay picture to this picture only
169 MODE_IngamePicture = 4, // draw picture of source def
170 MODE_Object = 5, // draw another object gfx
171 MODE_ExtraGraphics = 6, // draw like this were a ClrByOwner-surface
172 };
173
174protected:
175 Mode eMode; // overlay mode
176
177 C4DefGraphics *pSourceGfx; // source graphics - used for savegame saving and comparisons in ReloadDef
178 char Action[C4MaxName + 1]; // action used as overlay in source gfx
179 C4FacetEx fctBlit; // current blit data
180 uint32_t dwBlitMode; // extra parameters for additive blits, etc.
181 uint32_t dwClrModulation; // colormod for this overlay
182 C4EnumeratedObjectPtr pOverlayObj; // object to be drawn as overlay in MODE_Object
183 C4DrawTransform Transform; // drawing transformation: Rotation, zoom, etc.
184 int32_t iPhase; // action face for MODE_Action
185 bool fZoomToShape; // if true, overlay will be zoomed to match the target object shape
186
187 int32_t iID; // identification number for Z-ordering and script identification
188
189 C4GraphicsOverlay *pNext; // singly linked list
190
191 void UpdateFacet(); // update fctBlit to reflect current data
192 void Set(Mode aMode, C4DefGraphics *pGfx, const char *szAction, uint32_t dwBMode, C4Object *pOvrlObj);
193
194public:
195 C4GraphicsOverlay() : eMode(MODE_None), pSourceGfx(nullptr), fctBlit(), dwBlitMode(0), dwClrModulation(0xffffff),
196 Transform(+1), iPhase(0), fZoomToShape(false), iID(0), pNext(nullptr)
197 {
198 *Action = 0;
199 }
200
201 ~C4GraphicsOverlay();
202
203 void CompileFunc(StdCompiler *pComp);
204
205 // object pointer management
206 void EnumeratePointers();
207 void DenumeratePointers();
208
209 void SetAsBase(C4DefGraphics *pBaseGfx, uint32_t dwBMode) // set in MODE_Base
210 {
211 Set(aMode: MODE_Base, pGfx: pBaseGfx, szAction: nullptr, dwBMode, pOvrlObj: nullptr);
212 }
213
214 void SetAsAction(C4DefGraphics *pBaseGfx, const char *szAction, uint32_t dwBMode)
215 {
216 Set(aMode: MODE_Action, pGfx: pBaseGfx, szAction, dwBMode, pOvrlObj: nullptr);
217 }
218
219 void SetAsPicture(C4DefGraphics *pBaseGfx, uint32_t dwBMode)
220 {
221 Set(aMode: MODE_Picture, pGfx: pBaseGfx, szAction: nullptr, dwBMode, pOvrlObj: nullptr);
222 }
223
224 void SetAsIngamePicture(C4DefGraphics *pBaseGfx, uint32_t dwBMode)
225 {
226 Set(aMode: MODE_IngamePicture, pGfx: pBaseGfx, szAction: nullptr, dwBMode, pOvrlObj: nullptr);
227 }
228
229 void SetAsObject(C4Object *pOverlayObj, uint32_t dwBMode)
230 {
231 Set(aMode: MODE_Object, pGfx: nullptr, szAction: nullptr, dwBMode, pOvrlObj: pOverlayObj);
232 }
233
234 void SetAsExtraGraphics(C4DefGraphics *pGfx, uint32_t dwBMode)
235 {
236 Set(aMode: MODE_ExtraGraphics, pGfx, szAction: nullptr, dwBMode, pOvrlObj: nullptr);
237 }
238
239 bool IsValid(const C4Object *pForObj) const;
240
241 C4DrawTransform *GetTransform() { return &Transform; }
242 C4Object *GetOverlayObject() const { return pOverlayObj; }
243 int32_t GetID() const { return iID; }
244 void SetID(int32_t aID) { iID = aID; }
245 C4GraphicsOverlay *GetNext() const { return pNext; }
246 void SetNext(C4GraphicsOverlay *paNext) { pNext = paNext; }
247 bool IsPicture() { return eMode == MODE_Picture; }
248 C4DefGraphics *GetGfx() const { return pSourceGfx; }
249
250 void Draw(C4FacetEx &cgo, C4Object *pForObj, int32_t iByPlayer);
251 void DrawPicture(C4Facet &cgo, C4Object *pForObj);
252
253 bool operator==(const C4GraphicsOverlay &rCmp) const; // comparison operator
254
255 uint32_t GetClrModulation() const { return dwClrModulation; }
256 void SetClrModulation(uint32_t dwToMod) { dwClrModulation = dwToMod; }
257
258 uint32_t GetBlitMode() const { return dwBlitMode; }
259 void SetBlitMode(uint32_t dwToMode) { dwBlitMode = dwToMode; }
260
261 void UpdateSourceGraphics(C4DefGraphics *newSource); // for ReloadDef
262};
263
264// Helper to compile lists of C4GraphicsOverlay
265class C4GraphicsOverlayListAdapt
266{
267protected:
268 C4GraphicsOverlay *&pOverlay;
269
270public:
271 C4GraphicsOverlayListAdapt(C4GraphicsOverlay *&pOverlay) : pOverlay(pOverlay) {}
272 void CompileFunc(StdCompiler *pComp);
273
274 // Default checking / setting
275 bool operator==(C4GraphicsOverlay *pDefault) { return pOverlay == pDefault; }
276 void operator=(C4GraphicsOverlay *pDefault) { delete pOverlay; pOverlay = pDefault; }
277};
278