guiDefaultControlRender.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "graphics/dgl.h"
  23. #include "gui/guiDefaultControlRender.h"
  24. #include "gui/guiTypes.h"
  25. #include "graphics/gColor.h"
  26. #include "math/mRect.h"
  27. // Renders a rect in one of three ways: ImageAsset, bitmap, or default render. ImageAsset and bitmap can use
  28. // nine frames per state or one frame per state. The default render is used as a fall back if neither are present.
  29. void renderUniversalRect(RectI &bounds, GuiControlProfile *profile, GuiControlState state, const ColorI &fillColor, const bool bUseFillColor)
  30. {
  31. if (profile == NULL)
  32. {
  33. return;
  34. }
  35. U8 stateIndex = state;
  36. //prepare
  37. S32 bitmapFrameCount = 0;
  38. S32 imageFrameCount = 0;
  39. if (profile->mImageAsset != NULL && profile->mImageAsset->isAssetValid())
  40. {
  41. imageFrameCount = profile->mImageAsset->getFrameCount();
  42. }
  43. else if (profile->mBitmapName != NULL)
  44. {
  45. bitmapFrameCount = profile->constructBitmapArray();
  46. }
  47. if (imageFrameCount >= (9 * (stateIndex + 1)))
  48. {
  49. renderSizableBorderedImageAsset(bounds, stateIndex, profile->mImageAsset, imageFrameCount);
  50. }
  51. else if (imageFrameCount > stateIndex && imageFrameCount < 9)
  52. {
  53. renderStretchedImageAsset(bounds, stateIndex, profile);
  54. }
  55. else if (bitmapFrameCount >= (9 * (stateIndex + 1)))
  56. {
  57. renderSizableBorderedBitmap(bounds, stateIndex, profile->mTextureHandle, profile->mBitmapArrayRects.address(), bitmapFrameCount);
  58. }
  59. else if (bitmapFrameCount > stateIndex && bitmapFrameCount < 9)
  60. {
  61. renderStretchedBitmap(bounds, stateIndex, profile);
  62. }
  63. else
  64. {
  65. if (bUseFillColor)
  66. {
  67. renderBorderedRect(bounds, profile, state, fillColor);
  68. }
  69. else
  70. {
  71. renderBorderedRect(bounds, profile, state);
  72. }
  73. }
  74. }
  75. void renderBorderedRect(RectI &bounds, GuiControlProfile *profile, GuiControlState state)
  76. {
  77. if(profile)
  78. {
  79. ColorI fillColor = profile->getFillColor(state);
  80. renderBorderedRect(bounds, profile, state, fillColor);
  81. }
  82. }
  83. void renderBorderedRect(RectI &bounds, GuiControlProfile *profile, GuiControlState state, const ColorI &fillColor)
  84. {
  85. if (!profile)
  86. {
  87. return;
  88. }
  89. //Get the border profiles
  90. GuiBorderProfile *leftProfile = profile->getLeftBorder();
  91. GuiBorderProfile *rightProfile = profile->getRightBorder();
  92. GuiBorderProfile *topProfile = profile->getTopBorder();
  93. GuiBorderProfile *bottomProfile = profile->getBottomBorder();
  94. //Get the colors
  95. ColorI leftColor = (leftProfile) ? leftProfile->getBorderColor(state) : ColorI();
  96. ColorI rightColor = (rightProfile) ? rightProfile->getBorderColor(state) : ColorI();
  97. ColorI topColor = (topProfile) ? topProfile->getBorderColor(state) : ColorI();
  98. ColorI bottomColor = (bottomProfile) ? bottomProfile->getBorderColor(state) : ColorI();
  99. S32 leftSize = (leftProfile) ? leftProfile->getBorder(state) : 0;
  100. S32 rightSize = (rightProfile) ? rightProfile->getBorder(state) : 0;
  101. S32 topSize = (topProfile) ? topProfile->getBorder(state) : 0;
  102. S32 bottomSize = (bottomProfile) ? bottomProfile->getBorder(state) : 0;
  103. //Get the inner rect
  104. RectI innerRect = RectI(bounds.point.x + leftSize, bounds.point.y + topSize, (bounds.extent.x - leftSize) - rightSize, (bounds.extent.y - topSize) - bottomSize);
  105. //Draw the fill
  106. if(fillColor.alpha > 0)
  107. {
  108. S32 fillWidth = innerRect.extent.x + ((leftProfile && leftProfile->mUnderfill) ? leftSize : 0) + ((rightProfile && rightProfile->mUnderfill) ? rightSize : 0);
  109. S32 fillHeight = innerRect.extent.y + ((topProfile && topProfile->mUnderfill) ? topSize : 0) + ((bottomProfile && bottomProfile->mUnderfill) ? bottomSize : 0);
  110. RectI fillRect = RectI((leftProfile && leftProfile->mUnderfill) ? bounds.point.x : innerRect.point.x,
  111. (topProfile && topProfile->mUnderfill) ? bounds.point.y : innerRect.point.y, fillWidth, fillHeight);
  112. dglDrawRectFill(fillRect, fillColor);
  113. }
  114. //Draw the borders
  115. //Points for outer bounds starting top left and traveling counter-clockwise
  116. Point2I p1 = Point2I(bounds.point);
  117. Point2I p2 = Point2I(bounds.point.x, bounds.point.y + bounds.extent.y);
  118. Point2I p3 = Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + bounds.extent.y);
  119. Point2I p4 = Point2I(bounds.point.x + bounds.extent.x, bounds.point.y);
  120. //Points for inner bounds starting top left and traveling counter-clockwise
  121. Point2I p5 = Point2I(innerRect.point);
  122. Point2I p6 = Point2I(innerRect.point.x, innerRect.point.y + innerRect.extent.y);
  123. Point2I p7 = Point2I(innerRect.point.x + innerRect.extent.x, innerRect.point.y + innerRect.extent.y);
  124. Point2I p8 = Point2I(innerRect.point.x + innerRect.extent.x, innerRect.point.y);
  125. if (leftSize > 0)
  126. {
  127. dglDrawQuadFill(p1, p2, p6, p5, leftColor);
  128. }
  129. if (rightSize > 0)
  130. {
  131. dglDrawQuadFill(p8, p7, p3, p4, rightColor);
  132. }
  133. if (topSize > 0)
  134. {
  135. dglDrawQuadFill(p1, p5, p8, p4, topColor);
  136. }
  137. if (bottomSize > 0)
  138. {
  139. dglDrawQuadFill(p6, p2, p3, p7, bottomColor);
  140. }
  141. if (state > 3)
  142. {
  143. RectI checkRect = RectI(bounds);
  144. checkRect.inset(3, 3);
  145. if (checkRect.isValidRect())
  146. {
  147. renderBorderedRect(checkRect, profile, GuiControlState::SelectedState);
  148. }
  149. }
  150. }
  151. void renderBorderedCircle(Point2I& center, S32 radius, GuiControlProfile* profile, GuiControlState state = NormalState)
  152. {
  153. //Get the colors
  154. ColorI fillColor = profile->getFillColor(state);
  155. ColorI borderColor = (profile->mBorderDefault) ? profile->mBorderDefault->getBorderColor(state) : ColorI();
  156. S32 borderSize = (profile->mBorderDefault) ? profile->mBorderDefault->getBorder(state) : 0;
  157. //Draw the fill
  158. S32 fillRadius = (profile->mBorderDefault && profile->mBorderDefault->mUnderfill) ? radius : radius - borderSize;
  159. dglDrawCircleFill(center, (F32)fillRadius, fillColor);
  160. //Draw the border
  161. renderRing(center, (F32)radius, borderColor, (F32)borderSize);
  162. if (state > 3 && radius >= 8)
  163. {
  164. dglDrawCircleFill(center, radius - 6, profile->getFillColor(GuiControlState::SelectedState));
  165. }
  166. }
  167. void renderBorderedRing(Point2I& center, S32 outerRadius, S32 innerRadius, GuiControlProfile* profile, GuiControlState state = NormalState)
  168. {
  169. if (innerRadius <= 0)
  170. {
  171. renderBorderedCircle(center, outerRadius, profile, state);
  172. return;
  173. }
  174. //Get the colors
  175. ColorI fillColor = profile->getFillColor(state);
  176. ColorI borderColor = (profile->mBorderDefault) ? profile->mBorderDefault->getBorderColor(state) : ColorI();
  177. S32 borderSize = (profile->mBorderDefault) ? profile->mBorderDefault->getBorder(state) : 0;
  178. //Draw the fill
  179. S32 fillRadius = (profile->mBorderDefault && profile->mBorderDefault->mUnderfill) ? outerRadius : outerRadius - borderSize;
  180. renderRing(center, (F32)fillRadius, fillColor, (F32)(outerRadius - innerRadius));
  181. //Draw the border
  182. renderRing(center, (F32)outerRadius, borderColor, (F32)borderSize);
  183. }
  184. void renderRing(const Point2I& center, const F32 radius, const ColorI& color, F32 borderSize)
  185. {
  186. for (S32 i = 0; i < borderSize; i++)
  187. {
  188. if(i < (borderSize - 1))
  189. {
  190. dglDrawCircle(center, radius - i, color, 2);
  191. }
  192. else
  193. {
  194. dglDrawCircle(center, radius - i, color, 1);
  195. }
  196. }
  197. }
  198. // Based on the 'Skinnable GUI Controls in TGE' resource by Justin DuJardin
  199. void renderSizableBorderedImageAsset(RectI &bounds, U8 frame, ImageAsset *imageAsset, S32 frameCount)
  200. {
  201. S32 NumFrames = 9;
  202. S32 i = NumFrames * frame;
  203. if (frameCount >= (NumFrames + i))
  204. {
  205. const ImageAsset::FrameArea::PixelArea& pixelArea1 = imageAsset->getImageFrameArea((U32)i).mPixelArea;
  206. const ImageAsset::FrameArea::PixelArea& pixelArea2 = imageAsset->getImageFrameArea((U32)i+1).mPixelArea;
  207. const ImageAsset::FrameArea::PixelArea& pixelArea3 = imageAsset->getImageFrameArea((U32)i+2).mPixelArea;
  208. const ImageAsset::FrameArea::PixelArea& pixelArea4 = imageAsset->getImageFrameArea((U32)i+3).mPixelArea;
  209. const ImageAsset::FrameArea::PixelArea& pixelArea5 = imageAsset->getImageFrameArea((U32)i+4).mPixelArea;
  210. const ImageAsset::FrameArea::PixelArea& pixelArea6 = imageAsset->getImageFrameArea((U32)i+5).mPixelArea;
  211. const ImageAsset::FrameArea::PixelArea& pixelArea7 = imageAsset->getImageFrameArea((U32)i+6).mPixelArea;
  212. const ImageAsset::FrameArea::PixelArea& pixelArea8 = imageAsset->getImageFrameArea((U32)i+7).mPixelArea;
  213. const ImageAsset::FrameArea::PixelArea& pixelArea9 = imageAsset->getImageFrameArea((U32)i+8).mPixelArea;
  214. RectI topleft = pixelArea1.toRectI();
  215. RectI top = RectI(pixelArea2.mPixelOffset, Point2I(pixelArea2.mPixelWidth, pixelArea2.mPixelHeight));
  216. RectI topright = RectI(pixelArea3.mPixelOffset, Point2I(pixelArea3.mPixelWidth, pixelArea3.mPixelHeight));
  217. RectI left = RectI(pixelArea4.mPixelOffset, Point2I(pixelArea4.mPixelWidth, pixelArea4.mPixelHeight));
  218. RectI fill = RectI(pixelArea5.mPixelOffset, Point2I(pixelArea5.mPixelWidth, pixelArea5.mPixelHeight));
  219. RectI right = RectI(pixelArea6.mPixelOffset, Point2I(pixelArea6.mPixelWidth, pixelArea6.mPixelHeight));
  220. RectI bottomleft = RectI(pixelArea7.mPixelOffset, Point2I(pixelArea7.mPixelWidth, pixelArea7.mPixelHeight));
  221. RectI bottom = RectI(pixelArea8.mPixelOffset, Point2I(pixelArea8.mPixelWidth, pixelArea8.mPixelHeight));
  222. RectI bottomright = RectI(pixelArea9.mPixelOffset, Point2I(pixelArea9.mPixelWidth, pixelArea9.mPixelHeight));
  223. renderSizableBorderedTexture(bounds, imageAsset->getImageTexture(),
  224. topleft,
  225. top,
  226. topright,
  227. left,
  228. fill,
  229. right,
  230. bottomleft,
  231. bottom,
  232. bottomright);
  233. }
  234. }
  235. void renderSizableBorderedBitmap(RectI &bounds, U8 frame, TextureHandle &texture, RectI *bitmapBounds, S32 frameCount)
  236. {
  237. S32 NumFrames = 9;
  238. S32 i = NumFrames * frame;
  239. if (frameCount >= (NumFrames + i))
  240. {
  241. renderSizableBorderedTexture(bounds, texture, bitmapBounds[i], bitmapBounds[i+1], bitmapBounds[i+2], bitmapBounds[i+3], bitmapBounds[i+4], bitmapBounds[i+5], bitmapBounds[i+6], bitmapBounds[i+7], bitmapBounds[i+8]);
  242. }
  243. }
  244. void renderSizableBorderedTexture(RectI &bounds, TextureHandle &texture, RectI &TopLeft, RectI &Top, RectI &TopRight, RectI &Left, RectI &Fill, RectI &Right, RectI &BottomLeft, RectI &Bottom, RectI &BottomRight)
  245. {
  246. RectI oldClip = dglGetClipRect();
  247. RectI newClip = RectI(bounds);
  248. if (newClip.intersect(oldClip))
  249. {
  250. dglSetClipRect(newClip);
  251. dglClearBitmapModulation();
  252. RectI destRect;
  253. RectI stretchRect;
  254. //top corners
  255. dglDrawBitmapSR(texture, bounds.point, TopLeft);
  256. dglDrawBitmapSR(texture, Point2I(bounds.point.x + bounds.extent.x - TopRight.extent.x, bounds.point.y), TopRight);
  257. //bottom corners
  258. dglDrawBitmapSR(texture, Point2I(bounds.point.x, bounds.point.y + bounds.extent.y - BottomLeft.extent.y), BottomLeft);
  259. dglDrawBitmapSR(texture, Point2I(bounds.point.x + bounds.extent.x - BottomRight.extent.x, bounds.point.y + bounds.extent.y - BottomRight.extent.y), BottomRight);
  260. //top line stretch
  261. destRect.point.x = bounds.point.x + TopLeft.extent.x;
  262. destRect.extent.x = bounds.extent.x - TopRight.extent.x - TopLeft.extent.x;
  263. destRect.extent.y = Top.extent.y;
  264. destRect.point.y = bounds.point.y;
  265. stretchRect = Top;
  266. dglDrawBitmapStretchSR(texture, destRect, stretchRect);
  267. //bottom line stretch
  268. destRect.point.x = bounds.point.x + BottomLeft.extent.x;
  269. destRect.extent.x = bounds.extent.x - BottomRight.extent.x - BottomLeft.extent.x;
  270. destRect.extent.y = Bottom.extent.y;
  271. destRect.point.y = bounds.point.y + bounds.extent.y - Bottom.extent.y;
  272. stretchRect = Bottom;
  273. dglDrawBitmapStretchSR(texture, destRect, stretchRect);
  274. //left line stretch
  275. destRect.point.x = bounds.point.x;
  276. destRect.extent.x = Left.extent.x;
  277. destRect.extent.y = bounds.extent.y - TopLeft.extent.y - BottomLeft.extent.y;
  278. destRect.point.y = bounds.point.y + TopLeft.extent.y;
  279. stretchRect = Left;
  280. dglDrawBitmapStretchSR(texture, destRect, stretchRect);
  281. //right line stretch
  282. destRect.point.x = bounds.point.x + bounds.extent.x - Right.extent.x;
  283. destRect.extent.x = Right.extent.x;
  284. destRect.extent.y = bounds.extent.y - TopRight.extent.y - BottomRight.extent.y;
  285. destRect.point.y = bounds.point.y + TopRight.extent.y;
  286. stretchRect = Right;
  287. dglDrawBitmapStretchSR(texture, destRect, stretchRect);
  288. //fill stretch
  289. destRect.point.x = bounds.point.x + Left.extent.x;
  290. destRect.extent.x = (bounds.extent.x) - Left.extent.x - Right.extent.x;
  291. destRect.extent.y = bounds.extent.y - Top.extent.y - Bottom.extent.y;
  292. destRect.point.y = bounds.point.y + Top.extent.y;
  293. stretchRect = Fill;
  294. dglDrawBitmapStretchSR(texture, destRect, stretchRect);
  295. dglSetClipRect(oldClip);
  296. }
  297. }
  298. // Renders out the fixed bitmap borders based on a multiplier into the bitmap array.
  299. // It renders left and right caps, with a sizable fill area in the middle to reach
  300. // the x extent. It does not stretch in the y direction.
  301. void renderFixedBitmapBordersFilled(RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile)
  302. {
  303. S32 NumBitmaps = 3;
  304. S32 startIndex = NumBitmaps * (baseMultiplier - 1);
  305. S32 BorderLeft = startIndex;
  306. S32 Fill = 1 + startIndex;
  307. S32 BorderRight = 2 + startIndex;
  308. dglClearBitmapModulation();
  309. if(profile->mBitmapArrayRects.size() >= (startIndex + NumBitmaps))
  310. {
  311. RectI destRect;
  312. RectI stretchRect;
  313. RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
  314. //draw left endcap
  315. dglDrawBitmapSR(profile->mTextureHandle,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[BorderLeft]);
  316. //draw right endcap
  317. dglDrawBitmapSR(profile->mTextureHandle,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[BorderRight].extent.x,bounds.point.y),mBitmapBounds[BorderRight]);
  318. //draw stretched content
  319. destRect.point.x = bounds.point.x + mBitmapBounds[BorderLeft].extent.x;
  320. destRect.extent.x = (bounds.extent.x) - mBitmapBounds[BorderLeft].extent.x - mBitmapBounds[BorderRight].extent.x;
  321. destRect.extent.y = bounds.extent.y;
  322. destRect.point.y = bounds.point.y;
  323. //stretch it
  324. stretchRect = mBitmapBounds[Fill];
  325. //draw it
  326. dglDrawBitmapStretchSR(profile->mTextureHandle,destRect,stretchRect);
  327. }
  328. }
  329. // Renders out a stretched bitmap.
  330. void renderStretchedBitmap(RectI &bounds, U8 frame, GuiControlProfile *profile)
  331. {
  332. dglClearBitmapModulation();
  333. if (profile->mBitmapArrayRects.size() > frame)
  334. {
  335. RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
  336. dglDrawBitmapStretchSR(profile->mTextureHandle, bounds, mBitmapBounds[frame]);
  337. }
  338. }
  339. // Renders out a stretched image asset.
  340. void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profile)
  341. {
  342. dglClearBitmapModulation();
  343. ImageAsset *imageAsset = profile->mImageAsset;
  344. if (imageAsset != NULL && imageAsset->isAssetValid() && imageAsset->getFrameCount() > frame)
  345. {
  346. const ImageAsset::FrameArea::PixelArea& pixelArea = imageAsset->getImageFrameArea(frame).mPixelArea;
  347. RectI srcRect(pixelArea.mPixelOffset, Point2I(pixelArea.mPixelWidth, pixelArea.mPixelHeight));
  348. // Render image.
  349. dglDrawBitmapStretchSR(imageAsset->getImageTexture(), bounds, srcRect);
  350. }
  351. }
  352. //Renders a color bullet at or one pixel smaller than maxSize.
  353. //It shrinks the given box until it is less than or equal to the
  354. //maxSize in the x direction.
  355. void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize, bool useCircle)
  356. {
  357. if (bounds.extent.x > maxSize)
  358. {
  359. S32 delta = mCeil((bounds.extent.x - maxSize) / 2);
  360. bounds.inset(delta, delta);
  361. }
  362. if (!bounds.isValidRect())
  363. {
  364. return;
  365. }
  366. if(!useCircle)
  367. {
  368. dglDrawRectFill(bounds, ColorI(0, 0, 0, 100));
  369. bounds.inset(1, 1);
  370. if (!bounds.isValidRect())
  371. {
  372. return;
  373. }
  374. dglDrawRectFill(bounds, color);
  375. }
  376. else
  377. {
  378. Point2I center = Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y + (bounds.extent.y / 2));
  379. F32 radius = (F32)(bounds.extent.x / 2);
  380. dglDrawCircleFill(center, radius, ColorI(0, 0, 0, 100));
  381. dglDrawCircleFill(center, radius-1, color);
  382. }
  383. }
  384. void renderTriangleIcon(RectI &bounds, ColorI &color, GuiDirection pointsToward, S32 maxSize)
  385. {
  386. if (bounds.extent.x > maxSize)
  387. {
  388. S32 delta = mCeil((bounds.extent.x - maxSize) / 2);
  389. bounds.inset(delta, delta);
  390. }
  391. if (!bounds.isValidRect())
  392. {
  393. return;
  394. }
  395. if (pointsToward == GuiDirection::Up)
  396. {
  397. dglDrawTriangleFill(
  398. Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
  399. Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + bounds.extent.y),
  400. Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y),
  401. color
  402. );
  403. }
  404. else if (pointsToward == GuiDirection::Down)
  405. {
  406. dglDrawTriangleFill(
  407. bounds.point,
  408. Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y + bounds.extent.y),
  409. Point2I(bounds.point.x + bounds.extent.x, bounds.point.y),
  410. color
  411. );
  412. }
  413. else if (pointsToward == GuiDirection::Right)
  414. {
  415. dglDrawTriangleFill(
  416. bounds.point,
  417. Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
  418. Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + (bounds.extent.y / 2)),
  419. color
  420. );
  421. }
  422. else if (pointsToward == GuiDirection::Left)
  423. {
  424. dglDrawTriangleFill(
  425. Point2I(bounds.point.x + bounds.extent.x, bounds.point.y),
  426. Point2I(bounds.point.x, bounds.point.y + (bounds.extent.y / 2)),
  427. Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + bounds.extent.y),
  428. color
  429. );
  430. }
  431. }