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

Text rendering

This commit is contained in:
Daniel Evans 2015-02-07 22:55:06 +00:00
parent 538d0c02f9
commit 2344024f08
21 changed files with 405 additions and 129 deletions

View File

@ -28,6 +28,7 @@ class SCMFile;
* @brief Stores simple data about Textures such as transparency flags.
*
* @todo Covert usage to TextureHandles or something for streaming.
* @todo Move out of GameData.hpp and into TextureInfo.hpp
*/
struct TextureInfo
{

View File

@ -10,6 +10,7 @@
#include <render/OpenGLRenderer.hpp>
#include "MapRenderer.hpp"
#include "TextRenderer.hpp"
class Model;
class ModelFrame;
@ -244,6 +245,7 @@ public:
}
MapRenderer map;
TextRenderer text;
};
#endif

View File

@ -77,6 +77,7 @@ public:
/// @todo dont use GLint in the interface.
virtual void setProgramBlockBinding(ShaderProgram* p, const std::string& name, GLint point) = 0;
virtual void setUniformTexture(ShaderProgram*p, const std::string& name, GLint tex) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::mat4& m) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec4& v) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec3& v) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec2& v) = 0;
@ -89,7 +90,15 @@ public:
virtual void draw(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) = 0;
virtual void drawArrays(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) = 0;
void setViewport(const glm::ivec2& vp) { viewport = vp; }
const glm::ivec2& getViewport() const { return viewport; }
glm::mat4 get2DProjection() const;
virtual void invalidate() = 0;
private:
glm::ivec2 viewport;
};
class OpenGLRenderer : public Renderer
@ -127,6 +136,7 @@ public:
ShaderProgram* createShader(const std::string &vert, const std::string &frag);
void setProgramBlockBinding(ShaderProgram* p, const std::string &name, GLint point);
void setUniformTexture(ShaderProgram* p, const std::string &name, GLint tex);
void setUniform(ShaderProgram* p, const std::string& name, const glm::mat4& m);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec4& m);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec3& m);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec2& m);

View File

@ -0,0 +1,53 @@
#pragma once
#include <engine/GameData.hpp>
#include "OpenGLRenderer.hpp"
#define GAME_FONTS 3
class GameWorld;
class GameRenderer;
/**
* @brief Handles rendering of bitmap font textures.
*
* In future, strings textures might be cached to improve performance, but
* for now, we just render each glyph on it's own quad
*/
class TextRenderer
{
public:
/**
* @todo Can this be merged with the gamestate text entries?
*/
struct TextInfo
{
/// Font index @see TextRenderer::setFontTexture
int font;
/// Message to be displayed (including markup)
std::string text;
/// On screen position
glm::vec2 screenPosition;
/// font size
float size;
/// Base colour
glm::vec3 baseColour;
TextInfo();
};
TextRenderer(GameWorld* engine, GameRenderer* renderer);
~TextRenderer();
void setFontTexture( int index, const std::string& font );
void renderText( const TextInfo& ti );
private:
std::string fonts[GAME_FONTS];
GameWorld* engine;
GameRenderer* renderer;
Renderer::ShaderProgram* textShader;
GeometryBuffer gb;
DrawBuffer db;
};

View File

@ -107,6 +107,7 @@ void GameData::load()
_knownFiles.insert({"hud.txd", {false, datpath+"/models/hud.txd"}});
_knownFiles.insert({"english.gxt", {false, datpath+"/TEXT/english.gxt"}});
_knownFiles.insert({"ped.ifp", {false, datpath+"/anim/ped.ifp"}});
_knownFiles.insert({"fonts.txd", {false, datpath+"/models/fonts.txd"}});
_knownFiles.insert({"news.txd", {false, datpath+"/txd/NEWS.TXD"}});
_knownFiles.insert({"splash1.txd", {false, datpath+"/txd/SPLASH1.TXD"}});
@ -118,6 +119,7 @@ void GameData::load()
loadDFF("arrow.dff");
loadTXD("particle.txd");
loadTXD("hud.txd");
loadTXD("fonts.txd");
loadCarcols(datpath+"/data/carcols.dat");
loadWeather(datpath+"/data/timecyc.dat");

View File

