2016-08-08 17:29:20 +02:00
|
|
|
#define _USE_MATH_DEFINES
|
|
|
|
#include <cmath>
|
|
|
|
|
2015-02-15 13:41:51 +01:00
|
|
|
#include "DrawUI.hpp"
|
|
|
|
#include <render/GameRenderer.hpp>
|
|
|
|
#include <ai/PlayerController.hpp>
|
|
|
|
#include <objects/CharacterObject.hpp>
|
|
|
|
#include <engine/GameState.hpp>
|
2016-04-10 19:58:34 +02:00
|
|
|
#include <items/WeaponItem.hpp>
|
|
|
|
|
2016-04-10 06:53:49 +02:00
|
|
|
#include <iomanip>
|
|
|
|
|
2016-04-10 19:58:34 +02:00
|
|
|
constexpr size_t ui_textSize = 25;
|
|
|
|
constexpr size_t ui_textHeight = 22;
|
2016-04-10 06:53:49 +02:00
|
|
|
constexpr size_t ui_outerMargin = 20;
|
|
|
|
constexpr size_t ui_infoMargin = 10;
|
2016-04-10 19:58:34 +02:00
|
|
|
constexpr size_t ui_weaponSize = 64;
|
|
|
|
constexpr size_t ui_ammoSize = 14;
|
|
|
|
constexpr size_t ui_ammoHeight = 16;
|
|
|
|
constexpr size_t ui_armourOffset = ui_textSize * 3;
|
2016-04-10 20:21:58 +02:00
|
|
|
constexpr size_t ui_maxWantedLevel = 6;
|
2016-05-07 19:29:08 +02:00
|
|
|
const glm::u8vec3 ui_timeColour(196, 165, 119);
|
|
|
|
const glm::u8vec3 ui_moneyColour(89, 113, 147);
|
|
|
|
const glm::u8vec3 ui_healthColour(187, 102, 47);
|
|
|
|
const glm::u8vec3 ui_armourColour(123, 136, 93);
|
|
|
|
const glm::u8vec3 ui_shadowColour(0, 0, 0);
|
2016-04-12 02:02:09 +02:00
|
|
|
const float ui_mapSize = 150.f;
|
|
|
|
const float ui_worldSizeMin = 200.f;
|
|
|
|
const float ui_worldSizeMax = 300.f;
|
2015-02-15 13:41:51 +01:00
|
|
|
|
2016-04-12 02:02:09 +02:00
|
|
|
void drawMap(ViewCamera& currentView, PlayerController* player, GameWorld* world, GameRenderer* render)
|
2015-02-15 13:41:51 +01:00
|
|
|
{
|
|
|
|
MapRenderer::MapInfo map;
|
|
|
|
|
2016-04-12 02:02:09 +02:00
|
|
|
glm::quat camRot = currentView.rotation;
|
2015-02-15 13:41:51 +01:00
|
|
|
|
2016-04-12 02:02:09 +02:00
|
|
|
map.rotation = glm::roll(camRot) - M_PI/2.f;
|
|
|
|
map.worldSize = ui_worldSizeMin;
|
|
|
|
map.worldSize = ui_worldSizeMax;
|
2015-02-15 13:41:51 +01:00
|
|
|
if( player )
|
|
|
|
{
|
2016-04-12 02:02:09 +02:00
|
|
|
map.worldCenter = glm::vec2(player->getCharacter()->getPosition());
|
2015-02-15 13:41:51 +01:00
|
|
|
}
|
2016-04-12 02:02:09 +02:00
|
|
|
|
|
|
|
const glm::ivec2 &vp = render->getRenderer()->getViewport();
|
|
|
|
|
|
|
|
glm::vec2 mapTop = glm::vec2(ui_outerMargin, vp.y - (ui_outerMargin + ui_mapSize));
|
|
|
|
glm::vec2 mapBottom = glm::vec2(ui_outerMargin + ui_mapSize, vp.y - ui_outerMargin);
|
|
|
|
|
|
|
|
map.screenPosition = (mapTop + mapBottom)/2.f;
|
|
|
|
map.screenSize = ui_mapSize * 0.95;
|
2015-02-15 13:41:51 +01:00
|
|
|
|
2015-04-27 04:55:18 +02:00
|
|
|
render->map.draw(world, map);
|
2015-02-15 13:41:51 +01:00
|
|
|
}
|
|
|
|
|
2016-04-10 06:53:49 +02:00
|
|
|
void drawPlayerInfo(PlayerController* player, GameWorld* world, GameRenderer* render)
|
|
|
|
{
|
|
|
|
float infoTextX = render->getRenderer()->getViewport().x -
|
|
|
|
(ui_outerMargin + ui_weaponSize + ui_infoMargin);
|
|
|
|
float infoTextY = 0.f + ui_outerMargin;
|
2016-04-10 19:58:34 +02:00
|
|
|
float iconX = render->getRenderer()->getViewport().x -
|
|
|
|
(ui_outerMargin + ui_weaponSize);
|
|
|
|
float iconY = ui_outerMargin;
|
2016-04-10 20:21:58 +02:00
|
|
|
float wantedX = render->getRenderer()->getViewport().x -
|
|
|
|
(ui_outerMargin);
|
|
|
|
float wantedY = ui_outerMargin + ui_weaponSize + 3.f;
|
2016-04-10 06:53:49 +02:00
|
|
|
|
|
|
|
TextRenderer::TextInfo ti;
|
|
|
|
ti.font = 1;
|
2016-04-10 19:58:34 +02:00
|
|
|
ti.size = ui_textSize;
|
2016-04-10 06:53:49 +02:00
|
|
|
ti.align = TextRenderer::TextInfo::Right;
|
|
|
|
|
2016-04-10 19:58:34 +02:00
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::setw(2) << std::setfill('0') << world->getHour()
|
|
|
|
<< std::setw(0) << ":"
|
|
|
|
<< std::setw(2) << world->getMinute();
|
2016-04-10 06:53:49 +02:00
|
|
|
|
2016-08-16 01:53:27 +02:00
|
|
|
ti.text = GameStringUtil::fromString(ss.str());
|
2016-04-10 19:58:34 +02:00
|
|
|
}
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 06:53:49 +02:00
|
|
|
ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY+1.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
|
|
|
ti.baseColour = ui_timeColour;
|
|
|
|
ti.screenPosition = glm::vec2(infoTextX, infoTextY);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
2016-04-10 19:58:34 +02:00
|
|
|
infoTextY += ui_textHeight;
|
2016-04-10 06:53:49 +02:00
|
|
|
|
2016-08-21 19:02:13 +02:00
|
|
|
ti.text = GameSymbols::Money + GameStringUtil::fromString(std::to_string(world->state->playerInfo.money));
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 06:53:49 +02:00
|
|
|
ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY+1.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
|
|
|
ti.baseColour = ui_moneyColour;
|
|
|
|
ti.screenPosition = glm::vec2(infoTextX, infoTextY);
|
|
|
|
render->text.renderText(ti);
|
2016-04-10 19:58:34 +02:00
|
|
|
|
|
|
|
infoTextY += ui_textHeight;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2016-08-21 19:02:13 +02:00
|
|
|
ss << std::setw(3) << std::setfill('0')
|
2016-04-14 02:21:25 +02:00
|
|
|
<< (int)player->getCharacter()->getCurrentState().health;
|
2016-08-21 19:02:13 +02:00
|
|
|
ti.text = GameSymbols::Heart + GameStringUtil::fromString(ss.str());
|
2016-04-10 19:58:34 +02:00
|
|
|
}
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 19:58:34 +02:00
|
|
|
ti.screenPosition = glm::vec2(infoTextX + 1.f, infoTextY+1.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
|
|
|
ti.baseColour = ui_healthColour;
|
|
|
|
ti.screenPosition = glm::vec2(infoTextX, infoTextY);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
2016-04-10 20:21:58 +02:00
|
|
|
if (player->getCharacter()->getCurrentState().armour > 0)
|
2016-04-10 19:58:34 +02:00
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2016-08-21 19:02:13 +02:00
|
|
|
ss << std::setw(3) << std::setfill('0')
|
2016-04-14 02:21:25 +02:00
|
|
|
<< (int)player->getCharacter()->getCurrentState().armour;
|
2016-08-21 19:02:13 +02:00
|
|
|
ti.text = GameSymbols::Armour + GameStringUtil::fromString(ss.str());
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 20:21:58 +02:00
|
|
|
ti.screenPosition = glm::vec2(infoTextX + 1.f - ui_armourOffset, infoTextY+1.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
|
|
|
|
ti.baseColour = ui_armourColour;
|
|
|
|
ti.screenPosition = glm::vec2(infoTextX - ui_armourOffset, infoTextY);
|
|
|
|
render->text.renderText(ti);
|
2016-04-10 19:58:34 +02:00
|
|
|
}
|
|
|
|
|
2016-08-16 01:53:27 +02:00
|
|
|
GameString s;
|
2016-08-02 13:00:05 +02:00
|
|
|
for (size_t i = 0; i < ui_maxWantedLevel; ++i) {
|
2016-08-21 19:02:13 +02:00
|
|
|
s += GameSymbols::Star;
|
2016-04-10 20:21:58 +02:00
|
|
|
}
|
|
|
|
ti.text = s;
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 20:21:58 +02:00
|
|
|
ti.screenPosition = glm::vec2(wantedX + 1.f, wantedY + 1.f);
|
2016-04-10 19:58:34 +02:00
|
|
|
render->text.renderText(ti);
|
|
|
|
|
|
|
|
#if 0 // Useful for debugging
|
|
|
|
ti.text = "ABCDEFGHIJKLMANOQRTSWXYZ\nM0123456789";
|
|
|
|
ti.size = 30;
|
|
|
|
ti.align = TextRenderer::TextInfo::Left;
|
|
|
|
ti.baseColour = glm::vec3(0.f, 0.f, 0.f);
|
|
|
|
ti.screenPosition = glm::vec2(101.f, 202.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
ti.baseColour = glm::vec3(1.f, 1.f, 1.f);
|
|
|
|
ti.screenPosition = glm::vec2(100.f, 200.f);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
InventoryItem *current = player->getCharacter()->getActiveItem();
|
|
|
|
std::string itemTextureName = "fist";
|
|
|
|
if (current) {
|
|
|
|
uint16_t model = current->getModelID();
|
|
|
|
if (model > 0) {
|
|
|
|
ObjectDataPtr weaponData = world
|
|
|
|
->data
|
|
|
|
->findObjectType<ObjectData>(model);
|
|
|
|
if (weaponData != nullptr) {
|
|
|
|
itemTextureName = weaponData->modelName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Urgh
|
|
|
|
if (itemTextureName == "colt45") {
|
|
|
|
itemTextureName = "pistol";
|
|
|
|
}
|
|
|
|
|
|
|
|
TextureData::Handle itemTexture = render->getData()->findTexture(itemTextureName);
|
|
|
|
RW_CHECK(itemTexture != nullptr, "Item has 0 texture");
|
|
|
|
if (itemTexture != nullptr) {
|
|
|
|
RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture");
|
|
|
|
render->drawTexture(itemTexture.get(),
|
|
|
|
glm::vec4(iconX,
|
|
|
|
iconY,
|
|
|
|
ui_weaponSize,
|
|
|
|
ui_weaponSize));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current) {
|
|
|
|
WeaponItem* wep = static_cast<WeaponItem*>(current);
|
|
|
|
if (wep->getWeaponData()->fireType != WeaponData::MELEE) {
|
|
|
|
const CharacterState& cs = player->getCharacter()->getCurrentState();
|
|
|
|
const CharacterWeaponSlot& slotInfo = cs.weapons[cs.currentWeapon];
|
2016-08-16 01:53:27 +02:00
|
|
|
ti.text = GameStringUtil::fromString(
|
|
|
|
std::to_string(slotInfo.bulletsClip) + "-"
|
|
|
|
+ std::to_string(slotInfo.bulletsTotal));
|
2016-04-10 19:58:34 +02:00
|
|
|
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = ui_shadowColour;
|
2016-04-10 19:58:34 +02:00
|
|
|
ti.font = 2;
|
|
|
|
ti.size = ui_ammoSize;
|
|
|
|
ti.align = TextRenderer::TextInfo::Center;
|
|
|
|
ti.screenPosition = glm::vec2(iconX + ui_weaponSize / 2.f,
|
|
|
|
iconY + ui_weaponSize - ui_ammoHeight);
|
|
|
|
render->text.renderText(ti);
|
|
|
|
}
|
|
|
|
}
|
2016-04-10 06:53:49 +02:00
|
|
|
}
|
|
|
|
|
2016-04-12 02:02:09 +02:00
|
|
|
void drawHUD(ViewCamera& currentView, PlayerController* player, GameWorld* world, GameRenderer* render)
|
2015-02-15 13:41:51 +01:00
|
|
|
{
|
2016-04-16 15:06:54 +02:00
|
|
|
if(player && player->getCharacter()) {
|
|
|
|
drawMap(currentView, player, world, render);
|
|
|
|
drawPlayerInfo(player, world, render);
|
|
|
|
}
|
2015-02-15 13:41:51 +01:00
|
|
|
}
|
|
|
|
|
2015-03-05 17:36:14 +01:00
|
|
|
void drawOnScreenText(GameWorld* world, GameRenderer* renderer)
|
2015-02-15 13:41:51 +01:00
|
|
|
{
|
2016-05-07 19:29:08 +02:00
|
|
|
const auto vp = glm::vec2(renderer->getRenderer()->getViewport());
|
2015-02-15 13:41:51 +01:00
|
|
|
|
|
|
|
TextRenderer::TextInfo ti;
|
|
|
|
ti.font = 2;
|
|
|
|
ti.screenPosition = glm::vec2( 10.f, 10.f );
|
|
|
|
ti.size = 20.f;
|
2016-05-07 19:29:08 +02:00
|
|
|
|
|
|
|
auto& alltext = world->state->text.getAllText();
|
|
|
|
|
|
|
|
for(auto& l : alltext)
|
|
|
|
{
|
|
|
|
for (auto& t : l)
|
|
|
|
{
|
|
|
|
ti.size = t.size;
|
|
|
|
ti.font = t.font;
|
|
|
|
ti.text = t.text;
|
|
|
|
ti.wrapX = t.wrapX;
|
|
|
|
ti.screenPosition = (t.position/glm::vec2(640.f, 480.f)) * vp;
|
|
|
|
switch(t.alignment) {
|
|
|
|
case 0:
|
|
|
|
ti.align = TextRenderer::TextInfo::Left;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ti.align = TextRenderer::TextInfo::Center;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ti.align = TextRenderer::TextInfo::Right;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for the background type
|
|
|
|
if (t.colourBG.a == 0)
|
|
|
|
{
|
2016-06-02 18:36:26 +02:00
|
|
|
glm::vec2 shadowPosition((int8_t)t.colourBG.x, (int8_t)t.colourBG.y);
|
|
|
|
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.baseColour = glm::vec3(0.f);
|
2016-06-02 18:36:26 +02:00
|
|
|
ti.screenPosition += shadowPosition;
|
2016-05-07 19:29:08 +02:00
|
|
|
ti.backgroundColour = {0, 0, 0, 0};
|
|
|
|
|
2016-06-02 18:36:26 +02:00
|
|
|
renderer->text.renderText(ti, true);
|
2016-05-07 19:29:08 +02:00
|
|
|
|
2016-06-02 18:36:26 +02:00
|
|
|
ti.screenPosition -= shadowPosition;
|
2016-05-07 19:29:08 +02:00
|
|
|
}
|
|
|
|
else if(t.colourBG.a > 0)
|
|
|
|
{
|
|
|
|
ti.backgroundColour = t.colourBG;
|
|
|
|
}
|
|
|
|
|
|
|
|
ti.baseColour = t.colourFG;
|
|
|
|
renderer->text.renderText(ti);
|
|
|
|
}
|
|
|
|
}
|
2015-02-15 13:41:51 +01:00
|
|
|
}
|