1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 17:19:46 +02:00

Improve HUD and UI rendering

+ Add names for some styles to reduce confusion
+ Move some HUD drawing into a seperate file
This commit is contained in:
Daniel Evans 2015-02-15 12:41:51 +00:00
parent 9855bf2967
commit 9eb4c62a04
10 changed files with 199 additions and 126 deletions

View File

@ -28,6 +28,18 @@ struct OnscreenText
float osTextStart;
float osTextTime;
unsigned short osTextStyle;
enum /*TextStyle*/
{
/// Used for subtitles
HighPriority = 0,
/// Mission completed message
CenterBig = 1,
/// Right aligned mission names
MissionName = 2,
/// Help text (top left, black background)
Help = 12
};
};
/**

View File

@ -21,6 +21,13 @@ public:
*/
struct TextInfo
{
enum TextAlignemnt
{
Left = 0,
Right = 1,
Center = 2
};
/// Font index @see TextRenderer::setFontTexture
int font;
/// Message to be displayed (including markup)
@ -31,6 +38,8 @@ public:
float size;
/// Base colour
glm::vec3 baseColour;
/// Horizontal Alignment
TextAlignemnt align;
TextInfo();
};

View File

@ -53,7 +53,7 @@ struct TextVertex
TextRenderer::TextInfo::TextInfo()
: font(0), size(1.f), baseColour({1.f, 1.f, 1.f})
: font(0), size(1.f), baseColour({1.f, 1.f, 1.f}), align(Left)
{
}
@ -143,6 +143,16 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti)
dp.texture = engine->gameData.textures[{fonts[ti.font], ""}].texName;
glm::vec2 ss( ti.size );
/// @todo smarter alignment
if ( ti.align == TextInfo::Right )
{
coord.x -= ss.x * ti.text.length();
}
else if ( ti.align == TextInfo::Center )
{
coord.x -= glm::floor(ss.x * ti.text.length() * 0.5f);
}
glm::vec3 colour = ti.baseColour;
/// @todo make this less wastefull

View File