@ -80,7 +80,7 @@ DrawBuffer ssRectDraw;
GameRenderer::GameRenderer(GameWorld* engine)
: engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f),
map(engine, renderer)
map(engine, renderer), text(engine, this)
{
engine->logInfo("[DRAW] " + renderer->getIDString());

View File

@ -1,6 +1,7 @@
#include <render/OpenGLRenderer.hpp>
#include <GL/glew.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <sstream>
#include <iostream>
@ -79,6 +80,22 @@ GLuint compileProgram(const char* vertex, const char* fragment)
return prog;
}
glm::mat4 Renderer::get2DProjection() const
{
glm::vec2 aspect(1.f, 1.f);
if( viewport.x > viewport.y )
{
// Widescreen
aspect.x = viewport.x / (float) viewport.y;
}
else
{
// Tall-o-vision
aspect.y = viewport.y / (float)viewport.x;
}
return glm::ortho(0.f, 800.f * aspect.x, 600.f * aspect.y, 0.f, -1.f, 1.f);
}
void OpenGLRenderer::useDrawBuffer(DrawBuffer* dbuff)
{
if( dbuff != currentDbuff )
@ -147,6 +164,13 @@ void OpenGLRenderer::setUniformTexture(Renderer::ShaderProgram* p, const std::st
glUniform1i(currentProgram->getUniformLocation(name), tex);
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::mat4& m)
{
useProgram(p);
glUniformMatrix4fv(currentProgram->getUniformLocation(name.c_str()), 1, GL_FALSE, glm::value_ptr(m));
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::vec4& m)
{
useProgram(p);

View File

@ -0,0 +1,178 @@
#include "render/TextRenderer.hpp"
#include <render/GameRenderer.hpp>
#include <engine/GameWorld.hpp>
const char* TextVertexShader = R"(
#version 130
#extension GL_ARB_explicit_attrib_location : enable
#extension GL_ARB_uniform_buffer_object : enable
layout(location = 0) in vec2 position;
layout(location = 3) in vec2 texcoord;
layout(location = 2) in vec3 colour;
out vec2 TexCoord;
out vec3 Colour;
uniform mat4 proj;
void main()
{
gl_Position = proj * vec4(position, 0.0, 1.0);
TexCoord = texcoord;
Colour = colour;
})";
const char* TextFragmentShader = R"(
#version 130
in vec2 TexCoord;
in vec3 Colour;
uniform vec4 colour;
uniform sampler2D fontTexture;
out vec4 outColour;
void main()
{
float a = texture(fontTexture, TexCoord).a;
outColour = vec4(Colour, a);
})";
struct TextVertex
{
glm::vec2 position;
glm::vec2 texcoord;
glm::vec3 colour;
static const AttributeList vertex_attributes() {
return {
{ATRS_Position, 2, sizeof(TextVertex), 0ul},
{ATRS_TexCoord, 2, sizeof(TextVertex), 0ul + sizeof(glm::vec2)},
{ATRS_Colour, 3, sizeof(TextVertex), 0ul + sizeof(glm::vec2) * 2},
};
}
};
TextRenderer::TextInfo::TextInfo()
: font(0), size(1.f), baseColour({1.f, 1.f, 1.f})
{
}
TextRenderer::TextRenderer(GameWorld* engine, GameRenderer* renderer)
: fonts({}), engine(engine), renderer(renderer)
{
textShader = renderer->getRenderer()->createShader(
TextVertexShader, TextFragmentShader );
}
TextRenderer::~TextRenderer()
{
}
void TextRenderer::setFontTexture(int index, const std::string& texture)
{
if( index < GAME_FONTS )
{
fonts[index] = texture;
}
}
/// @todo This is very rough
int charToIndex(char g)
{
if( g >= '0' && g <= '9' )
{
return 16 + (g - '0');
}
else if( g >= 'A' && g <= 'Z' )
{
return 33 + (g - 'A');
}
else if( g >= 'a' && g <= 'z' )
{
return 65 + (g - 'a');
}
switch(g)
{
default: return 0;
case '!': return 1;
case '"': return 2;
case '#': return 3;
case '$': return 4;
case '%': return 5;
case '&': return 6;
case '\'': return 7;
case '(': return 8;
case ')': return 9;
case '*': return 10;
case '+': return 11;
case ',': return 12;
case '-': return 13;
case '.': return 14;
case '/': return 15;
}
}
glm::vec4 indexToCoord(int font, int index)
{
int x = index % 16;
int y = index / 16;
glm::vec2 gsize( 1.f / 16.f, 1.f / ((font == 0) ? 16.f : 13.f) );
return glm::vec4( x, y, x + 1, y + 1 ) *
glm::vec4( gsize, gsize ); // + glm::vec4( 0.0001f, 0.0001f,-0.0001f,-0.0001f);
}
void TextRenderer::renderText(const TextRenderer::TextInfo& ti)
{
renderer->getRenderer()->useProgram(textShader);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
renderer->getRenderer()->setUniform(textShader, "proj", renderer->getRenderer()->get2DProjection());
renderer->getRenderer()->setUniformTexture(textShader, "fontTexture", 0);
glm::vec2 coord = ti.screenPosition;
Renderer::DrawParameters dp;
dp.start = 0;
dp.count = gb.getCount();
dp.texture = engine->gameData.textures[{fonts[ti.font], ""}].texName;
glm::vec2 ss( ti.size );
glm::vec3 colour = ti.baseColour;
/// @todo make this less wastefull
for( const char& c : ti.text )
{
// Handle special chars.
if( c == '\n' )
{
coord.x = ti.screenPosition.x;
coord.y += ss.y;
continue;
}
int glyph = charToIndex(c);
auto tex = indexToCoord(ti.font, glyph);
glm::vec2 p = coord;
coord.x += ss.x;
std::vector<TextVertex> geo = {
{ { p.x, p.y + ss.y }, {tex.x, tex.w}, colour },
{ { p.x + ss.x, p.y + ss.y }, {tex.z, tex.w}, colour },
{ { p.x, p.y }, {tex.x, tex.y}, colour },
{ { p.x + ss.x, p.y }, {tex.z, tex.y}, colour },
};
gb.uploadVertices(geo);
db.addGeometry(&gb);
db.setFaceType(GL_TRIANGLE_STRIP);
renderer->getRenderer()->drawArrays(glm::mat4(), &db, dp);
}
}

