123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "gui/core/guiControl.h"
- #include "gui/controls/guiBitmapCtrl.h"
- #include "console/consoleTypes.h"
- #include "scene/sceneManager.h"
- #include "T3D/gameBase/gameConnection.h"
- #include "T3D/shapeBase.h"
- #include "gfx/gfxDrawUtil.h"
- #include "console/engineAPI.h"
- //-----------------------------------------------------------------------------
- /// Vary basic cross hair hud.
- /// Uses the base bitmap control to render a bitmap, and decides whether
- /// to draw or not depending on the current control object and it's state.
- /// If there is ShapeBase object under the cross hair and it's named,
- /// then a small health bar is displayed.
- class GuiCrossHairHud : public GuiBitmapCtrl
- {
- typedef GuiBitmapCtrl Parent;
- LinearColorF mDamageFillColor;
- LinearColorF mDamageFrameColor;
- Point2I mDamageRectSize;
- Point2I mDamageOffset;
- protected:
- void drawDamage(Point2I offset, F32 damage, F32 opacity);
- public:
- GuiCrossHairHud();
- void onRender( Point2I, const RectI &);
- static void initPersistFields();
- DECLARE_CONOBJECT( GuiCrossHairHud );
- DECLARE_CATEGORY( "Gui Game" );
- DECLARE_DESCRIPTION( "Basic cross hair hud. Reacts to state of control object.\n"
- "Also displays health bar for named objects under the cross hair." );
- };
- /// Valid object types for which the cross hair will render, this
- /// should really all be script controlled.
- static const U32 ObjectMask = PlayerObjectType | VehicleObjectType;
- //-----------------------------------------------------------------------------
- IMPLEMENT_CONOBJECT( GuiCrossHairHud );
- ConsoleDocClass( GuiCrossHairHud,
- "@brief Basic cross hair hud. Reacts to state of control object. Also displays health bar for named objects under the cross hair.\n\n"
- "Uses the base bitmap control to render a bitmap, and decides whether to draw or not depending "
- "on the current control object and it's state. If there is ShapeBase object under the cross hair "
- "and it's named, then a small health bar is displayed.\n\n"
-
- "@tsexample\n"
- "\n new GuiCrossHairHud()"
- "{\n"
- " damageFillColor = \"1.0 0.0 0.0 1.0\"; // Fills with a solid red color\n"
- " damageFrameColor = \"1.0 1.0 1.0 1.0\"; // Solid white frame color\n"
- " damageRect = \"15 5\";\n"
- " damageOffset = \"0 -10\";\n"
- "};\n"
- "@endtsexample\n"
-
- "@ingroup GuiGame\n"
- );
- GuiCrossHairHud::GuiCrossHairHud()
- {
- mDamageFillColor.set( 0.0f, 1.0f, 0.0f, 1.0f );
- mDamageFrameColor.set( 1.0f, 0.6f, 0.0f, 1.0f );
- mDamageRectSize.set(50, 4);
- mDamageOffset.set(0,32);
- }
- void GuiCrossHairHud::initPersistFields()
- {
- addGroup("Damage");
- addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiCrossHairHud ), "As the health bar depletes, this color will represent the health loss amount." );
- addField( "damageFrameColor", TypeColorF, Offset( mDamageFrameColor, GuiCrossHairHud ), "Color for the health bar's frame." );
- addField( "damageRect", TypePoint2I, Offset( mDamageRectSize, GuiCrossHairHud ), "Size for the health bar portion of the control." );
- addField( "damageOffset", TypePoint2I, Offset( mDamageOffset, GuiCrossHairHud ), "Offset for drawing the damage portion of the health control." );
- endGroup("Damage");
- Parent::initPersistFields();
- }
- //-----------------------------------------------------------------------------
- void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
- {
- // Must have a connection and player control object
- GameConnection* conn = GameConnection::getConnectionToServer();
- if (!conn)
- return;
- GameBase* control = dynamic_cast<GameBase*>(conn->getCameraObject());
- if (!control || !(control->getTypeMask() & ObjectMask) || !conn->isFirstPerson())
- return;
- // Parent render.
- Parent::onRender(offset,updateRect);
- // Get control camera info
- MatrixF cam;
- Point3F camPos;
- conn->getControlCameraTransform(0,&cam);
- cam.getColumn(3, &camPos);
- // Extend the camera vector to create an endpoint for our ray
- Point3F endPos;
- cam.getColumn(1, &endPos);
- endPos *= gClientSceneGraph->getVisibleDistance();
- endPos += camPos;
- // Collision info. We're going to be running LOS tests and we
- // don't want to collide with the control object.
- static U32 losMask = TerrainObjectType | ShapeBaseObjectType;
- control->disableCollision();
- RayInfo info;
- if (gClientContainer.castRay(camPos, endPos, losMask, &info)) {
- // Hit something... but we'll only display health for named
- // ShapeBase objects. Could mask against the object type here
- // and do a static cast if it's a ShapeBaseObjectType, but this
- // isn't a performance situation, so I'll just use dynamic_cast.
- if (ShapeBase* obj = dynamic_cast<ShapeBase*>(info.object))
- if (obj->getShapeName()) {
- offset.x = updateRect.point.x + updateRect.extent.x / 2;
- offset.y = updateRect.point.y + updateRect.extent.y / 2;
- drawDamage(offset + mDamageOffset, obj->getDamageValue(), 1);
- }
- }
- // Restore control object collision
- control->enableCollision();
- }
- //-----------------------------------------------------------------------------
- /**
- Display a damage bar ubove the shape.
- This is a support funtion, called by onRender.
- */
- void GuiCrossHairHud::drawDamage(Point2I offset, F32 damage, F32 opacity)
- {
- mDamageFillColor.alpha = mDamageFrameColor.alpha = opacity;
- // Damage should be 0->1 (0 being no damage,or healthy), but
- // we'll just make sure here as we flip it.
- damage = mClampF(1 - damage, 0, 1);
- // Center the bar
- RectI rect(offset, mDamageRectSize);
- rect.point.x -= mDamageRectSize.x / 2;
- // Draw the border
- GFX->getDrawUtil()->drawRect(rect, mDamageFrameColor.toColorI());
- // Draw the damage % fill
- rect.point += Point2I(1, 1);
- rect.extent -= Point2I(1, 1);
- rect.extent.x = (S32)(rect.extent.x * damage);
- if (rect.extent.x == 1)
- rect.extent.x = 2;
- if (rect.extent.x > 0)
- GFX->getDrawUtil()->drawRectFill(rect, mDamageFillColor.toColorI());
- }
|