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

Add new Logger system.

- Supports multiple log recievers.
- Onscreen log needs to be re-written.
- Replaces GameWorld::logX().
This commit is contained in:
Daniel Evans 2015-03-05 03:37:13 +00:00 committed by Daniel Evans
parent abf43f07c8
commit dfd68abd8e
8 changed files with 176 additions and 48 deletions

View File

@ -0,0 +1,63 @@
#pragma once
#include <string>
#include <vector>
/**
* Handles and stores messages from different components
*
* Dispatches recieved messages to logger outputs.
*/
class Logger
{
public:
enum MessageSeverity
{
Verbose,
Info,
Warning,
Error
};
struct LogMessage
{
/// The component that produced the message
std::string component;
/// Severity of the message.
MessageSeverity severity;
/// Logged message
std::string message;
LogMessage(const std::string& cc,
MessageSeverity ss,
const std::string& mm)
: component(cc), severity(ss), message(mm) { }
};
/**
* Interface for handling logged messages.
*
* The Logger class will not clean up allocated MessageRecievers.
*/
struct MessageReciever
{
virtual void messageRecieved(const LogMessage&) = 0;
};
void addReciever(MessageReciever* out);
void removeReciever(MessageReciever* out);
void log(const std::string& component, Logger::MessageSeverity severity, const std::string& message);
void verbose(const std::string& component, const std::string& message);
void info(const std::string& component, const std::string& message);
void warning(const std::string& component, const std::string& message);
void error(const std::string& component, const std::string& message);
private:
std::vector<MessageReciever*> recievers;
};
class StdOutReciever : public Logger::MessageReciever
{
virtual void messageRecieved(const Logger::LogMessage&);
};

View File