View File

@ -2,17 +2,16 @@
#define _GAME_MENUSYSTEM_HPP_
#include <string>
#include <memory>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <glm/glm.hpp>
#include <render/GameRenderer.hpp>
#include <functional>
class Menu
{
sf::Font font;
int font;
public:
Menu(const sf::Font& font)
Menu(int font)
: font(font), activeEntry(-1) {}
struct MenuEntry
@ -20,19 +19,26 @@ public:
std::string name;
float _size;
MenuEntry(const std::string& n, float size = 38.f) : name(n), _size(size) {}
MenuEntry(const std::string& n, float size = 30.f) : name(n), _size(size) {}
float getHeight() { return _size; }
virtual void draw(const sf::Font& font, sf::RenderWindow& window, glm::vec2& basis)
virtual void draw(int font, bool active, GameRenderer* r, glm::vec2& basis)
{
sf::Text t;
t.setFont(font);
t.setPosition(basis.x + 6, basis.y + 2);
t.setString(name);
auto cSize = getHeight() - 10.f;
t.setCharacterSize(cSize);
window.draw(t);
TextRenderer::TextInfo ti;
ti.font = font;
ti.screenPosition = basis;
ti.text = name;
ti.size = getHeight();
if( ! active )
{
ti.baseColour = glm::vec3(1.f, 1.f, 1.f);
}
else
{
ti.baseColour = glm::vec3(1.f, 1.f, 0.f);
}
r->text.renderText(ti);
basis.y += getHeight();
}
@ -49,7 +55,7 @@ public:
void activate(float clickX, float clickY) { callback(); }
};
static std::shared_ptr<MenuEntry> lambda(const std::string& n, std::function<void (void)> callback, float size = 38.f)
static std::shared_ptr<MenuEntry> lambda(const std::string& n, std::function<void (void)> callback, float size = 30.f)
{
return std::shared_ptr<MenuEntry>(new Entry(n, callback, size));
}
@ -68,20 +74,19 @@ public:
entries.push_back(entry);
}
void draw(sf::RenderWindow& window)
void draw(GameRenderer* r)
{
glm::vec2 basis(offset);
for(size_t i = 0;
i < entries.size();
++i)
{
if(activeEntry >= 0 && i == (unsigned) activeEntry) {
sf::RectangleShape rs(sf::Vector2f(250.f, entries[i]->getHeight()));
rs.setPosition(basis.x, basis.y);
rs.setFillColor(sf::Color::Cyan);
window.draw(rs);
bool active = false;
if(activeEntry >= 0 && i == (unsigned) activeEntry)
{
active = true;
}
entries[i]->draw(font, window, basis);
entries[i]->draw(font, active, r, basis);
}
}

View File

@ -4,6 +4,7 @@
#include <engine/GameObject.hpp>
#include <engine/GameState.hpp>
#include <engine/GameWorld.hpp>
#include <render/GameRenderer.hpp>
#include <render/DebugDraw.hpp>
#include <script/ScriptMachine.hpp>
@ -19,10 +20,6 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
: engine(nullptr), inFocus(true),
accum(0.f), timescale(1.f)
{
if(! font.loadFromFile(gamepath + "/DejaVuSansMono.ttf")) {
std::cerr << "Failed to load font" << std::endl;
}
size_t w = GAME_WINDOW_WIDTH, h = GAME_WINDOW_HEIGHT;
bool fullscreen = false;
@ -64,6 +61,11 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
engine->gameData.loadIMG("/models/gta3");
engine->gameData.loadIMG("/models/txd");
engine->gameData.loadIMG("/anim/cuts");
// Set up text renderer
engine->renderer.text.setFontTexture(0, "pager");
engine->renderer.text.setFontTexture(1, "font1");
engine->renderer.text.setFontTexture(2, "font2");
/// @TODO expand this here.
engine->load();
@ -139,7 +141,7 @@ int RWGame::run()
render(alpha);
StateManager::get().draw(window);
StateManager::get().draw(&engine->renderer);
window.display();
@ -202,6 +204,9 @@ void RWGame::tick(float dt)
void RWGame::render(float alpha)
{
auto size = getWindow().getSize();
engine->renderer.getRenderer()->setViewport({size.x, size.y});
ViewCamera viewCam;
if( engine->state.currentCutscene != nullptr && engine->state.cutsceneStartTime >= 0.f )
{
@ -285,8 +290,6 @@ void RWGame::render(float alpha)
debug->flush(&engine->renderer);
#endif
window.resetGLStates();
std::stringstream ss;
ss << std::setfill('0') << "Time: " << std::setw(2) << engine->getHour()
<< ":" << std::setw(2) << engine->getMinute() << " (" << engine->gameTime << "s)\n";
@ -302,39 +305,40 @@ void RWGame::render(float alpha)
}
ss << std::endl;
}
sf::Text text(ss.str(), font, 14);
text.setPosition(10, 10);
window.draw(text);
TextRenderer::TextInfo ti;
ti.text = ss.str();
ti.font = 2;
ti.screenPosition = glm::vec2( 10.f, 10.f );
ti.size = 20.f;
engine->renderer.text.renderText(ti);
while( engine->log.size() > 0 && engine->log.front().time + 10.f < engine->gameTime ) {
engine->log.pop_front();
}
sf::Vector2f tpos(10.f, window.getSize().y - 30.f);
text.setCharacterSize(14);
ti.screenPosition = glm::vec2( 10.f, 500.f );
ti.size = 15.f;
for(auto it = engine->log.begin(); it != engine->log.end(); ++it) {
text.setString(it->message);
ti.text = it->message;
switch(it->type) {
case GameWorld::LogEntry::Error:
text.setColor(sf::Color::Red);
ti.baseColour = glm::vec3(1.f, 0.f, 0.f);
break;
case GameWorld::LogEntry::Warning:
text.setColor(sf::Color::Yellow);
ti.baseColour = glm::vec3(1.f, 1.f, 0.f);
break;
default:
text.setColor(sf::Color::White);
ti.baseColour = glm::vec3(1.f, 1.f, 1.f);
break;
}
// Interpolate the color
auto c = text.getColor();
c.a = (engine->gameTime - it->time > 5.f) ? 255 - (((engine->gameTime - it->time) - 5.f)/5.f) * 255 : 255;
text.setColor(c);
// c.a = (engine->gameTime - it->time > 5.f) ? 255 - (((engine->gameTime - it->time) - 5.f)/5.f) * 255 : 255;
// text.setColor(c);
text.setPosition(tpos);
window.draw(text);
tpos.y -= text.getLocalBounds().height;
engine->renderer.text.renderText(ti);
ti.screenPosition.y -= ti.size;
}
for( int i = 0; i < engine->state.text.size(); )
@ -351,77 +355,79 @@ void RWGame::render(float alpha)
for(OnscreenText& t : engine->state.text)
{
float fontSize = 15.f;
float fontSize = 20.f;
switch(t.osTextStyle)
{
default:
fontSize = 15.f;
fontSize = 20.f;
break;
case 1:
fontSize = 25.f;
fontSize = 40.f;
break;
case 2:
fontSize = 20.f;
break;
}
sf::Text messageText(t.osTextString, font, fontSize);
auto sz = window.getSize();
auto b = messageText.getLocalBounds();
ti.size = fontSize;
ti.screenPosition = glm::vec2(0.f);
ti.font = 0;
if(t.osTextStyle == 1)
{
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), sz.y / 2.f - std::round(b.height / 2.f));
ti.screenPosition = glm::vec2(500.f, 500.f);
}
else if(t.osTextStyle == 2)
{
messageText.setPosition(sz.x * 0.9f - std::round(b.width), sz.y * 0.8f - std::round(b.height / 2.f));
ti.screenPosition = glm::vec2(500.f, 500.f);
}
else if(t.osTextStyle == 12)
{
messageText.setPosition(15.f, 15.f);
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);
// // 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 = sz.y - sz.y * 0.1f;
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), lowerBar - std::round(b.height / 2.f));
float lowerBar = 550.f;
ti.screenPosition = glm::vec2(300.f, lowerBar);
}
window.draw(messageText);
ti.text = t.osTextString;
engine->renderer.text.renderText(ti);
}
for(auto& t : engine->state.texts) {
/*for(auto& t : engine->state.texts) {
sf::Text messageText(t.text, font, 15);
glm::vec2 scpos(t.position.x, t.position.y);
@ -432,7 +438,7 @@ void RWGame::render(float alpha)
messageText.setPosition(scpos.x, scpos.y);
window.draw(messageText);
}
}*/
}
void RWGame::globalKeyEvent(const sf::Event& event)

