afxGuiTextHud.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. #include "afx/arcaneFX.h"
  25. #include "gui/3d/guiTSControl.h"
  26. #include "gfx/gfxDrawUtil.h"
  27. #include "T3D/gameBase/gameConnection.h"
  28. #include "T3D/shapeBase.h"
  29. #include "afx/ui/afxGuiTextHud.h"
  30. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  31. Vector<afxGuiTextHud::HudTextSpec> afxGuiTextHud::text_items;
  32. IMPLEMENT_CONOBJECT(afxGuiTextHud);
  33. ConsoleDocClass( afxGuiTextHud,
  34. "@brief Similar to GuiShapeNameHud, afxGuiTextHud displays ShapeBase object names but "
  35. "also allows Gui Text effects.\n\n"
  36. "@ingroup GuiGame\n"
  37. );
  38. afxGuiTextHud::afxGuiTextHud()
  39. {
  40. mFillColor.set( 0.25f, 0.25f, 0.25f, 0.25f );
  41. mFrameColor.set( 0, 0, 0, 1 );
  42. mTextColor.set( 0, 1, 0, 1 );
  43. mShowFill = false;
  44. mShowFrame = true;
  45. mVerticalOffset = 0.5f;
  46. mDistanceFade = 0.1f;
  47. mLabelAllShapes = false;
  48. mEnableControlObjectOcclusion = false;
  49. }
  50. void afxGuiTextHud::initPersistFields()
  51. {
  52. docsURL;
  53. addGroup("Colors");
  54. addField( "fillColor", TypeColorF, Offset( mFillColor, afxGuiTextHud ),
  55. "...");
  56. addField( "frameColor", TypeColorF, Offset( mFrameColor, afxGuiTextHud ),
  57. "...");
  58. addField( "textColor", TypeColorF, Offset( mTextColor, afxGuiTextHud ),
  59. "...");
  60. endGroup("Colors");
  61. addGroup("Misc");
  62. addField( "showFill", TypeBool, Offset( mShowFill, afxGuiTextHud ),
  63. "...");
  64. addField( "showFrame", TypeBool, Offset( mShowFrame, afxGuiTextHud ),
  65. "...");
  66. addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, afxGuiTextHud ),
  67. "...");
  68. addField( "distanceFade", TypeF32, Offset( mDistanceFade, afxGuiTextHud ),
  69. "...");
  70. addField( "labelAllShapes", TypeBool, Offset( mLabelAllShapes, afxGuiTextHud ),
  71. "...");
  72. addField( "enableControlObjectOcclusion", TypeBool, Offset( mEnableControlObjectOcclusion, afxGuiTextHud ),
  73. "...");
  74. endGroup("Misc");
  75. Parent::initPersistFields();
  76. }
  77. //----------------------------------------------------------------------------
  78. /// Core rendering method for this control.
  79. ///
  80. /// This method scans through all the current client ShapeBase objects.
  81. /// If one is named, it displays the name and damage information for it.
  82. ///
  83. /// Information is offset from the center of the object's bounding box,
  84. /// unless the object is a PlayerObjectType, in which case the eye point
  85. /// is used.
  86. ///
  87. /// @param updateRect Extents of control.
  88. void afxGuiTextHud::onRender( Point2I, const RectI &updateRect)
  89. {
  90. // Background fill first
  91. if (mShowFill)
  92. GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor.toColorI());
  93. // Must be in a TS Control
  94. GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
  95. if (!parent) return;
  96. // Must have a connection and control object
  97. GameConnection* conn = GameConnection::getConnectionToServer();
  98. if (!conn)
  99. return;
  100. GameBase * control = dynamic_cast<GameBase*>(conn->getControlObject());
  101. if (!control)
  102. return;
  103. // Get control camera info
  104. MatrixF cam;
  105. Point3F camPos;
  106. VectorF camDir;
  107. conn->getControlCameraTransform(0,&cam);
  108. cam.getColumn(3, &camPos);
  109. cam.getColumn(1, &camDir);
  110. F32 camFovCos;
  111. conn->getControlCameraFov(&camFovCos);
  112. camFovCos = mCos(mDegToRad(camFovCos) / 2);
  113. // Visible distance info & name fading
  114. F32 visDistance = gClientSceneGraph->getVisibleDistance();
  115. F32 visDistanceSqr = visDistance * visDistance;
  116. F32 fadeDistance = visDistance * mDistanceFade;
  117. // Collision info. We're going to be running LOS tests and we
  118. // don't want to collide with the control object.
  119. static U32 losMask = TerrainObjectType | TerrainLikeObjectType | ShapeBaseObjectType;
  120. if (!mEnableControlObjectOcclusion)
  121. control->disableCollision();
  122. if (mLabelAllShapes)
  123. {
  124. // This section works just like GuiShapeNameHud and renders labels for
  125. // all the shapes.
  126. // All ghosted objects are added to the server connection group,
  127. // so we can find all the shape base objects by iterating through
  128. // our current connection.
  129. for (SimSetIterator itr(conn); *itr; ++itr)
  130. {
  131. ///if ((*itr)->getTypeMask() & ShapeBaseObjectType)
  132. ///{
  133. ShapeBase* shape = dynamic_cast<ShapeBase*>(*itr);
  134. if ( shape ) {
  135. if (shape != control && shape->getShapeName())
  136. {
  137. // Target pos to test, if it's a player run the LOS to his eye
  138. // point, otherwise we'll grab the generic box center.
  139. Point3F shapePos;
  140. if (shape->getTypeMask() & PlayerObjectType)
  141. {
  142. MatrixF eye;
  143. // Use the render eye transform, otherwise we'll see jittering
  144. shape->getRenderEyeTransform(&eye);
  145. eye.getColumn(3, &shapePos);
  146. }
  147. else
  148. {
  149. // Use the render transform instead of the box center
  150. // otherwise it'll jitter.
  151. MatrixF srtMat = shape->getRenderTransform();
  152. srtMat.getColumn(3, &shapePos);
  153. }
  154. VectorF shapeDir = shapePos - camPos;
  155. // Test to see if it's in range
  156. F32 shapeDist = shapeDir.lenSquared();
  157. if (shapeDist == 0 || shapeDist > visDistanceSqr)
  158. continue;
  159. shapeDist = mSqrt(shapeDist);
  160. // Test to see if it's within our viewcone, this test doesn't
  161. // actually match the viewport very well, should consider
  162. // projection and box test.
  163. shapeDir.normalize();
  164. F32 dot = mDot(shapeDir, camDir);
  165. if (dot < camFovCos)
  166. continue;
  167. // Test to see if it's behind something, and we want to
  168. // ignore anything it's mounted on when we run the LOS.
  169. RayInfo info;
  170. shape->disableCollision();
  171. SceneObject *mount = shape->getObjectMount();
  172. if (mount)
  173. mount->disableCollision();
  174. bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info);
  175. shape->enableCollision();
  176. if (mount)
  177. mount->enableCollision();
  178. if (!los)
  179. continue;
  180. // Project the shape pos into screen space and calculate
  181. // the distance opacity used to fade the labels into the
  182. // distance.
  183. Point3F projPnt;
  184. shapePos.z += mVerticalOffset;
  185. if (!parent->project(shapePos, &projPnt))
  186. continue;
  187. F32 opacity = (shapeDist < fadeDistance)? 1.0:
  188. 1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance);
  189. // Render the shape's name
  190. drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
  191. }
  192. }
  193. }
  194. }
  195. // This section renders all text added by afxGuiText effects.
  196. for (S32 i = 0; i < text_items.size(); i++)
  197. {
  198. HudTextSpec* spec = &text_items[i];
  199. if (spec->text && spec->text[0] != '\0')
  200. {
  201. VectorF shapeDir = spec->pos - camPos;
  202. // do range test
  203. F32 shapeDist = shapeDir.lenSquared();
  204. if (shapeDist == 0 || shapeDist > visDistanceSqr)
  205. continue;
  206. shapeDist = mSqrt(shapeDist);
  207. // Test to see if it's within our viewcone, this test doesn't
  208. // actually match the viewport very well, should consider
  209. // projection and box test.
  210. shapeDir.normalize();
  211. F32 dot = mDot(shapeDir, camDir);
  212. if (dot < camFovCos)
  213. continue;
  214. // Test to see if it's behind something, and we want to
  215. // ignore anything it's mounted on when we run the LOS.
  216. RayInfo info;
  217. if (spec->obj)
  218. spec->obj->disableCollision();
  219. bool los = !gClientContainer.castRay(camPos, spec->pos, losMask, &info);
  220. if (spec->obj)
  221. spec->obj->enableCollision();
  222. if (!los)
  223. continue;
  224. // Project the shape pos into screen space.
  225. Point3F projPnt;
  226. if (!parent->project(spec->pos, &projPnt))
  227. continue;
  228. // Calculate the distance opacity used to fade text into the distance.
  229. F32 opacity = (shapeDist < fadeDistance)? 1.0 : 1.0 - (shapeDist - fadeDistance) / (25.0f);
  230. if (opacity > 0.01f)
  231. drawName(Point2I((S32)projPnt.x, (S32)projPnt.y), spec->text, opacity, &spec->text_clr);
  232. }
  233. }
  234. // Restore control object collision
  235. if (!mEnableControlObjectOcclusion)
  236. control->enableCollision();
  237. // Border last
  238. if (mShowFrame)
  239. GFX->getDrawUtil()->drawRect(updateRect, mFrameColor.toColorI());
  240. reset();
  241. }
  242. //----------------------------------------------------------------------------
  243. /// Render object names.
  244. ///
  245. /// Helper function for GuiShapeNameHud::onRender
  246. ///
  247. /// @param offset Screen coordinates to render name label. (Text is centered
  248. /// horizontally about this location, with bottom of text at
  249. /// specified y position.)
  250. /// @param name String name to display.
  251. /// @param opacity Opacity of name (a fraction).
  252. void afxGuiTextHud::drawName(Point2I offset, const char *name, F32 opacity, LinearColorF* color)
  253. {
  254. // Center the name
  255. offset.x -= mProfile->mFont->getStrWidth((const UTF8 *)name) / 2;
  256. offset.y -= mProfile->mFont->getHeight();
  257. // Deal with opacity and draw.
  258. LinearColorF draw_color = (color) ? *color : mTextColor;
  259. draw_color.alpha *= opacity;
  260. GFX->getDrawUtil()->setBitmapModulation(draw_color.toColorI());
  261. GFX->getDrawUtil()->drawText(mProfile->mFont, offset, name);
  262. GFX->getDrawUtil()->clearBitmapModulation();
  263. }
  264. void afxGuiTextHud::addTextItem(const Point3F& pos, const char* text, LinearColorF& color, SceneObject* obj)
  265. {
  266. if (!text || text[0] == '\0')
  267. return;
  268. HudTextSpec spec;
  269. spec.pos = pos;
  270. spec.text = text;
  271. spec.text_clr = color;
  272. spec.obj = obj;
  273. text_items.push_back(spec);
  274. }
  275. void afxGuiTextHud::reset()
  276. {
  277. text_items.clear();
  278. }
  279. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//