diff --git a/doc/StylesOverview.md b/doc/StylesOverview.md
index fecc6ce6..19691610 100644
--- a/doc/StylesOverview.md
+++ b/doc/StylesOverview.md
@@ -1,4 +1,4 @@
-# @title Style Tags Overview
+# Style Tags Overview
 
 ## Style Overview
 This document describes how style tags can be specified, how they affect your
diff --git a/modules/client/client.lua b/modules/client/client.lua
index ac6acb2d..2dc3de3f 100644
--- a/modules/client/client.lua
+++ b/modules/client/client.lua
@@ -38,7 +38,7 @@ function Client.init()
   addEvent(function()
     scheduleEvent(function()
         -- Play startup music (The Silver Tree, by Mattias Westlund)
-        g_sounds.playMusic("startup.ogg", 3)
+        --g_sounds.playMusic("startup.ogg", 3)
         connect(g_game, { onGameStart = function() g_sounds.stopMusic(3) end })
         connect(g_game, { onGameEnd= function() g_sounds.playMusic("startup.ogg", 3) end })
     end, 100)
diff --git a/src/framework/application.h b/src/framework/application.h
index 2c158bf2..4195435e 100644
--- a/src/framework/application.h
+++ b/src/framework/application.h
@@ -27,6 +27,7 @@
 #include <framework/core/adaptativeframecounter.h>
 #include <framework/graphics/declarations.h>
 
+//@bindsingleton g_app
 class Application
 {
     enum {
diff --git a/src/framework/core/clock.h b/src/framework/core/clock.h
index c78df9a1..fe494f95 100644
--- a/src/framework/core/clock.h
+++ b/src/framework/core/clock.h
@@ -25,6 +25,7 @@
 
 #include "declarations.h"
 
+// @bindsingleton g_clock
 class Clock
 {
 public:
diff --git a/src/framework/core/configmanager.h b/src/framework/core/configmanager.h
index 08104c76..b06bf12a 100644
--- a/src/framework/core/configmanager.h
+++ b/src/framework/core/configmanager.h
@@ -26,10 +26,12 @@
 #include "declarations.h"
 #include <framework/otml/declarations.h>
 
+// @bindsingleton g_configs
 class ConfigManager
 {
 public:
     ConfigManager();
+
     bool load(const std::string& file);
     bool save();
     void clear();
diff --git a/src/framework/core/eventdispatcher.h b/src/framework/core/eventdispatcher.h
index 1fb724bb..33779c30 100644
--- a/src/framework/core/eventdispatcher.h
+++ b/src/framework/core/eventdispatcher.h
@@ -26,6 +26,7 @@
 #include "clock.h"
 #include "scheduledevent.h"
 
+// @bindsingleton g_eventDispatcher
 class EventDispatcher
 {
 public:
diff --git a/src/framework/core/filestream.h b/src/framework/core/filestream.h
index 0af9c2f0..dbfe40f4 100644
--- a/src/framework/core/filestream.h
+++ b/src/framework/core/filestream.h
@@ -24,10 +24,12 @@
 #define FILESTREAM_H
 
 #include "declarations.h"
+#include <framework/luascript/luaobject.h>
 
 struct PHYSFS_File;
 
-class FileStream
+// @bindclass
+class FileStream : public LuaObject
 {
 public:
     FileStream(const std::string& name, PHYSFS_File *fileHandle);
@@ -44,8 +46,6 @@ public:
     int tell();
     std::string name() { return m_name; }
 
-    std::string readAll();
-
     uint8 getU8();
     uint16 getU16();
     uint32 getU32();
diff --git a/src/framework/core/logger.h b/src/framework/core/logger.h
index 12c7b052..7c088eaf 100644
--- a/src/framework/core/logger.h
+++ b/src/framework/core/logger.h
@@ -32,6 +32,7 @@ struct LogMessage {
     std::size_t when;
 };
 
+// @bindsingleton g_logger
 class Logger
 {
     enum {
diff --git a/src/framework/core/module.h b/src/framework/core/module.h
index 7fe95d11..0fdc1b30 100644
--- a/src/framework/core/module.h
+++ b/src/framework/core/module.h
@@ -28,6 +28,7 @@
 #include <framework/otml/declarations.h>
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class Module : public LuaObject
 {
 public:
@@ -52,6 +53,7 @@ public:
     bool isAutoLoad() { return m_autoLoad; }
     int getAutoLoadPriority() { return m_autoLoadPriority; }
 
+    // @dontbind
     ModulePtr asModule() { return std::static_pointer_cast<Module>(shared_from_this()); }
 
 protected:
diff --git a/src/framework/core/modulemanager.h b/src/framework/core/modulemanager.h
index e8a8be2a..a2b012dd 100644
--- a/src/framework/core/modulemanager.h
+++ b/src/framework/core/modulemanager.h
@@ -25,6 +25,7 @@
 
 #include "module.h"
 
+// @bindsingleton g_modules
 class ModuleManager
 {
 public:
diff --git a/src/framework/core/resourcemanager.h b/src/framework/core/resourcemanager.h
index af433c1a..26282f9f 100644
--- a/src/framework/core/resourcemanager.h
+++ b/src/framework/core/resourcemanager.h
@@ -25,10 +25,13 @@
 
 #include "declarations.h"
 
+// @bindsingleton g_resources
 class ResourceManager
 {
 public:
+    // @dontbind
     void init(const char *argv0);
+    // @dontbind
     void terminate();
 
     void discoverWorkDir(const std::string& appName, const std::string& existentFile);
@@ -41,10 +44,13 @@ public:
     bool fileExists(const std::string& fileName);
     bool directoryExists(const std::string& directoryName);
 
+    // @dontbind
     void loadFile(const std::string& fileName, std::iostream& out);
     std::string loadFile(const std::string& fileName);
+    // @dontbind
     bool saveFile(const std::string& fileName, const uchar* data, uint size);
     bool saveFile(const std::string& fileName, const std::string& data);
+    // @dontbind
     bool saveFile(const std::string& fileName, std::iostream& in);
 
     FileStreamPtr openFile(const std::string& fileName);
diff --git a/src/framework/graphics/fontmanager.h b/src/framework/graphics/fontmanager.h
index 724d126a..01b9ef52 100644
--- a/src/framework/graphics/fontmanager.h
+++ b/src/framework/graphics/fontmanager.h
@@ -25,6 +25,7 @@
 
 #include "bitmapfont.h"
 
+//@bindsingleton g_fonts
 class FontManager
 {
 public:
diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp
index cc80d2f0..50b92dda 100644
--- a/src/framework/graphics/graphics.cpp
+++ b/src/framework/graphics/graphics.cpp
@@ -82,7 +82,7 @@ void Graphics::init()
     glEnable(GL_BLEND);
 
     // determine max texture size
-    GLint maxTextureSize = 0;
+    int maxTextureSize = 0;
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
     if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize)
         m_maxTextureSize = maxTextureSize;
diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h
index d1dbe11b..0a09665f 100644
--- a/src/framework/graphics/graphics.h
+++ b/src/framework/graphics/graphics.h
@@ -26,6 +26,7 @@
 #include "declarations.h"
 #include "painter.h"
 
+// @bindsingleton g_graphics
 class Graphics
 {
 public:
@@ -37,8 +38,11 @@ public:
         Painter_OpenGL2
     };
 
+    // @dontbind
     void init();
+    // @dontbind
     void terminate();
+
     bool parseOption(const std::string& option);
 
     bool isPainterEngineAvailable(PainterEngine painterEngine);
@@ -47,8 +51,6 @@ public:
 
     void resize(const Size& size);
 
-    void setViewportSize(const Size& size);
-
     int getMaxTextureSize() { return m_maxTextureSize; }
     const Size& getViewportSize() { return m_viewportSize; }
 
diff --git a/src/framework/graphics/hardwarebuffer.h b/src/framework/graphics/hardwarebuffer.h
index 6565d969..923530d2 100644
--- a/src/framework/graphics/hardwarebuffer.h
+++ b/src/framework/graphics/hardwarebuffer.h
@@ -49,7 +49,7 @@ public:
 
 private:
     Type m_type;
-    GLuint m_id;
+    uint m_id;
 };
 
 #endif
diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp
index 4d4f2139..ed02931a 100644
--- a/src/framework/graphics/painter.cpp
+++ b/src/framework/graphics/painter.cpp
@@ -135,7 +135,7 @@ void Painter::setTexture(Texture* texture)
 
     m_texture = texture;
 
-    GLuint glTextureId;
+    uint glTextureId;
     if(texture) {
         setTextureMatrix(texture->getTransformMatrix());
         glTextureId = texture->getId();
diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h
index fdb69c99..e3ff81ad 100644
--- a/src/framework/graphics/painter.h
+++ b/src/framework/graphics/painter.h
@@ -137,7 +137,7 @@ protected:
     PainterState m_olderStates[10];
     int m_oldStateIndex;
 
-    GLuint m_glTextureId;
+    uint m_glTextureId;
 };
 
 extern Painter *g_painter;
diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp
index 0372264b..00554296 100644
--- a/src/framework/graphics/shader.cpp
+++ b/src/framework/graphics/shader.cpp
@@ -89,7 +89,7 @@ bool Shader::compileSourceFile(const std::string& sourceFile)
 std::string Shader::log()
 {
     std::string infoLog;
-    GLint infoLogLength = 0;
+    int infoLogLength = 0;
     glGetShaderiv(m_shaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
     if(infoLogLength > 1) {
         std::vector<char> buf(infoLogLength);
diff --git a/src/framework/graphics/shader.h b/src/framework/graphics/shader.h
index b380e0b3..414cd428 100644
--- a/src/framework/graphics/shader.h
+++ b/src/framework/graphics/shader.h
@@ -40,11 +40,11 @@ public:
     bool compileSourceFile(const std::string& sourceFile);
     std::string log();
 
-    GLuint getShaderId() { return m_shaderId; }
+    uint getShaderId() { return m_shaderId; }
     ShaderType getShaderType() { return m_shaderType; }
 
 private:
-    GLuint m_shaderId;
+    uint m_shaderId;
     ShaderType m_shaderType;
 };
 
diff --git a/src/framework/graphics/shaderprogram.cpp b/src/framework/graphics/shaderprogram.cpp
index 8706a814..f9841d70 100644
--- a/src/framework/graphics/shaderprogram.cpp
+++ b/src/framework/graphics/shaderprogram.cpp
@@ -25,7 +25,7 @@
 
 #include <framework/application.h>
 
-GLuint ShaderProgram::m_currentProgram = 0;
+uint ShaderProgram::m_currentProgram = 0;
 
 ShaderProgram::ShaderProgram()
 {
@@ -92,7 +92,7 @@ bool ShaderProgram::link()
 
     glLinkProgram(m_programId);
 
-    GLint value = GL_FALSE;
+    int value = GL_FALSE;
     glGetProgramiv(m_programId, GL_LINK_STATUS, &value);
     m_linked = (value != GL_FALSE);
 
@@ -123,7 +123,7 @@ void ShaderProgram::release()
 std::string ShaderProgram::log()
 {
     std::string infoLog;
-    GLint infoLogLength = 0;
+    int infoLogLength = 0;
     glGetProgramiv(m_programId, GL_INFO_LOG_LENGTH, &infoLogLength);
     if(infoLogLength > 1) {
         std::vector<char> buf(infoLogLength);
diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h
index e029c3d9..ac875549 100644
--- a/src/framework/graphics/shaderprogram.h
+++ b/src/framework/graphics/shaderprogram.h
@@ -26,6 +26,7 @@
 #include "shader.h"
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class ShaderProgram : public LuaObject
 {
     enum {
@@ -65,7 +66,7 @@ public:
     void setAttributeValue(const char *name, float x, float y, float z) { glVertexAttrib3f(getAttributeLocation(name), x, y, z); }
 
     void setUniformValue(int location, const Color& color) { glUniform4f(m_uniformLocations[location], color.rF(), color.gF(), color.bF(), color.aF()); }
-    void setUniformValue(int location, GLint value) { glUniform1i(m_uniformLocations[location], value); }
+    void setUniformValue(int location, int value) { glUniform1i(m_uniformLocations[location], value); }
     void setUniformValue(int location, float value) { glUniform1f(m_uniformLocations[location], value); }
     void setUniformValue(int location, float x, float y) { glUniform2f(m_uniformLocations[location], x, y); }
     void setUniformValue(int location, float x, float y, float z) { glUniform3f(m_uniformLocations[location], x, y, z); }
@@ -73,25 +74,25 @@ public:
     void setUniformValue(int location, const Matrix2& mat) { glUniformMatrix2fv(m_uniformLocations[location], 1, GL_FALSE, mat.data()); }
     void setUniformValue(int location, const Matrix3& mat) { glUniformMatrix3fv(m_uniformLocations[location], 1, GL_FALSE, mat.data()); }
     void setUniformValue(const char *name, const Color& color) { glUniform4f(glGetUniformLocation(m_programId, name), color.rF(), color.gF(), color.bF(), color.aF()); }
-    void setUniformValue(const char *name, GLint value) { glUniform1i(glGetUniformLocation(m_programId, name), value); }
+    void setUniformValue(const char *name, int value) { glUniform1i(glGetUniformLocation(m_programId, name), value); }
     void setUniformValue(const char *name, float value) { glUniform1f(glGetUniformLocation(m_programId, name), value); }
     void setUniformValue(const char *name, float x, float y) { glUniform2f(glGetUniformLocation(m_programId, name), x, y); }
     void setUniformValue(const char *name, float x, float y, float z) { glUniform3f(glGetUniformLocation(m_programId, name), x, y, z); }
     void setUniformValue(const char *name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(m_programId, name), x, y, z, w); }
     void setUniformValue(const char *name, const Matrix2& mat) { glUniformMatrix2fv(glGetUniformLocation(m_programId, name), 1, GL_FALSE, mat.data()); }
     void setUniformValue(const char *name, const Matrix3& mat) { glUniformMatrix3fv(glGetUniformLocation(m_programId, name), 1, GL_FALSE, mat.data()); }
+    // TODO: Point, PointF, Color, Size, SizeF ?
 
-    // Point, PointF, Color, Size, SizeF,
     bool isLinked() { return m_linked; }
-    GLuint getProgramId() { return m_programId; }
+    uint getProgramId() { return m_programId; }
     ShaderList getShaders() { return m_shaders; }
 
 private:
     bool m_linked;
-    GLuint m_programId;
-    static GLuint m_currentProgram;
+    uint m_programId;
+    static uint m_currentProgram;
     ShaderList m_shaders;
-    std::array<GLint, MAX_UNIFORM_LOCATIONS> m_uniformLocations;
+    std::array<int, MAX_UNIFORM_LOCATIONS> m_uniformLocations;
 };
 
 #endif
diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp
index 089f4f59..c1b33d39 100644
--- a/src/framework/graphics/texture.cpp
+++ b/src/framework/graphics/texture.cpp
@@ -176,7 +176,7 @@ bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
 
 void Texture::setupWrap()
 {
-    GLint texParam;
+    int texParam;
     if(!m_repeat && g_graphics.canUseClampToEdge())
         texParam = GL_CLAMP_TO_EDGE;
     else
@@ -188,8 +188,8 @@ void Texture::setupWrap()
 
 void Texture::setupFilters()
 {
-    GLint minFilter;
-    GLint magFilter;
+    int minFilter;
+    int magFilter;
     if(m_smooth) {
         minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
         magFilter = GL_LINEAR;
diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h
index 7939539e..e7dcca7e 100644
--- a/src/framework/graphics/texture.h
+++ b/src/framework/graphics/texture.h
@@ -41,7 +41,7 @@ public:
     void setRepeat(bool repeat);
     void setUpsideDown(bool upsideDown);
 
-    GLuint getId()  { return m_id; }
+    uint getId()  { return m_id; }
     int getWidth() { return m_size.width(); }
     int getHeight() { return m_size.height(); }
     const Size& getSize() { return m_size; }
@@ -59,7 +59,7 @@ protected:
     void setupTranformMatrix();
     void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4);
 
-    GLuint m_id;
+    uint m_id;
     Size m_size;
     Size m_glSize;
     Matrix3 m_transformMatrix;
diff --git a/src/framework/luascript/luaobject.h b/src/framework/luascript/luaobject.h
index 732ca36c..5ae02054 100644
--- a/src/framework/luascript/luaobject.h
+++ b/src/framework/luascript/luaobject.h
@@ -26,6 +26,7 @@
 #include "declarations.h"
 
 /// LuaObject, all script-able classes have it as base
+// @bindclass
 class LuaObject : public std::enable_shared_from_this<LuaObject>
 {
 public:
diff --git a/src/framework/net/inputmessage.h b/src/framework/net/inputmessage.h
index 08509281..0269ae04 100644
--- a/src/framework/net/inputmessage.h
+++ b/src/framework/net/inputmessage.h
@@ -26,6 +26,7 @@
 #include "declarations.h"
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class InputMessage : public LuaObject
 {
 public:
diff --git a/src/framework/net/outputmessage.h b/src/framework/net/outputmessage.h
index c0abb954..a8095c96 100644
--- a/src/framework/net/outputmessage.h
+++ b/src/framework/net/outputmessage.h
@@ -26,6 +26,7 @@
 #include "declarations.h"
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class OutputMessage : public LuaObject
 {
 public:
diff --git a/src/framework/net/protocol.h b/src/framework/net/protocol.h
index bd4083fd..e90e23b4 100644
--- a/src/framework/net/protocol.h
+++ b/src/framework/net/protocol.h
@@ -29,6 +29,7 @@
 
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class Protocol : public LuaObject
 {
 public:
diff --git a/src/framework/platform/platformwindow.h b/src/framework/platform/platformwindow.h
index 93c8a866..82c66b4c 100644
--- a/src/framework/platform/platformwindow.h
+++ b/src/framework/platform/platformwindow.h
@@ -27,6 +27,7 @@
 #include <framework/core/inputevent.h>
 #include <framework/core/timer.h>
 
+//@bindsingleton g_window
 class PlatformWindow
 {
     enum {
diff --git a/src/framework/sound/soundbuffer.h b/src/framework/sound/soundbuffer.h
index 90b79e49..21a1020a 100644
--- a/src/framework/sound/soundbuffer.h
+++ b/src/framework/sound/soundbuffer.h
@@ -36,10 +36,10 @@ public:
     bool fillBuffer(const SoundFilePtr& soundFile);
     bool fillBuffer(ALenum sampleFormat, const DataBuffer<char>& data, int size, int rate);
 
-    ALuint getBufferId() { return m_bufferId; }
+    uint getBufferId() { return m_bufferId; }
 
 private:
-    ALuint m_bufferId;
+    uint m_bufferId;
 };
 
 #endif
diff --git a/src/framework/sound/soundmanager.h b/src/framework/sound/soundmanager.h
index a8748d18..80cae1fa 100644
--- a/src/framework/sound/soundmanager.h
+++ b/src/framework/sound/soundmanager.h
@@ -25,6 +25,7 @@
 
 #include "declarations.h"
 
+//@bindsingleton g_sounds
 class SoundManager
 {
     enum {
@@ -53,7 +54,7 @@ public:
 private:
     StreamSoundSourcePtr createStreamSoundSource(const std::string& filename);
     SoundSourcePtr createSoundSource(const std::string& filename);
-    ALuint loadFileIntoBuffer(const SoundFilePtr& soundFile);
+    uint loadFileIntoBuffer(const SoundFilePtr& soundFile);
 
     std::map<std::string, SoundBufferPtr> m_buffers;
     std::vector<SoundSourcePtr> m_sources;
diff --git a/src/framework/sound/soundsource.cpp b/src/framework/sound/soundsource.cpp
index 7bd0ed1a..c439c6c5 100644
--- a/src/framework/sound/soundsource.cpp
+++ b/src/framework/sound/soundsource.cpp
@@ -65,7 +65,7 @@ void SoundSource::stop()
 
 bool SoundSource::isPlaying()
 {
-    ALint state = AL_PLAYING;
+    int state = AL_PLAYING;
     alGetSourcei(m_sourceId, AL_SOURCE_STATE, &state);
     return state != AL_STOPPED;
 }
diff --git a/src/framework/sound/soundsource.h b/src/framework/sound/soundsource.h
index b65c63cd..81df87b4 100644
--- a/src/framework/sound/soundsource.h
+++ b/src/framework/sound/soundsource.h
@@ -28,7 +28,7 @@
 class SoundSource
 {
 protected:
-    SoundSource(ALuint sourceId) : m_sourceId(sourceId) { }
+    SoundSource(uint sourceId) : m_sourceId(sourceId) { }
 
 public:
     enum FadeState { NoFading, FadingOn, FadingOff };
@@ -56,7 +56,7 @@ protected:
     friend class SoundManager;
     friend class CombinedSoundSource;
 
-    ALuint m_sourceId;
+    uint m_sourceId;
     SoundBufferPtr m_buffer;
     FadeState m_fadeState;
     float m_fadeStartTime;
diff --git a/src/framework/sound/streamsoundsource.cpp b/src/framework/sound/streamsoundsource.cpp
index de401064..e0b82a09 100644
--- a/src/framework/sound/streamsoundsource.cpp
+++ b/src/framework/sound/streamsoundsource.cpp
@@ -63,7 +63,7 @@ void StreamSoundSource::stop()
 
 void StreamSoundSource::queueBuffers()
 {
-    ALint queued;
+    int queued;
     alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queued);
     for(int i = 0; i < STREAM_FRAGMENTS - queued; ++i) {
         if(!fillBufferAndQueue(m_buffers[i]->getBufferId()))
@@ -73,10 +73,10 @@ void StreamSoundSource::queueBuffers()
 
 void StreamSoundSource::unqueueBuffers()
 {
-    ALint queued;
+    int queued;
     alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queued);
     for(int i = 0; i < queued; ++i) {
-        ALuint buffer;
+        uint buffer;
         alSourceUnqueueBuffers(m_sourceId, 1, &buffer);
     }
 }
@@ -85,10 +85,10 @@ void StreamSoundSource::update()
 {
     SoundSource::update();
 
-    ALint processed = 0;
+    int processed = 0;
     alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processed);
-    for(ALint i = 0; i < processed; ++i) {
-        ALuint buffer;
+    for(int i = 0; i < processed; ++i) {
+        uint buffer;
         alSourceUnqueueBuffers(m_sourceId, 1, &buffer);
         //SoundManager::check_al_error("Couldn't unqueue audio buffer: ");
 
@@ -105,7 +105,7 @@ void StreamSoundSource::update()
     }
 }
 
-bool StreamSoundSource::fillBufferAndQueue(ALuint buffer)
+bool StreamSoundSource::fillBufferAndQueue(uint buffer)
 {
     // fill buffer
     static DataBuffer<char> bufferData(2*STREAM_FRAGMENT_SIZE);
diff --git a/src/framework/sound/streamsoundsource.h b/src/framework/sound/streamsoundsource.h
index 676b3699..3fbaa4da 100644
--- a/src/framework/sound/streamsoundsource.h
+++ b/src/framework/sound/streamsoundsource.h
@@ -51,7 +51,7 @@ public:
 private:
     void queueBuffers();
     void unqueueBuffers();
-    bool fillBufferAndQueue(ALuint buffer);
+    bool fillBufferAndQueue(uint buffer);
 
     SoundFilePtr m_soundFile;
     std::array<SoundBufferPtr,STREAM_FRAGMENTS> m_buffers;
diff --git a/src/framework/ui/uianchorlayout.h b/src/framework/ui/uianchorlayout.h
index 4ded3d4d..35118973 100644
--- a/src/framework/ui/uianchorlayout.h
+++ b/src/framework/ui/uianchorlayout.h
@@ -58,6 +58,7 @@ private:
     bool m_updated;
 };
 
+// @bindclass
 class UIAnchorLayout : public UILayout
 {
 public:
diff --git a/src/framework/ui/uiboxlayout.h b/src/framework/ui/uiboxlayout.h
index 1200db63..f0bd6f3d 100644
--- a/src/framework/ui/uiboxlayout.h
+++ b/src/framework/ui/uiboxlayout.h
@@ -25,6 +25,7 @@
 
 #include "uilayout.h"
 
+// @bindclass
 class UIBoxLayout : public UILayout
 {
 public:
diff --git a/src/framework/ui/uigridlayout.h b/src/framework/ui/uigridlayout.h
index d8937d19..307df314 100644
--- a/src/framework/ui/uigridlayout.h
+++ b/src/framework/ui/uigridlayout.h
@@ -25,6 +25,7 @@
 
 #include <framework/ui/uilayout.h>
 
+// @bindclass
 class UIGridLayout : public UILayout
 {
 public:
diff --git a/src/framework/ui/uilayout.h b/src/framework/ui/uilayout.h
index b985116b..909c92a4 100644
--- a/src/framework/ui/uilayout.h
+++ b/src/framework/ui/uilayout.h
@@ -27,6 +27,7 @@
 #include <framework/luascript/luaobject.h>
 #include <framework/otml/otml.h>
 
+// @bindclass
 class UILayout : public LuaObject
 {
 public:
diff --git a/src/framework/ui/uimanager.h b/src/framework/ui/uimanager.h
index 255b43f2..38ca532c 100644
--- a/src/framework/ui/uimanager.h
+++ b/src/framework/ui/uimanager.h
@@ -27,6 +27,7 @@
 #include <framework/core/inputevent.h>
 #include <framework/otml/declarations.h>
 
+//@bindsingleton g_ui
 class UIManager
 {
 public:
diff --git a/src/framework/ui/uitextedit.h b/src/framework/ui/uitextedit.h
index 731eaca0..1a7ef69b 100644
--- a/src/framework/ui/uitextedit.h
+++ b/src/framework/ui/uitextedit.h
@@ -25,6 +25,7 @@
 
 #include "uiwidget.h"
 
+// @bindclass
 class UITextEdit : public UIWidget
 {
 public:
diff --git a/src/framework/ui/uiverticallayout.h b/src/framework/ui/uiverticallayout.h
index 33445b7f..bc0fd945 100644
--- a/src/framework/ui/uiverticallayout.h
+++ b/src/framework/ui/uiverticallayout.h
@@ -25,6 +25,7 @@
 
 #include "uiboxlayout.h"
 
+// @bindclass
 class UIVerticalLayout : public UIBoxLayout
 {
 public:
diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h
index f19833f0..e9c50ac8 100644
--- a/src/framework/ui/uiwidget.h
+++ b/src/framework/ui/uiwidget.h
@@ -41,9 +41,7 @@ struct EdgeGroup {
     T left;
 };
 
-// generate lua bindings for this class running:
-// ./tools/lua-binding-generator/generate_lua_bindings.lua src/framework/ui/uiwidget.h
-
+// @bindclass
 class UIWidget : public LuaObject
 {
 // widget core
diff --git a/src/otclient/core/animatedtext.h b/src/otclient/core/animatedtext.h
index 4b373bad..d2dc4ada 100644
--- a/src/otclient/core/animatedtext.h
+++ b/src/otclient/core/animatedtext.h
@@ -28,7 +28,8 @@
 #include <framework/core/timer.h>
 #include <framework/graphics/cachedtext.h>
 
-class AnimatedText
+// @bindclass
+class AnimatedText : public Thing
 {
 public:
     AnimatedText();
diff --git a/src/otclient/core/container.h b/src/otclient/core/container.h
index e75f6b07..a679605c 100644
--- a/src/otclient/core/container.h
+++ b/src/otclient/core/container.h
@@ -27,6 +27,7 @@
 
 #include <framework/luascript/luaobject.h>
 
+// @bindclass
 class Container : public LuaObject
 {
 protected:
diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h
index 312ae207..2d009372 100644
--- a/src/otclient/core/creature.h
+++ b/src/otclient/core/creature.h
@@ -30,6 +30,7 @@
 #include <framework/graphics/fontmanager.h>
 #include <framework/graphics/cachedtext.h>
 
+// @bindclass
 class Creature : public Thing
 {
 public:
@@ -142,13 +143,17 @@ protected:
     Otc::Direction m_walkTurnDirection;
 };
 
-class Npc : public Creature {
+// @bindclass
+class Npc : public Creature
+{
 public:
     NpcPtr asNpc() { return std::static_pointer_cast<Npc>(shared_from_this()); }
     bool isNpc() { return true; }
 };
 
-class Monster : public Creature {
+// @bindclass
+class Monster : public Creature
+{
 public:
     MonsterPtr asMonster() { return std::static_pointer_cast<Monster>(shared_from_this()); }
     bool isMonster() { return true; }
diff --git a/src/otclient/core/effect.h b/src/otclient/core/effect.h
index 1e46c63b..1b8d0dd3 100644
--- a/src/otclient/core/effect.h
+++ b/src/otclient/core/effect.h
@@ -27,6 +27,7 @@
 #include <framework/core/timer.h>
 #include "thing.h"
 
+// @bindclass
 class Effect : public Thing
 {
 public:
diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h
index 1b399179..10bfe3df 100644
--- a/src/otclient/core/game.h
+++ b/src/otclient/core/game.h
@@ -31,6 +31,7 @@
 
 typedef std::tuple<std::string, bool> Vip;
 
+//@bindsingleton g_game
 class Game
 {
 public:
diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h
index c39a2531..11ab1094 100644
--- a/src/otclient/core/item.h
+++ b/src/otclient/core/item.h
@@ -68,6 +68,7 @@ enum AttrTypes_t {
     ATTR_ATTRIBUTE_MAP = 128
 };
 
+// @bindclass
 class Item : public Thing
 {
 public:
diff --git a/src/otclient/core/localplayer.h b/src/otclient/core/localplayer.h
index 19c8a138..54f0aa5e 100644
--- a/src/otclient/core/localplayer.h
+++ b/src/otclient/core/localplayer.h
@@ -25,6 +25,7 @@
 
 #include "player.h"
 
+// @bindclass
 class LocalPlayer : public Player
 {
     enum {
diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h
index d7adccee..efc1081c 100644
--- a/src/otclient/core/map.h
+++ b/src/otclient/core/map.h
@@ -75,6 +75,7 @@ enum OTBM_NodeTypes_t
     OTBM_WAYPOINT = 16
 };
 
+//@bindsingleton g_map
 class Map
 {
 public:
diff --git a/src/otclient/core/mapview.h b/src/otclient/core/mapview.h
index 50936b05..73000425 100644
--- a/src/otclient/core/mapview.h
+++ b/src/otclient/core/mapview.h
@@ -28,6 +28,7 @@
 #include <framework/luascript/luaobject.h>
 #include <framework/core/declarations.h>
 
+// @bindclass
 class MapView : public LuaObject
 {
     enum {
diff --git a/src/otclient/core/missile.h b/src/otclient/core/missile.h
index 858768f2..666c2599 100644
--- a/src/otclient/core/missile.h
+++ b/src/otclient/core/missile.h
@@ -27,6 +27,7 @@
 #include <framework/core/timer.h>
 #include "thing.h"
 
+// @bindclass
 class Missile : public Thing
 {
     enum {
diff --git a/src/otclient/core/player.h b/src/otclient/core/player.h
index 8c7c50ef..36b9c318 100644
--- a/src/otclient/core/player.h
+++ b/src/otclient/core/player.h
@@ -25,6 +25,7 @@
 
 #include "creature.h"
 
+// @bindclass
 class Player : public Creature
 {
 public:
diff --git a/src/otclient/core/shadermanager.h b/src/otclient/core/shadermanager.h
index f2a9e908..9aee934f 100644
--- a/src/otclient/core/shadermanager.h
+++ b/src/otclient/core/shadermanager.h
@@ -20,12 +20,13 @@
  * THE SOFTWARE.
  */
 
-#ifndef GAMESHADERS_H
-#define GAMESHADERS_H
+#ifndef SHADERMANAGER_H
+#define SHADERMANAGER_H
 
 #include "declarations.h"
 #include <framework/graphics/paintershaderprogram.h>
 
+//@bindsingleton g_shaders
 class ShaderManager
 {
 public:
diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h
index b49582e2..235b79b8 100644
--- a/src/otclient/core/spritemanager.h
+++ b/src/otclient/core/spritemanager.h
@@ -26,6 +26,7 @@
 #include <framework/core/declarations.h>
 #include <framework/graphics/declarations.h>
 
+//@bindsingleton g_sprites
 class SpriteManager
 {
 public:
diff --git a/src/otclient/core/statictext.cpp b/src/otclient/core/statictext.cpp
index 1f187d1f..831fe40b 100644
--- a/src/otclient/core/statictext.cpp
+++ b/src/otclient/core/statictext.cpp
@@ -25,6 +25,7 @@
 #include <framework/core/clock.h>
 #include <framework/core/eventdispatcher.h>
 #include <framework/graphics/graphics.h>
+#include <framework/graphics/fontmanager.h>
 
 StaticText::StaticText()
 {
diff --git a/src/otclient/core/statictext.h b/src/otclient/core/statictext.h
index 1950093c..12145d0d 100644
--- a/src/otclient/core/statictext.h
+++ b/src/otclient/core/statictext.h
@@ -23,12 +23,12 @@
 #ifndef STATICTEXT_H
 #define STATICTEXT_H
 
+#include "thing.h"
 #include <framework/graphics/cachedtext.h>
-#include <framework/graphics/fontmanager.h>
 #include <framework/core/timer.h>
-#include <framework/luascript/luaobject.h>
 
-class StaticText : public LuaObject
+// @bindclass
+class StaticText : public Thing
 {
 public:
     StaticText();
diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h
index ad57cb8b..c85284de 100644
--- a/src/otclient/core/thing.h
+++ b/src/otclient/core/thing.h
@@ -33,6 +33,7 @@ struct Light
     uint8 color;
 };
 
+// @bindclass
 class Thing : public LuaObject
 {
 public:
diff --git a/src/otclient/core/thingstype.h b/src/otclient/core/thingstype.h
index e459b7e9..f4407e61 100644
--- a/src/otclient/core/thingstype.h
+++ b/src/otclient/core/thingstype.h
@@ -27,6 +27,7 @@
 #include <framework/core/declarations.h>
 #include "thingtype.h"
 
+//@bindsingleton g_thingsType
 class ThingsType
 {
 public:
diff --git a/tools/lua-binding-generator/generate_lua_bindings.lua b/tools/lua-binding-generator/generate_lua_bindings.lua
index 304acd5e..f3d2d0c1 100755
--- a/tools/lua-binding-generator/generate_lua_bindings.lua
+++ b/tools/lua-binding-generator/generate_lua_bindings.lua
@@ -1,20 +1,26 @@
 #!/usr/bin/lua
 
-if not (#arg >= 1 and #arg <= 4) then
-  print('usage: ' .. arg[0] .. ' <cpp class header> [class name] [cpp class instance] [lua class instance]')
-  return false
+-- parse options
+if #arg == 0 then
+  print('usage: ' .. arg[0] .. ' <headers> [--doc]')
+  os.exit(1)
 end
 
-cppclassheader = arg[1]
-cppclassname = arg[2]
-cppclassinstance = arg[3]
-luaclassname = arg[3] or luaclassname
-
-if not io.open(cppclassheader, 'r') then
-  print('could not open ' .. cppclassheader)
-  return false
+gendoc = false
+for i=1,#arg do
+  if arg[i] == '--doc' then
+    table.remove(arg, i)
+    gendoc = true
+    break
+  end
 end
 
+if #arg == 0 then
+  print('Specify a file.')
+  os.exit(1)
+end
+
+-- string utilities
 function string:matchcount(pattern)
   local count = 0
   for w in self:gmatch(pattern) do count = count + 1 end
@@ -28,68 +34,234 @@ function string:splitlines()
   return t
 end
 
-classfound = false
-publicmethods = false
-for line in io.lines(cppclassheader) do
-  foundclassname = line:match('^class ([%w_]+)')
-  if foundclassname then
-    if not cppclassname then
-      guessedclassname = cppclassheader:match('([%w_]+)\.h$'):lower()
-      if foundclassname:lower() == guessedclassname then
-        cppclassname = foundclassname
-      end
+
+function table.removevalue(t, value)
+  for k,v in pairs(t) do
+    if v == value then
+      table.remove(t, k)
+      break
     end
-    if foundclassname == cppclassname then
-      classfound = true
-      publicmethods = false
-
-      if cppclassinstance then
-        print('    g_lua.registerStaticClass("' .. luaclassname .. '");')
-      else
-        baseclassname = line:match(': public ([%w_]+)')
-        bindline = '    g_lua.registerClass<' .. cppclassname
-
-        if baseclassname and baseclassname ~= 'LuaObject' then
-          bindline = bindline .. ', ' .. baseclassname
-        end
-
-        bindline = bindline .. '>();'
-        print(bindline)
-
-        bindline = '    g_lua.bindClassStaticFunction<' .. cppclassname .. '>("create", []{ return ' .. cppclassname .. 'Ptr(new ' .. cppclassname ..  '); });'
-        print(bindline)
-      end
-    elseif classfound then
-      return true
-    end
-  end
-  if classfound then
-    if line:match('public:') then
-      publicmethods = true
-    elseif line:match('private:') or line:match('protected:') then
-      publicmethods = false
-    elseif publicmethods then
-      funcname, args = line:match('^ *[%w <>&\*:_]* ([%w_]+)%(([^%)]*%))[%w ]*[;{=].*$')
-      if funcname then
-        if funcname ~= cppclassname and funcname ~= 'create' then
-          numargs = args:matchcount('[^,)]+[,)]')
-
-          if cppclassinstance then
-            bindline = '    g_lua.bindClassStaticFunction("' .. luaclassname .. '", "' .. funcname .. '", ' ..
-                      'std::bind(&' .. cppclassname .. "::" .. funcname .. ', &' .. cppclassinstance
-            for i=1,numargs do
-              bindline = bindline .. ', std::placeholders::_' .. i
-            end
-            bindline = bindline .. '));'
-          else
-            bindline = '    g_lua.bindClassMemberFunction<' .. cppclassname .. '>("' .. funcname .. '", &' ..
-                      cppclassname .. '::' .. funcname .. ');'
-          end
-          print(bindline)
-        end
-      end
-     end
   end
 end
 
-return true
+function string.split(s, delim)
+  local start = 1
+  local results = {}
+  while true do
+    local pos = string.find(s, delim, start, true)
+    if not pos then
+      break
+    end
+    table.insert(results, string.sub(s, start, pos-1))
+    start = pos + string.len(delim)
+  end
+  table.insert(results, string.sub(s, start))
+  table.removevalue(results, '')
+  return results
+end
+
+function string.trim(s)
+  return string.match(s, '^%s*(.*%S)') or ''
+end
+
+function countbrackets(str)
+  local ret = 0
+  for _i in str:gmatch('{') do ret = ret+1 end
+  for _i in str:gmatch('}') do ret = ret-1 end
+  return ret
+end
+
+function filterType(arg)
+  arg = arg:gsub('^const[%s]+', '')
+  arg = arg:gsub('Ptr', '')
+  arg = arg:gsub('&', '')
+  arg = arg:gsub('.*List$', 'table')
+  arg = arg:gsub('^std::string$', 'string')
+  arg = arg:gsub('^OTMLNode$', 'table')
+  arg = arg:gsub('^std::vector<.*>$', 'table')
+  arg = arg:gsub('^std::map<.*>$', 'table')
+  arg = arg:gsub('^[u]?int[0-9_t]*$', 'integer')
+  arg = arg:gsub('^float$', 'number')
+  arg = arg:gsub('^double$', 'number')
+  arg = arg:gsub('^bool$', 'boolean')
+  arg = arg:gsub('^ticks_t$', 'integer')
+  arg = arg:gsub('.*\*.*', 'buffer')
+  arg = arg:gsub('.*::.*', 'enum')
+  return arg
+end
+
+function filterArgs(str)
+  local args = str:split(',') or { str }
+
+  newstr = ''
+  for i,argstr in pairs(args) do
+    argstr = argstr:gsub('[%s]*=.*','')
+    local argtype, argvar = argstr:match('^(.*[%s]+[&*]?)([%w_]*)')
+    newstr = newstr .. filterType(argtype:trim()) .. ' ' .. argvar:trim()
+
+    if i ~= #args then
+      newstr = newstr .. ', '
+    end
+  end
+
+  return newstr
+end
+
+function filterReturn(str)
+  str = str:gsub('virtual ', '')
+  str = str:gsub('static ', '')
+  return filterType(str:trim())
+end
+
+
+function emitSingletonDecl(cppclass, luaclass)
+  if gendoc then
+    outline = 'class ' .. luaclass .. ' {\n' ..
+              'public:'
+  else
+    outline = '    // ' .. luaclass .. '\n' ..
+              '    g_lua.registerStaticClass("' .. luaclass .. '");'
+  end
+  print(outline)
+  return outline
+end
+
+function emitClassDecl(cppclass, luaclass, baseclass)
+  local outline
+  if gendoc then
+    outline = 'class ' .. luaclass
+    if cppclass ~= 'LuaObject' and baseclass then
+      outline = outline .. ' : public ' .. baseclass
+    end
+    outline = outline .. ' {\npublic:'
+  else
+    print('    // ' .. luaclass)
+    outline = '    g_lua.registerClass<' .. cppclass
+    if cppclass ~= 'LuaObject' and baseclass and baseclass ~= 'LuaObject' then
+      outline = outline .. ', ' .. baseclass
+    end
+    outline = outline .. '>();'
+  end
+  print(outline)
+  return outline
+end
+
+function emitClassEnd()
+  local outline = '\n'
+  if gendoc then
+    outline = '};\n'
+  end
+  print(outline)
+  return outline
+end
+
+function emitSingletonFunctionDecl(cppclass, luaclass, funcname, funcargs, funcret)
+  local outline
+  if gendoc then
+    outline = '    ' .. filterReturn(funcret) .. ' ' .. funcname .. '(' .. filterArgs(funcargs) .. ');'
+  else
+    outline = '    g_lua.bindSingletonFunction("' .. luaclass .. '", "' .. funcname .. '", &' ..  cppclass .. '::' .. funcname .. ', &' .. luaclass .. ');'
+  end
+  print(outline)
+  return outline
+end
+
+function emitMemberFunctionDecl(cppclass, luaclass, funcname, funcargs, funcret)
+  local outline
+  if gendoc then
+    outline = '    ' .. filterReturn(funcret) .. ' ' .. funcname .. '(' .. filterArgs(funcargs) .. ');'
+  else
+    outline = '    g_lua.bindClassMemberFunction("' .. funcname .. '", &' ..  cppclass .. '::' .. funcname .. ');'
+  end
+  print(outline)
+  return outline
+end
+
+function parseClassHeader(line, param)
+  cppclass = line:match('^[%s]*class[%s]+([%w_]+)')
+  if not cppclass then
+    print('Invalid directive at ' .. header .. ':' .. linenumber)
+    os.exit(1)
+  end
+
+  luaclass = param or cppclass
+  insideclass = true
+  publicmethods = true
+  brackets = 0
+  bindnext = true
+
+  if singleton then
+    emitSingletonDecl(cppclass, luaclass)
+  else
+    baseclass = line:match(':[%s]+public[%s]+([%w_]+)')
+    emitClassDecl(cppclass, luaclass, baseclass)
+  end
+end
+
+function parseHeader(file)
+  header = file
+  linenumber = 0
+  brackets = 0
+  publicmethods = false
+  insideclass = false
+  singleton = false
+
+  if not io.open(header, 'r') then
+    print('Unable to open ' .. header)
+    exit(1)
+  end
+
+  lines = {}
+  for line in io.lines(header) do table.insert(lines, line) end
+
+  for linenumber=1,#lines do
+    local line = lines[linenumber]
+    local param = line:match('^[%s]*//[%s]*@[%w]+[%s]+(.*)[%s]*')
+
+    if not insideclass then
+      if line:match('[%s]*//[%s]*@bindsingleton') then
+        singleton = true
+        linenumber = linenumber+1
+        parseClassHeader(lines[linenumber], param)
+      elseif line:match('[%s]*//[%s]*@bindclass') then
+        singleton = false
+        linenumber = linenumber+1
+        parseClassHeader(lines[linenumber], param)
+      end
+    else
+      if brackets > 1 then
+        -- ignore
+      elseif line:match('[%s]*//[%s]*@dontbind') then
+        bindnext = false
+      elseif line:match('[%s]*template') then
+        bindnext = false
+      elseif line:match('[%s]*public:') then
+        publicmethods = true
+      elseif line:match('[%s]*private:') or line:match('[%s]*protected:') then
+        publicmethods = false
+      elseif line:match('^};') then
+        insideclass = false
+        emitClassEnd()
+      elseif bindnext then
+        funcreturn, funcname, funcargs = line:match('^[%s]*([%w <>&\*:_]*) ([%w_]+)%(([^%)]*%))[%w ]*[;{=].*$')
+        if funcname then
+          funcargs = funcargs:match('(.*)\%)')
+          if funcname ~= cppclass then
+            if singleton then
+              emitSingletonFunctionDecl(cppclass, luaclass, funcname, funcargs, funcreturn)
+            else
+              emitMemberFunctionDecl(cppclass, luaclass, funcname, funcargs, funcreturn)
+            end
+          end
+        end
+      else
+        bindnext = true
+      end
+      brackets = brackets + countbrackets(line)
+    end
+  end
+end
+
+for i=1,#arg do
+  parseHeader(arg[i])
+end
\ No newline at end of file