View File

@ -15,8 +15,6 @@ class RWGame
float accum;
float timescale;
sf::Font font;
public:
RWGame(const std::string& gamepath, int argc, char* argv[]);
@ -34,11 +32,6 @@ public:
return window;
}
sf::Font& getFont()
{
return font;
}
bool hitWorldRay(glm::vec3 &hit, glm::vec3 &normal, GameObject** object = nullptr)
{
auto vc = nextCam;

View File

@ -2,7 +2,8 @@
#define _GAME_STATE_HPP_
#include <functional>
#include <queue>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <render/ViewCamera.hpp>
#include "MenuSystem.hpp"
#include <glm/gtc/quaternion.hpp>
@ -26,10 +27,10 @@ struct State
virtual void tick(float dt) = 0;
virtual void draw(sf::RenderWindow& w)
virtual void draw(GameRenderer* r)
{
if(getCurrentMenu()) {
getCurrentMenu()->draw(w);
getCurrentMenu()->draw(r);
}
}
@ -117,9 +118,9 @@ struct StateManager
states.back()->tick(dt);
}
void draw(sf::RenderWindow& w)
void draw(GameRenderer* r)
{
states.back()->draw(w);
states.back()->draw(r);
}
void exit()

View File

@ -24,8 +24,8 @@ void jumpCharacter(RWGame* game, CharacterController* controller, const glm::vec
DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
: State(game), _freeLook( false ), _sonicMode( false )
{
Menu *m = new Menu(game->getFont());
m->offset = glm::vec2(50.f, 100.f);
Menu *m = new Menu(2);
m->offset = glm::vec2(200.f, 200.f);
float entryHeight = 24.f;
#if 0
m->addEntry(Menu::lambda("Random Vehicle", [this] {

View File

@ -187,14 +187,14 @@ void IngameState::tick(float dt)
}
}
void IngameState::draw(sf::RenderWindow& w)
void IngameState::draw(GameRenderer* r)
{
if( !getWorld()->state.isCinematic && getWorld()->isCutsceneDone() )
{
drawHUD(w);
drawHUD(getWindow());
}
State::draw(w);
State::draw(r);
}

View File

@ -24,7 +24,7 @@ public:
virtual void exit();
virtual void tick(float dt);
virtual void draw(sf::RenderWindow& w);
virtual void draw(GameRenderer* r);
virtual void handleEvent(const sf::Event& event);

View File

@ -47,10 +47,13 @@ void LoadingState::handleEvent(const sf::Event &e)
State::handleEvent(e);
}
void LoadingState::draw(sf::RenderWindow &w)
void LoadingState::draw(GameRenderer* r)
{
// Display some manner of loading screen.
sf::Text loadingText("Loading...", game->getFont(), 28);
loadingText.setPosition({30.f, 20.f});
w.draw(loadingText);
TextRenderer::TextInfo ti;
ti.text = "Loading...";
ti.screenPosition = glm::vec2( -1.f, 0.5f );
ti.size = 0.1f;
ti.font = 2;
r->text.renderText(ti);
}

View File

@ -13,7 +13,7 @@ public:
virtual void tick(float dt);
virtual void draw(sf::RenderWindow &w);
virtual void draw(GameRenderer* r);
virtual void handleEvent(const sf::Event& event);
};

View File

@ -7,8 +7,8 @@
MenuState::MenuState(RWGame* game)
: State(game)
{
Menu *m = new Menu(game->getFont());
m->offset = glm::vec2(50.f, 100.f);
Menu *m = new Menu(2);
m->offset = glm::vec2(200.f, 200.f);
m->addEntry(Menu::lambda("Start", [=] { StateManager::get().enter(new IngameState(game)); }));
m->addEntry(Menu::lambda("Test", [=] { StateManager::get().enter(new IngameState(game, true)); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));

View File

@ -6,8 +6,8 @@
PauseState::PauseState(RWGame* game)
: State(game)
{
Menu *m = new Menu(game->getFont());
m->offset = glm::vec2(50.f, 100.f);
Menu *m = new Menu(2);
m->offset = glm::vec2( 200.f, 200.f );
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [&] { getWindow().close(); }));
@ -29,10 +29,12 @@ void PauseState::tick(float dt)
}
void PauseState::draw(sf::RenderWindow& w)
void PauseState::draw(GameRenderer* r)
{
MapRenderer::MapInfo map;
auto& w = getWindow();
map.scale = 0.25f;
map.viewport = glm::vec2(w.getSize().x, w.getSize().y);
map.mapSize = map.viewport;
@ -44,7 +46,7 @@ void PauseState::draw(sf::RenderWindow& w)
}
getWorld()->renderer.map.draw(map);
State::draw(w);
State::draw(r);
}
void PauseState::handleEvent(const sf::Event &e)

