MyGUI 3.2.0

- Main Page
- Related Pages
- Namespaces
- Data Structures
- Files
- Examples

- File List
- Globals

MyGUI_TileRect.cpp
Go to the documentation of this file.
1
6 /*
7 This file is part of MyGUI.
8
9 MyGUI is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 MyGUI is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include "MyGUI_Precompiled.h"
23 #include "MyGUI_TileRect.h"
24 #include "MyGUI_RenderItem.h"
25 #include "MyGUI_SkinManager.h"
26 #include "MyGUI_LanguageManager.h"
27 #include "MyGUI_LayerNode.h"
28 #include "MyGUI_CommonStateInfo.h"
29 #include "MyGUI_RenderManager.h"
30 #include "MyGUI_TextureUtility.h"
31
32 namespace MyGUI
33 {
34
35 const size_t TILERECT_COUNT_VERTEX = 16 * VertexQuad::VertexCount;
36
37 TileRect::TileRect() :
38 mEmptyView(false),
39 mCurrentColour(0xFFFFFFFF),
40 mNode(nullptr),
41 mRenderItem(nullptr),
42 mCountVertex(TILERECT_COUNT_VERTEX),
43 mRealTileWidth(0),
44 mRealTileHeight(0),
45 mTextureHeightOne(0),
46 mTextureWidthOne(0),
47 mTileH(true),
48 mTileV(true)
49 {
50 mVertexFormat = RenderManager::getInstance().getVertexFormat();
51 }
52
53 TileRect::~TileRect()
54 {
55 }
56
57 void TileRect::setVisible(bool _visible)
58 {
59 if (mVisible == _visible) return;
60 mVisible = _visible;
61
62 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
63 }
64
65 void TileRect::setAlpha(float _alpha)
66 {
67 uint32 alpha = ((uint8)(_alpha * 255) << 24);
68 mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
69
70 if (nullptr != mNode)
71 mNode->outOfDate(mRenderItem);
72 }
73
74 void TileRect::_correctView()
75 {
76 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
77 }
78
79 void TileRect::_setAlign(const IntSize& _oldsize)
80 {
81 // необходимо разобраться
82 bool need_update = true;
83
84 // первоначальное выравнивание
85 if (mAlign.isHStretch())
86 {
87 // растягиваем
88 mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
89 need_update = true;
90 mIsMargin = true; // при изменении размеров все пересчитывать
91 }
92 else if (mAlign.isRight())
93 {
94 // двигаем по правому краю
95 mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
96 need_update = true;
97 }
98 else if (mAlign.isHCenter())
99 {
100 // выравнивание по горизонтали без растяжения
101 mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
102 need_update = true;
103 }
104
105 if (mAlign.isVStretch())
106 {
107 // растягиваем
108 mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
109 need_update = true;
110 mIsMargin = true; // при изменении размеров все пересчитывать
111 }
112 else if (mAlign.isBottom())
113 {
114 // двигаем по нижнему краю
115 mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
116 need_update = true;
117 }
118 else if (mAlign.isVCenter())
119 {
120 // выравнивание по вертикали без растяжения
121 mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
122 need_update = true;
123 }
124
125 if (need_update)
126 {
127 mCurrentCoord = mCoord;
128 if (!mTileH) mTileSize.width = mCoord.width;
129 if (!mTileV) mTileSize.height = mCoord.height;
130 _updateView();
131 }
132
133 }
134
135 void TileRect::_updateView()
136 {
137 bool margin = _checkMargin();
138
139 mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
140
141 mCurrentCoord.left = mCoord.left + mMargin.left;
142 mCurrentCoord.top = mCoord.top + mMargin.top;
143 mCurrentCoord.width = _getViewWidth();
144 mCurrentCoord.height = _getViewHeight();
145
146 // подсчитываем необходимое колличество тайлов
147 if (!mEmptyView)
148 {
149 size_t count = 0;
150 if (!mTileSize.empty())
151 {
152 size_t count_x = mCoord.width / mTileSize.width;
153 if ((mCoord.width % mTileSize.width) > 0) count_x ++;
154 size_t count_y = mCoord.height / mTileSize.height;
155 if ((mCoord.height % mTileSize.height) > 0) count_y ++;
156 count = count_y * count_x * VertexQuad::VertexCount;
157 }
158
159 // нужно больше вершин
160 if (count > mCountVertex)
161 {
162 mCountVertex = count + TILERECT_COUNT_VERTEX;
163 if (nullptr != mRenderItem) mRenderItem->reallockDrawItem(this, mCountVertex);
164 }
165 }
166
167 // вьюпорт стал битым
168 if (margin)
169 {
170 // проверка на полный выход за границу
171 if (_checkOutside())
172 {
173 // запоминаем текущее состояние
174 mIsMargin = margin;
175
176 // обновить перед выходом
177 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
178 return;
179 }
180 }
181
182 // запоминаем текущее состояние
183 mIsMargin = margin;
184
185 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
186 }
187
188 void TileRect::_setUVSet(const FloatRect& _rect)
189 {
190 mCurrentTexture = _rect;
191 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
192 }
193
194 void TileRect::doRender()
195 {
196 if (!mVisible || mEmptyView || mTileSize.empty()) return;
197
198 VertexQuad* quad = (VertexQuad*)mRenderItem->getCurrentVertexBuffer();
199
200 const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
201
202 // размер одного тайла
203 mRealTileWidth = info.pixScaleX * (float)(mTileSize.width) * 2;
204 mRealTileHeight = info.pixScaleY * (float)(mTileSize.height) * 2;
205
206 mTextureHeightOne = (mCurrentTexture.bottom - mCurrentTexture.top) / mRealTileHeight;
207 mTextureWidthOne = (mCurrentTexture.right - mCurrentTexture.left) / mRealTileWidth;
208
209 float vertex_z = info.maximumDepth;
210
211 // абсолютный размер окна
212 float window_left = ((info.pixScaleX * (float)(mCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
213 float window_top = -(((info.pixScaleY * (float)(mCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
214
215 // размер вьюпорта
216 float real_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
217 float real_right = real_left + (info.pixScaleX * (float)mCurrentCoord.width * 2);
218 float real_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
219 float real_bottom = real_top - (info.pixScaleY * (float)mCurrentCoord.height * 2);
220
221 size_t count = 0;
222
223 float left = window_left;
224 float right = window_left;
225 float top = window_top;
226 float bottom = window_top;
227
228 for (int y = 0; y < mCoord.height; y += mTileSize.height)
229 {
230 top = bottom;
231 bottom -= mRealTileHeight;
232 right = window_left;
233
234 float vertex_top = top;
235 float vertex_bottom = bottom;
236 bool texture_crop_height = false;
237
238 if (vertex_top > real_top)
239 {
240 // проверка на полный выход
241 if (vertex_bottom > real_top)
242 {
243 continue;
244 }
245 // обрезаем
246 vertex_top = real_top;
247 texture_crop_height = true;
248 }
249 if (vertex_bottom < real_bottom)
250 {
251 // вообще вниз ушли
252 if (vertex_top < real_bottom)
253 {
254 continue;
255 }
256 // обрезаем
257 vertex_bottom = real_bottom;
258 texture_crop_height = true;
259 }
260
261 for (int x = 0; x < mCoord.width; x += mTileSize.width)
262 {
263 left = right;
264 right += mRealTileWidth;
265
266 float vertex_left = left;
267 float vertex_right = right;
268 bool texture_crop_width = false;
269
270
271 if (vertex_left < real_left)
272 {
273 // проверка на полный выход
274 if (vertex_right < real_left)
275 {
276 continue;
277 }
278 // обрезаем
279 vertex_left = real_left;
280 texture_crop_width = true;
281 }
282
283 if (vertex_right > real_right)
284 {
285 // вообще строку до конца не нуна
286 if (vertex_left > real_right)
287 {
288 continue;
289 }
290 // обрезаем
291 vertex_right = real_right;
292 texture_crop_width = true;
293 }
294
295 // текущие текстурные координаты
296 float texture_left = mCurrentTexture.left;
297 float texture_right = mCurrentTexture.right;
298 float texture_top = mCurrentTexture.top;
299 float texture_bottom = mCurrentTexture.bottom;
300
301 // смещение текстуры по вертикили
302 if (texture_crop_height)
303 {
304 // прибавляем размер смещения в текстурных координатах
305 texture_top += (top - vertex_top) * mTextureHeightOne;
306 // отнимаем размер смещения в текстурных координатах
307 texture_bottom -= (vertex_bottom - bottom) * mTextureHeightOne;
308 }
309
310 // смещение текстуры по горизонтали
311 if (texture_crop_width)
312 {
313 // прибавляем размер смещения в текстурных координатах
314 texture_left += (vertex_left - left) * mTextureWidthOne;
315 // отнимаем размер смещения в текстурных координатах
316 texture_right -= (right - vertex_right) * mTextureWidthOne;
317 }
318
319 quad[count].set(
320 vertex_left,
321 vertex_top,
322 vertex_right,
323 vertex_bottom,
324 vertex_z,
325 texture_left,
326 texture_top,
327 texture_right,
328 texture_bottom,
329 mCurrentColour
330 );
331
332 count ++;
333 }
334 }
335
336 mRenderItem->setLastVertexCount(VertexQuad::VertexCount * count);
337 }
338
339 void TileRect::createDrawItem(ITexture* _texture, ILayerNode* _node)
340 {
341 MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
342
343 mNode = _node;
344 mRenderItem = mNode->addToRenderItem(_texture, true, false);
345 mRenderItem->addDrawItem(this, mCountVertex);
346 }
347
348 void TileRect::destroyDrawItem()
349 {
350 MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
351
352 mNode = nullptr;
353 mRenderItem->removeDrawItem(this);
354 mRenderItem = nullptr;
355 }
356
357 void TileRect::setStateData(IStateInfo* _data)
358 {
359 TileRectStateInfo* data = _data->castType<TileRectStateInfo>();
360
361 mTileSize = data->getTileSize();
362 mTileH = data->getTileH();
363 mTileV = data->getTileV();
364 _setUVSet(data->getRect());
365 }
366
367 void TileRect::_setColour(const Colour& _value)
368 {
369 uint32 colour = texture_utility::toColourARGB(_value);
370 texture_utility::convertColour(colour, mVertexFormat);
371 mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
372
373 if (nullptr != mNode)
374 mNode->outOfDate(mRenderItem);
375 }
376
377 } // namespace MyGUI
MyGUI::ICroppedRectangle::getAbsoluteLeft
int getAbsoluteLeft() const
Definition: MyGUI_ICroppedRectangle.h:98
MyGUI::TileRect::~TileRect
virtual ~TileRect()
Definition: MyGUI_TileRect.cpp:53
MyGUI::TileRect::setVisible
virtual void setVisible(bool _visible)
Definition: MyGUI_TileRect.cpp:57
MyGUI::TileRect::setAlpha
virtual void setAlpha(float _alpha)
Definition: MyGUI_TileRect.cpp:65
MyGUI_TextureUtility.h
MyGUI::types::TSize::empty
bool empty() const
Definition: MyGUI_TSize.h:123
MyGUI::Align::isVStretch
bool isVStretch() const
Definition: MyGUI_Align.h:99
MyGUI::TileRect::setStateData
virtual void setStateData(IStateInfo *_data)
Definition: MyGUI_TileRect.cpp:357
MyGUI::TileRect::_setColour
virtual void _setColour(const Colour &_value)
Definition: MyGUI_TileRect.cpp:367
MyGUI::uint32
unsigned int uint32
Definition: MyGUI_Types.h:63
MyGUI::ILayerNode::outOfDate
virtual void outOfDate(RenderItem *_item)=0
MyGUI::RenderTargetInfo::pixScaleY
float pixScaleY
Definition: MyGUI_RenderTargetInfo.h:54
MyGUI::ILayerNode
Definition: MyGUI_ILayerNode.h:42
MyGUI::RenderItem::removeDrawItem
void removeDrawItem(ISubWidget *_item)
Definition: MyGUI_RenderItem.cpp:113
MyGUI::RenderTargetInfo::maximumDepth
float maximumDepth
Definition: MyGUI_RenderTargetInfo.h:52
MyGUI::VertexQuad
Definition: MyGUI_VertexData.h:48
MyGUI::types::TRect::top
T top
Definition: MyGUI_TRect.h:36
MyGUI::RenderItem::addDrawItem
void addDrawItem(ISubWidget *_item, size_t _count)
Definition: MyGUI_RenderItem.cpp:138
MyGUI_Precompiled.h
MyGUI::RenderTargetInfo::leftOffset
int leftOffset
Definition: MyGUI_RenderTargetInfo.h:59
MyGUI::ICroppedRectangle::_getViewHeight
int _getViewHeight() const
Definition: MyGUI_ICroppedRectangle.h:168
MyGUI::ICroppedRectangle::mIsMargin
bool mIsMargin
Definition: MyGUI_ICroppedRectangle.h:263
MyGUI::ICroppedRectangle::getHeight
int getHeight() const
Definition: MyGUI_ICroppedRectangle.h:134
MyGUI::RenderItem::getRenderTarget
IRenderTarget * getRenderTarget()
Definition: MyGUI_RenderItem.cpp:250
MyGUI::Align::isBottom
bool isBottom() const
Definition: MyGUI_Align.h:94
MyGUI::texture_utility::convertColour
__inline void convertColour(uint32 &_colour, VertexColourType _format)
Definition: MyGUI_TextureUtility.h:38
MyGUI::IStateInfo
Definition: MyGUI_IStateInfo.h:31
MyGUI::types::TSize< int >
MyGUI::TileRect::doRender
virtual void doRender()
Definition: MyGUI_TileRect.cpp:194
MyGUI::Singleton< RenderManager >::getInstance
static RenderManager & getInstance()
Definition: MyGUI_Singleton.h:53
MyGUI::Align::isVCenter
bool isVCenter() const
Definition: MyGUI_Align.h:64
MyGUI::RenderTargetInfo::topOffset
int topOffset
Definition: MyGUI_RenderTargetInfo.h:60
MyGUI::TileRect::TileRect
TileRect()
Definition: MyGUI_TileRect.cpp:37
MyGUI::TILERECT_COUNT_VERTEX
const size_t TILERECT_COUNT_VERTEX
Definition: MyGUI_TileRect.cpp:35
MyGUI::TileRect::mTextureWidthOne
float mTextureWidthOne
Definition: MyGUI_TileRect.h:86
MyGUI::TileRect::mRenderItem
RenderItem * mRenderItem
Definition: MyGUI_TileRect.h:77
MyGUI::ICroppedRectangle::mCroppedParent
ICroppedRectangle * mCroppedParent
Definition: MyGUI_ICroppedRectangle.h:264
MyGUI::RenderManager::getVertexFormat
virtual VertexColourType getVertexFormat()=0
MyGUI::ICroppedRectangle::getAbsoluteTop
int getAbsoluteTop() const
Definition: MyGUI_ICroppedRectangle.h:103
MyGUI::VertexQuad::set
void set(float _l, float _t, float _r, float _b, float _z, float _u1, float _v1, float _u2, float _v2, uint32 _colour)
Definition: MyGUI_VertexData.h:61
MyGUI::TileRectStateInfo::getRect
const FloatRect & getRect() const
Definition: MyGUI_CommonStateInfo.h:81
MyGUI_TileRect.h
MyGUI::TileRect::_correctView
virtual void _correctView()
Definition: MyGUI_TileRect.cpp:74
nullptr
#define nullptr
Definition: MyGUI_Prerequest.h:47
MyGUI::TileRect::mEmptyView
bool mEmptyView
Definition: MyGUI_TileRect.h:68
MyGUI::Align::isHCenter
bool isHCenter() const
Definition: MyGUI_Align.h:59
MyGUI::types::TCoord::width
T width
Definition: MyGUI_TCoord.h:39
MyGUI_LanguageManager.h
MyGUI::TileRect::mCurrentTexture
FloatRect mCurrentTexture
Definition: MyGUI_TileRect.h:73
MyGUI::TileRect::_updateView
virtual void _updateView()
Definition: MyGUI_TileRect.cpp:135
MyGUI::ILayerNode::addToRenderItem
virtual RenderItem * addToRenderItem(ITexture *_texture, bool _firstQueue, bool _separate)=0
MyGUI::ICroppedRectangle::mCoord
IntCoord mCoord
Definition: MyGUI_ICroppedRectangle.h:260
MyGUI::TileRect::createDrawItem
virtual void createDrawItem(ITexture *_texture, ILayerNode *_node)
Definition: MyGUI_TileRect.cpp:339
MyGUI::types::TCoord::top
T top
Definition: MyGUI_TCoord.h:38
MyGUI::TileRect::mTileV
bool mTileV
Definition: MyGUI_TileRect.h:89
MyGUI::types::TRect::left
T left
Definition: MyGUI_TRect.h:35
MyGUI::TileRectStateInfo::getTileV
bool getTileV() const
Definition: MyGUI_CommonStateInfo.h:96
MyGUI::TileRectStateInfo::getTileH
bool getTileH() const
Definition: MyGUI_CommonStateInfo.h:91
MyGUI::TileRect::mRealTileWidth
float mRealTileWidth
Definition: MyGUI_TileRect.h:82
MyGUI_RenderManager.h
MyGUI::ICroppedRectangle::mMargin
IntRect mMargin
Definition: MyGUI_ICroppedRectangle.h:259
MyGUI::TileRectStateInfo::getTileSize
const IntSize & getTileSize() const
Definition: MyGUI_CommonStateInfo.h:86
MyGUI::RenderItem::getCurrentVertexBuffer
Vertex * getCurrentVertexBuffer() const
Definition: MyGUI_RenderItem.cpp:240
MyGUI::VertexQuad::VertexCount
Definition: MyGUI_VertexData.h:58
MyGUI::ICroppedRectangle::getWidth
int getWidth() const
Definition: MyGUI_ICroppedRectangle.h:129
MyGUI::types::TRect< float >
MyGUI::ICroppedRectangle::_getViewWidth
int _getViewWidth() const
Definition: MyGUI_ICroppedRectangle.h:164
MyGUI::types::TSize::width
T width
Definition: MyGUI_TSize.h:35
MyGUI::ISubWidget::mVisible
bool mVisible
Definition: MyGUI_ISubWidget.h:76
MyGUI::RenderTargetInfo::pixScaleX
float pixScaleX
Definition: MyGUI_RenderTargetInfo.h:53
MyGUI::TileRect::mRealTileHeight
float mRealTileHeight
Definition: MyGUI_TileRect.h:83
MyGUI_CommonStateInfo.h
MyGUI_RenderItem.h
MyGUI::TileRect::mCountVertex
size_t mCountVertex
Definition: MyGUI_TileRect.h:80
MyGUI::Align::isRight
bool isRight() const
Definition: MyGUI_Align.h:79
MyGUI::RenderItem::reallockDrawItem
void reallockDrawItem(ISubWidget *_item, size_t _count)
Definition: MyGUI_RenderItem.cpp:156
MyGUI::ICroppedRectangle::_checkOutside
bool _checkOutside() const
Definition: MyGUI_ICroppedRectangle.h:250
MYGUI_ASSERT
#define MYGUI_ASSERT(exp, dest)
Definition: MyGUI_Diagnostic.h:58
MyGUI::ITexture
Definition: MyGUI_ITexture.h:41
MyGUI::TileRect::mNode
ILayerNode * mNode
Definition: MyGUI_TileRect.h:76
MyGUI::TileRect::_setAlign
virtual void _setAlign(const IntSize &_oldsize)
Definition: MyGUI_TileRect.cpp:79
MyGUI::IRenderTarget::getInfo
virtual const RenderTargetInfo & getInfo()=0
MyGUI::texture_utility::toColourARGB
uint32 toColourARGB(const Colour &_colour)
Definition: MyGUI_TextureUtility.cpp:83
MyGUI::RenderTargetInfo::hOffset
float hOffset
Definition: MyGUI_RenderTargetInfo.h:55
MyGUI::IObject::castType
Type * castType(bool _throw=true)
Definition: MyGUI_IObject.h:33
MyGUI::TileRectStateInfo
Definition: MyGUI_CommonStateInfo.h:67
MyGUI_LayerNode.h
MyGUI::ISubWidget::mAlign
Align mAlign
Definition: MyGUI_ISubWidget.h:75
MyGUI::TileRect::destroyDrawItem
virtual void destroyDrawItem()
Definition: MyGUI_TileRect.cpp:348
MyGUI::TileRect::mCurrentCoord
IntCoord mCurrentCoord
Definition: MyGUI_TileRect.h:74
MyGUI::RenderTargetInfo
Definition: MyGUI_RenderTargetInfo.h:30
MyGUI::TileRect::mTextureHeightOne
float mTextureHeightOne
Definition: MyGUI_TileRect.h:85
MyGUI::TileRect::mTileH
bool mTileH
Definition: MyGUI_TileRect.h:88
MyGUI::Colour
Definition: MyGUI_Colour.h:31
MyGUI::TileRect::_setUVSet
virtual void _setUVSet(const FloatRect &_rect)
Definition: MyGUI_TileRect.cpp:188
MyGUI::RenderTargetInfo::vOffset
float vOffset
Definition: MyGUI_RenderTargetInfo.h:56
MyGUI::types::TSize::height
T height
Definition: MyGUI_TSize.h:36
MyGUI::types::TCoord::left
T left
Definition: MyGUI_TCoord.h:37
MyGUI::types::TRect::right
T right
Definition: MyGUI_TRect.h:37
MyGUI::Align::isHStretch
bool isHStretch() const
Definition: MyGUI_Align.h:84
MyGUI::uint8
unsigned char uint8
Definition: MyGUI_Types.h:61
MyGUI::types::TRect::bottom
T bottom
Definition: MyGUI_TRect.h:38
MyGUI::ICroppedRectangle::_checkMargin
bool _checkMargin()
Definition: MyGUI_ICroppedRectangle.h:200
MyGUI::RenderItem::setLastVertexCount
void setLastVertexCount(size_t _count)
Definition: MyGUI_RenderItem.cpp:245
MyGUI_SkinManager.h
MyGUI::types::TCoord::height
T height
Definition: MyGUI_TCoord.h:40
MyGUI::TileRect::mTileSize
IntSize mTileSize
Definition: MyGUI_TileRect.h:79
MyGUI::TileRect::mVertexFormat
VertexColourType mVertexFormat
Definition: MyGUI_TileRect.h:70
MyGUI::TileRect::mCurrentColour
uint32 mCurrentColour
Definition: MyGUI_TileRect.h:71