@ -24,7 +24,6 @@
#include <iostream>
#include <algorithm>
#include <boost/config/no_tr1/complex.hpp>
void game_print_big(const ScriptArguments& args)
{

View File

@ -10,6 +10,8 @@ add_executable(rwgame
pausestate.cpp
menustate.cpp
debugstate.cpp
DrawUI.cpp
)
include_directories("${CMAKE_SOURCE_DIR}/rwengine/include" ${BULLET_INCLUDE_DIR})

146
rwgame/DrawUI.cpp Normal file
View File

@ -0,0 +1,146 @@
#include "DrawUI.hpp"
#include <render/GameRenderer.hpp>
#include <ai/PlayerController.hpp>
#include <objects/CharacterObject.hpp>
#include <engine/GameState.hpp>
#include <glm/glm.hpp>
void drawMap(PlayerController* player, GameWorld* world, GameRenderer* render)
{
MapRenderer::MapInfo map;
map.scale = 0.4f;
glm::quat plyRot;
if( player )
{
plyRot = player->getCharacter()->getRotation();
}
map.rotation = glm::roll(plyRot);
const glm::ivec2& vp = render->getRenderer()->getViewport();
map.mapScreenTop = glm::vec2(260.f, vp.y - 10.f);
map.mapScreenBottom = glm::vec2(10.f, vp.y - 210.f);
if( player )
{
map.center = glm::vec2(player->getCharacter()->getPosition());
}
render->map.draw(map);
}
void drawHUD(PlayerController* player, GameWorld* world, GameRenderer* render)
{
drawMap(player, world, render);
}
void drawOnScreenText(GameWorld* world)
{
const glm::ivec2& vp = world->renderer.getRenderer()->getViewport();
TextRenderer::TextInfo ti;
ti.font = 2;
ti.screenPosition = glm::vec2( 10.f, 10.f );
ti.size = 20.f;
for(OnscreenText& t : world->state.text)
{
glm::vec2 shadowOffset( 0, 0 );
switch(t.osTextStyle)
{
default:
ti.size = 15.f;
ti.font = 0;
ti.align = TextRenderer::TextInfo::Left;
ti.baseColour = glm::vec3(1.f);
ti.screenPosition = vp / 2;
break;
case OnscreenText::HighPriority:
ti.size = 20.f;
ti.font = 2;
ti.baseColour = glm::vec3(1.f);
ti.screenPosition = glm::vec2(vp.x * 0.5f, vp.y - ti.size * 2.f);
ti.align = TextRenderer::TextInfo::Center;
break;
case OnscreenText::CenterBig:
ti.size = 30.f;
ti.font = 1;
ti.baseColour = glm::vec3(82, 114, 128) / 255.f;
ti.align = TextRenderer::TextInfo::Center;
ti.screenPosition = vp / 2;
ti.screenPosition += glm::vec2(0.f, ti.size / 2.f);
shadowOffset = glm::vec2(2.f, 0.f);
break;
case OnscreenText::MissionName:
ti.size = 30.f;
ti.font = 1;
ti.baseColour = glm::vec3(205, 162, 7)/255.f;
ti.screenPosition = glm::vec2(vp.x - 10.f, vp.y * 0.79f);
ti.align = TextRenderer::TextInfo::Right;
shadowOffset = glm::vec2(2.f, 2.f);
break;
case OnscreenText::Help:
ti.screenPosition = glm::vec2(20.f, 20.f);
ti.font = 2;
ti.size = 20.f;
ti.baseColour = glm::vec3(1.f);
ti.align = TextRenderer::TextInfo::Left;
break;
}
ti.text = t.osTextString;
if( t.osTextStyle == OnscreenText::Help )
{
// Insert line breaks into the message string.
auto m = ti.text;
const float boxWidth = 250.f;
int lastSpace = 0;
float lineLength = 0.f, wordLength = 0.f;
for( int c = 0; c < m.length(); ++c )
{
if(m[c] == ' ')
{
lastSpace = c;
lineLength += wordLength;
wordLength = 0.f;
}
wordLength += ti.size;
if( lineLength + wordLength > boxWidth )
{
m[lastSpace] = '\n';
lineLength = 0.f;
}
}
ti.text = m;
}
if( glm::length( shadowOffset ) > 0 )
{
TextRenderer::TextInfo shadow( ti );
shadow.baseColour = glm::vec3(0.f);
shadow.screenPosition += shadowOffset;
world->renderer.text.renderText(shadow);
}
world->renderer.text.renderText(ti);
}
for(auto& t : world->state.texts) {
ti.font = 2;
ti.screenPosition = t.position / glm::vec2(640, 480);
ti.screenPosition *= vp;
ti.baseColour = glm::vec3(t.colourFG);
ti.size = 20.f;
ti.text = t.text;
world->renderer.text.renderText(ti);
}
}

8
rwgame/DrawUI.hpp Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <engine/GameWorld.hpp>
class PlayerController;
void drawHUD(PlayerController* player, GameWorld* world, GameRenderer* render);
void drawOnScreenText(GameWorld* world);

View File

@ -1,6 +1,7 @@
#include "RWGame.hpp"
#include "State.hpp"
#include "loadingstate.hpp"
#include "DrawUI.hpp"
#include <engine/GameObject.hpp>
#include <engine/GameState.hpp>
@ -290,7 +291,7 @@ void RWGame::render(float alpha)
debug->flush(&engine->renderer);
#endif
std::stringstream ss;
/*std::stringstream ss;
ss << std::setfill('0') << "Time: " << std::setw(2) << engine->getHour()
<< ":" << std::setw(2) << engine->getMinute() << " (" << engine->gameTime << "s)\n";
ss << "View: " << viewCam.position.x << " " << viewCam.position.y << " " << viewCam.position.z << "\n";
@ -304,16 +305,16 @@ void RWGame::render(float alpha)
ss << "Idle";
}
ss << std::endl;
}
}*/
TextRenderer::TextInfo ti;
ti.text = ss.str();
//ti.text = ss.str();
ti.font = 2;
ti.screenPosition = glm::vec2( 10.f, 10.f );
ti.size = 20.f;
engine->renderer.text.renderText(ti);
//engine->renderer.text.renderText(ti);
while( engine->log.size() > 0 && engine->log.front().time + 10.f < engine->gameTime ) {
/*while( engine->log.size() > 0 && engine->log.front().time + 10.f < engine->gameTime ) {
engine->log.pop_front();
}
@ -339,7 +340,7 @@ void RWGame::render(float alpha)
engine->renderer.text.renderText(ti);
ti.screenPosition.y -= ti.size;
}
}*/
for( int i = 0; i < engine->state.text.size(); )
{
@ -352,93 +353,8 @@ void RWGame::render(float alpha)
i++;
}
}
for(OnscreenText& t : engine->state.text)
{
float fontSize = 20.f;
switch(t.osTextStyle)
{
default:
fontSize = 20.f;
break;
case 1:
fontSize = 40.f;
break;
case 2:
fontSize = 20.f;
break;
}
ti.size = fontSize;
ti.screenPosition = glm::vec2(0.f);
ti.font = 0;
if(t.osTextStyle == 1)
{
ti.screenPosition = glm::vec2(500.f, 500.f);
}
else if(t.osTextStyle == 2)
{
ti.screenPosition = glm::vec2(500.f, 500.f);
}
else if(t.osTextStyle == 12)
{
ti.screenPosition = glm::vec2(20.f, 20.f);
ti.font = 2;
// messageText.setPosition(15.f, 15.f);
// // Insert line breaks into the message string.
// auto m = messageText.getString();
// const float boxWidth = 250.f;
// int lastSpace = 0;
// float lineLength = 0.f, wordLength = 0.f;
// for( int c = 0; c < m.getSize(); ++c )
// {
// if(m[c] == ' ')
// {
// lastSpace = c;
// lineLength += wordLength;
// wordLength = 0.f;
// }
//
// auto& metrics = font.getGlyph(m[c], fontSize, false);
// wordLength += metrics.bounds.width;
//
// if( lineLength + wordLength > boxWidth )
// {
// m[lastSpace] = '\n';
// lineLength = 0.f;
// }
// }
// messageText.setString(m);
//
// auto bds = messageText.getGlobalBounds();
// sf::RectangleShape bg(sf::Vector2f(bds.width, bds.height) + sf::Vector2f(10.f, 10.f));
// bg.setFillColor(sf::Color::Black);
// bg.setPosition(sf::Vector2f(bds.left, bds.top) - sf::Vector2f(5.f, 5.f));
// window.draw(bg);
}
else
{
float lowerBar = 550.f;
ti.screenPosition = glm::vec2(300.f, lowerBar);
}
ti.text = t.osTextString;
engine->renderer.text.renderText(ti);
}
/*for(auto& t : engine->state.texts) {
sf::Text messageText(t.text, font, 15);
glm::vec2 scpos(t.position.x, t.position.y);
auto s = window.getSize();
scpos /= glm::vec2(640.f, 480.f);
scpos *= glm::vec2(s.x, s.y);
messageText.setPosition(scpos.x, scpos.y);
window.draw(messageText);
}*/
drawOnScreenText(engine);
}
void RWGame::globalKeyEvent(const sf::Event& event)

