guiCrossHairHud.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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/controls/guiBitmapCtrl.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. /// Vary basic cross hair hud.
  33. /// Uses the base bitmap control to render a bitmap, and decides whether
  34. /// to draw or not depending on the current control object and it's state.
  35. /// If there is ShapeBase object under the cross hair and it's named,
  36. /// then a small health bar is displayed.
  37. class GuiCrossHairHud : public GuiBitmapCtrl
  38. {
  39. typedef GuiBitmapCtrl Parent;
  40. LinearColorF mDamageFillColor;
  41. LinearColorF mDamageFrameColor;
  42. Point2I mDamageRectSize;
  43. Point2I mDamageOffset;
  44. protected:
  45. void drawDamage(Point2I offset, F32 damage, F32 opacity);
  46. public:
  47. GuiCrossHairHud();
  48. void onRender( Point2I, const RectI &);
  49. static void initPersistFields();
  50. DECLARE_CONOBJECT( GuiCrossHairHud );
  51. DECLARE_CATEGORY( "Gui Game" );
  52. DECLARE_DESCRIPTION( "Basic cross hair hud. Reacts to state of control object.\n"
  53. "Also displays health bar for named objects under the cross hair." );
  54. };
  55. /// Valid object types for which the cross hair will render, this
  56. /// should really all be script controlled.
  57. static const U32 ObjectMask = PlayerObjectType | VehicleObjectType;
  58. //-----------------------------------------------------------------------------
  59. IMPLEMENT_CONOBJECT( GuiCrossHairHud );
  60. ConsoleDocClass( GuiCrossHairHud,
  61. "@brief Basic cross hair hud. Reacts to state of control object. Also displays health bar for named objects under the cross hair.\n\n"
  62. "Uses the base bitmap control to render a bitmap, and decides whether to draw or not depending "
  63. "on the current control object and it's state. If there is ShapeBase object under the cross hair "
  64. "and it's named, then a small health bar is displayed.\n\n"
  65. "@tsexample\n"
  66. "\n new GuiCrossHairHud()"
  67. "{\n"
  68. " damageFillColor = \"1.0 0.0 0.0 1.0\"; // Fills with a solid red color\n"
  69. " damageFrameColor = \"1.0 1.0 1.0 1.0\"; // Solid white frame color\n"
  70. " damageRect = \"15 5\";\n"
  71. " damageOffset = \"0 -10\";\n"
  72. "};\n"
  73. "@endtsexample\n"
  74. "@ingroup GuiGame\n"
  75. );
  76. GuiCrossHairHud::GuiCrossHairHud()
  77. {
  78. mDamageFillColor.set( 0.0f, 1.0f, 0.0f, 1.0f );
  79. mDamageFrameColor.set( 1.0f, 0.6f, 0.0f, 1.0f );
  80. mDamageRectSize.set(50, 4);
  81. mDamageOffset.set(0,32);
  82. }
  83. void GuiCrossHairHud::initPersistFields()
  84. {
  85. addGroup("Damage");
  86. addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiCrossHairHud ), "As the health bar depletes, this color will represent the health loss amount." );
  87. addField( "damageFrameColor", TypeColorF, Offset( mDamageFrameColor, GuiCrossHairHud ), "Color for the health bar's frame." );
  88. addField( "damageRect", TypePoint2I, Offset( mDamageRectSize, GuiCrossHairHud ), "Size for the health bar portion of the control." );
  89. addField( "damageOffset", TypePoint2I, Offset( mDamageOffset, GuiCrossHairHud ), "Offset for drawing the damage portion of the health control." );
  90. endGroup("Damage");
  91. Parent::initPersistFields();
  92. }
  93. //-----------------------------------------------------------------------------
  94. void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
  95. {
  96. // Must have a connection and player control object
  97. GameConnection* conn = GameConnection::getConnectionToServer();
  98. if (!conn)
  99. return;
  100. GameBase* control = dynamic_cast<GameBase*>(conn->getCameraObject());
  101. if (!control || !(control->getTypeMask() & ObjectMask) || !conn->isFirstPerson())
  102. return;
  103. // Parent render.
  104. Parent::onRender(offset,updateRect);
  105. // Get control camera info
  106. MatrixF cam;
  107. Point3F camPos;
  108. conn->getControlCameraTransform(0,&cam);
  109. cam.getColumn(3, &camPos);
  110. // Extend the camera vector to create an endpoint for our ray
  111. Point3F endPos;
  112. cam.getColumn(1, &endPos);
  113. endPos *= gClientSceneGraph->getVisibleDistance();
  114. endPos += camPos;
  115. // Collision info. We're going to be running LOS tests and we
  116. // don't want to collide with the control object.
  117. static U32 losMask = TerrainObjectType | ShapeBaseObjectType;
  118. control->disableCollision();
  119. RayInfo info;
  120. if (gClientContainer.castRay(camPos, endPos, losMask, &info)) {
  121. // Hit something... but we'll only display health for named
  122. // ShapeBase objects. Could mask against the object type here
  123. // and do a static cast if it's a ShapeBaseObjectType, but this
  124. // isn't a performance situation, so I'll just use dynamic_cast.
  125. if (ShapeBase* obj = dynamic_cast<ShapeBase*>(info.object))
  126. if (obj->getShapeName()) {
  127. offset.x = updateRect.point.x + updateRect.extent.x / 2;
  128. offset.y = updateRect.point.y + updateRect.extent.y / 2;
  129. drawDamage(offset + mDamageOffset, obj->getDamageValue(), 1);
  130. }
  131. }
  132. // Restore control object collision
  133. control->enableCollision();
  134. }
  135. //-----------------------------------------------------------------------------
  136. /**
  137. Display a damage bar ubove the shape.
  138. This is a support funtion, called by onRender.
  139. */
  140. void GuiCrossHairHud::drawDamage(Point2I offset, F32 damage, F32 opacity)
  141. {
  142. mDamageFillColor.alpha = mDamageFrameColor.alpha = opacity;
  143. // Damage should be 0->1 (0 being no damage,or healthy), but
  144. // we'll just make sure here as we flip it.
  145. damage = mClampF(1 - damage, 0, 1);
  146. // Center the bar
  147. RectI rect(offset, mDamageRectSize);
  148. rect.point.x -= mDamageRectSize.x / 2;
  149. // Draw the border
  150. GFX->getDrawUtil()->drawRect(rect, mDamageFrameColor.toColorI());
  151. // Draw the damage % fill
  152. rect.point += Point2I(1, 1);
  153. rect.extent -= Point2I(1, 1);
  154. rect.extent.x = (S32)(rect.extent.x * damage);
  155. if (rect.extent.x == 1)
  156. rect.extent.x = 2;
  157. if (rect.extent.x > 0)
  158. GFX->getDrawUtil()->drawRectFill(rect, mDamageFillColor.toColorI());
  159. }