1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2021, The LegacyClonk 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
17/* A piece of a DirectDraw surface */
18
19#pragma once
20
21#include <StdDDraw2.h>
22
23const int32_t C4FCT_None = 0,
24
25 C4FCT_Left = 1,
26 C4FCT_Right = 2,
27 C4FCT_Top = 4,
28 C4FCT_Bottom = 8,
29 C4FCT_Center = 16,
30
31 C4FCT_Alignment = C4FCT_Left | C4FCT_Right | C4FCT_Top | C4FCT_Bottom | C4FCT_Center,
32
33 C4FCT_Half = 32,
34 C4FCT_Double = 64,
35 C4FCT_Triple = 128;
36
37// tuple of two integers
38struct C4Vec2D
39{
40 int32_t x, y;
41
42 C4Vec2D(int32_t x = 0, int32_t y = 0) : x(x), y(y) {}
43};
44
45class C4DrawTransform : public CBltTransform
46{
47public:
48 int32_t FlipDir; // +1 or -1; multiplied as x-flip
49
50 C4DrawTransform(C4DrawTransform &rCopy, float iOffX, float iOffY) // ctor doing transform at given offset - doesn't init FlipDir (for temp use only)
51 {
52 SetTransformAt(rCopy, iOffX, iOffY);
53 }
54
55 C4DrawTransform()
56 {
57 // ctor without matrix initialization
58 FlipDir = 1;
59 }
60
61 C4DrawTransform(int32_t iFlipDir)
62 {
63 // ctor setting flipdir only
64 FlipDir = iFlipDir;
65 // set identity
66 Set(fA: 1, fB: 0, fC: 0, fD: 0, fE: 1, fF: 0, fG: 0, fH: 0, fI: 1);
67 }
68
69 ~C4DrawTransform() {}
70
71 // do transform at given offset - doesn't init FlipDir (for temp use only)
72 void SetTransformAt(C4DrawTransform &rCopy, float iOffX, float iOffY);
73
74 void Set(float fA, float fB, float fC, float fD, float fE, float fF, float fG, float fH, float fI)
75 {
76 // set values; apply flipdir
77 CBltTransform::Set(fA: fA * FlipDir, fB, fC, fD, fE, fF, fG, fH, fI);
78 }
79
80 void SetFlipDir(int32_t iNewFlipDir)
81 {
82 // no change?
83 if (iNewFlipDir == FlipDir) return;
84 // set and apply in matrix
85 FlipDir = iNewFlipDir; mat[0] = -mat[0];
86 }
87
88 bool IsIdentity()
89 {
90 return
91 (mat[0] == 1.0f) && (mat[1] == 0.0f) && (mat[2] == 0.0f) &&
92 (mat[3] == 0.0f) && (mat[4] == 1.0f) && (mat[5] == 0.0f) &&
93 (mat[6] == 0.0f) && (mat[7] == 0.0f) && (mat[8] == 1.0f) &&
94 (FlipDir == 1); // flipdir must be 1, because otherwise matrices flipped by action+script would be removed
95 }
96
97 // default comparison op won't work :(
98 bool operator==(const C4DrawTransform &rCmp) const
99 {
100 return
101 (mat[0] == rCmp.mat[0]) && (mat[1] == rCmp.mat[1]) && (mat[2] == rCmp.mat[2]) &&
102 (mat[3] == rCmp.mat[3]) && (mat[4] == rCmp.mat[4]) && (mat[5] == rCmp.mat[5]) &&
103 (mat[6] == rCmp.mat[6]) && (mat[7] == rCmp.mat[7]) && (mat[8] == rCmp.mat[8]) &&
104 (FlipDir == rCmp.FlipDir);
105 }
106
107 C4DrawTransform *operator&() { return this; }
108 void CompileFunc(StdCompiler *pComp);
109
110 // rounded pixel offsets generated by this transformation
111 int32_t GetXOffset() const { return static_cast<int32_t>(mat[2]); }
112 int32_t GetYOffset() const { return static_cast<int32_t>(mat[5]); }
113};
114
115class C4Facet
116{
117public:
118 C4Surface *Surface;
119 int32_t X, Y, Wdt, Hgt;
120
121public:
122 C4Facet();
123 C4Facet(C4Surface *pSfc, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
124 : Surface(pSfc), X(iX), Y(iY), Wdt(iWdt), Hgt(iHgt) {}
125
126public:
127 void Default();
128 void Set(C4Surface *nsfc, int32_t nx, int32_t ny, int32_t nwdt, int32_t nhgt);
129 void Set(const C4Facet &cpy) { *this = cpy; }
130 void DrawEnergyLevelEx(int32_t iLevel, int32_t iRange, const C4Facet &gfx, int32_t bar_idx); // draw energy level using graphics
131 void DrawX(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX = 0, int32_t iPhaseY = 0, float scale = 1.0f) const;
132 void DrawXFloat(C4Surface *sfcTarget, float fX, float fY, float fWdt, float fHgt) const;
133 void DrawValue(C4Facet &cgo, int32_t iValue, int32_t iPhaseX = 0, int32_t iPhaseY = 0, int32_t iAlign = C4FCT_Center);
134 void DrawValue2(C4Facet &cgo, int32_t iValue1, int32_t iValue2, int32_t iPhaseX = 0, int32_t iPhaseY = 0, int32_t iAlign = C4FCT_Center, int32_t *piUsedWidth = nullptr);
135 void Draw(C4Facet &cgo, bool fAspect = true, int32_t iPhaseX = 0, int32_t iPhaseY = 0, bool fTransparent = true, float scale = 1.0f);
136 void DrawFullScreen(C4Facet &cgo);
137 void DrawT(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform, bool noScalingCorrection = false, float scale = 1.0f); // draw with transformation (if pTransform is assigned)
138 void DrawT(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform, bool noScalingCorrection = false, float scale = 1.0f);
139 void DrawXT(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform, bool noScalingCorrection = false, float scale = 1.0f);
140 void DrawClr(C4Facet &cgo, bool fAspect = true, uint32_t dwClr = 0); // set surface color and draw
141 void DrawValue2Clr(C4Facet &cgo, int32_t iValue1, int32_t iValue2, uint32_t dwClr); // set surface color and draw
142 void DrawXR(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX = 0, int32_t iPhaseY = 0, int32_t r = 0); // draw rotated
143 void DrawClrMod(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iPhaseX = 0, int32_t iPhaseY = 0, uint32_t dwModClr = 0); // draw the facet modulated by given color
144 void Draw(C4Surface *sfcTarget, int32_t iX, int32_t iY, int32_t iPhaseX = 0, int32_t iPhaseY = 0, float scale = 1.0f);
145 bool GetPhaseNum(int32_t &rX, int32_t &rY); // return number of phases in this graphic
146 C4Facet GetSection(int32_t iSection);
147 C4Facet GetFraction(int32_t percentWdt, int32_t percentHgt = 0, int32_t alignX = C4FCT_Left, int32_t alignY = C4FCT_Top);
148 C4Facet TruncateSection(int32_t iAlign = C4FCT_Left);
149 C4Facet Truncate(int32_t iAlign, int32_t iSize);
150 int32_t GetSectionCount();
151
152 int32_t GetWidthByHeight(int32_t iHeight) // calc width so it matches facet aspect to height
153 {
154 return iHeight * Wdt / (Hgt ? Hgt : 1);
155 }
156
157 int32_t GetHeightByWidth(int32_t iWidth) // calc height so it matches facet aspect to width
158 {
159 return iWidth * Hgt / (Wdt ? Wdt : 1);
160 }
161};
162