guiShapeNameHud.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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 "platform/platform.h"
  23. #include "gui/core/guiControl.h"
  24. #include "gui/3d/guiTSControl.h"
  25. #include "console/consoleTypes.h"
  26. #include "scene/sceneManager.h"
  27. #include "T3D/gameBase/gameConnection.h"
  28. #include "T3D/shapeBase.h"
  29. #include "gfx/gfxDrawUtil.h"
  30. #include "console/engineAPI.h"
  31. //----------------------------------------------------------------------------
  32. /// Displays name & damage above shape objects.
  33. ///
  34. /// This control displays the name and damage value of all named
  35. /// ShapeBase objects on the client. The name and damage of objects
  36. /// within the control's display area are overlayed above the object.
  37. ///
  38. /// This GUI control must be a child of a TSControl, and a server connection
  39. /// and control object must be present.
  40. ///
  41. /// This is a stand-alone control and relies only on the standard base GuiControl.
  42. class GuiShapeNameHud : public GuiControl {
  43. typedef GuiControl Parent;
  44. // field data
  45. ColorF mFillColor;
  46. ColorF mFrameColor;
  47. ColorF mTextColor;
  48. F32 mVerticalOffset;
  49. F32 mDistanceFade;
  50. bool mShowFrame;
  51. bool mShowFill;
  52. protected:
  53. void drawName( Point2I offset, const char *buf, F32 opacity);
  54. public:
  55. GuiShapeNameHud();
  56. // GuiControl
  57. virtual void onRender(Point2I offset, const RectI &updateRect);
  58. static void initPersistFields();
  59. DECLARE_CONOBJECT( GuiShapeNameHud );
  60. DECLARE_CATEGORY( "Gui Game" );
  61. DECLARE_DESCRIPTION( "Displays name and damage of ShapeBase objects in its bounds.\n"
  62. "Must be a child of a GuiTSCtrl and a server connection must be present." );
  63. };
  64. //-----------------------------------------------------------------------------
  65. IMPLEMENT_CONOBJECT(GuiShapeNameHud);
  66. ConsoleDocClass( GuiShapeNameHud,
  67. "@brief Displays name and damage of ShapeBase objects in its bounds. Must be a child of a GuiTSCtrl and a server connection must be present.\n\n"
  68. "This control displays the name and damage value of all named ShapeBase objects on the client. "
  69. "The name and damage of objects within the control's display area are overlayed above the object.\n\n"
  70. "This GUI control must be a child of a TSControl, and a server connection and control object must be present. "
  71. "This is a stand-alone control and relies only on the standard base GuiControl.\n\n"
  72. "@tsexample\n"
  73. "\n new GuiShapeNameHud()"
  74. "{\n"
  75. " fillColor = \"0.0 1.0 0.0 1.0\"; // Fills with a solid green color\n"
  76. " frameColor = \"1.0 1.0 1.0 1.0\"; // Solid white frame color\n"
  77. " textColor = \"1.0 1.0 1.0 1.0\"; // Solid white text Color\n"
  78. " showFill = \"true\";\n"
  79. " showFrame = \"true\";\n"
  80. " verticalOffset = \"0.15\";\n"
  81. " distanceFade = \"15.0\";\n"
  82. "};\n"
  83. "@endtsexample\n\n"
  84. "@ingroup GuiGame\n"
  85. );
  86. /// Default distance for object's information to be displayed.
  87. static const F32 cDefaultVisibleDistance = 500.0f;
  88. GuiShapeNameHud::GuiShapeNameHud()
  89. {
  90. mFillColor.set( 0.25f, 0.25f, 0.25f, 0.25f );
  91. mFrameColor.set( 0, 1, 0, 1 );
  92. mTextColor.set( 0, 1, 0, 1 );
  93. mShowFrame = mShowFill = true;
  94. mVerticalOffset = 0.5f;
  95. mDistanceFade = 0.1f;
  96. }
  97. void GuiShapeNameHud::initPersistFields()
  98. {
  99. addGroup("Colors");
  100. addField( "fillColor", TypeColorF, Offset( mFillColor, GuiShapeNameHud ), "Standard color for the background of the control." );
  101. addField( "frameColor", TypeColorF, Offset( mFrameColor, GuiShapeNameHud ), "Color for the control's frame." );
  102. addField( "textColor", TypeColorF, Offset( mTextColor, GuiShapeNameHud ), "Color for the text on this control." );
  103. endGroup("Colors");
  104. addGroup("Misc");
  105. addField( "showFill", TypeBool, Offset( mShowFill, GuiShapeNameHud ), "If true, we draw the background color of the control." );
  106. addField( "showFrame", TypeBool, Offset( mShowFrame, GuiShapeNameHud ), "If true, we draw the frame of the control." );
  107. addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, GuiShapeNameHud ), "Amount to vertically offset the control in relation to the ShapeBase object in focus." );
  108. addField( "distanceFade", TypeF32, Offset( mDistanceFade, GuiShapeNameHud ), "Visibility distance (how far the player must be from the ShapeBase object in focus) for this control to render." );
  109. endGroup("Misc");
  110. Parent::initPersistFields();
  111. }
  112. //----------------------------------------------------------------------------
  113. /// Core rendering method for this control.
  114. ///
  115. /// This method scans through all the current client ShapeBase objects.
  116. /// If one is named, it displays the name and damage information for it.
  117. ///
  118. /// Information is offset from the center of the object's bounding box,
  119. /// unless the object is a PlayerObjectType, in which case the eye point
  120. /// is used.
  121. ///
  122. /// @param updateRect Extents of control.
  123. void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
  124. {
  125. // Background fill first
  126. if (mShowFill)
  127. GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor);
  128. // Must be in a TS Control
  129. GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
  130. if (!parent) return;
  131. // Must have a connection and control object
  132. GameConnection* conn = GameConnection::getConnectionToServer();
  133. if (!conn) return;
  134. GameBase * control = dynamic_cast<GameBase*>(conn->getControlObject());
  135. if (!control) return;
  136. // Get control camera info
  137. MatrixF cam;
  138. Point3F camPos;
  139. VectorF camDir;
  140. conn->getControlCameraTransform(0,&cam);
  141. cam.getColumn(3, &camPos);
  142. cam.getColumn(1, &camDir);
  143. F32 camFov;
  144. conn->getControlCameraFov(&camFov);
  145. camFov = mDegToRad(camFov) / 2;
  146. // Visible distance info & name fading
  147. F32 visDistance = gClientSceneGraph->getVisibleDistance();
  148. F32 visDistanceSqr = visDistance * visDistance;
  149. F32 fadeDistance = visDistance * mDistanceFade;
  150. // Collision info. We're going to be running LOS tests and we
  151. // don't want to collide with the control object.
  152. static U32 losMask = TerrainObjectType | InteriorObjectType | ShapeBaseObjectType;
  153. control->disableCollision();
  154. // All ghosted objects are added to the server connection group,
  155. // so we can find all the shape base objects by iterating through
  156. // our current connection.
  157. for (SimSetIterator itr(conn); *itr; ++itr) {
  158. ShapeBase* shape = dynamic_cast< ShapeBase* >(*itr);
  159. if ( shape ) {
  160. if (shape != control && shape->getShapeName())
  161. {
  162. // Target pos to test, if it's a player run the LOS to his eye
  163. // point, otherwise we'll grab the generic box center.
  164. Point3F shapePos;
  165. if (shape->getTypeMask() & PlayerObjectType)
  166. {
  167. MatrixF eye;
  168. // Use the render eye transform, otherwise we'll see jittering
  169. shape->getRenderEyeTransform(&eye);
  170. eye.getColumn(3, &shapePos);
  171. }
  172. else
  173. {
  174. // Use the render transform instead of the box center
  175. // otherwise it'll jitter.
  176. MatrixF srtMat = shape->getRenderTransform();
  177. srtMat.getColumn(3, &shapePos);
  178. }
  179. VectorF shapeDir = shapePos - camPos;
  180. // Test to see if it's in range
  181. F32 shapeDist = shapeDir.lenSquared();
  182. if (shapeDist == 0 || shapeDist > visDistanceSqr)
  183. continue;
  184. shapeDist = mSqrt(shapeDist);
  185. // Test to see if it's within our viewcone, this test doesn't
  186. // actually match the viewport very well, should consider
  187. // projection and box test.
  188. shapeDir.normalize();
  189. F32 dot = mDot(shapeDir, camDir);
  190. if (dot < camFov)
  191. continue;
  192. // Test to see if it's behind something, and we want to
  193. // ignore anything it's mounted on when we run the LOS.
  194. RayInfo info;
  195. shape->disableCollision();
  196. SceneObject *mount = shape->getObjectMount();
  197. if (mount)
  198. mount->disableCollision();
  199. bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info);
  200. shape->enableCollision();
  201. if (mount)
  202. mount->enableCollision();
  203. if (!los)
  204. continue;
  205. // Project the shape pos into screen space and calculate
  206. // the distance opacity used to fade the labels into the
  207. // distance.
  208. Point3F projPnt;
  209. shapePos.z += mVerticalOffset;
  210. if (!parent->project(shapePos, &projPnt))
  211. continue;
  212. F32 opacity = (shapeDist < fadeDistance)? 1.0:
  213. 1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance);
  214. // Render the shape's name
  215. drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
  216. }
  217. }
  218. }
  219. // Restore control object collision
  220. control->enableCollision();
  221. // Border last
  222. if (mShowFrame)
  223. GFX->getDrawUtil()->drawRect(updateRect, mFrameColor);
  224. }
  225. //----------------------------------------------------------------------------
  226. /// Render object names.
  227. ///
  228. /// Helper function for GuiShapeNameHud::onRender
  229. ///
  230. /// @param offset Screen coordinates to render name label. (Text is centered
  231. /// horizontally about this location, with bottom of text at
  232. /// specified y position.)
  233. /// @param name String name to display.
  234. /// @param opacity Opacity of name (a fraction).
  235. void GuiShapeNameHud::drawName(Point2I offset, const char *name, F32 opacity)
  236. {
  237. // Center the name
  238. offset.x -= mProfile->mFont->getStrWidth((const UTF8 *)name) / 2;
  239. offset.y -= mProfile->mFont->getHeight();
  240. // Deal with opacity and draw.
  241. mTextColor.alpha = opacity;
  242. GFX->getDrawUtil()->setBitmapModulation(mTextColor);
  243. GFX->getDrawUtil()->drawText(mProfile->mFont, offset, name);
  244. GFX->getDrawUtil()->clearBitmapModulation();
  245. }