| 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 | |
| 23 | const 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 |
| 38 | struct C4Vec2D |
| 39 | { |
| 40 | int32_t x, y; |
| 41 | |
| 42 | C4Vec2D(int32_t x = 0, int32_t y = 0) : x(x), y(y) {} |
| 43 | }; |
| 44 | |
| 45 | class C4DrawTransform : public CBltTransform |
| 46 | { |
| 47 | public: |
| 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 | |
| 115 | class C4Facet |
| 116 | { |
| 117 | public: |
| 118 | C4Surface *Surface; |
| 119 | int32_t X, Y, Wdt, Hgt; |
| 120 | |
| 121 | public: |
| 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 | |
| 126 | public: |
| 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 | |