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) 2011-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 /* A piece of a DirectDraw surface */
19 
20 #ifndef INC_C4Facet
21 #define INC_C4Facet
22 
23 #include "graphics/C4BltTransform.h"
24 
25 const int32_t C4FCT_None   = 0,
26 
27               C4FCT_Left   = 1,
28               C4FCT_Right  = 2,
29               C4FCT_Top    = 4,
30               C4FCT_Bottom = 8,
31               C4FCT_Center = 16,
32 
33               C4FCT_Alignment = C4FCT_Left | C4FCT_Right | C4FCT_Top | C4FCT_Bottom | C4FCT_Center,
34 
35               C4FCT_Half   = 32,
36               C4FCT_Double = 64,
37               C4FCT_Triple = 128;
38 
39 // tuple of two integers
40 struct C4Vec2D
41 {
42 	int32_t x,y;
43 
xC4Vec2D44 	C4Vec2D(int32_t x=0, int32_t y=0) : x(x), y(y) {}
45 };
46 
47 class C4DrawTransform : public C4BltTransform
48 {
49 public:
50 	int32_t FlipDir; // +1 or -1; multiplied as x-flip
51 
C4DrawTransform(C4DrawTransform & rCopy,float iOffX,float iOffY)52 	C4DrawTransform(C4DrawTransform &rCopy, float iOffX, float iOffY) // ctor doing transform at given offset - doesn't init FlipDir (for temp use only)
53 	{
54 		SetTransformAt(rCopy, iOffX, iOffY);
55 	}
56 
C4DrawTransform()57 	C4DrawTransform()
58 	{
59 		// ctor without matrix initialization
60 		FlipDir = 1;
61 	}
62 
C4DrawTransform(int32_t iFlipDir)63 	C4DrawTransform(int32_t iFlipDir)
64 	{
65 		// ctor setting flipdir only
66 		FlipDir = iFlipDir;
67 		// set identity
68 		Set(1,0,0,0,1,0,0,0,1);
69 	}
70 
71 	~C4DrawTransform() = default;
72 
73 	// do transform at given offset - doesn't init FlipDir (for temp use only)
74 	void SetTransformAt(C4DrawTransform &rCopy, float iOffX, float iOffY);
75 
Set(float fA,float fB,float fC,float fD,float fE,float fF,float fG,float fH,float fI)76 	void Set(float fA, float fB, float fC, float fD, float fE, float fF, float fG, float fH, float fI)
77 	{
78 		// set values; apply flipdir
79 		C4BltTransform::Set(fA*FlipDir, fB, fC, fD, fE, fF, fG, fH, fI);
80 	}
81 
SetFlipDir(int32_t iNewFlipDir)82 	void SetFlipDir(int32_t iNewFlipDir)
83 	{
84 		// no change?
85 		if (iNewFlipDir == FlipDir) return;
86 		// set and apply in matrix
87 		FlipDir = iNewFlipDir; mat[0] = -mat[0];
88 	}
89 
IsIdentity()90 	bool IsIdentity() const
91 	{
92 		return (mat[0]==1.0f) && (mat[1]==0.0f) && (mat[2]==0.0f)
93 		       && (mat[3]==0.0f) && (mat[4]==1.0f) && (mat[5]==0.0f)
94 		       && (mat[6]==0.0f) && (mat[7]==0.0f) && (mat[8]==1.0f)
95 		       && (FlipDir==1); // flipdir must be 1, because otherwise matrices flipped by action+script would be removed
96 	}
97 
98 	// default comparison op won't work :(
99 	bool operator == (const C4DrawTransform &rCmp) const
100 	{
101 		return (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]) && (FlipDir == rCmp.FlipDir);
104 	}
105 	C4DrawTransform * operator&() { return this; }
106 	void CompileFunc(StdCompiler *pComp);
107 
108 	// rounded pixel offsets generated by this transformation
GetXOffset()109 	int32_t GetXOffset() const { return static_cast<int32_t>(mat[2]); }
GetYOffset()110 	int32_t GetYOffset() const { return static_cast<int32_t>(mat[5]); }
111 
112 };
113 
114 class C4Facet
115 {
116 public:
117 	C4Surface * Surface;
118 	float X,Y,Wdt,Hgt;
119 public:
120 	C4Facet();
C4Facet(C4Surface * pSfc,float iX,float iY,float iWdt,float iHgt)121 	C4Facet(C4Surface * pSfc, float iX, float iY, float iWdt, float iHgt)
122 			: Surface(pSfc), X(iX), Y(iY), Wdt(iWdt), Hgt(iHgt) {  }
123 public:
124 	void Default();
125 	void Set(C4Surface &rSfc);
126 	void Set(C4Surface * nsfc, float nx, float ny, float nwdt, float nhgt);
Set(const C4Facet & cpy)127 	void Set(const C4Facet &cpy) { *this=cpy; }
128 	void Expand(int32_t iLeft=0, int32_t iRight=0, int32_t iTop=0, int32_t iBottom=0);
129 	void DrawEnergyLevelEx(int32_t iLevel, int32_t iRange, const C4Facet &gfx, int32_t bar_idx); // draw energy level using graphics
130 	void DrawX(C4Surface * sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iPhaseX=0, int32_t iPhaseY=0) const;
131 	void DrawXFloat(C4Surface * sfcTarget, float fX, float fY, float fWdt, float fHgt) const;
132 	void DrawValue(C4Facet &cgo, int32_t iValue, int32_t iPhaseX=0, int32_t iPhaseY=0, int32_t iAlign=C4FCT_Center);
133 	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);
134 	void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true);
135 	void DrawFullScreen(C4Facet &cgo);
136 	void DrawT(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); // draw with transformation (if pTransform is assigned)
137 	void DrawT(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform);
138 	void DrawTUnscaled(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); // interpret source coordinates as unscaled
139 	void DrawTUnscaled(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform);
140 	void DrawXT(C4Surface * sfcTarget, float iX, float iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform);
141 	void DrawClr(C4Facet &cgo, bool fAspect=true, DWORD dwClr=0); // set surface color and draw
142 	void DrawXClr(C4Surface * sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, DWORD dwClr); // set surface color and draw
143 	void DrawValue2Clr(C4Facet &cgo, int32_t iValue1, int32_t iValue2, DWORD dwClr); // set surface color and draw
144 	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
145 	void Draw(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX=0, int32_t iPhaseY=0);
146 	bool GetPhaseNum(int32_t &rX, int32_t &rY);   // return number of phases in this graphic
147 	C4Facet GetSection(int32_t iSection);
148 	C4Facet GetPhase(int iPhaseX=0, int iPhaseY=0);
149 	C4Facet GetFraction(int32_t percentWdt, int32_t percentHgt=0, int32_t alignX=C4FCT_Left, int32_t alignY=C4FCT_Top);
150 	C4Facet TruncateSection(int32_t iAlign=C4FCT_Left);
151 	C4Facet Truncate(int32_t iAlign, int32_t iSize);
152 	int32_t GetSectionCount();
GetWidthByHeight(int32_t iHeight)153 	int32_t GetWidthByHeight(int32_t iHeight) // calc width so it matches facet aspect to height
154 	{ return iHeight * Wdt / (Hgt ? Hgt : 1); }
GetHeightByWidth(int32_t iWidth)155 	int32_t GetHeightByWidth(int32_t iWidth) // calc height so it matches facet aspect to width
156 	{ return iWidth * Hgt / (Wdt ? Wdt : 1); }
157 };
158 
159 class C4TargetFacet: public C4Facet
160 {
161 public:
C4TargetFacet()162 	C4TargetFacet() { Default(); }
163 	~C4TargetFacet() = default;
164 public:
165 	float TargetX,TargetY,Zoom;
166 
167 	// Reference values for parallax computations. This is similar to
168 	// a scrolling position. In most cases these are the same as TargetX
169 	// and TargetY, however for full map screenshots, which are composed
170 	// of several individual screenshots, these are kept fixed while
171 	// TargetX/TargetY are varied to cover the full map. This prevents
172 	// duplicate parallax objects in fullscreen map screenshots. If
173 	// TargetX/TargetY are different from ParRefX/ParRefY it can be thought
174 	// of as drawing only a part of a window/viewport at a given fixed
175 	// scroll position.
176 	// See bug #1042.
177 	float ParRefX, ParRefY;
178 public:
Default()179 	void Default() { TargetX=TargetY=0; Zoom=1; ParRefX=ParRefY=0; C4Facet::Default(); }
Clear()180 	void Clear() { Surface=nullptr; }
181 
Set(const C4Facet & cpy)182 	void Set(const C4Facet &cpy) { TargetX=TargetY=0; Zoom=1; ParRefX=ParRefY=0; C4Facet::Set(cpy); }
Set(const C4TargetFacet & cpy)183 	void Set(const C4TargetFacet &cpy) { *this = cpy; }
184 	void Set(class C4Surface *nsfc, float nx, float ny, float nwdt, float nhgt, float ntx=0, float nty=0, float Zoom=1);
185 	void Set(class C4Surface *nsfc, const C4Rect & r, float ntx=0, float nty=0, float Zoom=1);
186 	void Set(class C4Surface *nsfc, float nx, float ny, float nwdt, float nhgt, float ntx, float nty, float Zoom, float prx, float pry);
187 
188 public:
189 	C4TargetFacet &operator = (const C4Facet& rhs)
190 	{
191 		Set(rhs.Surface,rhs.X,rhs.Y,rhs.Wdt,rhs.Hgt);
192 		return *this;
193 	}
194 	void SetRect(C4TargetRect &rSrc);
195 };
196 
197 #endif // INC_C4Facet
198