@ -2,6 +2,8 @@
#ifndef _GAMEWORLD_HPP_
#define _GAMEWORLD_HPP_
#include <core/Logger.hpp>
#include <engine/GameData.hpp>
#include <engine/GameState.hpp>
#include <render/GameRenderer.hpp>
@ -77,22 +79,7 @@ public:
std::string message;
};
std::deque<LogEntry> log;
/**
* Displays an informative message
*/
void logInfo(const std::string& info);
/**
* Displays an alarming error
*/
void logError(const std::string& error);
/**
* Displays a comforting warning
*/
void logWarning(const std::string& warning);
Logger logger;
/**
* Loads an IDE into the game

View File

@ -0,0 +1,59 @@
#include <core/Logger.hpp>
#include <algorithm>
#include <iostream>
#include <map>
void Logger::log(const std::string& component, Logger::MessageSeverity severity, const std::string& message)
{
LogMessage m { component, severity, message };
for(MessageReciever* r : recievers)
{
r->messageRecieved( m );
}
}
void Logger::addReciever(Logger::MessageReciever* out)
{
recievers.push_back(out);
}
void Logger::removeReciever(Logger::MessageReciever* out)
{
recievers.erase(std::remove(recievers.begin(), recievers.end(), out), recievers.end());
}
void Logger::error(const std::string& component, const std::string& message)
{
log(component, Logger::Error, message);
}
void Logger::info(const std::string& component, const std::string& message)
{
log(component, Logger::Info, message);
}
void Logger::warning(const std::string& component, const std::string& message)
{
log(component, Logger::Warning, message);
}
void Logger::verbose(const std::string& component, const std::string& message)
{
log(component, Logger::Verbose, message);
}
std::map<Logger::MessageSeverity, char> severityStr {
{Logger::Error, 'E'},
{Logger::Warning, 'W'},
{Logger::Info, 'I'},
{Logger::Verbose, 'V'}
};
void StdOutReciever::messageRecieved(const Logger::LogMessage& message)
{
std::cout << severityStr[message.severity] << " [" << message.component << "] " << message.message << std::endl;
}

View File

@ -600,10 +600,7 @@ char* GameData::openFile(const std::string& name)
}
else
{
std::stringstream err;
err << "Unable to locate file " << name;
engine->logError(err.str());
std::cerr << err.str() << std::endl;
engine->logger.error("Data", "Unable to locate file: " + name);
}
return nullptr;
@ -654,10 +651,7 @@ FileHandle GameData::openFile2(const std::string &name)
}
else
{
std::stringstream err;
err << "Unable to locate file " << name;
engine->logError(err.str());
std::cerr << err.str() << std::endl;
engine->logger.error("Data", "Unable to locate file: " + name);
}
return nullptr;
}

View File

@ -117,22 +117,6 @@ bool GameWorld::load()
return true;
}
void GameWorld::logInfo(const std::string& info)
{
log.push_back({LogEntry::Info, gameTime, info});
std::cout << info << std::endl;
}
void GameWorld::logError(const std::string& error)
{
log.push_back({LogEntry::Error, gameTime, error});
}
void GameWorld::logWarning(const std::string& warning)
{
log.push_back({LogEntry::Warning, gameTime, warning});
}
bool GameWorld::defineItems(const std::string& name)
{
auto i = gameData.ideLocations.find(name);
@ -185,7 +169,7 @@ void GameWorld::runScript(const std::string &name)
script = new ScriptMachine(this, f, opcodes);
}
else {
logError("Failed to load SCM: " + name);
logger.error("World", "Failed to load SCM: " + name);
}
}
@ -267,7 +251,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
}
if( modelname.empty() ) {
logWarning("Instance with missing model: " + std::to_string(id));
logger.warning("World", "Instance with missing model: " + std::to_string(id));
}
auto instance = new InstanceObject(
@ -428,7 +412,7 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
sec = gameData.vehicleColours[palit->second[set].second];
}
else {
logWarning("No colour palette for vehicle " + vti->modelName);
logger.warning("World", "No colour palette for vehicle " + vti->modelName);
}
auto wi = findObjectType<ObjectData>(vti->wheelModelID);

View File

@ -82,7 +82,7 @@ GameRenderer::GameRenderer(GameWorld* engine)
: engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f),
map(engine, renderer), text(engine, this)
{
engine->logInfo("[DRAW] " + renderer->getIDString());
engine->logger.info("Renderer", renderer->getIDString());
worldProg = renderer->createShader(
GameShaders::WorldObject::VertexShader,

View File

@ -0,0 +1,38 @@
#include <boost/test/unit_test.hpp>
#include <core/Logger.hpp>
#include <test_globals.hpp>
class CallbackReceiver : public Logger::MessageReciever
{
public:
std::function<void(const Logger::LogMessage&)> func;
CallbackReceiver(std::function<void(const Logger::LogMessage&)> func)
: func(func) { }
virtual void messageRecieved(const Logger::LogMessage& message)
{
func(message);
}
};
BOOST_AUTO_TEST_SUITE(LoggerTests)
BOOST_AUTO_TEST_CASE(test_reciever)
{
Logger log;
Logger::LogMessage lastMessage("", Logger::Error, "");
CallbackReceiver reciever([&](const Logger::LogMessage& m) { lastMessage = m; });
log.addReciever(&reciever);
log.info("Tests", "Test");
BOOST_CHECK_EQUAL( lastMessage.component, "Tests" );
BOOST_CHECK_EQUAL( lastMessage.severity, Logger::Info );
BOOST_CHECK_EQUAL( lastMessage.message, "Test" );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -19,6 +19,8 @@
DebugDraw* debug;
StdOutReciever logPrinter;
RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
: engine(nullptr), inFocus(true), showDebugStats(false),
accum(0.f), timescale(1.f)
@ -64,6 +66,7 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
glewInit();
engine = new GameWorld(gamepath);
engine->logger.addReciever(&logPrinter);
// Initalize all the archives.
engine->gameData.loadIMG("/models/gta3");
@ -106,7 +109,7 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
StateManager::get().enter(loading);
engine->logInfo("Started");
engine->logger.info("Game", "Started");
}
RWGame::~RWGame()
@ -220,7 +223,7 @@ void RWGame::tick(float dt)
}
catch( SCMException& ex ) {
std::cerr << ex.what() << std::endl;
engine->logError( ex.what() );
engine->logger.error( "Script", ex.what() );
throw;
}
}
@ -372,7 +375,7 @@ void RWGame::renderDebugStats(float time)
ti.size = 15.f;
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();
}
@ -398,7 +401,7 @@ void RWGame::renderDebugStats(float time)
engine->renderer.text.renderText(ti);
ti.screenPosition.y -= ti.size;
}
}*/
for( int i = 0; i < engine->state.text.size(); )
{