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:
parent
9855bf2967
commit
9eb4c62a04
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/config/no_tr1/complex.hpp>
|
||||
|
||||
void game_print_big(const ScriptArguments& args)
|
||||
{
|
||||
|
@ -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
146
rwgame/DrawUI.cpp
Normal 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
8
rwgame/DrawUI.hpp
Normal 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);
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,6 @@ public:
|
||||
virtual void handleEvent(const sf::Event& event);
|
||||
|
||||
const ViewCamera& getCamera();
|
||||
|
||||
private:
|
||||
void drawHUD(GameRenderer* r);
|
||||
};
|
||||
|
||||
#endif // INGAMESTATE_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user