diff --git a/src/Makefile.am b/src/Makefile.am
index c6fd0411..fd3e866d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,6 +12,7 @@ liblolcore_a_SOURCES = \
tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h \
world.cpp world.h sample.cpp sample.h sampler.cpp sampler.h \
profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h numeric.h utils.h \
+ messageservice.cpp messageservice.h \
worldentity.cpp worldentity.h gradient.cpp gradient.h gradient.lolfx \
platform.cpp platform.h sprite.cpp sprite.h camera.cpp camera.h \
light.cpp light.h \
diff --git a/src/camera.cpp b/src/camera.cpp
index ebf72b07..2cfcfba6 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -107,7 +107,7 @@ void Camera::SetProjection(float fov, float near, float far, float screen_size,
m_screen_size = screen_size;
m_screen_ratio = screen_ratio;
mat4 screen_scale = mat4::scale(vec3(m_screen_scale.xy, 1.f));
- if (m_fov > .0f)
+ if (m_fov > .001f)
{
if (m_is_shifted)
SetProjection(screen_scale * mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_near, m_far));
diff --git a/src/core.h b/src/core.h
index f4b73e65..ff641f72 100644
--- a/src/core.h
+++ b/src/core.h
@@ -126,6 +126,7 @@ static inline int isnan(float f)
#include "audio.h"
#include "scene.h"
#include "profiler.h"
+#include "messageservice.h"
// Input
#include "input/input.h"
diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj
index 890907fc..7e3e1443 100644
--- a/src/lolcore.vcxproj
+++ b/src/lolcore.vcxproj
@@ -155,6 +155,7 @@
+
@@ -253,6 +254,7 @@
+
@@ -298,6 +300,7 @@
+
diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters
index e40bd989..d88c6d5c 100644
--- a/src/lolcore.vcxproj.filters
+++ b/src/lolcore.vcxproj.filters
@@ -309,6 +309,9 @@
input
+
+ ...
+
@@ -611,6 +614,9 @@
...
+
+ ...
+
@@ -663,5 +669,6 @@
gpu
+
\ No newline at end of file
diff --git a/src/math/vector.cpp b/src/math/vector.cpp
index c47f4f47..3981ee8f 100644
--- a/src/math/vector.cpp
+++ b/src/math/vector.cpp
@@ -785,7 +785,9 @@ template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size,
float screen_ratio_yx, float near, float far)
{
float new_fov_y = fov_y * (F_PI / 180.0f);
- float dist_scr = (screen_size * screen_ratio_yx * .5f) / tanf(new_fov_y * .5f);
+ float tan_y = tanf(new_fov_y * .5f);
+ ASSERT(tan_y > 0.000001f);
+ float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y;
return mat4::perspective(fov_y, screen_size, screen_size * screen_ratio_yx,
max(.001f, dist_scr + near),
diff --git a/src/messageservice.cpp b/src/messageservice.cpp
new file mode 100644
index 00000000..7269ead5
--- /dev/null
+++ b/src/messageservice.cpp
@@ -0,0 +1,143 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2013 Benjamin "Touky" Huet
+// 2013 Sam Hocevar
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the Do What The Fuck You Want To
+// Public License, Version 2, as published by Sam Hocevar. See
+// http://www.wtfpl.net/ for more details.
+//
+
+#if defined HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include
+#include
+#include
+
+#include "core.h"
+
+namespace lol
+{
+
+/*
+ * The global g_renderer object, initialised by Video::Init
+ */
+MessageService *g_messageservice = nullptr;
+
+//-----------------------------------------------------------------------------
+// Ctor/Dtor
+//----
+MessageService::MessageService()
+{
+}
+
+MessageService::~MessageService()
+{
+ m_bucket.Empty();
+}
+
+//Setup/Destroy
+void MessageService::Setup(int bucket_size)
+{
+ g_messageservice = new MessageService();
+ g_messageservice->m_bucket.Resize(bucket_size);
+}
+
+void MessageService::Destroy()
+{
+ delete g_messageservice;
+ g_messageservice = nullptr;
+}
+
+//-----------------------------------------------------------------------------
+bool MessageService::Send(int id, const String& message)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ return g_messageservice->Send(id, message.C());
+ }
+ return false;
+}
+
+bool MessageService::Send(int id, const char* message)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ MessageService& g = *g_messageservice;
+ Array& bucket = g.m_bucket[id];
+ bucket << MessageList(time(nullptr), String(message));
+ return true;
+ }
+ return false;
+}
+
+//----
+bool MessageService::FetchFirst(int id, String& message)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ time_t timestamp;
+ return g_messageservice->FetchFirst(id, message, timestamp);
+ }
+ return false;
+}
+
+bool MessageService::FetchFirst(int id, String& message, time_t& timestamp)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ MessageService& g = *g_messageservice;
+ Array& bucket = g.m_bucket[id];
+
+ if (bucket.Count())
+ {
+ message = bucket[0].m_message;
+ timestamp = bucket[0].m_timestamp;
+ bucket.Remove(0);
+ return true;
+ }
+ }
+ return false;
+}
+
+//----
+bool MessageService::FetchAll(int id, String& message)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ time_t timestamp;
+ return g_messageservice->FetchAll(id, message, timestamp);
+ }
+ return false;
+}
+
+bool MessageService::FetchAll(int id, String& message, time_t& first_timestamp)
+{
+ if (g_messageservice)
+ {
+ ASSERT(0 <= id && id < g_messageservice->m_bucket.Count());
+ MessageService& g = *g_messageservice;
+ Array& bucket = g.m_bucket[id];
+ message = String("");
+
+ if (bucket.Count())
+ {
+ first_timestamp = bucket[0].m_timestamp;
+ for (int i = 0; i < bucket.Count(); ++i)
+ message += bucket[i].m_message;
+ bucket.Empty();
+ return true;
+ }
+ }
+ return false;
+}
+
+} /* namespace lol */
diff --git a/src/messageservice.h b/src/messageservice.h
new file mode 100644
index 00000000..11471c5f
--- /dev/null
+++ b/src/messageservice.h
@@ -0,0 +1,67 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2013 Benjamin "Touky" Huet
+// (c) 2013 Sam Hocevar
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the Do What The Fuck You Want To
+// Public License, Version 2, as published by Sam Hocevar. See
+// http://www.wtfpl.net/ for more details.
+//
+
+//
+// The Message Service class
+// ----------------
+//
+
+#if !defined __MESSAGESERVICE_H__
+#define __MESSAGESERVICE_H__
+
+namespace lol
+{
+
+struct MessageList
+{
+ MessageList(time_t timestamp, String& message)
+ {
+ m_timestamp = timestamp;
+ m_message = message;
+ }
+
+ time_t m_timestamp;
+ String m_message;
+};
+
+/*
+ A template class perhaps ?
+*/
+class MessageService
+{
+public:
+ //CTor/DTor
+ MessageService();
+ ~MessageService();
+
+ static char const *GetName() { return ""; }
+
+ //Setup/Destroy
+ static void Setup(int bucket_size);
+ static void Destroy();
+
+ //Common interactions
+ static bool Send(int id, const String& message);
+ static bool Send(int id, const char* message);
+ static bool FetchFirst(int id, String& message);
+ static bool FetchFirst(int id, String& message, time_t ×tamp);
+ static bool FetchAll(int id, String& message);
+ static bool FetchAll(int id, String& message, time_t &first_timestamp);
+
+private:
+ Array > m_bucket;
+};
+
+extern MessageService *g_messageservice;
+
+} /* namespace lol */
+
+#endif /* __MESSAGESERVICE_H__ */