View File

@ -2,6 +2,7 @@
#include "RWGame.hpp"
#include "pausestate.hpp"
#include "debugstate.hpp"
#include "DrawUI.hpp"
#include <ai/PlayerController.hpp>
#include <objects/CharacterObject.hpp>
@ -191,13 +192,12 @@ void IngameState::draw(GameRenderer* r)
{
if( !getWorld()->state.isCinematic && getWorld()->isCutsceneDone() )
{
drawHUD(r);
drawHUD(getPlayer(), getWorld(), r);
}
State::draw(r);
}
void IngameState::handleEvent(const sf::Event &event)
{
auto player = getPlayer();
@ -299,30 +299,4 @@ const ViewCamera &IngameState::getCamera()
return _look;
}
void IngameState::drawHUD(GameRenderer* renderer)
{
MapRenderer::MapInfo map;
map.scale = 0.4f;
glm::quat plyRot;
if( getPlayer() )
{
auto p = getPlayer();
plyRot = p->getCharacter()->getRotation();
}
map.rotation = glm::roll(plyRot);
const glm::ivec2& vp = renderer->getRenderer()->getViewport();
map.mapScreenTop = glm::vec2(260.f, vp.y - 10.f);
map.mapScreenBottom = glm::vec2(10.f, vp.y - 210.f);
if( getWorld()->state.player )
{
map.center = glm::vec2(getWorld()->state.player->getCharacter()->getPosition());
}
getWorld()->renderer.map.draw(map);
}

View File

@ -29,9 +29,6 @@ public:
virtual void handleEvent(const sf::Event& event);
const ViewCamera& getCamera();
private:
void drawHUD(GameRenderer* r);
};
#endif // INGAMESTATE_HPP