View File

@ -13,7 +13,7 @@ public:
virtual void tick(float dt);
virtual void draw(sf::RenderWindow& w);
virtual void draw(GameRenderer* r);
virtual void handleEvent(const sf::Event& event);
};

View File

@ -7,8 +7,7 @@ BOOST_AUTO_TEST_SUITE(MenuUnitTests)
BOOST_AUTO_TEST_CASE(menu_test_click)
{
bool clickered = false;
sf::Font f;
Menu test(f);
Menu test(0);
test.addEntry(Menu::lambda("Test", [&]{ clickered = true; }));
BOOST_CHECK(! clickered );
@ -32,8 +31,7 @@ BOOST_AUTO_TEST_CASE(menu_test_click)
BOOST_AUTO_TEST_CASE(menu_test_click_offset)
{
bool clickered = false;
sf::Font f;
Menu test(f);
Menu test(0);
test.offset = glm::vec2(200.f, 200.f);
test.addEntry(Menu::lambda("Test", [&]{ clickered = true; }));
@ -58,8 +56,7 @@ BOOST_AUTO_TEST_CASE(menu_test_click_offset)
BOOST_AUTO_TEST_CASE(menu_test_active_index)
{
int clickindex = -1;
sf::Font f;
Menu test(f);
Menu test(0);
test.addEntry(Menu::lambda("Test1", [&]{ clickindex = 0; }));
test.addEntry(Menu::lambda("Test2", [&]{ clickindex = 1; }));
@ -86,8 +83,7 @@ BOOST_AUTO_TEST_CASE(menu_test_active_index)
BOOST_AUTO_TEST_CASE(menu_test_hover_index)
{
int clickindex = -1;
sf::Font f;
Menu test(f);
Menu test(0);
test.addEntry(Menu::lambda("Test1", [&]{ clickindex = 0; }));
test.addEntry(Menu::lambda("Test2", [&]{ clickindex = 1; }));