From 6b7a9e3c5aba3659dd4210a27335d14a334f7680 Mon Sep 17 00:00:00 2001
From: Joseph Walton-Rivers <joseph@walton-rivers.uk>
Date: Sun, 17 Apr 2022 11:10:48 +0100
Subject: [PATCH] use consistant style for headers

---
 fggl/gfx/ogl/backend.cpp            |  25 +-
 fggl/gfx/ogl/renderer.cpp           | 415 ++++++++++++++--------------
 fggl/gfx/window.cpp                 |   7 +-
 include/fggl/app.hpp                | 206 +++++++-------
 include/fggl/data/heightmap.h       |  59 ++--
 include/fggl/data/model.hpp         |  67 ++---
 include/fggl/data/procedural.hpp    |  20 +-
 include/fggl/data/procedure.hpp     |   1 -
 include/fggl/data/storage.hpp       |  38 ++-
 include/fggl/debug/debug.h          |   9 +-
 include/fggl/ecs/component.hpp      |  73 ++---
 include/fggl/ecs/ecs.hpp            | 205 +++++++-------
 include/fggl/ecs/utility.hpp        |   1 +
 include/fggl/ecs3/ecs.hpp           |   2 +-
 include/fggl/ecs3/fast/Container.h  | 169 ++++++-----
 include/fggl/ecs3/fast/ecs.hpp      | 230 +++++++--------
 include/fggl/ecs3/module/module.h   | 112 ++++----
 include/fggl/ecs3/prototype/world.h | 402 +++++++++++++--------------
 include/fggl/ecs3/types.hpp         | 313 ++++++++++-----------
 include/fggl/ecs3/utils.hpp         |  38 +--
 include/fggl/gfx/atlas.hpp          |  78 +++---
 include/fggl/gfx/camera.hpp         |   2 +-
 include/fggl/gfx/common.hpp         |   5 +-
 include/fggl/gfx/compat.hpp         |  29 +-
 include/fggl/gfx/input.hpp          |  22 +-
 include/fggl/gfx/ogl/backend.hpp    |  52 ++--
 include/fggl/gfx/ogl/compat.hpp     | 104 +++----
 include/fggl/gfx/ogl/renderer.hpp   |  42 ++-
 include/fggl/gfx/ogl/shader.hpp     |  32 +--
 include/fggl/gfx/paint.hpp          | 172 ++++++------
 include/fggl/gfx/renderer.hpp       |  19 +-
 include/fggl/gfx/vector.hpp         |  14 +-
 include/fggl/gfx/vulkan/vulkan.hpp  |  27 +-
 include/fggl/gfx/window.hpp         |  72 ++---
 include/fggl/gfx/window_input.hpp   |  23 +-
 include/fggl/gfx/windowing.hpp      |  72 ++---
 include/fggl/gui/containers.hpp     | 106 +++----
 include/fggl/gui/widget.hpp         |  48 ++--
 include/fggl/gui/widgets.hpp        |  52 ++--
 include/fggl/input/camera_input.h   |  88 +++---
 include/fggl/input/gamepad.hpp      | 133 +++++----
 include/fggl/input/input.hpp        |   2 +-
 include/fggl/input/keyboard.hpp     |  44 +--
 include/fggl/input/mouse.hpp        |  52 ++--
 include/fggl/math/easing.hpp        | 209 +++++++-------
 include/fggl/math/triangulation.hpp | 301 ++++++++++----------
 include/fggl/math/types.hpp         | 146 +++++-----
 include/fggl/scenes/Scene.h         |  68 ++---
 include/fggl/scenes/menu.hpp        |  32 +--
 include/fggl/util/chrono.hpp        |   2 +-
 include/fggl/util/service.h         |  72 ++---
 include/fggl/util/states.hpp        |  88 +++---
 52 files changed, 2307 insertions(+), 2293 deletions(-)

diff --git a/fggl/gfx/ogl/backend.cpp b/fggl/gfx/ogl/backend.cpp
index 99b0631..1eb7c94 100644
--- a/fggl/gfx/ogl/backend.cpp
+++ b/fggl/gfx/ogl/backend.cpp
@@ -1,27 +1,6 @@
-#include <fggl/gfx/ogl/backend.hpp>
+#include <spdlog/spdlog.h>
 
+#include <fggl/gfx/ogl/backend.hpp>
 #include <stdexcept>
-#include <spdlog/spdlog.h>
 
 using namespace fggl::gfx;
-
-GlGraphics::GlGraphics(const Window& window) {
-    spdlog::debug("[OGL] attaching window context");
-	window.activate();
-	GLenum err = glewInit();
-	if ( GLEW_OK != err ) {
-		throw std::runtime_error("couldn't init glew");
-	}
-
-	glViewport(0, 0, 1920, 1080);
-    spdlog::debug("[OGL] window context ready");
-}
-
-GlGraphics::~GlGraphics() {
-    spdlog::debug("[OGL] gl window context killed!");
-}
-
-void GlGraphics::clear() {
-	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-}
diff --git a/fggl/gfx/ogl/renderer.cpp b/fggl/gfx/ogl/renderer.cpp
index 410f146..4a0f570 100644
--- a/fggl/gfx/ogl/renderer.cpp
+++ b/fggl/gfx/ogl/renderer.cpp
@@ -1,14 +1,11 @@
+#include <fggl/util/service.h>
 #include <spdlog/spdlog.h>
 
+#include <fggl/data/model.hpp>
+#include <fggl/gfx/camera.hpp>
 #include <fggl/gfx/ogl/renderer.hpp>
 #include <fggl/gfx/paint.hpp>
-
 #include <fggl/math/triangulation.hpp>
-#include <fggl/data/model.hpp>
-#include <fggl/util/service.h>
-
-#include <fggl/gfx/camera.hpp>
-
 #include <glm/ext/matrix_clip_space.hpp>
 #include <glm/ext/matrix_transform.hpp>
 #include <glm/glm.hpp>
@@ -17,247 +14,259 @@
 
 /**
  * Future optimisations:
- *   recommended approach is to group stuff in to as few vao as possible - this will do one vao per mesh, aka bad.
- *   Add support for instanced rendering (particles)
- *   Look at packing vertex data in better ways (with profiling)
+ *   recommended approach is to group stuff in to as few vao as possible - this
+ * will do one vao per mesh, aka bad. Add support for instanced rendering
+ * (particles) Look at packing vertex data in better ways (with profiling)
  *   Support shader specialisation (ie, dynamic/streamed data)
- *   Follow best recommendations for Vertex attributes (ie normals not using floats, bytes for colour)
+ *   Follow best recommendations for Vertex attributes (ie normals not using
+ * floats, bytes for colour)
  *
  * Future features:
  *   Add support for models with weights (for animations)
- *   OpenGL ES for the FOSS thinkpad users who can't run anything even remotely modern
+ *   OpenGL ES for the FOSS thinkpad users who can't run anything even remotely
+ * modern
  */
 namespace fggl::gfx {
 
-    using data::Vertex2D;
-    using data::Mesh2D;
-
-    GlRenderToken setupVertex2D() {
-        GlRenderToken token{};
-        glGenVertexArrays(1, &token.vao);
-        glBindVertexArray(token.vao);
+using data::Mesh2D;
+using data::Vertex2D;
 
-	    glGenBuffers(2, token.buffs);
+GlRenderToken setupVertex2D() {
+  GlRenderToken token{};
+  glGenVertexArrays(1, &token.vao);
+  glBindVertexArray(token.vao);
 
-	    glBindBuffer(GL_ARRAY_BUFFER, token.buffs[0]);
-        glEnableVertexAttribArray(0);
-        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<void*>(offsetof(Vertex2D, position)));
-        glEnableVertexAttribArray(1);
-        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<void*>(offsetof(Vertex2D, colour)));
+  glGenBuffers(2, token.buffs);
 
-        glBindVertexArray(0);
-        return token;
-    }
-
-    OpenGL4Backend::OpenGL4Backend() : fggl::gfx::Graphics() {
-        GLenum err = glewInit();
-        if ( GLEW_OK != err ) {
-            throw std::runtime_error("couldn't init glew");
-        }
-        glViewport(0, 0, 2560, 1440);
+  glBindBuffer(GL_ARRAY_BUFFER, token.buffs[0]);
+  glEnableVertexAttribArray(0);
+  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D),
+                        reinterpret_cast<void*>(offsetof(Vertex2D, position)));
+  glEnableVertexAttribArray(1);
+  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2D),
+                        reinterpret_cast<void*>(offsetof(Vertex2D, colour)));
 
-        m_token2D = setupVertex2D();
-
-        auto& locator = util::ServiceLocator::instance();
+  glBindVertexArray(0);
+  return token;
+}
 
-        auto storage = locator.get<data::Storage>();
-        m_cache = std::make_unique<ShaderCache>(storage);
+OpenGL4Backend::OpenGL4Backend(const Window& owner) : fggl::gfx::Graphics() {
+  // initialise GLEW, or fail
+  GLenum err = glewInit();
+  if (GLEW_OK != err) {
+    throw std::runtime_error("couldn't init glew");
+  }
+
+  // setup the viewport based on the window's framebuffer
+  auto fbSize = owner.frameSize();
+  glViewport(0, 0, fbSize.x, fbSize.y);
+
+  // setup the shader cache
+  auto& locator = util::ServiceLocator::instance();
+  auto storage = locator.get<data::Storage>();
+  m_cache = std::make_unique<ShaderCache>(storage);
+
+  // setup 2D rendering system
+  m_token2D = setupVertex2D();
+  ShaderConfig shader2DConfig = ShaderFromName("shader2D");
+  m_cache->load(shader2DConfig);
+};
+
+void OpenGL4Backend::clear() {
+  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
 
-        ShaderConfig shader2DConfig = ShaderFromName( "shader2D" );
-        m_cache->load( shader2DConfig );
-    };
+static void generateMesh(const gfx::Paint& paint, Mesh2D& mesh) {
+  for (auto& cmd : paint.cmds()) {
+    auto path = cmd.path;
+
+    std::vector<data::Vertex2D> verts;
+    math::vec3 colour{1.0f, 1.0f, 1.0f};
+    auto idx = 0;
+    auto colourIdx = 0;
+
+    for (auto& type : path.m_types) {
+      if (type == PathType::PATH) {
+        verts.push_back({.position = path.m_points[idx++], .colour = colour});
+      } else if (type == PathType::MOVE) {
+        // polygon finished
+        if (verts.size() < 3) {
+          // empty, point, or line
+        } else if (verts.size() == 3) {
+          // triangle
+        } else {
+          // polygon
+          math::fanTriangulation(verts, mesh);
+        }
 
-    void OpenGL4Backend::clear() {
-        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+        verts.clear();
+        verts.push_back({.position = path.m_points[idx++], .colour = colour});
+      } else if (type == PathType::COLOUR) {
+        colour = path.m_colours[colourIdx++];
+      } else {
+        // unsupported type
+      }
     }
 
-    static void generateMesh( const gfx::Paint& paint, Mesh2D& mesh ) {
-        for ( auto& cmd : paint.cmds() ) {
-
-            auto path = cmd.path;
-
-            std::vector<data::Vertex2D> verts;
-            math::vec3 colour{1.0f, 1.0f, 1.0f};
-            auto idx = 0;
-            auto colourIdx = 0;
-
-            for ( auto& type : path.m_types ) {
-                if ( type == PathType::PATH ) {
-                    verts.push_back({
-                            .position = path.m_points[ idx++ ],
-                            .colour = colour
-                            });
-                } else if ( type == PathType::MOVE ) {
-                    // polygon finished
-                    if ( verts.size() < 3 ) {
-                        // empty, point, or line
-                    } else if ( verts.size() == 3 ) {
-                        // triangle
-                    } else {
-                        // polygon
-                        math::fanTriangulation( verts, mesh );
-                    }
-
-                    verts.clear();
-                    verts.push_back({
-                            .position = path.m_points[ idx++ ],
-                            .colour = colour
-                            });
-                } else if ( type == PathType::COLOUR ) {
-                    colour = path.m_colours[ colourIdx++ ];
-                } else {
-                    // unsupported type
-                }
-            }
-
-            if ( !verts.empty() ) {
-                math::fanTriangulation( verts, mesh );
-            }
-            
-        }
+    if (!verts.empty()) {
+      math::fanTriangulation(verts, mesh);
     }
+  }
+}
 
-    void OpenGL4Backend::draw2D( const gfx::Paint& paint ) {
+void OpenGL4Backend::draw2D(const gfx::Paint& paint) {
+  // generate the mesh from a paint command list
+  data::Mesh2D mesh;
+  generateMesh(paint, mesh);
 
-        // generate the mesh from a paint command list
-        data::Mesh2D mesh;
-        generateMesh( paint, mesh );
+  // render the resulting mesh
+  auto shader2D = m_cache->get("shader2D");
 
-        // render the resulting mesh
-        auto shader2D = m_cache->get( "shader2D" );
+  glUseProgram(shader2D);
 
-	    glUseProgram( shader2D );
+  auto projMat = glm::ortho(0.0f, 1920.0f, 0.0f, 1080.f);
+  glUniformMatrix4fv(glGetUniformLocation(shader2D, "projection"), 1, GL_FALSE,
+                     glm::value_ptr(projMat));
 
-        auto projMat = glm::ortho(0.0f, 1920.0f, 0.0f, 1080.f);
-	    glUniformMatrix4fv( glGetUniformLocation(shader2D, "projection"), 1, GL_FALSE, glm::value_ptr( projMat ) );
+  glBindVertexArray(m_token2D.vao);
 
-        glBindVertexArray( m_token2D.vao );
+  glBindBuffer(GL_ARRAY_BUFFER, m_token2D.buffs[0]);
+  glBufferData(GL_ARRAY_BUFFER, mesh.vertexList.size() * sizeof(Vertex2D),
+               mesh.vertexList.data(), GL_DYNAMIC_DRAW);
 
-        glBindBuffer( GL_ARRAY_BUFFER, m_token2D.buffs[0] );
-        glBufferData( GL_ARRAY_BUFFER, mesh.vertexList.size() * sizeof(Vertex2D), mesh.vertexList.data(), GL_DYNAMIC_DRAW );
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_token2D.buffs[1]);
+  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+               mesh.indexList.size() * sizeof(uint32_t), mesh.indexList.data(),
+               GL_DYNAMIC_DRAW);
 
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_token2D.buffs[1]);
-      	glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indexList.size() * sizeof(uint32_t), mesh.indexList.data(), GL_DYNAMIC_DRAW);
-        
-        glDrawElements( GL_TRIANGLES, mesh.indexList.size(), GL_UNSIGNED_INT, (GLvoid*)0);
+  glDrawElements(GL_TRIANGLES, mesh.indexList.size(), GL_UNSIGNED_INT,
+                 (GLvoid*)0);
 
-        glBindVertexArray( 0 );
-	    glUseProgram( 0 );
-        //glDisable(GL_PRIMITIVE_RESTART);
-    }
+  glBindVertexArray(0);
+  glUseProgram(0);
+  // glDisable(GL_PRIMITIVE_RESTART);
+}
 
-template<typename T>
+template <typename T>
 static GLuint createArrayBuffer(std::vector<T>& vertexData) {
-	GLuint buffId;
-	glGenBuffers(1, &buffId);
-	glBindBuffer(GL_ARRAY_BUFFER, buffId);
-	glBufferData(GL_ARRAY_BUFFER,
-			vertexData.size() * sizeof(T),
-			vertexData.data(),
-			GL_STATIC_DRAW);
-	return buffId;	
+  GLuint buffId;
+  glGenBuffers(1, &buffId);
+  glBindBuffer(GL_ARRAY_BUFFER, buffId);
+  glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(T),
+               vertexData.data(), GL_STATIC_DRAW);
+  return buffId;
 }
 
 static GLuint createIndexBuffer(std::vector<uint32_t>& indexData) {
-	GLuint buffId;
-	glGenBuffers(1, &buffId);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffId);
-	glBufferData(GL_ELEMENT_ARRAY_BUFFER,
-			indexData.size() * sizeof(uint32_t),
-			indexData.data(),
-			GL_STATIC_DRAW);
-	return buffId;
+  GLuint buffId;
+  glGenBuffers(1, &buffId);
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffId);
+  glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(uint32_t),
+               indexData.data(), GL_STATIC_DRAW);
+  return buffId;
 }
 
-
 GlRenderToken MeshRenderer::upload(fggl::data::Mesh& mesh) {
-	GlRenderToken token{};
-	glGenVertexArrays(1, &token.vao);
-	glBindVertexArray(token.vao);
-
-	token.buffs[0] = createArrayBuffer<fggl::data::Vertex>( mesh.vertexList() );
-	glEnableVertexAttribArray(0);
-	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(fggl::data::Vertex), reinterpret_cast<void*>(offsetof(fggl::data::Vertex, posititon)));
-	glEnableVertexAttribArray(1);
-	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(fggl::data::Vertex), reinterpret_cast<void*>(offsetof(fggl::data::Vertex, normal)));
-
-	token.buffs[1] = createIndexBuffer( mesh.indexList() );
-	token.idxOffset = 0;
-	token.idxSize = mesh.indexCount();
-    token.restartVertex = mesh.restartVertex;
-	glBindVertexArray(0);
-
-	return token;
+  GlRenderToken token{};
+  glGenVertexArrays(1, &token.vao);
+  glBindVertexArray(token.vao);
+
+  token.buffs[0] = createArrayBuffer<fggl::data::Vertex>(mesh.vertexList());
+  glEnableVertexAttribArray(0);
+  glVertexAttribPointer(
+      0, 3, GL_FLOAT, GL_FALSE, sizeof(fggl::data::Vertex),
+      reinterpret_cast<void*>(offsetof(fggl::data::Vertex, posititon)));
+  glEnableVertexAttribArray(1);
+  glVertexAttribPointer(
+      1, 3, GL_FLOAT, GL_FALSE, sizeof(fggl::data::Vertex),
+      reinterpret_cast<void*>(offsetof(fggl::data::Vertex, normal)));
+
+  token.buffs[1] = createIndexBuffer(mesh.indexList());
+  token.idxOffset = 0;
+  token.idxSize = mesh.indexCount();
+  token.restartVertex = mesh.restartVertex;
+  glBindVertexArray(0);
+
+  return token;
 }
 
-//TODO(webpigeon): this shouldn't be hard-coded
+// TODO(webpigeon): this shouldn't be hard-coded
 constexpr glm::vec3 DEFAULT_LIGHTPOS = glm::vec3(20.0F, 20.0F, 15.0F);
 
-void MeshRenderer::render(fggl::ecs3::World& ecs, ecs3::entity_t camera, float dt) {
-    if ( camera == ecs::NULL_ENTITY ){
-        spdlog::warn("tried to render a scene, but no camera exists!");
-        return;
-    }
-
-    auto entities = ecs.findMatching<GlRenderToken>();
-    if ( entities.empty() ) {
-        spdlog::warn("asked to render, but no entities are renderable");
-        return;
-    }
-
-    total += dt;
-
-    glEnable(GL_CULL_FACE);
-    glCullFace(GL_BACK);
-
-    glEnable(GL_DEPTH_TEST);
-
-    // camera logic
-    auto *const camTransform = ecs.get<math::Transform>(camera);
-    auto *const camComp = ecs.get<gfx::Camera>(camera);
-    glm::mat4 proj = glm::perspective( camComp->fov, camComp->aspectRatio, camComp->nearPlane, camComp->farPlane);
-    glm::mat4 view = glm::lookAt( camTransform->origin(), camComp->target, camTransform->up() );
+void MeshRenderer::render(fggl::ecs3::World& ecs, ecs3::entity_t camera,
+                          float dt) {
+  if (camera == ecs::NULL_ENTITY) {
+    spdlog::warn("tried to render a scene, but no camera exists!");
+    return;
+  }
+
+  auto entities = ecs.findMatching<GlRenderToken>();
+  if (entities.empty()) {
+    spdlog::warn("asked to render, but no entities are renderable");
+    return;
+  }
+
+  total += dt;
+
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+
+  glEnable(GL_DEPTH_TEST);
+
+  // camera logic
+  auto* const camTransform = ecs.get<math::Transform>(camera);
+  auto* const camComp = ecs.get<gfx::Camera>(camera);
+  glm::mat4 proj = glm::perspective(camComp->fov, camComp->aspectRatio,
+                                    camComp->nearPlane, camComp->farPlane);
+  glm::mat4 view =
+      glm::lookAt(camTransform->origin(), camComp->target, camTransform->up());
+
+  // lighting
+  glm::vec3 lightPos = DEFAULT_LIGHTPOS;
+
+  // TODO(webpigeon): better performance if grouped by vao first
+  // TODO(webpigeon): the nvidia performance presentation said I shouldn't use
+  // uniforms for large data
+  for (auto& entity : entities) {
+    const auto& transform = ecs.get<fggl::math::Transform>(entity);
+    const auto& mesh = ecs.get<GlRenderToken>(entity);
+
+    glm::mat4 model = transform->model();
+    //	    model = glm::rotate(model, glm::radians(total/2048.0f * 360.0f),
+    //glm::vec3(0.0f,1.0f,0.0f));
+
+    auto shader = mesh->pipeline;
+    glUseProgram(shader);
+
+    glUniformMatrix4fv(glGetUniformLocation(shader, "model"), 1, GL_FALSE,
+                       glm::value_ptr(model));
+    glUniformMatrix4fv(glGetUniformLocation(shader, "view"), 1, GL_FALSE,
+                       glm::value_ptr(view));
+    glUniformMatrix4fv(glGetUniformLocation(shader, "projection"), 1, GL_FALSE,
+                       glm::value_ptr(proj));
 
     // lighting
-    glm::vec3 lightPos = DEFAULT_LIGHTPOS;
-
-    // TODO(webpigeon): better performance if grouped by vao first
-    // TODO(webpigeon): the nvidia performance presentation said I shouldn't use uniforms for large data
-    for ( auto& entity : entities ) {
-	    const auto& transform = ecs.get<fggl::math::Transform>(entity);
-	    const auto& mesh = ecs.get<GlRenderToken>(entity);
-
-	    glm::mat4 model = transform->model();
-//	    model = glm::rotate(model, glm::radians(total/2048.0f * 360.0f), glm::vec3(0.0f,1.0f,0.0f));
-
-	    auto shader = mesh->pipeline;
-	    glUseProgram( shader );
-
-	    glUniformMatrix4fv( glGetUniformLocation(shader, "model"), 1, GL_FALSE, glm::value_ptr( model ) );
-	    glUniformMatrix4fv( glGetUniformLocation(shader, "view"), 1, GL_FALSE, glm::value_ptr( view ) );
-	    glUniformMatrix4fv( glGetUniformLocation(shader, "projection"), 1, GL_FALSE, glm::value_ptr( proj ) );
-
-	    // lighting
-	    GLint lightID = glGetUniformLocation(shader, "lightPos");
-	    if ( lightID != -1 ) {
-		    glUniform3fv( lightID, 1, glm::value_ptr( lightPos ) );
-	    }
+    GLint lightID = glGetUniformLocation(shader, "lightPos");
+    if (lightID != -1) {
+      glUniform3fv(lightID, 1, glm::value_ptr(lightPos));
+    }
 
-	    glBindVertexArray( mesh->vao );
+    glBindVertexArray(mesh->vao);
 
-        if ( mesh->renderType == GlRenderType::triangle_strip) {
-            glEnable(GL_PRIMITIVE_RESTART);
-            glPrimitiveRestartIndex(mesh->restartVertex);
-        }
+    if (mesh->renderType == GlRenderType::triangle_strip) {
+      glEnable(GL_PRIMITIVE_RESTART);
+      glPrimitiveRestartIndex(mesh->restartVertex);
+    }
 
-        glDrawElements( mesh->renderType, mesh->idxSize, GL_UNSIGNED_INT, reinterpret_cast<void*>(mesh->idxOffset) );
-        if ( mesh->renderType == GlRenderType::triangle_strip) {
-            glDisable(GL_PRIMITIVE_RESTART);
-        }
+    glDrawElements(mesh->renderType, mesh->idxSize, GL_UNSIGNED_INT,
+                   reinterpret_cast<void*>(mesh->idxOffset));
+    if (mesh->renderType == GlRenderType::triangle_strip) {
+      glDisable(GL_PRIMITIVE_RESTART);
     }
+  }
 
-    glBindVertexArray(0);
+  glBindVertexArray(0);
 }
 
-}
+}  // namespace fggl::gfx
diff --git a/fggl/gfx/window.cpp b/fggl/gfx/window.cpp
index 4c6b21c..c5097c3 100644
--- a/fggl/gfx/window.cpp
+++ b/fggl/gfx/window.cpp
@@ -250,4 +250,9 @@ void GlfwWindow::activate() const {
 	assert( m_window != nullptr );
 	glfwMakeContextCurrent(m_window);
 }
-
+fggl::math::vec2i GlfwWindow::frameSize() const {
+  assert( m_window != nullptr );
+  math::vec2i size;
+  glfwGetFramebufferSize(m_window, &size.x, &size.y);
+  return size;
+}
diff --git a/include/fggl/app.hpp b/include/fggl/app.hpp
index 160a58e..6b9732a 100644
--- a/include/fggl/app.hpp
+++ b/include/fggl/app.hpp
@@ -36,108 +36,110 @@
 
 namespace fggl {
 
-    class App;
-    class AppState;
-
-    using Identifer = std::string;
-    using AppMachine = util::StateMachine<AppState, Identifer>;
-
-    class AppState {
-        public:
-            /**
-             * Create an Application State.
-             *
-             * A state is responsible for managing user interaction with the app. When created, the appstate
-             * is passed a reference to the application that owns it. The lifetime of the state is bounded
-             * by the lifetype of this object.
-             *
-             * @param owner a non-owned reference to the owner of the state.
-             */
-            explicit AppState(App& owner) : m_owner( owner ) {}
-
-            /**
-             * Update the underlying model of this state.
-             *
-             * States should not assume that one update means one render call, as the game loop may issue
-             * multiple updates per render or vice-versa depending on requriements. Update is intended for
-             * dispatching game-system related infomation.
-             */
-            virtual void update() = 0;
-
-            /**
-             * Perform actions neccerary for rendering the scene.
-             * 
-             * When this method is invoked it is safe to assume that rendering of some form will take place
-             * after it returns and the rendering state should be updated to reflect this. The rendering
-             * environment will be passed in as an argument.
-             *
-             * It is not safe to assume the render target will always be the same, as the scene may be
-             * rendered in mutliple passes (eg, for VR requirements).
-             */
-            virtual void render(gfx::Paint& paint) = 0;
-
-            virtual void activate() {}
-            virtual void deactivate() {}
-
-        protected:
-            App& m_owner;
-    };
-
-    class App {
-        public:
-            explicit App(const Identifer& name);
-            App(const Identifer& name, const Identifer& folderName);
-
-            // class is non copy-able
-            App(const App& app) = delete;
-            App& operator=(App other) = delete;
-
-            inline void setWindow( std::unique_ptr<gfx::Window>&& window ) {
-                m_window = std::move(window);
-            }
-
-            /**
-             * Perform main game loop functions.
-             */
-            int run(int argc, const char** argv);
-
-            template<typename T>
-            T* add_state(const Identifer& name) {
-                static_assert( std::is_base_of<AppState,T>::value, "States must be AppStates");
-                return m_states.put<T>(name, *this);
-            }
-
-            template<typename T, typename... Args>
-            T& use(Args&& ...args) {
-                auto ptr = m_modules->load<T>(args...);
-                return *ptr;
-            }
-
-            inline void change_state(const Identifer& name) {
-                m_states.active().deactivate();
-                m_states.change(name);
-                m_states.active().activate();
-            }
-
-            inline AppState& active_state() const {
-                return m_states.active();
-            }
-
-            inline bool running() const {
-                return m_running;
-            }
-
-            inline void running(bool state) {
-                m_running = state;
-            }
-
-        private:
-            bool m_running;
-            std::unique_ptr<ecs3::TypeRegistry> m_types;
-            std::unique_ptr<ecs3::ModuleManager> m_modules;
-            std::unique_ptr<gfx::Window> m_window;
-            AppMachine m_states;
-    };
+	class App;
+
+	class AppState;
+
+	using Identifer = std::string;
+	using AppMachine = util::StateMachine<AppState, Identifer>;
+
+	class AppState {
+		public:
+			/**
+			 * Create an Application State.
+			 *
+			 * A state is responsible for managing user interaction with the app. When created, the appstate
+			 * is passed a reference to the application that owns it. The lifetime of the state is bounded
+			 * by the lifetype of this object.
+			 *
+			 * @param owner a non-owned reference to the owner of the state.
+			 */
+			explicit AppState(App &owner) : m_owner(owner) {}
+
+			/**
+			 * Update the underlying model of this state.
+			 *
+			 * States should not assume that one update means one render call, as the game loop may issue
+			 * multiple updates per render or vice-versa depending on requriements. Update is intended for
+			 * dispatching game-system related infomation.
+			 */
+			virtual void update() = 0;
+
+			/**
+			 * Perform actions neccerary for rendering the scene.
+			 *
+			 * When this method is invoked it is safe to assume that rendering of some form will take place
+			 * after it returns and the rendering state should be updated to reflect this. The rendering
+			 * environment will be passed in as an argument.
+			 *
+			 * It is not safe to assume the render target will always be the same, as the scene may be
+			 * rendered in mutliple passes (eg, for VR requirements).
+			 */
+			virtual void render(gfx::Paint &paint) = 0;
+
+			virtual void activate() {}
+
+			virtual void deactivate() {}
+
+		protected:
+			App &m_owner;
+	};
+
+	class App {
+		public:
+			explicit App(const Identifer &name);
+			App(const Identifer &name, const Identifer &folderName);
+
+			// class is non copy-able
+			App(const App &app) = delete;
+			App &operator=(App other) = delete;
+
+			inline void setWindow(std::unique_ptr<gfx::Window> &&window) {
+				m_window = std::move(window);
+			}
+
+			/**
+			 * Perform main game loop functions.
+			 */
+			int run(int argc, const char **argv);
+
+			template<typename T>
+			T *add_state(const Identifer &name) {
+				static_assert(std::is_base_of<AppState, T>::value, "States must be AppStates");
+				return m_states.put<T>(name, *this);
+			}
+
+			template<typename T, typename... Args>
+			T &use(Args &&...args) {
+				auto ptr = m_modules->load<T>(args...);
+				return *ptr;
+			}
+
+			inline void change_state(const Identifer &name) {
+				m_states.active().deactivate();
+				m_states.change(name);
+				m_states.active().activate();
+			}
+
+			inline AppState &active_state() const {
+				return m_states.active();
+			}
+
+			inline bool running() const {
+				return m_running;
+			}
+
+			inline void running(bool state) {
+				m_running = state;
+			}
+
+		private:
+			bool m_running;
+			std::unique_ptr<ecs3::TypeRegistry> m_types;
+			std::unique_ptr<ecs3::ModuleManager> m_modules;
+			std::unique_ptr<gfx::Window> m_window;
+			AppMachine m_states;
+	};
 
 }
 
diff --git a/include/fggl/data/heightmap.h b/include/fggl/data/heightmap.h
index 48908bd..5043b24 100644
--- a/include/fggl/data/heightmap.h
+++ b/include/fggl/data/heightmap.h
@@ -9,36 +9,35 @@
 
 namespace fggl::data {
 
-    constexpr std::size_t heightMaxX = 255;
-    constexpr std::size_t heightMaxZ = 255;
-    constexpr float heightSeaLevel = 0.0f;
-
-    struct HeightMap {
-        constexpr static const char name[] = "Heightmap";
-        float heightValues[heightMaxX * heightMaxZ];
-
-        void clear() {
-            for (float & heightValue : heightValues){
-                heightValue = heightSeaLevel;
-            }
-        }
-
-        [[nodiscard]]
-        inline float getValue(std::size_t x, std::size_t z) const {
-            return heightValues[x * heightMaxZ + z];
-        }
-
-        inline void setValue(std::size_t x, std::size_t z, float value) {
-            heightValues[x * heightMaxZ + z] = value;
-        }
-    };
-
-
-    inline int idx(int x, int z, int zMax) {
-        return x * zMax + z;
-    }
-
-    void generateHeightMesh(const data::HeightMap* heights, data::Mesh &mesh);
+	constexpr std::size_t heightMaxX = 255;
+	constexpr std::size_t heightMaxZ = 255;
+	constexpr float heightSeaLevel = 0.0f;
+
+	struct HeightMap {
+		constexpr static const char name[] = "Heightmap";
+		float heightValues[heightMaxX * heightMaxZ];
+
+		void clear() {
+			for (float &heightValue : heightValues) {
+				heightValue = heightSeaLevel;
+			}
+		}
+
+		[[nodiscard]]
+		inline float getValue(std::size_t x, std::size_t z) const {
+			return heightValues[x * heightMaxZ + z];
+		}
+
+		inline void setValue(std::size_t x, std::size_t z, float value) {
+			heightValues[x * heightMaxZ + z] = value;
+		}
+	};
+
+	inline int idx(int x, int z, int zMax) {
+		return x * zMax + z;
+	}
+
+	void generateHeightMesh(const data::HeightMap *heights, data::Mesh &mesh);
 }
 
 #endif //FGGL_HEIGHTMAP_H
diff --git a/include/fggl/data/model.hpp b/include/fggl/data/model.hpp
index 955231a..f59db12 100644
--- a/include/fggl/data/model.hpp
+++ b/include/fggl/data/model.hpp
@@ -13,41 +13,41 @@ namespace fggl::data {
 		math::vec3 colour;
 	};
 
-    struct Vertex2D{
-        fggl::math::vec2 position;
-        fggl::math::vec3 colour;
-    };
+	struct Vertex2D {
+		fggl::math::vec2 position;
+		fggl::math::vec3 colour;
+	};
 
-    struct Mesh2D {
-        std::vector<Vertex2D> vertexList;
-        std::vector<uint32_t> indexList;
+	struct Mesh2D {
+		std::vector<Vertex2D> vertexList;
+		std::vector<uint32_t> indexList;
 
-        inline std::size_t add_vertex(const Vertex2D& vertex) {
-            vertexList.push_back( vertex );
-            return vertexList.size() - 1;
-        }
+		inline std::size_t add_vertex(const Vertex2D &vertex) {
+			vertexList.push_back(vertex);
+			return vertexList.size() - 1;
+		}
 
-        inline void add_index(uint32_t idx) {
-            indexList.push_back( idx );
-        }
-    };
+		inline void add_index(uint32_t idx) {
+			indexList.push_back(idx);
+		}
+	};
 
 
 	// comparison operators
 
-	inline bool operator<(const Vertex& lhs, const Vertex& rhs) {
-		return std::tie( lhs.posititon, lhs.normal, lhs.colour )
-		     < std::tie( rhs.posititon, rhs.normal, rhs.colour );
+	inline bool operator<(const Vertex &lhs, const Vertex &rhs) {
+		return std::tie(lhs.posititon, lhs.normal, lhs.colour)
+			< std::tie(rhs.posititon, rhs.normal, rhs.colour);
 	}
 
-	inline bool operator==(const Vertex& lhs, const Vertex& rhs) {
+	inline bool operator==(const Vertex &lhs, const Vertex &rhs) {
 		return lhs.posititon == rhs.posititon
 			&& lhs.colour == rhs.colour
 			&& lhs.normal == rhs.normal;
 	}
 
-	inline bool operator!=(const Vertex& lhs, const Vertex& rhs) {
-		return !(lhs==rhs);
+	inline bool operator!=(const Vertex &lhs, const Vertex &rhs) {
+		return !(lhs == rhs);
 	}
 
 	class Mesh {
@@ -63,12 +63,12 @@ namespace fggl::data {
 			 */
 			inline void push(Vertex vert) {
 				auto idx = indexOf(vert);
-				if ( idx == -1 ) {
-                    idx = pushVertex(vert);
-                    pushIndex(idx);
-                } else {
-                    pushIndex(idx);
-                }
+				if (idx == -1) {
+					idx = pushVertex(vert);
+					pushIndex(idx);
+				} else {
+					pushIndex(idx);
+				}
 			}
 
 			/**
@@ -100,7 +100,7 @@ namespace fggl::data {
 			 */
 			int indexOf(Vertex vert);
 
-			inline std::vector<Vertex>& vertexList() {
+			inline std::vector<Vertex> &vertexList() {
 				return m_verts;
 			}
 
@@ -108,7 +108,7 @@ namespace fggl::data {
 				return m_verts.size();
 			}
 
-			inline std::vector<uint32_t>& indexList() {
+			inline std::vector<uint32_t> &indexList() {
 				return m_index;
 			}
 
@@ -116,10 +116,11 @@ namespace fggl::data {
 				return m_index.size();
 			}
 
-			inline Vertex& vertex(int idx) {
+			inline Vertex &vertex(int idx) {
 				return m_verts[idx];
 			}
-            unsigned int restartVertex;
+
+			unsigned int restartVertex;
 
 		private:
 			std::vector<Vertex> m_verts;
@@ -131,8 +132,8 @@ namespace fggl::data {
 			Model() = default;
 			~Model() = default;
 
-			inline void append(const Mesh& mesh) {
-				m_meshes.push_back( mesh );
+			inline void append(const Mesh &mesh) {
+				m_meshes.push_back(mesh);
 			}
 
 		private:
diff --git a/include/fggl/data/procedural.hpp b/include/fggl/data/procedural.hpp
index 35a2180..d8431a9 100644
--- a/include/fggl/data/procedural.hpp
+++ b/include/fggl/data/procedural.hpp
@@ -12,24 +12,28 @@ namespace fggl::data {
 	Mesh make_quad_xz();
 
 	// simple shapes
-	Mesh make_cube(Mesh& mesh, const math::mat4& offset);
-	inline Mesh make_cube(Mesh& mesh) {
+	Mesh make_cube(Mesh &mesh, const math::mat4 &offset);
+
+	inline Mesh make_cube(Mesh &mesh) {
 		return make_cube(mesh, OFFSET_NONE);
 	}
 
 	// blockout shapes
-	Mesh make_slope(Mesh& mesh, const math::mat4& offset);
-	inline Mesh make_slope(Mesh& mesh) {
+	Mesh make_slope(Mesh &mesh, const math::mat4 &offset);
+
+	inline Mesh make_slope(Mesh &mesh) {
 		return make_slope(mesh, OFFSET_NONE);
 	}
 
-	Mesh make_ditch(Mesh& mesh, const math::mat4& offset);
-	inline Mesh make_ditch(Mesh& mesh) {
+	Mesh make_ditch(Mesh &mesh, const math::mat4 &offset);
+
+	inline Mesh make_ditch(Mesh &mesh) {
 		return make_ditch(mesh, OFFSET_NONE);
 	}
 
-	Mesh make_point(Mesh& mesh, const math::mat4& offset);
-	inline Mesh make_point(Mesh& mesh) {
+	Mesh make_point(Mesh &mesh, const math::mat4 &offset);
+
+	inline Mesh make_point(Mesh &mesh) {
 		return make_point(mesh, OFFSET_NONE);
 	}
 }
diff --git a/include/fggl/data/procedure.hpp b/include/fggl/data/procedure.hpp
index 6354283..41843a1 100644
--- a/include/fggl/data/procedure.hpp
+++ b/include/fggl/data/procedure.hpp
@@ -9,7 +9,6 @@ namespace fggl::data {
 			DataRegistry();
 			~DataRegistry();
 
-			
 	};
 
 }
diff --git a/include/fggl/data/storage.hpp b/include/fggl/data/storage.hpp
index 98ab993..6ae22d0 100644
--- a/include/fggl/data/storage.hpp
+++ b/include/fggl/data/storage.hpp
@@ -8,50 +8,48 @@
 namespace fggl::data {
 
 	template<typename T>
-	bool fggl_serialize(std::filesystem::path& data, const T* out);
+	bool fggl_serialize(std::filesystem::path &data, const T *out);
 
 	template<typename T>
-	bool fggl_deserialize(std::filesystem::path& data, T* out);
+	bool fggl_deserialize(std::filesystem::path &data, T *out);
+
+	enum StorageType { Data, User, Cache };
 
-	enum StorageType {Data, User, Cache};
 	class Storage {
 
 		public:
 			template<typename T>
-			bool load(StorageType pool, const std::string& name, T* out) {
+			bool load(StorageType pool, const std::string &name, T *out) {
 				auto path = resolvePath(pool, name);
-				if ( !std::filesystem::exists(path) ) {
-                    //spdlog::warn("Path {} does not exist!", path.c_str());
+				if (!std::filesystem::exists(path)) {
+					//spdlog::warn("Path {} does not exist!", path.c_str());
 					return false;
 				}
 				return fggl_deserialize<T>(path, out);
 			}
 
 			template<typename T>
-			void save(StorageType pool, const std::string& name, const T* out) {
+			void save(StorageType pool, const std::string &name, const T *out) {
 				auto path = resolvePath(pool, name);
 				fggl_serialize<T>(path, out);
 			}
 
-			inline std::filesystem::path resolvePath(StorageType pool, const std::string& name) {
+			inline std::filesystem::path resolvePath(StorageType pool, const std::string &name) {
 				std::filesystem::path path;
 
-				switch ( pool ) {
-					case Data:
-						path = std::filesystem::current_path() / "data";
-						break;
-					case User:
-						path = "./user-data/";
-						break;
-					case Cache:
-						path = "/tmp/fggl/";
-						break;
+				switch (pool) {
+				case Data: path = std::filesystem::current_path() / "data";
+					break;
+				case User: path = "./user-data/";
+					break;
+				case Cache: path = "/tmp/fggl/";
+					break;
 				}
 
-				if ( !std::filesystem::exists(path) ) {
+				if (!std::filesystem::exists(path)) {
 					std::filesystem::create_directories(path);
 				}
-				
+
 				return path / name;
 			}
 	};
diff --git a/include/fggl/debug/debug.h b/include/fggl/debug/debug.h
index 2457733..88419fb 100644
--- a/include/fggl/debug/debug.h
+++ b/include/fggl/debug/debug.h
@@ -9,7 +9,7 @@
 
 namespace fggl::debug {
 
-	using DebugUIDraw = std::function<void(bool*)>;
+	using DebugUIDraw = std::function<void(bool *)>;
 
 	struct DebugWindow {
 		bool m_visible;
@@ -18,16 +18,16 @@ namespace fggl::debug {
 
 	class DebugUI {
 		public:
-			explicit DebugUI(std::shared_ptr<gfx::GlfwWindow>& window);
+			explicit DebugUI(std::shared_ptr<gfx::GlfwWindow> &window);
 			~DebugUI();
 
 			void frameStart();
 			void draw();
 
-			inline void addWindow(const std::string& name, DebugUIDraw window){
+			inline void addWindow(const std::string &name, DebugUIDraw window) {
 				m_windows[name] = DebugWindow{
 					.m_visible = true,
-						.m_callback = std::move(window)
+					.m_callback = std::move(window)
 				};
 			}
 
@@ -46,5 +46,4 @@ namespace fggl::debug {
 
 }
 
-
 #endif
diff --git a/include/fggl/ecs/component.hpp b/include/fggl/ecs/component.hpp
index 51edda3..4e0e491 100644
--- a/include/fggl/ecs/component.hpp
+++ b/include/fggl/ecs/component.hpp
@@ -17,20 +17,21 @@ namespace fggl::ecs {
 	class ComponentBase {
 		public:
 			using data_t = unsigned char;
+
 			virtual ~ComponentBase() {};
 
-            // in place
-			virtual void destroy(data_t* data) const = 0;
-			virtual void move(data_t* src, data_t* dest) const = 0;
-			virtual void bulkMove(data_t* src, data_t* dest, std::size_t count) = 0; 
-			virtual void construct(data_t* data) const = 0;
+			// in place
+			virtual void destroy(data_t *data) const = 0;
+			virtual void move(data_t *src, data_t *dest) const = 0;
+			virtual void bulkMove(data_t *src, data_t *dest, std::size_t count) = 0;
+			virtual void construct(data_t *data) const = 0;
 
-            // virtual
-            virtual void* construct() const = 0;
-            virtual void* copyConstruct(const void* src) = 0;
+			// virtual
+			virtual void *construct() const = 0;
+			virtual void *copyConstruct(const void *src) = 0;
 
-            virtual const char* name() const = 0;
-            virtual const component_type_t id() const = 0;
+			virtual const char *name() const = 0;
+			virtual const component_type_t id() const = 0;
 
 			virtual std::size_t size() const = 0;
 	};
@@ -38,47 +39,47 @@ namespace fggl::ecs {
 	template<class C>
 	class Component : public ComponentBase {
 		public:
-			virtual void destroy(data_t* data) const override {
-				C* location = std::launder(reinterpret_cast<C*>(data));
+			virtual void destroy(data_t *data) const override {
+				C *location = std::launder(reinterpret_cast<C *>(data));
 				location->~C();
 			}
 
-            virtual const char* name() const override {
-                return C::name;
-            }
+			virtual const char *name() const override {
+				return C::name;
+			}
 
-            virtual const component_type_t id() const {
-                return Component<C>::typeID();
-            }
+			virtual const component_type_t id() const {
+				return Component<C>::typeID();
+			}
 
-			virtual void construct(unsigned char* data) const override {
-				new (data) C();
+			virtual void construct(unsigned char *data) const override {
+				new(data) C();
 			}
 
-            void* copyConstruct(const void* src) override {
-                const C* srcPtr = (C*)src;
-                return new C(*srcPtr);
-            }
+			void *copyConstruct(const void *src) override {
+				const C *srcPtr = (C *) src;
+				return new C(*srcPtr);
+			}
 
-            void* construct() const override {
-                return new C();
-            }
+			void *construct() const override {
+				return new C();
+			}
 
-			virtual void move(data_t* src, data_t* dest) const override {
+			virtual void move(data_t *src, data_t *dest) const override {
 				assert(src != nullptr);
 				assert(dest != nullptr);
-				new (&dest[0]) C(std::move(*reinterpret_cast<C*>(src)));
+				new(&dest[0]) C(std::move(*reinterpret_cast<C *>(src)));
 			}
 
-			virtual void bulkMove(data_t* src, data_t* dest, std::size_t count) {
-				if ( std::is_trivially_copyable<C>::value ) {
-					std::memcpy( dest, src, count * size() );
+			virtual void bulkMove(data_t *src, data_t *dest, std::size_t count) {
+				if (std::is_trivially_copyable<C>::value) {
+					std::memcpy(dest, src, count * size());
 				} else {
-					unsigned char* srcPtr = src;
-					unsigned char* destPtr = dest;
+					unsigned char *srcPtr = src;
+					unsigned char *destPtr = dest;
 
-					for ( std::size_t i = 0; i < count; ++i ){
-						new (destPtr) C(std::move(*reinterpret_cast<C*>(srcPtr)));
+					for (std::size_t i = 0; i < count; ++i) {
+						new(destPtr) C(std::move(*reinterpret_cast<C *>(srcPtr)));
 						srcPtr += sizeof(C);
 						destPtr += sizeof(C);
 					}
diff --git a/include/fggl/ecs/ecs.hpp b/include/fggl/ecs/ecs.hpp
index e62b683..b467357 100644
--- a/include/fggl/ecs/ecs.hpp
+++ b/include/fggl/ecs/ecs.hpp
@@ -17,35 +17,35 @@ namespace fggl::ecs {
 	struct Archetype {
 		constexpr static unsigned int default_cap = 0;
 		const archToken_t type;
-		std::vector<ComponentBase::data_t*> data;
+		std::vector<ComponentBase::data_t *> data;
 		std::vector<std::size_t> dataSizes;
 		std::vector<entity_t> entities;
 
-		Archetype(const archToken_t& type_a);
+		Archetype(const archToken_t &type_a);
 
-		inline archToken_t create( const component_type_t cid ) const {
-			assert( !contains(cid) );
+		inline archToken_t create(const component_type_t cid) const {
+			assert(!contains(cid));
 
 			// create the new type
 			auto newType = type;
-			newType.push_back( cid );
-			std::sort( newType.begin(), newType.end() );
+			newType.push_back(cid);
+			std::sort(newType.begin(), newType.end());
 			return newType;
 		}
 
-		inline bool contains( const component_type_t cid ) const {
-			return ( std::find( type.begin(), type.end(), cid ) != type.end() );
+		inline bool contains(const component_type_t cid) const {
+			return (std::find(type.begin(), type.end(), cid) != type.end());
 		}
 	};
 
 	class ECS {
-		struct Record {
-			Archetype* archetype;
-			std::size_t index;
-		};
-		using componentmap_t = std::unordered_map<component_type_t, ComponentBase*>;
-		using entitymap_t = std::unordered_map<entity_t, Record>;
-		using archetype_t = std::vector<Archetype*>;
+			struct Record {
+				Archetype *archetype;
+				std::size_t index;
+			};
+			using componentmap_t = std::unordered_map<component_type_t, ComponentBase *>;
+			using entitymap_t = std::unordered_map<entity_t, Record>;
+			using archetype_t = std::vector<Archetype *>;
 
 		public:
 			ECS();
@@ -58,52 +58,52 @@ namespace fggl::ecs {
 			template<class C>
 			void registerComponent() {
 				component_type_t type = Component<C>::typeID();
-				if ( m_componentMap.find( type ) != m_componentMap.end() )
+				if (m_componentMap.find(type) != m_componentMap.end())
 					return;
-				m_componentMap.emplace( type, new Component<C> );
+				m_componentMap.emplace(type, new Component<C>);
 			}
 
 			template<class C>
 			bool isComponentRegistered() {
 				component_type_t type = Component<C>::typeID();
-				return ( m_componentMap.find(type) != m_componentMap.end() );
+				return (m_componentMap.find(type) != m_componentMap.end());
 			}
 
 			template<class C, typename... Args>
-			C* addComponent(const entity_t& id, Args&&... args) {
+			C *addComponent(const entity_t &id, Args &&... args) {
 				component_type_t type = Component<C>::typeID();
-				assert( isComponentRegistered<C>() );
+				assert(isComponentRegistered<C>());
 
-				Record& record = m_entityArchtypes[id];
-				Archetype* oldArch = record.archetype;
-				C* newComp = nullptr;
-				Archetype* newArch = nullptr;
+				Record &record = m_entityArchtypes[id];
+				Archetype *oldArch = record.archetype;
+				C *newComp = nullptr;
+				Archetype *newArch = nullptr;
 
-				if ( !oldArch ) {
+				if (!oldArch) {
 					archToken_t newID(1, type);
-					const ComponentBase* const newCompType = m_componentMap[ type ];
+					const ComponentBase *const newCompType = m_componentMap[type];
 
 					// fetch type
-					newArch = getArchetype( newID );
-					assert( newArch->type.size() == 1 );
+					newArch = getArchetype(newID);
+					assert(newArch->type.size() == 1);
 
 					// calculate if we have enouph space to allocate
-					std::size_t emplacementPos = ensureCapacity( newArch, 0, newCompType );
-					newComp = new (&newArch->data[0][emplacementPos])C(std::forward<Args>(args)...);
+					std::size_t emplacementPos = ensureCapacity(newArch, 0, newCompType);
+					newComp = new(&newArch->data[0][emplacementPos])C(std::forward<Args>(args)...);
 				} else {
 					// check if the arch contains the component
-					if ( oldArch->contains(type) ) {
+					if (oldArch->contains(type)) {
 						return nullptr;
 					}
 
 					// create a new archetype with the component
-					auto newID = oldArch->create( type );
-					newArch = getArchetype( newID );
+					auto newID = oldArch->create(type);
+					newArch = getArchetype(newID);
 
 					// relocate the old data to the new archetype
-					for ( std::size_t j=0; j < newID.size(); ++j ){
+					for (std::size_t j = 0; j < newID.size(); ++j) {
 						const component_type_t compType = newID[j];
-						const ComponentBase* const comp = m_componentMap.at(compType);
+						const ComponentBase *const comp = m_componentMap.at(compType);
 
 
 						// TODO this seems a little suspect - surely we could allocate all blocks at once?
@@ -111,81 +111,81 @@ namespace fggl::ecs {
 						int newOffset = ensureCapacity(newArch, j, comp);
 						int oldIdx = getComponentIdx(oldArch, compType);
 
-						if ( oldIdx != -1 ) {
-							assert( oldArch->contains(compType) );
+						if (oldIdx != -1) {
+							assert(oldArch->contains(compType));
 							const std::size_t compSize = comp->size();
 							const std::size_t oldOffset = record.index * compSize;
 
-							comp->move( &oldArch->data[oldIdx][oldOffset],
-								    &newArch->data[j][newOffset] );
-							comp->destroy( &oldArch->data[oldIdx][oldOffset] );
+							comp->move(&oldArch->data[oldIdx][oldOffset],
+									   &newArch->data[j][newOffset]);
+							comp->destroy(&oldArch->data[oldIdx][oldOffset]);
 						} else {
-							assert( !oldArch->contains(compType) );
-							newComp = new (&newArch->data[j][newOffset])
-									C(std::forward<Args>(args)...);
+							assert(!oldArch->contains(compType));
+							newComp = new(&newArch->data[j][newOffset])
+								C(std::forward<Args>(args)...);
 						}
 					}
 
 					// ensure the old archetype is still contigious
 					const int lastEnt = oldArch->entities.size() - 1;
-					if ( lastEnt != record.index )  {
-						for ( std::size_t i=0;  i < oldArch->type.size(); ++i ) {
+					if (lastEnt != record.index) {
+						for (std::size_t i = 0; i < oldArch->type.size(); ++i) {
 							const component_type_t typeID = oldArch->type[i];
-							const ComponentBase* const comp = m_componentMap[typeID];
-							const std::size_t& compSize = comp->size();
+							const ComponentBase *const comp = m_componentMap[typeID];
+							const std::size_t &compSize = comp->size();
 
 							// shift the empty record to the end of the list
 							std::size_t slotOffset = record.index * compSize;
 							std::size_t lastOffset = lastEnt * compSize;
 
 							// if we're not the last entity, swap
-							if ( slotOffset != lastOffset ) {
-								comp->move( &oldArch->data[i][lastOffset],
-									    &oldArch->data[i][slotOffset] );
-								comp->destroy( &oldArch->data[i][lastOffset] );
+							if (slotOffset != lastOffset) {
+								comp->move(&oldArch->data[i][lastOffset],
+										   &oldArch->data[i][slotOffset]);
+								comp->destroy(&oldArch->data[i][lastOffset]);
 							}
 						}
 
 						// fix the position
-						oldArch->entities[ record.index ] = oldArch->entities[ lastEnt ];
+						oldArch->entities[record.index] = oldArch->entities[lastEnt];
 					}
 					oldArch->entities.pop_back();
 				}
 
 				// register the new data with the new archetype
-				newArch->entities.push_back( id );
+				newArch->entities.push_back(id);
 				record.index = newArch->entities.size() - 1;
 				record.archetype = newArch;
 				return newComp;
 			}
 
 			template<class C>
-			void removeComponent(const entity_t& entityId);
+			void removeComponent(const entity_t &entityId);
 
 			template<class C>
-			bool hasComponent(const entity_t& entityId) const {
+			bool hasComponent(const entity_t &entityId) const {
 				const component_type_t componentID = Component<C>::typeID();
-				const auto* arch = m_entityArchtypes.at(entityId).archetype;
-				if ( arch == nullptr ) {
+				const auto *arch = m_entityArchtypes.at(entityId).archetype;
+				if (arch == nullptr) {
 					return false;
 				}
-				return ( std::find( arch->type.begin(), arch->type.end(), componentID) !=
-						arch->type.end() );
+				return (std::find(arch->type.begin(), arch->type.end(), componentID) !=
+					arch->type.end());
 			}
 
 			template<class C>
-			C* getComponent(const entity_t& entityId) {
-				assert( hasComponent<C>( entityId ) );
+			C *getComponent(const entity_t &entityId) {
+				assert(hasComponent<C>(entityId));
 				const auto type = Component<C>::typeID();
 
-				const ComponentBase* const newComp = m_componentMap[type];
+				const ComponentBase *const newComp = m_componentMap[type];
 				const auto record = m_entityArchtypes.at(entityId);
-				const auto* arch = record.archetype;
+				const auto *arch = record.archetype;
 
 				// JWR: linear search... seems a little suspect, they're ordered after all
-				for ( std::size_t i=0; i < arch->type.size(); ++i ) {
-					if ( arch->type[i] == type ) {
-						return reinterpret_cast<C*>(& (arch->data[i][ record.index * newComp->size() ]) );
+				for (std::size_t i = 0; i < arch->type.size(); ++i) {
+					if (arch->type[i] == type) {
+						return reinterpret_cast<C *>(&(arch->data[i][record.index * newComp->size()]));
 					}
 				}
 
@@ -193,75 +193,75 @@ namespace fggl::ecs {
 			}
 
 			template<class C>
-			const C* getComponent(const entity_t& entityId) const {
-                assert( hasComponent<C>( entityId ) );
-                const auto type = Component<C>::typeID();
-
-                const ComponentBase* const newComp = m_componentMap.at(type);
-                const auto record = m_entityArchtypes.at(entityId);
-                const auto* arch = record.archetype;
-
-                // JWR: linear search... seems a little suspect, they're ordered after all
-                for ( std::size_t i=0; i < arch->type.size(); ++i ) {
-                    if ( arch->type[i] == type ) {
-                        return reinterpret_cast<C*>(& (arch->data[i][ record.index * newComp->size() ]) );
-                    }
-                }
-
-                return nullptr;
+			const C *getComponent(const entity_t &entityId) const {
+				assert(hasComponent<C>(entityId));
+				const auto type = Component<C>::typeID();
+
+				const ComponentBase *const newComp = m_componentMap.at(type);
+				const auto record = m_entityArchtypes.at(entityId);
+				const auto *arch = record.archetype;
+
+				// JWR: linear search... seems a little suspect, they're ordered after all
+				for (std::size_t i = 0; i < arch->type.size(); ++i) {
+					if (arch->type[i] == type) {
+						return reinterpret_cast<C *>(&(arch->data[i][record.index * newComp->size()]));
+					}
+				}
+
+				return nullptr;
 			}
 
 			template<class... Cs>
 			std::vector<entity_t> getEntityWith() const {
 				// construct the key
 				archToken_t key;
-				(key.push_back( Component<Cs>::typeID() ), ...);
+				(key.push_back(Component<Cs>::typeID()), ...);
 
 				// entities
 				std::vector<entity_t> entities;
-				for ( Archetype* arch : m_archetypes ) {
-					if ( std::includes( arch->type.begin(), arch->type.end(), key.begin(), key.end() ) ) {
-						if( !arch->entities.empty() ) {
-							entities.insert( entities.begin(), arch->entities.begin(), arch->entities.end() );
+				for (Archetype *arch : m_archetypes) {
+					if (std::includes(arch->type.begin(), arch->type.end(), key.begin(), key.end())) {
+						if (!arch->entities.empty()) {
+							entities.insert(entities.begin(), arch->entities.begin(), arch->entities.end());
 						}
 					}
 				}
 
 				return entities;
 			}
-			
+
 		private:
 			entitymap_t m_entityArchtypes;
 			archetype_t m_archetypes;
 			entity_t m_entityIDCounter;
 			componentmap_t m_componentMap;
-			Archetype* getArchetype(const archToken_t& id);
+			Archetype *getArchetype(const archToken_t &id);
 
-			inline std::string arch2str(Archetype* arch) {
+			inline std::string arch2str(Archetype *arch) {
 				std::string str;
-				for ( const auto& type : arch->type ) {
-					str += std::to_string( type );
+				for (const auto &type : arch->type) {
+					str += std::to_string(type);
 				}
 				return str;
 			}
 
-			inline std::size_t ensureCapacity(Archetype* arch, const int idx, const ComponentBase* const comp) {
-				const std::size_t& compSize = comp->size();
+			inline std::size_t ensureCapacity(Archetype *arch, const int idx, const ComponentBase *const comp) {
+				const std::size_t &compSize = comp->size();
 				std::size_t currSize = arch->entities.size() * compSize;
 				std::size_t newSize = currSize + compSize;
 
 				std::size_t cap = arch->dataSizes[idx];
 
-				if ( newSize > arch->dataSizes[idx] ) {
+				if (newSize > arch->dataSizes[idx]) {
 					arch->dataSizes[idx] *= 2;
 					arch->dataSizes[idx] += compSize;
 
 					// copy data over
-					unsigned char* newData = new unsigned char[arch->dataSizes[idx]];
-					for ( std::size_t e=0; e<arch->entities.size(); ++e ) {
+					unsigned char *newData = new unsigned char[arch->dataSizes[idx]];
+					for (std::size_t e = 0; e < arch->entities.size(); ++e) {
 						const int offset = e * compSize;
-						comp->move( &arch->data[idx][offset], &newData[offset] );
-						comp->destroy( &arch->data[idx][offset] );
+						comp->move(&arch->data[idx][offset], &newData[offset]);
+						comp->destroy(&arch->data[idx][offset]);
 					}
 
 					// free the old data and swap the pointers
@@ -272,10 +272,11 @@ namespace fggl::ecs {
 				return currSize;
 			}
 
-			inline int getComponentIdx(const Archetype* arch, const component_type_t goal) {
+			inline int getComponentIdx(const Archetype *arch, const component_type_t goal) {
 				// JWR could do binary search for speedup
-				for ( std::size_t i=0; i < arch->type.size(); ++i ) {
-					if ( arch->type[i] == goal ) return i;
+				for (std::size_t i = 0; i < arch->type.size(); ++i) {
+					if (arch->type[i] == goal)
+						return i;
 				}
 				return -1;
 			}
diff --git a/include/fggl/ecs/utility.hpp b/include/fggl/ecs/utility.hpp
index 323074e..7906e4f 100644
--- a/include/fggl/ecs/utility.hpp
+++ b/include/fggl/ecs/utility.hpp
@@ -22,6 +22,7 @@ namespace fggl::ecs {
 				return idCounter;
 			}
 	};
+
 	template<class T> IDType TypeIdGenerator<T>::m_count = 0;
 }
 
diff --git a/include/fggl/ecs3/ecs.hpp b/include/fggl/ecs3/ecs.hpp
index b920ca6..bdd1fe0 100644
--- a/include/fggl/ecs3/ecs.hpp
+++ b/include/fggl/ecs3/ecs.hpp
@@ -6,7 +6,7 @@
 
 namespace fggl::ecs3 {
 
-    using World = prototype::World;
+	using World = prototype::World;
 
 }
 
diff --git a/include/fggl/ecs3/fast/Container.h b/include/fggl/ecs3/fast/Container.h
index 6910cc4..4b6a529 100644
--- a/include/fggl/ecs3/fast/Container.h
+++ b/include/fggl/ecs3/fast/Container.h
@@ -13,92 +13,91 @@
 
 namespace fggl::ecs3 {
 
-
-    class Container {
-    public:
-        const RecordIdentifier m_identifier;
-        Container(const TypeRegistry& reg, RecordIdentifier id) :
-            m_types(reg),
-            m_identifier( id ),
-            backingStore(nullptr),
-            m_capacity(0),
-            m_size(0) {
-        };
-
-        ~Container() {
-            delete[] backingStore;
-        }
-
-        std::size_t create();
-
-        void remove(std::size_t pos);
-
-        std::size_t expand(Container& other, std::size_t otherPos, component_type_t newComp);
-
-        void contract(Container& other, std::size_t otherPos);
-
-        void ensure(std::size_t size);
-
-        inline unsigned char* data_raw(component_type_t type) {
-            auto seek_id = m_identifier.idx(type);
-
-            // you asked for something I don't contain...
-            if ( seek_id == m_identifier.count ) {
-                std::cerr << "asked for " << type << " from " << m_identifier << std::endl;
-                assert( seek_id != m_identifier.count );
-                return nullptr;
-            }
-
-            // figure out the offset
-            return backingStore + offsets[seek_id];
-        }
-
-        template<typename T>
-        inline T* data() {
-            auto comp_id = Component<T>::typeID();
-            return (T*)data_raw(comp_id);
-        }
-
-        template<typename T>
-        T* set(std::size_t entity, T* compData) {
-            auto* comps = data<T>();
-            auto entityPos = idx(entity);
-
-            auto compMeta = m_types.template meta<T>();
-
-            unsigned char* usrPtr = (unsigned char*)&comps[entityPos];
-            compMeta->destroy(usrPtr);
-            compMeta->move((unsigned char*)compData, usrPtr);
-
-            return &comps[entityPos];
-        }
-
-        [[nodiscard]]
-        inline std::size_t size() const {
-            return m_size;
-        }
-
-        inline std::size_t idx(entity_t entity) {
-            auto* entityData = data<EntityMeta>();
-            for (int i=0; i<m_size; i++) {
-                if ( entityData[i].id == entity ) {
-                    return i;
-                }
-            }
-            return m_size;
-        }
-
-    private:
-        const TypeRegistry& m_types;
-        unsigned char* backingStore;
-        std::size_t offsets[RecordIdentifier::MAX_COMPS]{};
-        std::size_t m_size;
-        std::size_t m_capacity;
-
-        void move(std::size_t newPos, Container& oldContainer, std::size_t oldPos);
-    };
+	class Container {
+		public:
+			const RecordIdentifier m_identifier;
+
+			Container(const TypeRegistry &reg, RecordIdentifier id) :
+				m_types(reg),
+				m_identifier(id),
+				backingStore(nullptr),
+				m_capacity(0),
+				m_size(0) {
+			};
+
+			~Container() {
+				delete[] backingStore;
+			}
+
+			std::size_t create();
+
+			void remove(std::size_t pos);
+
+			std::size_t expand(Container &other, std::size_t otherPos, component_type_t newComp);
+
+			void contract(Container &other, std::size_t otherPos);
+
+			void ensure(std::size_t size);
+
+			inline unsigned char *data_raw(component_type_t type) {
+				auto seek_id = m_identifier.idx(type);
+
+				// you asked for something I don't contain...
+				if (seek_id == m_identifier.count) {
+					std::cerr << "asked for " << type << " from " << m_identifier << std::endl;
+					assert(seek_id != m_identifier.count);
+					return nullptr;
+				}
+
+				// figure out the offset
+				return backingStore + offsets[seek_id];
+			}
+
+			template<typename T>
+			inline T *data() {
+				auto comp_id = Component<T>::typeID();
+				return (T *) data_raw(comp_id);
+			}
+
+			template<typename T>
+			T *set(std::size_t entity, T *compData) {
+				auto *comps = data<T>();
+				auto entityPos = idx(entity);
+
+				auto compMeta = m_types.template meta<T>();
+
+				unsigned char *usrPtr = (unsigned char *) &comps[entityPos];
+				compMeta->destroy(usrPtr);
+				compMeta->move((unsigned char *) compData, usrPtr);
+
+				return &comps[entityPos];
+			}
+
+			[[nodiscard]]
+			inline std::size_t size() const {
+				return m_size;
+			}
+
+			inline std::size_t idx(entity_t entity) {
+				auto *entityData = data<EntityMeta>();
+				for (int i = 0; i < m_size; i++) {
+					if (entityData[i].id == entity) {
+						return i;
+					}
+				}
+				return m_size;
+			}
+
+		private:
+			const TypeRegistry &m_types;
+			unsigned char *backingStore;
+			std::size_t offsets[RecordIdentifier::MAX_COMPS]{};
+			std::size_t m_size;
+			std::size_t m_capacity;
+
+			void move(std::size_t newPos, Container &oldContainer, std::size_t oldPos);
+	};
 
 }
 
-
 #endif //FGGL_ECS3_CONTAINER_H
diff --git a/include/fggl/ecs3/fast/ecs.hpp b/include/fggl/ecs3/fast/ecs.hpp
index 3d4ea7c..542106c 100644
--- a/include/fggl/ecs3/fast/ecs.hpp
+++ b/include/fggl/ecs3/fast/ecs.hpp
@@ -17,121 +17,121 @@
 
 namespace fggl::ecs3::fast {
 
-    using entity_t = unsigned int;
-    constexpr entity_t NULL_ENTITY = 0;
-
-    class World {
-        public:
-            explicit World(TypeRegistry& reg) : m_registry(reg), m_last(NULL_ENTITY) {}
-
-            entity_t create() {
-                auto next = m_last++;
-
-                auto arch = make_id(1, Component<EntityMeta>::typeID());
-                auto& container = getContainer(arch);
-
-                m_entities[next] = container.m_identifier;
-
-                auto pos = container.create();
-                auto* entityMeta = container.data<EntityMeta>();
-                entityMeta[pos].id = next;
-
-                return next;
-            }
-
-            void remove(entity_t entity) {
-                auto arch = m_entities.at(entity);
-                auto container = m_records.at(arch);
-
-                auto entPos = container.idx(entity);
-                container.remove(entPos);
-            }
-
-            inline Container& getContainer(RecordIdentifier& arch) {
-                try {
-                    return m_records.at(arch);
-                } catch (std::out_of_range& e) {
-                    auto v = m_records.emplace(std::pair<RecordIdentifier, Container>(arch, {m_registry, arch}));
-                    return v.first->second;
-                }
-            }
-
-            template<typename T>
-            T* add(const entity_t entity){
-                auto currArch = m_entities.at( entity );
-                auto newArch = currArch.with<T>();
-                m_entities[entity] = newArch;
-
-                auto& oldContainer = m_records.at(currArch);
-                auto& newContainer = getContainer(newArch);
-
-                auto oldPos = oldContainer.idx(entity);
-
-                auto newPos = newContainer.expand(oldContainer, oldPos, Component<T>::typeID());
-                auto* data = newContainer.template data<T>();
-                return &data[newPos];
-            }
-
-            template<typename T>
-            T* set(const entity_t entity, T* record) {
-                auto currArch = m_entities.at( entity );
-
-                // check we already have that component type...
-                if ( currArch.idx(Component<T>::typeID()) == currArch.count ) {
-                    add<T>(entity);
-                    currArch = m_entities.at( entity );
-                }
-
-                auto& container = m_records.at(currArch);
-                auto pos = container.idx(entity);
-                return container.set<T>(pos, record);
-            }
-
-            template<typename T>
-            T* get(entity_t entity) {
-                auto currArch = m_entities.at( entity );
-                auto pos = currArch.idx(entity);
-                auto& container = m_records.at(currArch);
-
-                auto* data = container.template data<T>();
-                return &data[pos];
-            }
-
-            template<typename T>
-            const T* get(entity_t entity) const {
-                auto currArch = m_entities.at( entity );
-                auto pos = currArch.idx(entity);
-                auto& container = m_records.at(currArch);
-
-                auto* data = container.template data<T>();
-                return &data[pos];
-            }
-
-            template<typename T>
-            void remove(entity_t entity) {
-                auto currArch = m_entities.at( entity );
-                auto newArch = currArch.without<T>();
-
-                auto& oldContainer = m_records[currArch];
-                auto& newContainer = m_records[newArch];
-
-                auto oldPos = oldContainer.idx(entity);
-                auto newPos = newContainer.create();
-
-                m_records[newArch].contract(newPos, oldContainer, oldPos);
-            }
-
-            template<typename... T>
-            std::vector<entity_t> findMatching() const {
-                return {};
-            }
-
-    private:
-            TypeRegistry& m_registry;
-            std::map<RecordIdentifier, Container> m_records;
-            std::map<entity_t, RecordIdentifier> m_entities;
-            entity_t m_last{};
-    };
+	using entity_t = unsigned int;
+	constexpr entity_t NULL_ENTITY = 0;
+
+	class World {
+		public:
+			explicit World(TypeRegistry &reg) : m_registry(reg), m_last(NULL_ENTITY) {}
+
+			entity_t create() {
+				auto next = m_last++;
+
+				auto arch = make_id(1, Component<EntityMeta>::typeID());
+				auto &container = getContainer(arch);
+
+				m_entities[next] = container.m_identifier;
+
+				auto pos = container.create();
+				auto *entityMeta = container.data<EntityMeta>();
+				entityMeta[pos].id = next;
+
+				return next;
+			}
+
+			void remove(entity_t entity) {
+				auto arch = m_entities.at(entity);
+				auto container = m_records.at(arch);
+
+				auto entPos = container.idx(entity);
+				container.remove(entPos);
+			}
+
+			inline Container &getContainer(RecordIdentifier &arch) {
+				try {
+					return m_records.at(arch);
+				} catch (std::out_of_range &e) {
+					auto v = m_records.emplace(std::pair<RecordIdentifier, Container>(arch, {m_registry, arch}));
+					return v.first->second;
+				}
+			}
+
+			template<typename T>
+			T *add(const entity_t entity) {
+				auto currArch = m_entities.at(entity);
+				auto newArch = currArch.with<T>();
+				m_entities[entity] = newArch;
+
+				auto &oldContainer = m_records.at(currArch);
+				auto &newContainer = getContainer(newArch);
+
+				auto oldPos = oldContainer.idx(entity);
+
+				auto newPos = newContainer.expand(oldContainer, oldPos, Component<T>::typeID());
+				auto *data = newContainer.template data<T>();
+				return &data[newPos];
+			}
+
+			template<typename T>
+			T *set(const entity_t entity, T *record) {
+				auto currArch = m_entities.at(entity);
+
+				// check we already have that component type...
+				if (currArch.idx(Component<T>::typeID()) == currArch.count) {
+					add<T>(entity);
+					currArch = m_entities.at(entity);
+				}
+
+				auto &container = m_records.at(currArch);
+				auto pos = container.idx(entity);
+				return container.set<T>(pos, record);
+			}
+
+			template<typename T>
+			T *get(entity_t entity) {
+				auto currArch = m_entities.at(entity);
+				auto pos = currArch.idx(entity);
+				auto &container = m_records.at(currArch);
+
+				auto *data = container.template data<T>();
+				return &data[pos];
+			}
+
+			template<typename T>
+			const T *get(entity_t entity) const {
+				auto currArch = m_entities.at(entity);
+				auto pos = currArch.idx(entity);
+				auto &container = m_records.at(currArch);
+
+				auto *data = container.template data<T>();
+				return &data[pos];
+			}
+
+			template<typename T>
+			void remove(entity_t entity) {
+				auto currArch = m_entities.at(entity);
+				auto newArch = currArch.without<T>();
+
+				auto &oldContainer = m_records[currArch];
+				auto &newContainer = m_records[newArch];
+
+				auto oldPos = oldContainer.idx(entity);
+				auto newPos = newContainer.create();
+
+				m_records[newArch].contract(newPos, oldContainer, oldPos);
+			}
+
+			template<typename... T>
+			std::vector<entity_t> findMatching() const {
+				return {};
+			}
+
+		private:
+			TypeRegistry &m_registry;
+			std::map<RecordIdentifier, Container> m_records;
+			std::map<entity_t, RecordIdentifier> m_entities;
+			entity_t m_last{};
+	};
 
 }
 
diff --git a/include/fggl/ecs3/module/module.h b/include/fggl/ecs3/module/module.h
index a71ae98..c65ea22 100644
--- a/include/fggl/ecs3/module/module.h
+++ b/include/fggl/ecs3/module/module.h
@@ -13,63 +13,63 @@
 
 namespace fggl::ecs3 {
 
-    class Module {
-        public:
-            virtual ~Module() = default;
-
-            [[nodiscard]] virtual std::string name() const = 0;
-
-            virtual void onLoad(ModuleManager& manager, TypeRegistry& tr) {};
-
-            virtual void onUpdate();
-            virtual void onFrameStart();
-            virtual void onFrameEnd();
-    };
-
-    class ModuleManager {
-        public:
-            explicit ModuleManager(TypeRegistry& types) : m_types(types), m_modules(){ }
-            ~ModuleManager() = default;
-
-            template<typename C, typename... Args>
-            std::shared_ptr<C> load(Args&... args) {
-                auto ptr = std::make_shared<C>(args...);
-                m_modules[ptr->name()] = ptr;
-
-                ptr->onLoad(*this, m_types);
-                //spdlog::info("loaded ECS module: {}", ptr->name());
-                return ptr;
-            }
-
-            template<typename C>
-            void onAdd(const callback_t& cb) {
-                m_types.callbackAdd( Component<C>::typeID(), cb);
-            }
-
-            void onUpdate() {
-                for ( auto& [id,ptr] : m_modules ) {
-                    ptr->onUpdate();
-                }
-            }
-
-            void onFrameStart() {
-                for ( auto& [id,ptr] : m_modules ) {
-                    ptr->onFrameStart();
-                }
-            }
-
-            void onFrameEnd() {
-                for ( auto& [id,ptr] : m_modules ) {
-                    ptr->onFrameEnd();
-                }
-            }
-
-        private:
-            TypeRegistry& m_types;
-            std::map<std::string, std::shared_ptr<Module>> m_modules;
-    };
+	class Module {
+		public:
+			virtual ~Module() = default;
+
+			[[nodiscard]] virtual std::string name() const = 0;
+
+			virtual void onLoad(ModuleManager &manager, TypeRegistry &tr) {};
+
+			virtual void onUpdate();
+			virtual void onFrameStart();
+			virtual void onFrameEnd();
+	};
+
+	class ModuleManager {
+		public:
+			explicit ModuleManager(TypeRegistry &types) : m_types(types), m_modules() {}
+
+			~ModuleManager() = default;
+
+			template<typename C, typename... Args>
+			std::shared_ptr<C> load(Args &... args) {
+				auto ptr = std::make_shared<C>(args...);
+				m_modules[ptr->name()] = ptr;
+
+				ptr->onLoad(*this, m_types);
+				//spdlog::info("loaded ECS module: {}", ptr->name());
+				return ptr;
+			}
+
+			template<typename C>
+			void onAdd(const callback_t &cb) {
+				m_types.callbackAdd(Component<C>::typeID(), cb);
+			}
+
+			void onUpdate() {
+				for (auto &[id, ptr] : m_modules) {
+					ptr->onUpdate();
+				}
+			}
+
+			void onFrameStart() {
+				for (auto &[id, ptr] : m_modules) {
+					ptr->onFrameStart();
+				}
+			}
+
+			void onFrameEnd() {
+				for (auto &[id, ptr] : m_modules) {
+					ptr->onFrameEnd();
+				}
+			}
+
+		private:
+			TypeRegistry &m_types;
+			std::map<std::string, std::shared_ptr<Module>> m_modules;
+	};
 
 }
 
-
 #endif //FGGL_ECS3_MODULE_H
diff --git a/include/fggl/ecs3/prototype/world.h b/include/fggl/ecs3/prototype/world.h
index 1ffcaec..314668d 100644
--- a/include/fggl/ecs3/prototype/world.h
+++ b/include/fggl/ecs3/prototype/world.h
@@ -15,207 +15,207 @@
  */
 namespace fggl::ecs3::prototype {
 
-
-    class Entity {
-        public:
-            bool m_abstract;
-
-            explicit Entity(entity_t id) : m_id(id), m_abstract(false) {};
-            Entity(const Entity& entity) : m_id(entity.m_id), m_components(entity.m_components) {
-                //spdlog::info("entity created fro copy: {}", m_id);
-            }
-            ~Entity() = default;
-
-            template<typename C>
-            C* add() {
-                C* ptr = new C();
-                m_components[Component<C>::typeID()] = ptr;
-                return ptr;
-            }
-
-            void* add(std::shared_ptr<ComponentBase> t) {
-                void* ptr = t->construct();
-                m_components[t->id()] = ptr;
-                return ptr;
-            }
-
-            template<typename C>
-            C* set(const C* ptr) {
-                C* newPtr = new C(*ptr);
-                m_components[Component<C>::typeID()] = newPtr;
-                return newPtr;
-            }
-
-            void* set(const std::shared_ptr<ComponentBase>& t, const void* ptr) {
-                void* newPtr = t->copyConstruct(ptr);
-                m_components[t->id()] = newPtr;
-                return newPtr;
-            }
-
-            template<typename C>
-            C* get() {
-                void* ptr = m_components.at(Component<C>::typeID());
-                return (C*)ptr;
-            }
-
-            inline void* get(component_type_t t){
-                return m_components.at(t);
-            }
-
-            std::vector<component_type_t> getComponentIDs() {
-                std::vector<component_type_t> comps{};
-                for (auto& [k,_] : m_components) {
-                    comps.push_back(k);
-                }
-                return comps;
-            }
-
-            bool hasComponents(std::vector<component_type_t>& Cs) {
-                for (auto c : Cs) {
-                    if ( m_components.find(c) == m_components.end() ) {
-                        return false;
-                    }
-                }
-                return true;
-            }
-
-        private:
-            entity_t m_id;
-            std::map<component_type_t, void*> m_components;
-    };
-
-
-    class World {
-        public:
-            explicit World(TypeRegistry& reg) : m_types(reg), m_next(1), m_entities() {};
-            ~World() = default;
-
-            entity_t create(bool abstract) {
-                auto nextID = m_next++;
-                m_entities.emplace(nextID, nextID);
-
-                auto& entity = m_entities.at(nextID);
-                entity.m_abstract = abstract;
-
-                // meta data
-                auto* meta = entity.add<ecs3::EntityMeta>();
-                meta->id = nextID;
-                meta->abstract = abstract;
-
-                return nextID;
-            }
-
-            entity_t copy(entity_t prototype) {
-                auto clone = create(false);
-
-                auto components = getComponents(prototype);
-                for (auto component : components) {
-                    auto protoComp = get(prototype, component);
-                    set(clone, component, protoComp);
-                }
-
-                return clone;
-            }
-
-            void destroy(entity_t entity) {
-                // TOOD resolve and clean components
-                m_entities.erase(entity);
-            }
-
-            inline TypeRegistry& types() {
-                return m_types;
-            }
-
-            std::vector<entity_t> all() {
-                std::vector<entity_t> entities{};
-                for( auto& [eid, entity] : m_entities) {
-                    entities.push_back(eid);
-                }
-                return entities;
-            }
-
-            std::vector<component_type_t> getComponents(entity_t entityID){
-                std::vector<component_type_t> components{};
-                auto& entity = m_entities.at(entityID);
-                auto comps = entity.getComponentIDs();
-                for (auto id : comps) {
-                    components.push_back(id);
-                }
-                return components;
-            }
-
-            template<typename... Cs>
-            std::vector<entity_t> findMatching() {
-                // construct the key
-                std::vector<ecs::component_type_t> key;
-                (key.push_back( Component<Cs>::typeID() ), ...);
-
-                // entities
-                std::vector<entity_t> entities{};
-                for( auto& [eid, entity] : m_entities) {
-                    if ( entity.hasComponents(key) && !entity.m_abstract ) {
-                        entities.push_back(eid);
-                    }
-                }
-
-                return entities;
-            }
-
-            template<typename C>
-            C* add(entity_t entity_id) {
-                //spdlog::info("component '{}' added to '{}'", C::name, entity_id);
-                auto& entity = m_entities.at(entity_id);
-                auto comp = entity.template add<C>();
-
-                m_types.fireAdd(this, entity_id, Component<C>::typeID());
-                return comp;
-            }
-
-            void* add(entity_t entity_id, component_type_t component_id) {
-                auto meta = m_types.meta(component_id);
-                auto& entity = m_entities.at(entity_id);
-
-                void* ptr = entity.add(meta);
-                m_types.fireAdd(this, entity_id, meta->id());
-                return ptr;
-            }
-
-            template<typename C>
-            C* set(entity_t entity_id, const C* ptr) {
-                //spdlog::info("component '{}' set on '{}'", C::name, entity_id);
-                auto& entity = m_entities.at(entity_id);
-                auto comp = entity.set<C>(ptr);
-
-                m_types.fireAdd(this, entity_id, Component<C>::typeID());
-                return comp;
-            }
-
-            void* set(entity_t entity_id, component_type_t cid, const void* ptr){
-                auto& entity = m_entities.at(entity_id);
-                auto cMeta = m_types.meta(cid);
-
-                auto comp = entity.set(cMeta, ptr);
-                m_types.fireAdd(this, entity_id, cid);
-                return comp;
-            }
-
-            template<typename C>
-            C* get(entity_t entity_id) {
-                auto& entity = m_entities.at(entity_id);
-                return entity.get<C>();
-            }
-
-            void* get(entity_t entity_id, component_type_t t){
-                auto& entity = m_entities.at(entity_id);
-                return entity.get(t);
-            }
-
-        private:
-            TypeRegistry& m_types;
-            entity_t m_next;
-            std::map<entity_t, Entity> m_entities;
-
-    };
+	class Entity {
+		public:
+			bool m_abstract;
+
+			explicit Entity(entity_t id) : m_id(id), m_abstract(false) {};
+
+			Entity(const Entity &entity) : m_id(entity.m_id), m_components(entity.m_components) {
+				//spdlog::info("entity created fro copy: {}", m_id);
+			}
+
+			~Entity() = default;
+
+			template<typename C>
+			C *add() {
+				C *ptr = new C();
+				m_components[Component<C>::typeID()] = ptr;
+				return ptr;
+			}
+
+			void *add(std::shared_ptr<ComponentBase> t) {
+				void *ptr = t->construct();
+				m_components[t->id()] = ptr;
+				return ptr;
+			}
+
+			template<typename C>
+			C *set(const C *ptr) {
+				C *newPtr = new C(*ptr);
+				m_components[Component<C>::typeID()] = newPtr;
+				return newPtr;
+			}
+
+			void *set(const std::shared_ptr<ComponentBase> &t, const void *ptr) {
+				void *newPtr = t->copyConstruct(ptr);
+				m_components[t->id()] = newPtr;
+				return newPtr;
+			}
+
+			template<typename C>
+			C *get() {
+				void *ptr = m_components.at(Component<C>::typeID());
+				return (C *) ptr;
+			}
+
+			inline void *get(component_type_t t) {
+				return m_components.at(t);
+			}
+
+			std::vector<component_type_t> getComponentIDs() {
+				std::vector<component_type_t> comps{};
+				for (auto &[k, _] : m_components) {
+					comps.push_back(k);
+				}
+				return comps;
+			}
+
+			bool hasComponents(std::vector<component_type_t> &Cs) {
+				for (auto c : Cs) {
+					if (m_components.find(c) == m_components.end()) {
+						return false;
+					}
+				}
+				return true;
+			}
+
+		private:
+			entity_t m_id;
+			std::map<component_type_t, void *> m_components;
+	};
+
+	class World {
+		public:
+			explicit World(TypeRegistry &reg) : m_types(reg), m_next(1), m_entities() {};
+			~World() = default;
+
+			entity_t create(bool abstract) {
+				auto nextID = m_next++;
+				m_entities.emplace(nextID, nextID);
+
+				auto &entity = m_entities.at(nextID);
+				entity.m_abstract = abstract;
+
+				// meta data
+				auto *meta = entity.add<ecs3::EntityMeta>();
+				meta->id = nextID;
+				meta->abstract = abstract;
+
+				return nextID;
+			}
+
+			entity_t copy(entity_t prototype) {
+				auto clone = create(false);
+
+				auto components = getComponents(prototype);
+				for (auto component : components) {
+					auto protoComp = get(prototype, component);
+					set(clone, component, protoComp);
+				}
+
+				return clone;
+			}
+
+			void destroy(entity_t entity) {
+				// TOOD resolve and clean components
+				m_entities.erase(entity);
+			}
+
+			inline TypeRegistry &types() {
+				return m_types;
+			}
+
+			std::vector<entity_t> all() {
+				std::vector<entity_t> entities{};
+				for (auto &[eid, entity] : m_entities) {
+					entities.push_back(eid);
+				}
+				return entities;
+			}
+
+			std::vector<component_type_t> getComponents(entity_t entityID) {
+				std::vector<component_type_t> components{};
+				auto &entity = m_entities.at(entityID);
+				auto comps = entity.getComponentIDs();
+				for (auto id : comps) {
+					components.push_back(id);
+				}
+				return components;
+			}
+
+			template<typename... Cs>
+			std::vector<entity_t> findMatching() {
+				// construct the key
+				std::vector<ecs::component_type_t> key;
+				(key.push_back(Component<Cs>::typeID()), ...);
+
+				// entities
+				std::vector<entity_t> entities{};
+				for (auto &[eid, entity] : m_entities) {
+					if (entity.hasComponents(key) && !entity.m_abstract) {
+						entities.push_back(eid);
+					}
+				}
+
+				return entities;
+			}
+
+			template<typename C>
+			C *add(entity_t entity_id) {
+				//spdlog::info("component '{}' added to '{}'", C::name, entity_id);
+				auto &entity = m_entities.at(entity_id);
+				auto comp = entity.template add<C>();
+
+				m_types.fireAdd(this, entity_id, Component<C>::typeID());
+				return comp;
+			}
+
+			void *add(entity_t entity_id, component_type_t component_id) {
+				auto meta = m_types.meta(component_id);
+				auto &entity = m_entities.at(entity_id);
+
+				void *ptr = entity.add(meta);
+				m_types.fireAdd(this, entity_id, meta->id());
+				return ptr;
+			}
+
+			template<typename C>
+			C *set(entity_t entity_id, const C *ptr) {
+				//spdlog::info("component '{}' set on '{}'", C::name, entity_id);
+				auto &entity = m_entities.at(entity_id);
+				auto comp = entity.set<C>(ptr);
+
+				m_types.fireAdd(this, entity_id, Component<C>::typeID());
+				return comp;
+			}
+
+			void *set(entity_t entity_id, component_type_t cid, const void *ptr) {
+				auto &entity = m_entities.at(entity_id);
+				auto cMeta = m_types.meta(cid);
+
+				auto comp = entity.set(cMeta, ptr);
+				m_types.fireAdd(this, entity_id, cid);
+				return comp;
+			}
+
+			template<typename C>
+			C *get(entity_t entity_id) {
+				auto &entity = m_entities.at(entity_id);
+				return entity.get<C>();
+			}
+
+			void *get(entity_t entity_id, component_type_t t) {
+				auto &entity = m_entities.at(entity_id);
+				return entity.get(t);
+			}
+
+		private:
+			TypeRegistry &m_types;
+			entity_t m_next;
+			std::map<entity_t, Entity> m_entities;
+
+	};
 
 }
 
diff --git a/include/fggl/ecs3/types.hpp b/include/fggl/ecs3/types.hpp
index 4cce5ac..f6fe4e5 100644
--- a/include/fggl/ecs3/types.hpp
+++ b/include/fggl/ecs3/types.hpp
@@ -19,144 +19,145 @@ namespace fggl::ecs3 {
 		using namespace fggl::ecs;
 	};
 
-    namespace prototype {
-        class World;
-    }
-
-    using fggl::ecs::component_type_t;
-    class ModuleManager;
-
-    using callback_t = std::function<void(prototype::World*, ecs3::entity_t)>;
-    struct TypeCallbacks {
-        std::vector<callback_t> add;
-    };
-
-    // core component types
-    struct EntityMeta {
-        constexpr static const char name[] = "meta";
-        entity_t id;
-        bool abstract;
-    };
-
-    struct RecordIdentifier {
-        constexpr static std::size_t MAX_COMPS = 32;
-        component_type_t types[MAX_COMPS];
-        std::size_t count;
-
-        [[nodiscard]]
-        inline std::size_t idx(component_type_t t) const {
-            return utils::search(types, count, t);
-        }
-
-        template<typename T>
-        [[nodiscard]]
-        RecordIdentifier with() const {
-            // check the caller wasn't a muppet
-            const auto typeID = ecs::Component<T>::typeID();
-            if ( idx(typeID) != count ) {
-                return *this;
-            }
-
-            RecordIdentifier re{};
-            re.count = count + 1;
-            re.types[ count ] = ecs::Component<T>::typeID();
-
-            // add old types
-            for (std::size_t i = 0; i < count; ++i) {
-                re.types[i] = types[i];
-            }
-            std::sort( re.types, re.types + re.count );
-            return re;
-        }
-
-        template<typename T>
-        [[nodiscard]]
-        RecordIdentifier without() const {
-            // check the caller wasn't a muppet
-            const auto typeID = ecs::Component<T>::typeID();
-            const auto typeIdx = idx(typeID);
-            if ( typeIdx == count ) {
-                return *this;
-            }
-
-            RecordIdentifier re{};
-            re.count = count - 1;
-
-            // add old types
-            for (std::size_t i = 0, j = 0; i < count; ++i) {
-                if (typeIdx != i) {
-                    re.types[j] = types[i];
-                    j++;
-                }
-            }
-            std::sort( re.types, re.types + re.count );
-            return re;
-        }
-
-        bool operator<(const RecordIdentifier& other) const {
-            if ( count < other.count) {
-                return true;
-            } else if ( count > other.count ) {
-                return false;
-            } else {
-                for (int i = 0; i < count; i++) {
-                    if ( types[i] != other.types[i] ) {
-                        return types[i] < other.types[i];
-                    }
-                }
-                return false;
-            }
-        }
-
-        bool operator==(const RecordIdentifier& arg) const {
-            if ( arg.count != count ) {
-                return false;
-            }
-
-            for (int i=0; i<count; i++) {
-                if ( types[i] != arg.types[i] ) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        bool operator!=(const RecordIdentifier& arg) const {
-            return !( *this == arg );
-        }
-    };
-
-    std::ostream& operator<<(std::ostream& out, RecordIdentifier const& curr);
-
-    inline RecordIdentifier make_id(std::size_t count, ...) {
-        assert(count < RecordIdentifier::MAX_COMPS);
-
-        RecordIdentifier re{};
-
-        std::va_list args;
-        va_start(args, count);
-        for ( std::size_t i = 0; i < count; ++i ) {
-            re.types[i] = va_arg(args, component_type_t);
-        }
-        va_end(args);
-        re.count = count;
-        std::sort( re.types, re.types + count );
-
-        return re;
-    }
+	namespace prototype {
+		class World;
+	}
+
+	using fggl::ecs::component_type_t;
+
+	class ModuleManager;
+
+	using callback_t = std::function<void(prototype::World *, ecs3::entity_t)>;
+	struct TypeCallbacks {
+		std::vector<callback_t> add;
+	};
+
+	// core component types
+	struct EntityMeta {
+		constexpr static const char name[] = "meta";
+		entity_t id;
+		bool abstract;
+	};
+
+	struct RecordIdentifier {
+		constexpr static std::size_t MAX_COMPS = 32;
+		component_type_t types[MAX_COMPS];
+		std::size_t count;
+
+		[[nodiscard]]
+		inline std::size_t idx(component_type_t t) const {
+			return utils::search(types, count, t);
+		}
+
+		template<typename T>
+		[[nodiscard]]
+		RecordIdentifier with() const {
+			// check the caller wasn't a muppet
+			const auto typeID = ecs::Component<T>::typeID();
+			if (idx(typeID) != count) {
+				return *this;
+			}
+
+			RecordIdentifier re{};
+			re.count = count + 1;
+			re.types[count] = ecs::Component<T>::typeID();
+
+			// add old types
+			for (std::size_t i = 0; i < count; ++i) {
+				re.types[i] = types[i];
+			}
+			std::sort(re.types, re.types + re.count);
+			return re;
+		}
+
+		template<typename T>
+		[[nodiscard]]
+		RecordIdentifier without() const {
+			// check the caller wasn't a muppet
+			const auto typeID = ecs::Component<T>::typeID();
+			const auto typeIdx = idx(typeID);
+			if (typeIdx == count) {
+				return *this;
+			}
+
+			RecordIdentifier re{};
+			re.count = count - 1;
+
+			// add old types
+			for (std::size_t i = 0, j = 0; i < count; ++i) {
+				if (typeIdx != i) {
+					re.types[j] = types[i];
+					j++;
+				}
+			}
+			std::sort(re.types, re.types + re.count);
+			return re;
+		}
+
+		bool operator<(const RecordIdentifier &other) const {
+			if (count < other.count) {
+				return true;
+			} else if (count > other.count) {
+				return false;
+			} else {
+				for (int i = 0; i < count; i++) {
+					if (types[i] != other.types[i]) {
+						return types[i] < other.types[i];
+					}
+				}
+				return false;
+			}
+		}
+
+		bool operator==(const RecordIdentifier &arg) const {
+			if (arg.count != count) {
+				return false;
+			}
+
+			for (int i = 0; i < count; i++) {
+				if (types[i] != arg.types[i]) {
+					return false;
+				}
+			}
+			return true;
+		}
+
+		bool operator!=(const RecordIdentifier &arg) const {
+			return !(*this == arg);
+		}
+	};
+
+	std::ostream &operator<<(std::ostream &out, RecordIdentifier const &curr);
+
+	inline RecordIdentifier make_id(std::size_t count, ...) {
+		assert(count < RecordIdentifier::MAX_COMPS);
+
+		RecordIdentifier re{};
+
+		std::va_list args;
+		va_start(args, count);
+		for (std::size_t i = 0; i < count; ++i) {
+			re.types[i] = va_arg(args, component_type_t);
+		}
+		va_end(args);
+		re.count = count;
+		std::sort(re.types, re.types + count);
+
+		return re;
+	}
 
 	class TypeRegistry {
 		public:
 
-            TypeRegistry() : m_last_virtual(9000), m_callbacks() {
-                // core types always exist
-                make<EntityMeta>();
-            }
-			
+			TypeRegistry() : m_last_virtual(9000), m_callbacks() {
+				// core types always exist
+				make<EntityMeta>();
+			}
+
 			template<typename T>
 			void make() {
 				auto type_id = Component<T>::typeID();
-				if ( m_types.find( type_id ) != m_types.end() )
+				if (m_types.find(type_id) != m_types.end())
 					return;
 				m_types[type_id] = std::make_shared<Component<T>>();
 			}
@@ -164,52 +165,52 @@ namespace fggl::ecs3 {
 			template<typename T>
 			bool exists() {
 				auto type_id = Component<T>::typeID();
-				return m_types.find( type_id ) != m_types.end();
+				return m_types.find(type_id) != m_types.end();
 			}
 
 			template<typename T>
 			std::shared_ptr<fggl::ecs::ComponentBase> meta() const {
 				auto type_id = Component<T>::typeID();
-				return m_types.at( type_id );
+				return m_types.at(type_id);
 			}
 
 			inline std::shared_ptr<fggl::ecs::ComponentBase> meta(component_type_t type_id) const {
-				return m_types.at( type_id );
+				return m_types.at(type_id);
 			}
 
-            inline component_type_t find(const char* name) const {
-                for (auto& [type, meta] : m_types) {
-                    if ( std::strcmp(name, meta->name()) == 0) {
-                        return type;
-                    }
-                }
-                return 0;
-            }
+			inline component_type_t find(const char *name) const {
+				for (auto &[type, meta] : m_types) {
+					if (std::strcmp(name, meta->name()) == 0) {
+						return type;
+					}
+				}
+				return 0;
+			}
 
 			inline void make_virtual(std::shared_ptr<ComponentBase> vtype) {
 				auto type_id = m_last_virtual++;
 				m_types[type_id] = std::move(vtype);
 			}
 
-            void callbackAdd(component_type_t component, const callback_t& callback) {
-                m_callbacks[component].add.push_back(callback);
-            }
+			void callbackAdd(component_type_t component, const callback_t &callback) {
+				m_callbacks[component].add.push_back(callback);
+			}
 
-            void fireAdd(prototype::World* world, entity_t entity, component_type_t type) {
-                try {
-                    auto& callbacks = m_callbacks.at(type).add;
-                    for ( auto& callback : callbacks) {
-                        callback(world, entity);
-                    }
-                } catch ( std::out_of_range& e) {
-                    //spdlog::debug("no callbacks for {}", m_types[type]->name());
-                }
-            }
+			void fireAdd(prototype::World *world, entity_t entity, component_type_t type) {
+				try {
+					auto &callbacks = m_callbacks.at(type).add;
+					for (auto &callback : callbacks) {
+						callback(world, entity);
+					}
+				} catch (std::out_of_range &e) {
+					//spdlog::debug("no callbacks for {}", m_types[type]->name());
+				}
+			}
 
 		private:
 			std::unordered_map<component_type_t, std::shared_ptr<fggl::ecs::ComponentBase>> m_types;
 			component_type_t m_last_virtual;
-            std::map<component_type_t, TypeCallbacks> m_callbacks;
+			std::map<component_type_t, TypeCallbacks> m_callbacks;
 	};
 
 };
diff --git a/include/fggl/ecs3/utils.hpp b/include/fggl/ecs3/utils.hpp
index 0881c12..3ebf17f 100644
--- a/include/fggl/ecs3/utils.hpp
+++ b/include/fggl/ecs3/utils.hpp
@@ -6,26 +6,26 @@
 namespace fggl::utils {
 
 	template<typename T>
-	std::size_t search(const T* data, const std::size_t size, const T& v) {
-        // empty list == not found
-        if ( size == 0) {
-            return size;
-        }
+	std::size_t search(const T *data, const std::size_t size, const T &v) {
+		// empty list == not found
+		if (size == 0) {
+			return size;
+		}
 
-        std::size_t left = 0;
-        std::size_t right = size - 1;
-		while ( left <= right ) {
-			std::size_t m = (left+right) / 2;
-			if ( data[m] == v ) {
-                return m;
-            } else if ( v < data[m] ) {
-                if ( m == 0 ) {
-                    return size;
-                }
-                right = m - 1;
-            } else {
-                left = m + 1;
-            }
+		std::size_t left = 0;
+		std::size_t right = size - 1;
+		while (left <= right) {
+			std::size_t m = (left + right) / 2;
+			if (data[m] == v) {
+				return m;
+			} else if (v < data[m]) {
+				if (m == 0) {
+					return size;
+				}
+				right = m - 1;
+			} else {
+				left = m + 1;
+			}
 		}
 
 		return size;
diff --git a/include/fggl/gfx/atlas.hpp b/include/fggl/gfx/atlas.hpp
index 7eeef4e..50362ae 100644
--- a/include/fggl/gfx/atlas.hpp
+++ b/include/fggl/gfx/atlas.hpp
@@ -6,45 +6,45 @@
 
 namespace fggl::gfx {
 
-    struct Bounds2D {
-        glm::ivec2 pos;
-        glm::ivec2 size;
-    };
-    bool pack( std::vector<Bounds2D>& bounds);
-
-    template<typename T>
-    class ImageAtlas {
-        public:
-            struct SubImage {
-                const T name;
-                Bounds2D bounds;
-            };
-
-            SubImage& locate( int id ) const;
-            SubImage& locate( const T& name ) const;
-
-            static ImageAtlas<T>* pack( std::vector<SubImage>& images ) {
-                // extract bounds
-                std::vector<Bounds2D> bounds;
-                for( auto& image : images ) {
-                    bounds.push_back( image.bounds );
-                }
-
-                // allocate the bounds back
-                auto result = gfx::pack( bounds );
-                for ( std::size_t i = 0; i < images.size(); i++ ) {
-                    images[i].bounds = bounds[i];
-                }
-
-                return new ImageAtlas<T>(images);
-            }
-
-        private:
-            ImageAtlas(const std::vector<SubImage>& images) : m_images( images ) {
-            }
-
-            std::vector<SubImage> m_images;
-    };
+	struct Bounds2D {
+		glm::ivec2 pos;
+		glm::ivec2 size;
+	};
+	bool pack(std::vector<Bounds2D> &bounds);
+
+	template<typename T>
+	class ImageAtlas {
+		public:
+			struct SubImage {
+				const T name;
+				Bounds2D bounds;
+			};
+
+			SubImage &locate(int id) const;
+			SubImage &locate(const T &name) const;
+
+			static ImageAtlas<T> *pack(std::vector<SubImage> &images) {
+				// extract bounds
+				std::vector<Bounds2D> bounds;
+				for (auto &image : images) {
+					bounds.push_back(image.bounds);
+				}
+
+				// allocate the bounds back
+				auto result = gfx::pack(bounds);
+				for (std::size_t i = 0; i < images.size(); i++) {
+					images[i].bounds = bounds[i];
+				}
+
+				return new ImageAtlas<T>(images);
+			}
+
+		private:
+			ImageAtlas(const std::vector<SubImage> &images) : m_images(images) {
+			}
+
+			std::vector<SubImage> m_images;
+	};
 
 };
 
diff --git a/include/fggl/gfx/camera.hpp b/include/fggl/gfx/camera.hpp
index c1eaa43..3895e9e 100644
--- a/include/fggl/gfx/camera.hpp
+++ b/include/fggl/gfx/camera.hpp
@@ -6,7 +6,7 @@
 namespace fggl::gfx {
 
 	struct Camera {
-        constexpr const static char name[] = "Camera";
+		constexpr const static char name[] = "Camera";
 		math::vec3 target = math::vec3(0.0f, 0.0f, 0.0f);
 		float aspectRatio = 1280.0f / 720.0f;
 		float fov = glm::radians(45.0f);
diff --git a/include/fggl/gfx/common.hpp b/include/fggl/gfx/common.hpp
index 71101f5..82845e2 100644
--- a/include/fggl/gfx/common.hpp
+++ b/include/fggl/gfx/common.hpp
@@ -14,12 +14,13 @@
 namespace fggl::gfx {
 
 	struct StaticMesh {
-        constexpr static const char name[] = "StaticMesh";
+		constexpr static const char name[] = "StaticMesh";
 		data::Mesh mesh;
 		std::string pipeline;
 
 		inline StaticMesh() : mesh(), pipeline() {}
-		inline StaticMesh(const data::Mesh& aMesh, std::string aPipeline) :
+
+		inline StaticMesh(const data::Mesh &aMesh, std::string aPipeline) :
 			mesh(aMesh), pipeline(std::move(aPipeline)) {}
 	};
 
diff --git a/include/fggl/gfx/compat.hpp b/include/fggl/gfx/compat.hpp
index 3a1b370..32b766d 100644
--- a/include/fggl/gfx/compat.hpp
+++ b/include/fggl/gfx/compat.hpp
@@ -25,28 +25,27 @@ namespace fggl::gfx {
 		GlfwContext context;
 
 		inline explicit
-        ecsGlfwModule(std::shared_ptr<fggl::input::Input> inputs) : context(std::move(inputs) ) {
+		ecsGlfwModule(std::shared_ptr<fggl::input::Input> inputs) : context(std::move(inputs)) {
 		}
 
-        inline
-        std::unique_ptr<GlfwWindow> createWindow(const std::string& title) {
-            auto window = std::make_unique<GlfwWindow>();
-            window->title(title);
-            return window;
-        }
+		inline
+		std::unique_ptr<GlfwWindow> createWindow(const std::string &title) {
+			auto window = std::make_unique<GlfwWindow>();
+			window->title(title);
+			return window;
+		}
 
-        void onUpdate() override {
-            context.pollEvents();
-        }
+		void onUpdate() override {
+			context.pollEvents();
+		}
 
-        [[nodiscard]]
-        std::string name() const override {
-            return "gfx::glfw";
-        }
+		[[nodiscard]]
+		std::string name() const override {
+			return "gfx::glfw";
+		}
 
 	};
 
 }
 
-
 #endif
diff --git a/include/fggl/gfx/input.hpp b/include/fggl/gfx/input.hpp
index 5e29c8b..74d15b8 100644
--- a/include/fggl/gfx/input.hpp
+++ b/include/fggl/gfx/input.hpp
@@ -83,7 +83,7 @@ namespace fggl::gfx {
 		TRIGGER_LEFT,
 		TRIGGER_RIGHT
 	};
-	constexpr std::array<PadAxis,6> PadAxes = {
+	constexpr std::array<PadAxis, 6> PadAxes = {
 		PadAxis::LEFT_X,
 		PadAxis::LEFT_Y,
 		PadAxis::RIGHT_X,
@@ -107,10 +107,10 @@ namespace fggl::gfx {
 	};
 
 	struct Joystick {
-		const char* name = nullptr;
-		const float* axes = nullptr;
-		const unsigned char* buttons = nullptr;
-		const unsigned char* hats = nullptr;
+		const char *name = nullptr;
+		const float *axes = nullptr;
+		const unsigned char *buttons = nullptr;
+		const unsigned char *hats = nullptr;
 		int hatCount = 0;
 		int axisCount = 0;
 		int buttonCount = 0;
@@ -120,7 +120,7 @@ namespace fggl::gfx {
 	class Input {
 		public:
 			// this is a neccerry evil due to glfw's design :'(
-			static Input& instance() {
+			static Input &instance() {
 				static Input *instance = new Input();
 				return *instance;
 			}
@@ -134,12 +134,12 @@ namespace fggl::gfx {
 			void mouseBtn(const MouseButton btn, bool state);
 
 			// mouse position
-			const double* mousePos() const;
+			const double *mousePos() const;
 			double cursorDeltaX() const;
 			double cursorDeltaY() const;
 
 			// mouse scroll
-			const double* mouseScroll() const;
+			const double *mouseScroll() const;
 			double scrollDeltaX() const;
 			double scrollDeltaY() const;
 
@@ -165,14 +165,14 @@ namespace fggl::gfx {
 			bool mouseReleased(const MouseButton btn) const;
 
 			// joysticks
-			void joystickConnect(int id, Joystick& data);
+			void joystickConnect(int id, Joystick &data);
 			void joystickDisconnect(int id);
 
 			bool hasJoystick(int id) const;
-			const Joystick& joystick(int id) const;
+			const Joystick &joystick(int id) const;
 
 			// gamepads
-			void padState(int id, const PadState& state);
+			void padState(int id, const PadState &state);
 
 			bool padDown(int id, PadButton btn);
 			bool padPressed(int id, PadButton btn);
diff --git a/include/fggl/gfx/ogl/backend.hpp b/include/fggl/gfx/ogl/backend.hpp
index c30f2cb..047d713 100644
--- a/include/fggl/gfx/ogl/backend.hpp
+++ b/include/fggl/gfx/ogl/backend.hpp
@@ -12,69 +12,61 @@
  */
 namespace fggl::gfx {
 
-	class GlGraphics {
-		public:
-			GlGraphics(const Window& window);
-			~GlGraphics();
-
-			void clear();
-	};
-
 	class Shader {
 		public:
 			Shader();
 			~Shader();
 
 			inline void use() const {
-				glUseProgram( m_handle );
+				glUseProgram(m_handle);
 			}
 
-			inline GLuint uniform(const std::string& name) {
-				GLint loc = glGetUniformLocation( m_handle, name.c_str() );
-				if ( loc == -1 ) {
+			inline GLuint uniform(const std::string &name) {
+				GLint loc = glGetUniformLocation(m_handle, name.c_str());
+				if (loc == -1) {
 					throw std::runtime_error("invalid shader uniform");
 				}
 				return loc;
 			}
 
-			inline void setInt(const std::string& name, const GLint value) {
-				setInt( uniform(name), value );
+			inline void setInt(const std::string &name, const GLint value) {
+				setInt(uniform(name), value);
 			}
 
 			inline void setInt(GLuint idx, const GLint value) {
-				glUniform1i( idx, value );
+				glUniform1i(idx, value);
 			}
 
-			inline void setFloat(const std::string& name, const GLfloat value) {
-				setFloat( uniform(name), value );
+			inline void setFloat(const std::string &name, const GLfloat value) {
+				setFloat(uniform(name), value);
 			}
 
 			inline void setFloat(GLuint idx, const GLfloat value) {
-				glUniform1f( idx, value );
+				glUniform1f(idx, value);
 			}
 
-			inline void setVec2(const std::string& name, const GLfloat* vec) {
-				setVec2( uniform(name), vec );
+			inline void setVec2(const std::string &name, const GLfloat *vec) {
+				setVec2(uniform(name), vec);
 			}
 
-			inline void setVec2(GLuint idx, const GLfloat* vec) {
-				glUniform2f( idx, vec[0], vec[1] );
+			inline void setVec2(GLuint idx, const GLfloat *vec) {
+				glUniform2f(idx, vec[0], vec[1]);
 			}
 
-			inline void setVec3(const std::string& name, const GLfloat* vec) {
-				setVec3( uniform(name), vec );
+			inline void setVec3(const std::string &name, const GLfloat *vec) {
+				setVec3(uniform(name), vec);
 			}
 
-			inline void setVec3(GLuint idx, const GLfloat* vec) {
-				glUniform3f( idx, vec[0], vec[1], vec[2] );
+			inline void setVec3(GLuint idx, const GLfloat *vec) {
+				glUniform3f(idx, vec[0], vec[1], vec[2]);
 			}
 
-			inline void setMat4(const std::string& name, const GLfloat* mat) {
-				setMat4( uniform(name), mat);
+			inline void setMat4(const std::string &name, const GLfloat *mat) {
+				setMat4(uniform(name), mat);
 			}
 
-			inline void setMat4(GLuint idx, const GLfloat* mat) {
-				glUniformMatrix4fv( idx, 1, GL_FALSE, mat );
+			inline void setMat4(GLuint idx, const GLfloat *mat) {
+				glUniformMatrix4fv(idx, 1, GL_FALSE, mat);
 			}
 
 		private:
diff --git a/include/fggl/gfx/ogl/compat.hpp b/include/fggl/gfx/ogl/compat.hpp
index 3c1cecd..187f46a 100644
--- a/include/fggl/gfx/ogl/compat.hpp
+++ b/include/fggl/gfx/ogl/compat.hpp
@@ -24,7 +24,7 @@
 
 namespace fggl::gfx {
 
-    void generateHeightMesh(data::HeightMap* heightMap, data::Mesh);
+	void generateHeightMesh(data::HeightMap *heightMap, data::Mesh);
 
 	//
 	// fake module support - allows us to still RAII
@@ -33,82 +33,83 @@ namespace fggl::gfx {
 		fggl::gfx::MeshRenderer renderer;
 		fggl::gfx::ShaderCache cache;
 
-		ecsOpenGLModule(Window& window, std::shared_ptr<fggl::data::Storage> storage) :
-            renderer(),
-            cache(std::move(storage)) {	}
+		ecsOpenGLModule(Window &window, std::shared_ptr<fggl::data::Storage> storage) :
+			renderer(),
+			cache(std::move(storage)) {}
 
-        std::string name() const override {
-            return "gfx::opengl";
-        }
+		std::string name() const override {
+			return "gfx::opengl";
+		}
 
-        void uploadMesh(ecs3::World* world, ecs::entity_t entity) {
-            auto meshData = world->get<gfx::StaticMesh>(entity);
+		void uploadMesh(ecs3::World *world, ecs::entity_t entity) {
+			auto meshData = world->get<gfx::StaticMesh>(entity);
 
-            auto pipeline = cache.get(meshData->pipeline);
-            auto glMesh = renderer.upload(meshData->mesh);
+			auto pipeline = cache.get(meshData->pipeline);
+			auto glMesh = renderer.upload(meshData->mesh);
 
-            glMesh.pipeline = pipeline;
-            world->set<fggl::gfx::GlRenderToken>(entity, &glMesh);
-        }
+			glMesh.pipeline = pipeline;
+			world->set<fggl::gfx::GlRenderToken>(entity, &glMesh);
+		}
 
-        void uploadHeightmap(ecs3::World *world, ecs::entity_t entity) {
-            const auto heightmap = world->get<data::HeightMap>(entity);
+		void uploadHeightmap(ecs3::World *world, ecs::entity_t entity) {
+			const auto heightmap = world->get<data::HeightMap>(entity);
 
-            data::Mesh tmpMesh{};
-            data::generateHeightMesh(heightmap, tmpMesh);
-            auto glMesh = renderer.upload( tmpMesh );
+			data::Mesh tmpMesh{};
+			data::generateHeightMesh(heightmap, tmpMesh);
+			auto glMesh = renderer.upload(tmpMesh);
 
-            auto pipeline = cache.get("phong");
-            glMesh.pipeline = pipeline;
-            glMesh.renderType = GlRenderType::triangle_strip;
-            world->set<fggl::gfx::GlRenderToken>(entity, &glMesh);
-        }
+			auto pipeline = cache.get("phong");
+			glMesh.pipeline = pipeline;
+			glMesh.renderType = GlRenderType::triangle_strip;
+			world->set<fggl::gfx::GlRenderToken>(entity, &glMesh);
+		}
 
-        void onLoad(ecs3::ModuleManager& manager, ecs3::TypeRegistry& types) override {
-            // TODO implement dependencies
-            types.make<fggl::gfx::StaticMesh>();
-            types.make<fggl::data::HeightMap>();
-            types.make<fggl::gfx::Camera>();
+		void onLoad(ecs3::ModuleManager &manager, ecs3::TypeRegistry &types) override {
+			// TODO implement dependencies
+			types.make<fggl::gfx::StaticMesh>();
+			types.make<fggl::data::HeightMap>();
+			types.make<fggl::gfx::Camera>();
 
-            // FIXME probably shouldn't be doing this...
-            types.make<fggl::input::FreeCamKeys>();
+			// FIXME probably shouldn't be doing this...
+			types.make<fggl::input::FreeCamKeys>();
 
-            // opengl
-            types.make<fggl::gfx::GlRenderToken>();
+			// opengl
+			types.make<fggl::gfx::GlRenderToken>();
 
-            // callbacks
-            auto upload_cb = [this](auto a, auto b) { this->uploadMesh(a, b); };
-            manager.onAdd<fggl::gfx::StaticMesh>( upload_cb );
-            manager.onAdd<fggl::data::HeightMap>( [this](auto a, auto b) { this->uploadHeightmap(a, b); });
-        }
+			// callbacks
+			auto upload_cb = [this](auto a, auto b) { this->uploadMesh(a, b); };
+			manager.onAdd<fggl::gfx::StaticMesh>(upload_cb);
+			manager.onAdd<fggl::data::HeightMap>([this](auto a, auto b) { this->uploadHeightmap(a, b); });
+		}
 
 	};
+
 	using OglModule = std::shared_ptr<ecsOpenGLModule>;
 
 	//
 	// Loading related functions - should be handled in modules/data-driven
 	//
-	inline void loadPipeline(OglModule& mod, const std::string& name, bool hasGeom) {
+	inline void loadPipeline(OglModule &mod, const std::string &name, bool hasGeom) {
 		fggl::gfx::ShaderConfig config;
 		config.name = name;
-		config.vertex = name+"_vert.glsl";
-		config.fragment = name+"_frag.glsl";
-		if ( hasGeom ) {
-			config.geometry = name+"_geom.glsl";
+		config.vertex = name + "_vert.glsl";
+		config.fragment = name + "_frag.glsl";
+		if (hasGeom) {
+			config.geometry = name + "_geom.glsl";
 		}
 		mod->cache.load(config);
 	}
 
-	inline void loadBasicPipeline(OglModule& mod, const std::string &name) {
+	inline void loadBasicPipeline(OglModule &mod, const std::string &name) {
 		loadPipeline(mod, name, false);
 	}
 
 	//
 	// fake module/callbacks - our ECS doesn't have module/callback support yet.
 	// 
-	void onStaticMeshAdded(ecs3::World& ecs, ecs::entity_t entity, OglModule& mod) {
-        //spdlog::info("[CALLBACK] static mesh added, renderable?");
-        /*
+	void onStaticMeshAdded(ecs3::World &ecs, ecs::entity_t entity, OglModule &mod) {
+		//spdlog::info("[CALLBACK] static mesh added, renderable?");
+		/*
 		auto meshData = ecs.get<gfx::StaticMesh>(entity);
 		auto pipeline = mod->cache.get(meshData->pipeline);
 
@@ -116,22 +117,21 @@ namespace fggl::gfx {
 		glMesh.pipeline = pipeline;
 
 		ecs.set<fggl::gfx::GlRenderToken>(entity, &glMesh);
-         */
+		 */
 	}
 
-	inline void renderMeshes(OglModule& mod, ecs3::World& ecs, float dt) {
+	inline void renderMeshes(OglModule &mod, ecs3::World &ecs, float dt) {
 		// get the camera
 		auto cameras = ecs.findMatching<fggl::gfx::Camera>();
-		if ( cameras.empty() ) {
+		if (cameras.empty()) {
 			return;
 		}
 		auto camera = cameras[0];
 
 		// get the models
-        mod->renderer.render(ecs, camera, dt);
+		mod->renderer.render(ecs, camera, dt);
 	}
 
 }
 
-
 #endif
diff --git a/include/fggl/gfx/ogl/renderer.hpp b/include/fggl/gfx/ogl/renderer.hpp
index 59a3dd9..b4fbb92 100644
--- a/include/fggl/gfx/ogl/renderer.hpp
+++ b/include/fggl/gfx/ogl/renderer.hpp
@@ -1,22 +1,20 @@
 #ifndef FGGL_GFX_RENDERER_H
 #define FGGL_GFX_RENDERER_H
 
-#include <memory>
-#include <vector>
-
 #include <fggl/data/model.hpp>
 #include <fggl/ecs3/ecs.hpp>
-
 #include <fggl/gfx/ogl/backend.hpp>
 #include <fggl/gfx/ogl/shader.hpp>
-
-#include <fggl/gfx/renderer.hpp>
 #include <fggl/gfx/paint.hpp>
+#include <fggl/gfx/renderer.hpp>
+#include <memory>
+#include <vector>
 
 namespace fggl::gfx {
 
 	enum GlRenderType {
-		triangles = GL_TRIANGLES, triangle_strip = GL_TRIANGLE_STRIP
+		triangles = GL_TRIANGLES,
+		triangle_strip = GL_TRIANGLE_STRIP
 	};
 
 	struct GlRenderToken {
@@ -34,33 +32,33 @@ namespace fggl::gfx {
 		public:
 			using token_t = GlRenderToken;
 
-			token_t upload(fggl::data::Mesh& mesh);
+			token_t upload(fggl::data::Mesh &mesh);
 
-			void render(ecs3::World& ecs, ecs3::entity_t camera, float dt);
+			void render(ecs3::World &ecs, ecs3::entity_t camera, float dt);
 
 			float total;
 	};
 
-    class OpenGL4Backend : public Graphics {
-        public:
-            OpenGL4Backend();
-            ~OpenGL4Backend() override = default;
+	class OpenGL4Backend : public Graphics {
+		public:
+			explicit OpenGL4Backend(const Window &owner);
+			~OpenGL4Backend() override = default;
 
-            void clear() override;
+			void clear() override;
 
-            void draw2D(const Paint& paint) override;
+			void draw2D(const Paint &paint) override;
 
-        private:
-            GlRenderToken m_token2D;
-            std::unique_ptr<ShaderCache> m_cache;
-    };
+		private:
+			GlRenderToken m_token2D;
+			std::unique_ptr<ShaderCache> m_cache;
+	};
 
-    using OpenGL4 = OpenGL4Backend;
+	using OpenGL4 = OpenGL4Backend;
 
-	// specialisation hooks
+// specialisation hooks
 	using MeshRenderer = GlMeshRenderer;
 	using MeshToken = GlRenderToken;
 
-};
+};  // namespace fggl::gfx
 
 #endif
diff --git a/include/fggl/gfx/ogl/shader.hpp b/include/fggl/gfx/ogl/shader.hpp
index c74d89f..a6abc94 100644
--- a/include/fggl/gfx/ogl/shader.hpp
+++ b/include/fggl/gfx/ogl/shader.hpp
@@ -22,16 +22,16 @@ namespace fggl::gfx {
 		bool hasGeom = false;
 	};
 
-    inline ShaderConfig ShaderFromName( const std::string& name ) {
-        return {
-            .name = name,
-            .vertex = name + "_vert.glsl",
-            .fragment = name + "_frag.glsl"
-        };
-    }
+	inline ShaderConfig ShaderFromName(const std::string &name) {
+		return {
+			.name = name,
+			.vertex = name + "_vert.glsl",
+			.fragment = name + "_frag.glsl"
+		};
+	}
 
 	struct BinaryCache {
-		void* data = nullptr;
+		void *data = nullptr;
 		GLsizei size = 0;
 		GLenum format = GL_INVALID_ENUM;
 	};
@@ -41,25 +41,25 @@ namespace fggl::gfx {
 			ShaderCache(std::shared_ptr<fggl::data::Storage> storage);
 			~ShaderCache() = default;
 
-			GLuint load(const ShaderConfig& config);
-			GLuint getOrLoad(const ShaderConfig& config);
+			GLuint load(const ShaderConfig &config);
+			GLuint getOrLoad(const ShaderConfig &config);
 
-			GLuint get(const std::string& name);
+			GLuint get(const std::string &name);
 
 		private:
 			std::shared_ptr<fggl::data::Storage> m_storage;
 			std::unordered_map<std::string, GLuint> m_shaders;
 
 			// opengl operations
-			bool compileShader(const std::string&, GLuint);
+			bool compileShader(const std::string &, GLuint);
 
 			// file io operations
-			bool loadFromDisk(GLuint pid, const ShaderConfig& config);
-			void saveToDisk(GLuint pid, const ShaderConfig& config);
+			bool loadFromDisk(GLuint pid, const ShaderConfig &config);
+			void saveToDisk(GLuint pid, const ShaderConfig &config);
 
 			bool m_binary;
-			void cacheSave(GLuint pid, BinaryCache* cache);
-			bool cacheLoad(GLuint pid, const BinaryCache* cache);
+			void cacheSave(GLuint pid, BinaryCache *cache);
+			bool cacheLoad(GLuint pid, const BinaryCache *cache);
 	};
 
 }
diff --git a/include/fggl/gfx/paint.hpp b/include/fggl/gfx/paint.hpp
index cc2a3e1..6082674 100644
--- a/include/fggl/gfx/paint.hpp
+++ b/include/fggl/gfx/paint.hpp
@@ -6,92 +6,92 @@
 
 namespace fggl::gfx {
 
-    using RadianAngle = float;
-
-    enum class PathType {
-        MOVE,
-        PATH,
-        BAZIER2,
-        BAZIER3,
-        COLOUR,
-        CLOSE
-    };
-
-    struct Path2D {
-        inline explicit Path2D( math::vec2 start ) : m_points(), m_types() {
-            moveTo( start );
-        }
-
-        inline void moveTo(math::vec2 pos) {
-            m_points.push_back( pos );
-            m_types.push_back( PathType::MOVE );
-        }
-
-        inline void pathTo(math::vec2 pos) {
-            m_points.push_back( pos );
-            m_types.push_back( PathType::PATH );
-        }
-
-        void bezierTo(math::vec2 cp1, math::vec2 pos);
-        void bezierTo(math::vec2 cp1, math::vec2 cp2, math::vec2 pos);
-
-        void arc(math::vec2 center, float radius, RadianAngle startAngle, RadianAngle endAngle, bool ccw);
-
-        void colour(math::vec3 colour) {
-            m_colours.push_back( colour );
-            m_types.push_back( PathType::COLOUR );
-        }
-
-        void close() {
-            pathTo( m_points[0] );
-            m_types.push_back( PathType::CLOSE );
-        }
-
-        std::vector< math::vec2 > m_points;
-        std::vector< PathType > m_types;
-        std::vector< math::vec3 > m_colours;
-    };
-
-    enum class PaintType {
-        FILL,
-        STROKE
-    };
-
-    struct PaintCmd {
-        PaintType type;
-        Path2D path;
-    };
-    
-    struct TextCmd {
-    	const std::string text;
-    	const math::vec2 pos;
-    };
-
-    class Paint {
-        public:
-            Paint() = default;
-            Paint(Paint& paint) = delete;
-
-            inline void fill(Path2D& path) {
-                m_cmds.push_back( { PaintType::FILL, path } );
-            }
-
-            void stroke(Path2D& path) {
-                m_cmds.push_back( { PaintType::STROKE, path } );
-            }
-            
-            void text(const std::string& text, const math::vec2& pos) {
-            	m_text.push_back( { text, pos } );
-            }
-
-            const std::vector< PaintCmd >& cmds() const {
-                return m_cmds;
-            }
-
-        private:
-            std::vector< PaintCmd > m_cmds;
-            std::vector< TextCmd > m_text;
-    };
+	using RadianAngle = float;
+
+	enum class PathType {
+		MOVE,
+		PATH,
+		BAZIER2,
+		BAZIER3,
+		COLOUR,
+		CLOSE
+	};
+
+	struct Path2D {
+		inline explicit Path2D(math::vec2 start) : m_points(), m_types() {
+			moveTo(start);
+		}
+
+		inline void moveTo(math::vec2 pos) {
+			m_points.push_back(pos);
+			m_types.push_back(PathType::MOVE);
+		}
+
+		inline void pathTo(math::vec2 pos) {
+			m_points.push_back(pos);
+			m_types.push_back(PathType::PATH);
+		}
+
+		void bezierTo(math::vec2 cp1, math::vec2 pos);
+		void bezierTo(math::vec2 cp1, math::vec2 cp2, math::vec2 pos);
+
+		void arc(math::vec2 center, float radius, RadianAngle startAngle, RadianAngle endAngle, bool ccw);
+
+		void colour(math::vec3 colour) {
+			m_colours.push_back(colour);
+			m_types.push_back(PathType::COLOUR);
+		}
+
+		void close() {
+			pathTo(m_points[0]);
+			m_types.push_back(PathType::CLOSE);
+		}
+
+		std::vector<math::vec2> m_points;
+		std::vector<PathType> m_types;
+		std::vector<math::vec3> m_colours;
+	};
+
+	enum class PaintType {
+		FILL,
+		STROKE
+	};
+
+	struct PaintCmd {
+		PaintType type;
+		Path2D path;
+	};
+
+	struct TextCmd {
+		const std::string text;
+		const math::vec2 pos;
+	};
+
+	class Paint {
+		public:
+			Paint() = default;
+			Paint(Paint &paint) = delete;
+
+			inline void fill(Path2D &path) {
+				m_cmds.push_back({PaintType::FILL, path});
+			}
+
+			void stroke(Path2D &path) {
+				m_cmds.push_back({PaintType::STROKE, path});
+			}
+
+			void text(const std::string &text, const math::vec2 &pos) {
+				m_text.push_back({text, pos});
+			}
+
+			const std::vector<PaintCmd> &cmds() const {
+				return m_cmds;
+			}
+
+		private:
+			std::vector<PaintCmd> m_cmds;
+			std::vector<TextCmd> m_text;
+	};
 
 }
 
diff --git a/include/fggl/gfx/renderer.hpp b/include/fggl/gfx/renderer.hpp
index c112cd2..5fe42c6 100644
--- a/include/fggl/gfx/renderer.hpp
+++ b/include/fggl/gfx/renderer.hpp
@@ -3,18 +3,17 @@
 
 namespace fggl::gfx {
 
-    class RenderBackend {
-        public:
-            RenderBackend();
-            virtual ~RenderBackend() = default;
+	class RenderBackend {
+		public:
+			RenderBackend();
+			virtual ~RenderBackend() = default;
 
-            virtual void clear() = 0;
-            virtual void swap() = 0;
+			virtual void clear() = 0;
+			virtual void swap() = 0;
 
-    };
-
-    using RenderBackendPtr = std::unique_ptr<RenderBackend>;
-    using RenderBackendFactory = std::function< fggl::gfx::RenderBackendPtr&&() >;
+	};
 
+	using RenderBackendPtr = std::unique_ptr<RenderBackend>;
+	using RenderBackendFactory = std::function<fggl::gfx::RenderBackendPtr &&()>;
 
 };
diff --git a/include/fggl/gfx/vector.hpp b/include/fggl/gfx/vector.hpp
index 979f9e2..72d7649 100644
--- a/include/fggl/gfx/vector.hpp
+++ b/include/fggl/gfx/vector.hpp
@@ -6,14 +6,14 @@
 
 namespace fggl::gfx {
 
-    struct Rectangle {
-        math::vec2 topLeft;
-        math::vec2 size;
-    };
+	struct Rectangle {
+		math::vec2 topLeft;
+		math::vec2 size;
+	};
 
-    struct Polygon {
-        std::vector<math::vec2> points;
-    };
+	struct Polygon {
+		std::vector<math::vec2> points;
+	};
 
 }
 
diff --git a/include/fggl/gfx/vulkan/vulkan.hpp b/include/fggl/gfx/vulkan/vulkan.hpp
index e32d6b3..39d8428 100644
--- a/include/fggl/gfx/vulkan/vulkan.hpp
+++ b/include/fggl/gfx/vulkan/vulkan.hpp
@@ -10,25 +10,24 @@
 
 namespace fggl::gfx::vkgfx {
 
-    constexpr char const* EngineName = "FGGL";
+	constexpr char const *EngineName = "FGGL";
 
-    class VulkanGraphics {
+	class VulkanGraphics {
 
-        private:
-            vk::raii::Instance m_instance;
-            std::unique_ptr<vk::raii::SwapchainKHR> m_swapchain;
-    };
+		private:
+			vk::raii::Instance m_instance;
+			std::unique_ptr<vk::raii::SwapchainKHR> m_swapchain;
+	};
 
-    class VulkanContext {
-        public:
-            VulkanContext();
+	class VulkanContext {
+		public:
+			VulkanContext();
 
-            VulkanGraphics& createGraphics();
-
-        private:
-            vk::raii::Context m_context;
-    };
+			VulkanGraphics &createGraphics();
 
+		private:
+			vk::raii::Context m_context;
+	};
 
 }
 
diff --git a/include/fggl/gfx/window.hpp b/include/fggl/gfx/window.hpp
index 3a4c6f2..73c8408 100644
--- a/include/fggl/gfx/window.hpp
+++ b/include/fggl/gfx/window.hpp
@@ -29,7 +29,7 @@ namespace fggl::gfx {
 		FocusOnShow = GLFW_FOCUS_ON_SHOW
 	};
 
-    enum WindowHint {
+	enum WindowHint {
 		Focused = GLFW_FOCUSED,
 		Iconified = GLFW_ICONIFIED,
 		Maximised = GLFW_MAXIMIZED,
@@ -42,18 +42,20 @@ namespace fggl::gfx {
 		NoError = GLFW_CONTEXT_NO_ERROR
 	};
 
-    class GlfwWindow : public Window {
+	class GlfwWindow : public Window {
 		public:
 			GlfwWindow();
 			~GlfwWindow();
-            GlfwWindow(Window&) = delete;
-            GlfwWindow(Window&&) = delete;
+			GlfwWindow(Window &) = delete;
+			GlfwWindow(Window &&) = delete;
+
+			virtual math::vec2i frameSize() const override;
 
 			// window <-> opengl stuff
-            void activate() const override;
+			void activate() const override;
 
-            void frameStart() override;
-            void frameEnd() override;
+			void frameStart() override;
+			void frameEnd() override;
 
 			inline float width() const {
 				return m_framesize.x;
@@ -64,40 +66,40 @@ namespace fggl::gfx {
 			}
 
 			inline void framesize(int width, int height) {
-				m_framesize = math::vec2( width, height );
+				m_framesize = math::vec2(width, height);
 			}
 
 			// window manager stuff
 			[[nodiscard]]
 			inline bool closeRequested() const {
-				assert( m_window != nullptr );
+				assert(m_window != nullptr);
 				return glfwWindowShouldClose(m_window);
 			}
 
-			inline void title(const std::string& title) {
-				assert( m_window != nullptr );
-				glfwSetWindowTitle( m_window, title.c_str() );
+			inline void title(const std::string &title) {
+				assert(m_window != nullptr);
+				glfwSetWindowTitle(m_window, title.c_str());
 			}
 
 			[[nodiscard]]
 			inline bool fullscreen() const {
-				assert( m_window != nullptr );
-				return glfwGetWindowMonitor( m_window ) != nullptr;
+				assert(m_window != nullptr);
+				return glfwGetWindowMonitor(m_window) != nullptr;
 			}
 
 			inline void fullscreen(bool state) {
-				assert( m_window != nullptr );
-				if ( state ) {
+				assert(m_window != nullptr);
+				if (state) {
 					auto monitor = glfwGetPrimaryMonitor();
-					const auto mode = glfwGetVideoMode( monitor );
-					glfwSetWindowMonitor( m_window, monitor,
-							0, 0,
-							mode->width, mode->height,
-							mode->refreshRate);
+					const auto mode = glfwGetVideoMode(monitor);
+					glfwSetWindowMonitor(m_window, monitor,
+										 0, 0,
+										 mode->width, mode->height,
+										 mode->refreshRate);
 				} else {
-					glfwSetWindowMonitor( m_window, nullptr,
-							0, 0,
-							800, 600, 0);
+					glfwSetWindowMonitor(m_window, nullptr,
+										 0, 0,
+										 800, 600, 0);
 				}
 			}
 
@@ -116,32 +118,32 @@ namespace fggl::gfx {
 			}
 
 			inline void visible(bool state) {
-				assert( m_window != nullptr );
-				if ( state ) {
-					glfwShowWindow( m_window );
+				assert(m_window != nullptr);
+				if (state) {
+					glfwShowWindow(m_window);
 				} else {
-					glfwHideWindow( m_window );
+					glfwHideWindow(m_window);
 				}
 			}
 
-			inline GLFWwindow* handle() {
-				assert( m_window != nullptr );
+			inline GLFWwindow *handle() {
+				assert(m_window != nullptr);
 				return m_window;
 			}
 
 		private:
-			GLFWwindow* m_window;
+			GLFWwindow *m_window;
 			math::vec2 m_framesize;
 
 			inline void set_hint(int hint, bool state) const {
-				assert( m_window != nullptr );
-				glfwSetWindowAttrib( m_window, hint, state );
+				assert(m_window != nullptr);
+				glfwSetWindowAttrib(m_window, hint, state);
 			}
 
 			[[nodiscard]]
 			inline bool check_hint(int hint) const {
-				assert( m_window != nullptr );
-				return glfwGetWindowAttrib( m_window, hint) == GLFW_TRUE;
+				assert(m_window != nullptr);
+				return glfwGetWindowAttrib(m_window, hint) == GLFW_TRUE;
 			}
 	};
 
diff --git a/include/fggl/gfx/window_input.hpp b/include/fggl/gfx/window_input.hpp
index 153fcd9..1aff51f 100644
--- a/include/fggl/gfx/window_input.hpp
+++ b/include/fggl/gfx/window_input.hpp
@@ -7,12 +7,11 @@
 #include <fggl/gfx/window.hpp>
 #include <fggl/input/input.hpp>
 
-
 namespace fggl::gfx {
 
 	class GlfwInputManager {
 		public:
-			static GlfwInputManager& instance() {
+			static GlfwInputManager &instance() {
 				static GlfwInputManager *instance = new GlfwInputManager();
 				return *instance;
 			}
@@ -21,28 +20,28 @@ namespace fggl::gfx {
 				m_inputs = input;
 			}
 
-            inline void frame() {
-                m_inputs->frame(0.0f);
-            }
+			inline void frame() {
+				m_inputs->frame(0.0f);
+			}
 
 			inline bool alive() {
 				return m_inputs != nullptr;
 			}
 
-			inline input::MouseInput& mouse() {
+			inline input::MouseInput &mouse() {
 				return m_inputs->mouse;
 			}
 
-			inline input::KeyboardInput& keyboard() {
+			inline input::KeyboardInput &keyboard() {
 				return m_inputs->keyboard;
 			}
 
-			inline input::GamepadInput& gamepads() {
+			inline input::GamepadInput &gamepads() {
 				return m_inputs->gamepads;
 			}
 
 			inline void onMouseMove(float x, float y) {
-				if (m_inputs != nullptr ) {
+				if (m_inputs != nullptr) {
 					m_inputs->mouse.axis(input::MouseAxis::X, x);
 					m_inputs->mouse.axis(input::MouseAxis::Y, y);
 				}
@@ -56,13 +55,13 @@ namespace fggl::gfx {
 			}
 
 			inline void onMouseButton(int btn, bool state) {
-				if ( m_inputs != nullptr ) {
-					m_inputs->mouse.button((fggl::input::MouseButton)btn, state);
+				if (m_inputs != nullptr) {
+					m_inputs->mouse.button((fggl::input::MouseButton) btn, state);
 				}
 			}
 
 			inline void onKeyEvent(int scancode, bool state) {
-				if ( m_inputs != nullptr ) {
+				if (m_inputs != nullptr) {
 					m_inputs->keyboard.set(scancode, state);
 				}
 			}
diff --git a/include/fggl/gfx/windowing.hpp b/include/fggl/gfx/windowing.hpp
index 9f912a0..6405553 100644
--- a/include/fggl/gfx/windowing.hpp
+++ b/include/fggl/gfx/windowing.hpp
@@ -7,40 +7,44 @@
 
 namespace fggl::gfx {
 
-    class Graphics {
-        public:
-            virtual ~Graphics() = default;
-            virtual void clear() = 0;
-
-            virtual void draw2D(const Paint& paint) = 0;
-    };
-
-    class Window {
-        public:
-            virtual ~Window() = default;
-            virtual void activate() const = 0;
-
-            template<typename T>
-            void make_graphics() {
-                activate();
-                m_graphics = std::make_unique<T>();
-            }
-
-            virtual void frameStart() = 0;
-            virtual void frameEnd() = 0;
-
-            Graphics& graphics() {
-                return *m_graphics;
-            }
-
-        protected:
-            std::unique_ptr<Graphics> m_graphics;
-    };
-
-    class WindowService {
-        public:
-            Window& create();
-    };
+	class Graphics {
+		public:
+			virtual ~Graphics() = default;
+			virtual void clear() = 0;
+
+			virtual void draw2D(const Paint &paint) = 0;
+	};
+
+	class Window {
+		public:
+			virtual ~Window() = default;
+			virtual void activate() const = 0;
+
+			template<typename T>
+			void make_graphics() {
+				activate();
+				m_graphics = std::make_unique<T>(*this);
+			}
+
+			// window-related
+			[[nodiscard]]
+			virtual math::vec2i frameSize() const = 0;
+
+			virtual void frameStart() = 0;
+			virtual void frameEnd() = 0;
+
+			Graphics &graphics() {
+				return *m_graphics;
+			}
+
+		protected:
+			std::unique_ptr<Graphics> m_graphics;
+	};
+
+	class WindowService {
+		public:
+			Window &create();
+	};
 
 } // namespace fggl::gfx
 
diff --git a/include/fggl/gui/containers.hpp b/include/fggl/gui/containers.hpp
index 5192fcc..813e450 100644
--- a/include/fggl/gui/containers.hpp
+++ b/include/fggl/gui/containers.hpp
@@ -4,59 +4,59 @@
 #include <fggl/gui/widget.hpp>
 
 namespace fggl::gui {
-   
-   class Widget {
-       public:
-           Widget() = default;
-           
-           virtual math::vec2 baseSize();
-           
-           void size(math::vec2 size);
-           math::vec2 size() const;
-           
-           virtual bool contains(const math::vec2& point);
-           virtual Widget* getChildAt(const math::vec2& point);
-           
-           virtual void render(gfx::Paint& paint) = 0;
-   };
-   
-   class Container : public Widget {
-   	public:
-   		Container() = default;
-   		
-   		void clear();
-   		Widget* getChildAt(const std::math& point) override;
-   		
-   		void add(Widget&& widget);
-   		virtual void layout() = 0;
-   
-   	private:
-   		bool requireLayout;
-   		std::vector<std::unique_ptr<Widget>> m_children;
-   };
-   
-   enum class LayoutAxis {
-   	LINE_AXIS,
-   	PAGE_AXIS
-   };
-   
-   /**
-    * A box-like container.
-    * This container lines child elements up along an axis.
-    * 
-    * This is a fairly common approach in may layout frameworks, for example:
-    *   * Java's BoxLayout
-    *   * GTK's Boxes
-    *   * QT's QBoxLayout
-    *   * Android's XML box things
-    */
-   class Box : public Container {
-   	public:
-   		Box( LayoutAxis axis );
-   		void layout() override;
-   	private:
-   		const LayoutAxis m_axis;
-   }
+
+	class Widget {
+		public:
+			Widget() = default;
+
+			virtual math::vec2 baseSize();
+
+			void size(math::vec2 size);
+			math::vec2 size() const;
+
+			virtual bool contains(const math::vec2 &point);
+			virtual Widget *getChildAt(const math::vec2 &point);
+
+			virtual void render(gfx::Paint &paint) = 0;
+	};
+
+	class Container : public Widget {
+		public:
+			Container() = default;
+
+			void clear();
+			Widget *getChildAt(const std::math &point) override;
+
+			void add(Widget &&widget);
+			virtual void layout() = 0;
+
+		private:
+			bool requireLayout;
+			std::vector<std::unique_ptr<Widget>> m_children;
+	};
+
+	enum class LayoutAxis {
+		LINE_AXIS,
+		PAGE_AXIS
+	};
+
+	/**
+	 * A box-like container.
+	 * This container lines child elements up along an axis.
+	 *
+	 * This is a fairly common approach in may layout frameworks, for example:
+	 *   * Java's BoxLayout
+	 *   * GTK's Boxes
+	 *   * QT's QBoxLayout
+	 *   * Android's XML box things
+	 */
+	class Box : public Container {
+		public:
+			Box(LayoutAxis axis);
+			void layout() override;
+		private:
+			const LayoutAxis m_axis;
+	}
 
 }; //namespace fggl::gui
 
diff --git a/include/fggl/gui/widget.hpp b/include/fggl/gui/widget.hpp
index a78b8e4..50a092d 100644
--- a/include/fggl/gui/widget.hpp
+++ b/include/fggl/gui/widget.hpp
@@ -5,30 +5,30 @@
 #include <fggl/gfx/paint.hpp>
 
 namespace fggl::gui {
-   
-   class Widget {
-       public:
-           Widget() = default;
-           
-           virtual bool contains(const math::vec2& point);
-           virtual Widget* getChildAt(const math::vec2& point);
-           
-           virtual void render(gfx::Paint& paint) = 0;
-   };
-   
-   class Container : public Widget {
-   	public:
-   		Container() = default;
-   		
-   		void clear();
-   		Widget* getChildAt(const std::math& point) override;
-   		
-   		void add(Widget&& widget);
-   
-   	private:
-   		bool requireLayout;
-   		std::vector<std::unique_ptr<Widget>> m_children;
-   };
+
+	class Widget {
+		public:
+			Widget() = default;
+
+			virtual bool contains(const math::vec2 &point);
+			virtual Widget *getChildAt(const math::vec2 &point);
+
+			virtual void render(gfx::Paint &paint) = 0;
+	};
+
+	class Container : public Widget {
+		public:
+			Container() = default;
+
+			void clear();
+			Widget *getChildAt(const std::math &point) override;
+
+			void add(Widget &&widget);
+
+		private:
+			bool requireLayout;
+			std::vector<std::unique_ptr<Widget>> m_children;
+	};
 
 }; //namespace fggl::gui
 
diff --git a/include/fggl/gui/widgets.hpp b/include/fggl/gui/widgets.hpp
index 5442c9c..7fff237 100644
--- a/include/fggl/gui/widgets.hpp
+++ b/include/fggl/gui/widgets.hpp
@@ -4,32 +4,32 @@
 #include <fggl/gui/widget.hpp>
 
 namespace fggl::gui {
-   
-   class Button : public Widget {
-   	public:
-   		Button();
-   		void render(gfx::Paint& paint) override;
-   	private:
-   		const std::string m_value;
-   };
-   
-   class Label : public Widget {
-   	public:
-   		Label();
-   		void render(gfx::Paint& paint) override;
-   };
-   
-   class TextField : public Widget {
-   	public:
-   		TextField();
-   		void render(gfx::Paint& paint) override;
-   };
-   
-   class Toggle : public Widget {
-   	public:
-   		Toggle();
-   		void render(gfx::Paint& paint) override;
-   };
+
+	class Button : public Widget {
+		public:
+			Button();
+			void render(gfx::Paint &paint) override;
+		private:
+			const std::string m_value;
+	};
+
+	class Label : public Widget {
+		public:
+			Label();
+			void render(gfx::Paint &paint) override;
+	};
+
+	class TextField : public Widget {
+		public:
+			TextField();
+			void render(gfx::Paint &paint) override;
+	};
+
+	class Toggle : public Widget {
+		public:
+			Toggle();
+			void render(gfx::Paint &paint) override;
+	};
 
 }; //namespace fggl::gui
 
diff --git a/include/fggl/input/camera_input.h b/include/fggl/input/camera_input.h
index b2c2735..4e796b1 100644
--- a/include/fggl/input/camera_input.h
+++ b/include/fggl/input/camera_input.h
@@ -10,50 +10,50 @@
 
 namespace fggl::input {
 
-    constexpr float ROT_SPEED = 0.05f;
-    constexpr float PAN_SPEED = 0.05f;
-    constexpr math::mat4 MAT_IDENTITY(1.0f);
-
-    struct FreeCamKeys {
-        constexpr const static char name[] = "FreeCameraKeys";
-        scancode_t forward;
-        scancode_t backward;
-        scancode_t left;
-        scancode_t right;
-        scancode_t rotate_cw;
-        scancode_t rotate_ccw;
-    };
-
-    /**
-     * Process the camera based on rotation around a fixed point.
-     *
-     * @param ecs the world that contains the camera
-     * @param input the input module to read the mouse location from
-     * @param cam the ID of the camera entity
-     */
-    void process_arcball(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
-
-    /**
-     * Process free (floating) camera movement.
-     *
-     * @param ecs the world that contains the camera
-     * @param input the input module to read the mouse location from
-     * @param cam the ID of the camera entity
-     */
-    void process_freecam(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
-
-    /**
-     * Input processing for moving the camera when the mouse is close to the edge of the screen.
-     *
-     * This function deals with ensuring the camera moves if the user moves their mouse button close
-     * to the edge of the screen. It will apply this as movement to the camera entity passed in as
-     * an argument.
-     *
-     * @param ecs the world that contains the camera
-     * @param input the input module to read the mouse location from
-     * @param cam the ID of the camera entity
-     */
-    void process_edgescroll(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
+	constexpr float ROT_SPEED = 0.05f;
+	constexpr float PAN_SPEED = 0.05f;
+	constexpr math::mat4 MAT_IDENTITY(1.0f);
+
+	struct FreeCamKeys {
+		constexpr const static char name[] = "FreeCameraKeys";
+		scancode_t forward;
+		scancode_t backward;
+		scancode_t left;
+		scancode_t right;
+		scancode_t rotate_cw;
+		scancode_t rotate_ccw;
+	};
+
+	/**
+	 * Process the camera based on rotation around a fixed point.
+	 *
+	 * @param ecs the world that contains the camera
+	 * @param input the input module to read the mouse location from
+	 * @param cam the ID of the camera entity
+	 */
+	void process_arcball(fggl::ecs3::World &ecs, const Input &input, fggl::ecs::entity_t cam);
+
+	/**
+	 * Process free (floating) camera movement.
+	 *
+	 * @param ecs the world that contains the camera
+	 * @param input the input module to read the mouse location from
+	 * @param cam the ID of the camera entity
+	 */
+	void process_freecam(fggl::ecs3::World &ecs, const Input &input, fggl::ecs::entity_t cam);
+
+	/**
+	 * Input processing for moving the camera when the mouse is close to the edge of the screen.
+	 *
+	 * This function deals with ensuring the camera moves if the user moves their mouse button close
+	 * to the edge of the screen. It will apply this as movement to the camera entity passed in as
+	 * an argument.
+	 *
+	 * @param ecs the world that contains the camera
+	 * @param input the input module to read the mouse location from
+	 * @param cam the ID of the camera entity
+	 */
+	void process_edgescroll(fggl::ecs3::World &ecs, const Input &input, fggl::ecs::entity_t cam);
 
 }
 
diff --git a/include/fggl/input/gamepad.hpp b/include/fggl/input/gamepad.hpp
index 96a3ada..3b92dd3 100644
--- a/include/fggl/input/gamepad.hpp
+++ b/include/fggl/input/gamepad.hpp
@@ -50,49 +50,64 @@ namespace fggl::input {
 	};
 
 	constexpr std::array<GamepadButtonRecord, 15> GamepadButtonsMicrosoft = {{
-		{GamepadButton::A, "A"},
-		{GamepadButton::B, "B"},
-		{GamepadButton::X, "X"},
-		{GamepadButton::Y, "Y"},
-		{GamepadButton::BUMPER_LEFT,  "Left Bumper"},
-		{GamepadButton::BUMPER_RIGHT, "Right Bumper"},
-		{GamepadButton::BACK, "Back"},
-		{GamepadButton::START, "Start"},
-		{GamepadButton::GUIDE, "Guide"},
-		{GamepadButton::THUMB_LEFT, "Thumb Left"},
-		{GamepadButton::THUMB_RIGHT, "Thumb Right"},
-		{GamepadButton::DPAD_UP, "Dpad Up"},
-		{GamepadButton::DPAD_RIGHT, "Dpad Right"},
-		{GamepadButton::DPAD_DOWN, "Dpad Down"},
-		{GamepadButton::DPAD_LEFT, "Dpad Left"},
-	}};
+																				 {GamepadButton::A, "A"},
+																				 {GamepadButton::B, "B"},
+																				 {GamepadButton::X, "X"},
+																				 {GamepadButton::Y, "Y"},
+																				 {GamepadButton::BUMPER_LEFT,
+																				  "Left Bumper"},
+																				 {GamepadButton::BUMPER_RIGHT,
+																				  "Right Bumper"},
+																				 {GamepadButton::BACK, "Back"},
+																				 {GamepadButton::START, "Start"},
+																				 {GamepadButton::GUIDE, "Guide"},
+																				 {GamepadButton::THUMB_LEFT,
+																				  "Thumb Left"},
+																				 {GamepadButton::THUMB_RIGHT,
+																				  "Thumb Right"},
+																				 {GamepadButton::DPAD_UP, "Dpad Up"},
+																				 {GamepadButton::DPAD_RIGHT,
+																				  "Dpad Right"},
+																				 {GamepadButton::DPAD_DOWN,
+																				  "Dpad Down"},
+																				 {GamepadButton::DPAD_LEFT,
+																				  "Dpad Left"},
+																			 }};
 
 	constexpr std::array<GamepadAxisRecord, 6> GamepadAxes = {{
-		{GamepadAxis::LEFT_X, "left stick left/right"},
-		{GamepadAxis::LEFT_Y, "left stick up/down"},
-		{GamepadAxis::RIGHT_X, "right stick left/right"},
-		{GamepadAxis::RIGHT_Y, "right stick up/down"},
-		{GamepadAxis::TRIGGER_LEFT, "left trigger"},
-		{GamepadAxis::TRIGGER_RIGHT, "right trigger"},
-	}};
+																  {GamepadAxis::LEFT_X, "left stick left/right"},
+																  {GamepadAxis::LEFT_Y, "left stick up/down"},
+																  {GamepadAxis::RIGHT_X, "right stick left/right"},
+																  {GamepadAxis::RIGHT_Y, "right stick up/down"},
+																  {GamepadAxis::TRIGGER_LEFT, "left trigger"},
+																  {GamepadAxis::TRIGGER_RIGHT, "right trigger"},
+															  }};
 
 	constexpr std::array<GamepadButtonRecord, 15> GamepadButtonsPlaystation = {{
-		{GamepadButton::SQUARE, "Square"},
-		{GamepadButton::CIRCLE, "Circle"},
-		{GamepadButton::TRIANGLE, "Triangle"},
-		{GamepadButton::CROSS, "Cross"},
-		{GamepadButton::BUMPER_LEFT,  "Left Bumper"},
-		{GamepadButton::BUMPER_RIGHT, "Right Bumper"},
-		{GamepadButton::BACK, "Back"},
-		{GamepadButton::START, "Start"},
-		{GamepadButton::GUIDE, "Guide"},
-		{GamepadButton::THUMB_LEFT, "Thumb Left"},
-		{GamepadButton::THUMB_RIGHT, "Thumb Right"},
-		{GamepadButton::DPAD_UP, "Dpad Up"},
-		{GamepadButton::DPAD_RIGHT, "Dpad Right"},
-		{GamepadButton::DPAD_DOWN, "Dpad Down"},
-		{GamepadButton::DPAD_LEFT, "Dpad Left"},
-	}};
+																				   {GamepadButton::SQUARE, "Square"},
+																				   {GamepadButton::CIRCLE, "Circle"},
+																				   {GamepadButton::TRIANGLE,
+																					"Triangle"},
+																				   {GamepadButton::CROSS, "Cross"},
+																				   {GamepadButton::BUMPER_LEFT,
+																					"Left Bumper"},
+																				   {GamepadButton::BUMPER_RIGHT,
+																					"Right Bumper"},
+																				   {GamepadButton::BACK, "Back"},
+																				   {GamepadButton::START, "Start"},
+																				   {GamepadButton::GUIDE, "Guide"},
+																				   {GamepadButton::THUMB_LEFT,
+																					"Thumb Left"},
+																				   {GamepadButton::THUMB_RIGHT,
+																					"Thumb Right"},
+																				   {GamepadButton::DPAD_UP, "Dpad Up"},
+																				   {GamepadButton::DPAD_RIGHT,
+																					"Dpad Right"},
+																				   {GamepadButton::DPAD_DOWN,
+																					"Dpad Down"},
+																				   {GamepadButton::DPAD_LEFT,
+																					"Dpad Left"},
+																			   }};
 
 	struct GamepadState {
 		std::bitset<GamepadButtonsMicrosoft.size()> buttons;
@@ -104,76 +119,76 @@ namespace fggl::input {
 	struct GamepadInput {
 		public:
 			inline bool present(size_t id) const {
-				assert( id < MaxControllers );
+				assert(id < MaxControllers);
 				return m_active[id];
 			}
 
-			inline void name(size_t id, const std::string& name) {
-				assert( id < MaxControllers );
+			inline void name(size_t id, const std::string &name) {
+				assert(id < MaxControllers);
 				m_names[id] = name;
 			}
 
 			inline std::string name(size_t id) const {
-				std::string name = m_names[id].empty() ? "gamepad "+std::to_string(id) : m_names[id];
-				if ( !present(id) ) {
+				std::string name = m_names[id].empty() ? "gamepad " + std::to_string(id) : m_names[id];
+				if (!present(id)) {
 					return name + " (disconnected)";
 				}
 				return name;
 			}
 
 			inline float axis(size_t id, GamepadAxis axis) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return m_current[id].axes[(int)axis];
+				return m_current[id].axes[(int) axis];
 			}
 
 			inline float axisDelta(size_t id, GamepadAxis axis) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return m_current[id].axes[(int)axis] - m_previous[id].axes[(int)axis];
+				return m_current[id].axes[(int) axis] - m_previous[id].axes[(int) axis];
 			}
 
 			inline bool button(size_t id, GamepadButton btn) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return m_current[id].buttons[(int)btn];
+				return m_current[id].buttons[(int) btn];
 			}
 
 			inline bool buttonPressed(size_t id, GamepadButton btn) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return m_current[id].buttons[(int)btn] && !m_previous[id].buttons[(int)btn];
+				return m_current[id].buttons[(int) btn] && !m_previous[id].buttons[(int) btn];
 			}
 
 			inline bool buttonReleased(size_t id, GamepadButton btn) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return !m_current[id].buttons[(int)btn] && m_previous[id].buttons[(int)btn];
+				return !m_current[id].buttons[(int) btn] && m_previous[id].buttons[(int) btn];
 			}
 
 			inline bool buttonChanged(size_t id, GamepadButton btn) const {
-				if ( !present(id) ) {
+				if (!present(id)) {
 					return 0.0f;
 				}
-				return m_current[id].buttons[(int)btn] != m_previous[id].buttons[(int)btn];
+				return m_current[id].buttons[(int) btn] != m_previous[id].buttons[(int) btn];
 			}
 
 			inline void frame(float dt) {
 				m_previous = m_current;
 			}
 
-			inline void update(size_t id, const GamepadState& state) {
-				assert( present(id) );
+			inline void update(size_t id, const GamepadState &state) {
+				assert(present(id));
 				m_current[id] = state;
 			}
 
 			inline void setActive(size_t id, bool state) {
-				assert( id < MaxControllers );
+				assert(id < MaxControllers);
 				m_active[id] = state;
 			}
 
diff --git a/include/fggl/input/input.hpp b/include/fggl/input/input.hpp
index a2f0307..9352945 100644
--- a/include/fggl/input/input.hpp
+++ b/include/fggl/input/input.hpp
@@ -12,7 +12,7 @@ namespace fggl::input {
 		public:
 			Input() = default;
 			void frame(float dt);
-			
+
 			KeyboardInput keyboard;
 			MouseInput mouse;
 			GamepadInput gamepads;
diff --git a/include/fggl/input/keyboard.hpp b/include/fggl/input/keyboard.hpp
index 853e652..44e0b68 100644
--- a/include/fggl/input/keyboard.hpp
+++ b/include/fggl/input/keyboard.hpp
@@ -10,28 +10,28 @@ namespace fggl::input {
 	using scancode_t = int;
 
 	class KeyboardState {
-        public:
-            KeyboardState() = default;
-
-            inline void clear() {
-                m_keys.clear();
-            }
-
-            inline void set(scancode_t code, bool state) {
-                if ( state ) {
-                    m_keys.insert( code );
-                } else {
-                    m_keys.erase( code );
-                }
-            }
-
-            inline bool down(scancode_t scancode) const {
-                if ( m_keys.empty() )
-                    return false;
-
-                return m_keys.count(scancode) > 0;
-            }
-		
+		public:
+			KeyboardState() = default;
+
+			inline void clear() {
+				m_keys.clear();
+			}
+
+			inline void set(scancode_t code, bool state) {
+				if (state) {
+					m_keys.insert(code);
+				} else {
+					m_keys.erase(code);
+				}
+			}
+
+			inline bool down(scancode_t scancode) const {
+				if (m_keys.empty())
+					return false;
+
+				return m_keys.count(scancode) > 0;
+			}
+
 		private:
 			std::unordered_set<scancode_t> m_keys;
 	};
diff --git a/include/fggl/input/mouse.hpp b/include/fggl/input/mouse.hpp
index 09af8e9..5c7e6e8 100644
--- a/include/fggl/input/mouse.hpp
+++ b/include/fggl/input/mouse.hpp
@@ -36,70 +36,70 @@ namespace fggl::input {
 	};
 
 	constexpr std::array<MouseButtonRecord, 8> MouseButtons = {{
-		{MouseButton::LEFT, "Left"},
-		{MouseButton::MIDDLE, "Middle"},
-		{MouseButton::RIGHT, "Right"},
-		{MouseButton::EXTRA_1, "Extra 1"},
-		{MouseButton::EXTRA_2, "Extra 2"},
-		{MouseButton::EXTRA_3, "Extra 3"},
-		{MouseButton::EXTRA_4, "Extra 4"},
-		{MouseButton::EXTRA_5, "Extra 5"},
-	}};
+																   {MouseButton::LEFT, "Left"},
+																   {MouseButton::MIDDLE, "Middle"},
+																   {MouseButton::RIGHT, "Right"},
+																   {MouseButton::EXTRA_1, "Extra 1"},
+																   {MouseButton::EXTRA_2, "Extra 2"},
+																   {MouseButton::EXTRA_3, "Extra 3"},
+																   {MouseButton::EXTRA_4, "Extra 4"},
+																   {MouseButton::EXTRA_5, "Extra 5"},
+															   }};
 
 	constexpr std::array<MouseAxisRecord, 4> MouseAxes = {{
-		{MouseAxis::X, "Left/Right"},
-		{MouseAxis::Y, "Up/Down"},
-		{MouseAxis::SCROLL_X, "Scroll X"},
-		{MouseAxis::SCROLL_Y, "Scroll Y"}
-	}};
+															  {MouseAxis::X, "Left/Right"},
+															  {MouseAxis::Y, "Up/Down"},
+															  {MouseAxis::SCROLL_X, "Scroll X"},
+															  {MouseAxis::SCROLL_Y, "Scroll Y"}
+														  }};
 
 	struct MouseState {
 		float axis[MouseAxes.size()];
 		std::bitset<MouseButtons.size()> buttons;
 
-        void operator=(const MouseState& rhs);
+		void operator=(const MouseState &rhs);
 	};
 
 	class MouseInput {
 		public:
-            MouseInput() = default;
-            MouseInput(const MouseInput& rhs) = delete;
-            void operator=(const MouseInput& rhs) = delete;
+			MouseInput() = default;
+			MouseInput(const MouseInput &rhs) = delete;
+			void operator=(const MouseInput &rhs) = delete;
 
 			inline void frame(float dt) {
 				m_prev = m_curr;
 			}
 
 			inline void axis(MouseAxis axis, float value) {
-				m_curr.axis[(int)axis] = value;
+				m_curr.axis[(int) axis] = value;
 			}
 
 			inline float axis(MouseAxis axis) const {
-				return m_curr.axis[(int)axis];
+				return m_curr.axis[(int) axis];
 			}
 
 			inline float axisDelta(MouseAxis axis) const {
-				return m_curr.axis[(int)axis] - m_prev.axis[(int)axis];
+				return m_curr.axis[(int) axis] - m_prev.axis[(int) axis];
 			}
 
 			inline void button(MouseButton btn, bool state) {
-				m_curr.buttons[(int)btn] = state;
+				m_curr.buttons[(int) btn] = state;
 			}
 
 			inline bool down(MouseButton btn) const {
-				return m_curr.buttons[(int)btn];
+				return m_curr.buttons[(int) btn];
 			}
 
 			inline bool downPrev(MouseButton btn) const {
-				return m_prev.buttons[(int)btn];
+				return m_prev.buttons[(int) btn];
 			}
 
 			inline bool pressed(MouseButton btn) const {
-				return m_curr.buttons[(int)btn] && !m_prev.buttons[(int)btn];
+				return m_curr.buttons[(int) btn] && !m_prev.buttons[(int) btn];
 			}
 
 			inline bool released(MouseButton btn) const {
-				return !m_curr.buttons[(int)btn] && m_prev.buttons[(int)btn];
+				return !m_curr.buttons[(int) btn] && m_prev.buttons[(int) btn];
 			}
 
 		private:
diff --git a/include/fggl/math/easing.hpp b/include/fggl/math/easing.hpp
index db53218..9a1a82c 100644
--- a/include/fggl/math/easing.hpp
+++ b/include/fggl/math/easing.hpp
@@ -9,111 +9,110 @@
 
 namespace fggl::math {
 
-    inline float lerp(float a, float b, float w) {
-        return (b - a) * w + a;
-    }
-
-    inline float scale(float in, float inMin, float inMax, float outMin, float outMax) {
-        return ( (in - inMin) * (outMax - outMin) ) / (inMax - inMin);
-    }
-
-    //
-    // Functions
-    //
-    using transformF = std::function<float(float)>;
-
-    inline float scaleFilter(float in, float inMin, float inMax, float outMin, float outMax, transformF filter) {
-        float out = in - inMin;
-        out /= (inMax - inMin);
-        out = f(out);
-        out *= (outEnd - outStart);
-        return out + outMin;
-    }
-
-    inline float mix(transformF a, transformF b, float weightB, float t) {
-        return ( (1 - weightB) * a(t) ) + (  weightB * b(t) );
-    }
-
-    inline float crossFade( transformF a, transformF b, float t) {
-        return ((1 - t) * a(t))+ (t * b);
-    }
-
-    //
-    // building blocks
-    //
-    inline float scale(transformF a, float t) {
-        return t * f(t);
-    }
-
-    inline float reverseScale(transformF a, float t) {
-        return (1 - t) * a(t);
-    }
-
-    inline float Arch2(float t) {
-        return t * (1 - t);
-    }
-
-    inline float BounceClampBottom( float t ){
-        return fabs(t);
-    }
-
-    inline float BounceClampTop( float t ) {
-        return 1.f - fabs( 1.f - t );
-    }
-
-    //
-    // Easing function library
-    // see Math for Game Programmers: Fast and Funky 1D Nonlinear Transformations, GDC 2015
-    //
-
-    inline float SmoothStart2(float t) {
-        return t * t;
-    }
-
-    inline float SmoothStart3(float t) {
-        return t * t * t;
-    }
-
-    inline float SmoothStart4(float t) {
-        return t * t * t * t;
-    }
-
-    inline float SmoothStart5(float t) {
-        return t * t * t * t * t;
-    }
-
-    inline float SmoothStop2(float t) {
-        constexpr tFlip = 1 - y;
-        return 1 - (tFlip * tFlip);
-    }
-
-    inline float SmoothStop3(float t) {
-        constexpr tFlip = 1 - y;
-        return 1 - (tFlip * tFlip);
-    }
-
-    inline float SmoothStop4(float t) {
-        constexpr tFlip = 1 - y;
-        return 1 - (tFlip * tFlip * tFlip * tFlip);
-    }
-
-    inline float SmoothStop5(float t) {
-        constexpr tFlip = 1 - y;
-        return 1 - (tFlip * tFlip * tFlip * tFlip * tFlip);
-    }
-
-    //
-    // Bezier curves
-    //
-
-    inline float NormalizedBezier3( float B, float C, float t) {
-        const float s = 1.f - t;
-        const float t2 = t * t;
-        const float s2 = s * s;
-        const float t3 = t2 * t;
-        return (3.f*B*s2*t) + (3.f*C*s*t2) + t3;
-    }
-
+	inline float lerp(float a, float b, float w) {
+		return (b - a) * w + a;
+	}
+
+	inline float scale(float in, float inMin, float inMax, float outMin, float outMax) {
+		return ((in - inMin) * (outMax - outMin)) / (inMax - inMin);
+	}
+
+	//
+	// Functions
+	//
+	using transformF = std::function<float(float)>;
+
+	inline float scaleFilter(float in, float inMin, float inMax, float outMin, float outMax, transformF filter) {
+		float out = in - inMin;
+		out /= (inMax - inMin);
+		out = f(out);
+		out *= (outEnd - outStart);
+		return out + outMin;
+	}
+
+	inline float mix(transformF a, transformF b, float weightB, float t) {
+		return ((1 - weightB) * a(t)) + (weightB * b(t));
+	}
+
+	inline float crossFade(transformF a, transformF b, float t) {
+		return ((1 - t) * a(t)) + (t * b);
+	}
+
+	//
+	// building blocks
+	//
+	inline float scale(transformF a, float t) {
+		return t * f(t);
+	}
+
+	inline float reverseScale(transformF a, float t) {
+		return (1 - t) * a(t);
+	}
+
+	inline float Arch2(float t) {
+		return t * (1 - t);
+	}
+
+	inline float BounceClampBottom(float t) {
+		return fabs(t);
+	}
+
+	inline float BounceClampTop(float t) {
+		return 1.f - fabs(1.f - t);
+	}
+
+	//
+	// Easing function library
+	// see Math for Game Programmers: Fast and Funky 1D Nonlinear Transformations, GDC 2015
+	//
+
+	inline float SmoothStart2(float t) {
+		return t * t;
+	}
+
+	inline float SmoothStart3(float t) {
+		return t * t * t;
+	}
+
+	inline float SmoothStart4(float t) {
+		return t * t * t * t;
+	}
+
+	inline float SmoothStart5(float t) {
+		return t * t * t * t * t;
+	}
+
+	inline float SmoothStop2(float t) {
+		constexpr tFlip = 1 - y;
+		return 1 - (tFlip * tFlip);
+	}
+
+	inline float SmoothStop3(float t) {
+		constexpr tFlip = 1 - y;
+		return 1 - (tFlip * tFlip);
+	}
+
+	inline float SmoothStop4(float t) {
+		constexpr tFlip = 1 - y;
+		return 1 - (tFlip * tFlip * tFlip * tFlip);
+	}
+
+	inline float SmoothStop5(float t) {
+		constexpr tFlip = 1 - y;
+		return 1 - (tFlip * tFlip * tFlip * tFlip * tFlip);
+	}
+
+	//
+	// Bezier curves
+	//
+
+	inline float NormalizedBezier3(float B, float C, float t) {
+		const float s = 1.f - t;
+		const float t2 = t * t;
+		const float s2 = s * s;
+		const float t3 = t2 * t;
+		return (3.f * B * s2 * t) + (3.f * C * s * t2) + t3;
+	}
 
 }
 
diff --git a/include/fggl/math/triangulation.hpp b/include/fggl/math/triangulation.hpp
index 9861a1d..fa7a20f 100644
--- a/include/fggl/math/triangulation.hpp
+++ b/include/fggl/math/triangulation.hpp
@@ -6,157 +6,156 @@
 
 namespace fggl::math {
 
-    using Polygon = std::vector<math::vec2>;
-    using PolygonVertex = std::vector<data::Vertex2D>;
-
-    constexpr int POSITIVE = 1;
-    constexpr int NEGATIVE = -1;
-    constexpr int UNSET = 0;
-
-    /**
-     * Put an angle in the range [-PI, PI].
-     */
-    inline float clampAngle( float radianAngle ) {
-        if ( radianAngle <= M_PI ) {
-            return radianAngle + M_PI_2;
-        } else if ( radianAngle > M_PI ) {
-            return radianAngle - M_PI_2;
-        } else {
-            return radianAngle;
-        }
-    }
-
-    static void checkSign( float value, int& sign, int& firstSign, int& flips ) {
-        if ( value > 0 ) {
-            if ( sign == UNSET ) {
-                firstSign = POSITIVE;
-            } else if ( sign < 0 ) {
-                flips++;
-            }
-        } else if ( value < 0 ) {
-            if ( sign == UNSET ) {
-                firstSign = NEGATIVE;
-            } else if ( sign > 0 ) {
-                flips++;
-            }
-            sign = NEGATIVE;
-        }
-    }
-
-    /**
-     * Check if a polygon is convex.
-     *
-     * see https://math.stackexchange.com/a/1745427
-     */
-    bool isConvex(const Polygon& polygon) {
-        if ( polygon.size() < 3 ) {
-            return false;
-        }
-
-        const auto n = polygon.size();
-
-        auto wSign = UNSET;
-
-        auto xSign = UNSET;
-        auto xFirstSign = UNSET;
-        auto xFlips = 0;
-
-        auto ySign = UNSET;
-        auto yFirstSign = UNSET;
-        auto yFlips = 0;
-
-        auto curr = polygon[ n - 1 ];
-        auto next = polygon[ n ];
-
-        for ( auto& v : polygon ) {
-            auto prev = curr;
-            curr = next;
-            next = v;
-
-            auto before = curr - prev;
-            auto after = next - curr;
-
-            checkSign( after.x, xSign, xFirstSign, xFlips );
-            if ( xFlips > 2 ) {
-                return false;
-            }
-
-            checkSign( after.y, ySign, yFirstSign, yFlips );
-            if ( yFlips > 2 ) {
-                return false;
-            }
-
-            auto w = before.x * after.y - after.x * before.y;
-            if ( wSign == UNSET && w != 0 ) {
-                wSign = w;
-            } else if ( wSign > 0 && w < 0 ) {
-                return false;
-            } else if ( wSign < 0 && w > 0 ){
-                return false;
-            }
-        }
-
-        if ( xSign != UNSET && ( xFirstSign != UNSET ) && ( xSign != xFirstSign ) ) {
-            xFlips += 1;
-        }
-        if ( ySign != UNSET && ( yFirstSign != UNSET ) && ( ySign != yFirstSign ) ) {
-            yFlips += 1;
-        }
-        if ( xFlips != 2 || yFlips != 2 ) {
-            return false;
-        }
-
-        return true;
-    }
-
-    static data::Vertex2D pointToVertex( const math::vec2& point ) {
-        return data::Vertex2D{
-            .position = point,
-            .colour = {1.0f, 1.0f, 1.0f}
-        };
-    }
-
-    /**
-     * Fast Triangulation for convex polygons.
-     */
-    void fanTriangulation(const Polygon& polygon, data::Mesh2D& mesh) {
-        assert(polygon.size() >= 3);
-
-        // add the first two points to the mesh
-        auto firstIdx = mesh.add_vertex( pointToVertex(polygon[0]) );
-        auto prevIdx = mesh.add_vertex( pointToVertex(polygon[1]) );
-
-        // deal with the indicies
-        const auto nTris = polygon.size() - 2;
-        for ( auto i=0; i < nTris; i++ ) {
-            mesh.add_index( firstIdx );
-            mesh.add_index( prevIdx );
-
-            auto currIdx = mesh.add_vertex( pointToVertex(polygon[i + 2]) );
-            mesh.add_index( currIdx );
-            prevIdx = currIdx;
-        }
-    }
-
-    void fanTriangulation(const PolygonVertex polygon, data::Mesh2D& mesh) {
-        assert(polygon.size() >= 3);
-
-        // add the first two points to the mesh
-        auto firstIdx = mesh.add_vertex( polygon[0] );
-        auto prevIdx = mesh.add_vertex( polygon[1] );
-
-        // deal with the indicies
-        const auto nTris = polygon.size() - 2;
-        for ( auto i=0; i < nTris; i++ ) {
-            mesh.add_index( firstIdx );
-            mesh.add_index( prevIdx );
-
-            auto currIdx = mesh.add_vertex( polygon[i + 2] );
-            mesh.add_index( currIdx );
-            prevIdx = currIdx;
-        }
-    }
-
+	using Polygon = std::vector<math::vec2>;
+	using PolygonVertex = std::vector<data::Vertex2D>;
+
+	constexpr int POSITIVE = 1;
+	constexpr int NEGATIVE = -1;
+	constexpr int UNSET = 0;
+
+	/**
+	 * Put an angle in the range [-PI, PI].
+	 */
+	inline float clampAngle(float radianAngle) {
+		if (radianAngle <= M_PI) {
+			return radianAngle + M_PI_2;
+		} else if (radianAngle > M_PI) {
+			return radianAngle - M_PI_2;
+		} else {
+			return radianAngle;
+		}
+	}
+
+	static void checkSign(float value, int &sign, int &firstSign, int &flips) {
+		if (value > 0) {
+			if (sign == UNSET) {
+				firstSign = POSITIVE;
+			} else if (sign < 0) {
+				flips++;
+			}
+		} else if (value < 0) {
+			if (sign == UNSET) {
+				firstSign = NEGATIVE;
+			} else if (sign > 0) {
+				flips++;
+			}
+			sign = NEGATIVE;
+		}
+	}
+
+	/**
+	 * Check if a polygon is convex.
+	 *
+	 * see https://math.stackexchange.com/a/1745427
+	 */
+	bool isConvex(const Polygon &polygon) {
+		if (polygon.size() < 3) {
+			return false;
+		}
+
+		const auto n = polygon.size();
+
+		auto wSign = UNSET;
+
+		auto xSign = UNSET;
+		auto xFirstSign = UNSET;
+		auto xFlips = 0;
+
+		auto ySign = UNSET;
+		auto yFirstSign = UNSET;
+		auto yFlips = 0;
+
+		auto curr = polygon[n - 1];
+		auto next = polygon[n];
+
+		for (auto &v : polygon) {
+			auto prev = curr;
+			curr = next;
+			next = v;
+
+			auto before = curr - prev;
+			auto after = next - curr;
+
+			checkSign(after.x, xSign, xFirstSign, xFlips);
+			if (xFlips > 2) {
+				return false;
+			}
+
+			checkSign(after.y, ySign, yFirstSign, yFlips);
+			if (yFlips > 2) {
+				return false;
+			}
+
+			auto w = before.x * after.y - after.x * before.y;
+			if (wSign == UNSET && w != 0) {
+				wSign = w;
+			} else if (wSign > 0 && w < 0) {
+				return false;
+			} else if (wSign < 0 && w > 0) {
+				return false;
+			}
+		}
+
+		if (xSign != UNSET && (xFirstSign != UNSET) && (xSign != xFirstSign)) {
+			xFlips += 1;
+		}
+		if (ySign != UNSET && (yFirstSign != UNSET) && (ySign != yFirstSign)) {
+			yFlips += 1;
+		}
+		if (xFlips != 2 || yFlips != 2) {
+			return false;
+		}
+
+		return true;
+	}
+
+	static data::Vertex2D pointToVertex(const math::vec2 &point) {
+		return data::Vertex2D{
+			.position = point,
+			.colour = {1.0f, 1.0f, 1.0f}
+		};
+	}
+
+	/**
+	 * Fast Triangulation for convex polygons.
+	 */
+	void fanTriangulation(const Polygon &polygon, data::Mesh2D &mesh) {
+		assert(polygon.size() >= 3);
+
+		// add the first two points to the mesh
+		auto firstIdx = mesh.add_vertex(pointToVertex(polygon[0]));
+		auto prevIdx = mesh.add_vertex(pointToVertex(polygon[1]));
+
+		// deal with the indicies
+		const auto nTris = polygon.size() - 2;
+		for (auto i = 0; i < nTris; i++) {
+			mesh.add_index(firstIdx);
+			mesh.add_index(prevIdx);
+
+			auto currIdx = mesh.add_vertex(pointToVertex(polygon[i + 2]));
+			mesh.add_index(currIdx);
+			prevIdx = currIdx;
+		}
+	}
+
+	void fanTriangulation(const PolygonVertex polygon, data::Mesh2D &mesh) {
+		assert(polygon.size() >= 3);
+
+		// add the first two points to the mesh
+		auto firstIdx = mesh.add_vertex(polygon[0]);
+		auto prevIdx = mesh.add_vertex(polygon[1]);
+
+		// deal with the indicies
+		const auto nTris = polygon.size() - 2;
+		for (auto i = 0; i < nTris; i++) {
+			mesh.add_index(firstIdx);
+			mesh.add_index(prevIdx);
+
+			auto currIdx = mesh.add_vertex(polygon[i + 2]);
+			mesh.add_index(currIdx);
+			prevIdx = currIdx;
+		}
+	}
 
 } // namespace fggl::util
 
diff --git a/include/fggl/math/types.hpp b/include/fggl/math/types.hpp
index 4d12beb..4730553 100644
--- a/include/fggl/math/types.hpp
+++ b/include/fggl/math/types.hpp
@@ -12,84 +12,91 @@ namespace fggl::math {
 
 	// math types (aliased for ease of use)
 	using vec4 = glm::vec4;
+
 	using vec3 = glm::vec3;
+	using vec3i = glm::ivec3;
+	using vec3f = glm::vec3;
+
 	using vec2 = glm::vec2;
+	using vec2i = glm::ivec2;
+	using vec2f = glm::vec2;
+
 	using mat4 = glm::mat4;
 	using quat = glm::quat;
 
-    // fastFloor from OpenSimplex2
-    inline int fastFloor(double x) {
-        int xi = (int)x;
-        return x < xi ? xi - 1 : xi;
-    }
+	// fastFloor from OpenSimplex2
+	inline int fastFloor(double x) {
+		int xi = (int) x;
+		return x < xi ? xi - 1 : xi;
+	}
 
 	// reference vectors
-	constexpr vec3 UP { 0.0f, 1.0f, 0.0f };
-	constexpr vec3 FORWARD { 1.0f, 0.0f, 0.0f };
-	constexpr vec3 RIGHT { 0.0f, 0.0f, 1.0f };
+	constexpr vec3f UP{0.0f, 1.0f, 0.0f};
+	constexpr vec3f FORWARD{1.0f, 0.0f, 0.0f};
+	constexpr vec3f RIGHT{0.0f, 0.0f, 1.0f};
 
-	inline glm::mat4 modelMatrix( const vec3 offset, const quat rotation ) {
-		return glm::translate( glm::mat4(1.0f), offset ) * glm::toMat4( rotation );
+	inline glm::mat4 modelMatrix(const vec3 offset, const quat rotation) {
+		return glm::translate(glm::mat4(1.0f), offset) * glm::toMat4(rotation);
 	}
 
-	inline glm::mat4 modelMatrix( glm::vec3 offset, glm::vec3 eulerAngles ) {
-		return modelMatrix( offset, glm::quat( eulerAngles ) );
+	inline glm::mat4 modelMatrix(glm::vec3 offset, glm::vec3 eulerAngles) {
+		return modelMatrix(offset, glm::quat(eulerAngles));
 	}
 
 	struct Transform {
-        constexpr static const char name[] = "Transform";
-
-		Transform() : m_local(1.0f), m_origin(0.0f), m_model(1.0f), m_rotation() {
-		}
-
-		// local reference vectors
-		[[nodiscard]]
-		inline vec3 up() const {
-			return vec4( UP, 1.0 ) * m_local;
-		}
-
-		[[nodiscard]]
-		inline vec3 forward() const {
-			return vec4( FORWARD, 1.0 ) * m_local;
-		}
-
-		[[nodiscard]]
-		inline vec3 right() const {
-			return vec4( RIGHT, 1.0 ) * m_local;
-		}
-
-		inline void translate(const vec3 change) {
-			m_origin += change;
-			update();
-		}
-
-		inline void origin(const vec3 pos) {
-			m_origin = pos;
-			update();
-		}
-
-		[[nodiscard]]
-		inline vec3 origin() const {
-			return m_origin;
-		}
-
-		inline void euler(vec3 angles) {
-			m_rotation = quat( angles );
-			update();
-		}
-
-		[[nodiscard]]
-		inline glm::vec3 euler() const {
-			return glm::eulerAngles(m_rotation);
-		}
-
-		inline mat4 model() const {
-			mat4 tmp(1.0f);
-			tmp = glm::translate(tmp, m_origin);
-			tmp = tmp * glm::toMat4(m_rotation);
-
-			return tmp;
-		}
+			constexpr static const char name[] = "Transform";
+
+			Transform() : m_local(1.0f), m_origin(0.0f), m_model(1.0f), m_rotation() {
+			}
+
+			// local reference vectors
+			[[nodiscard]]
+			inline vec3 up() const {
+				return vec4(UP, 1.0) * m_local;
+			}
+
+			[[nodiscard]]
+			inline vec3 forward() const {
+				return vec4(FORWARD, 1.0) * m_local;
+			}
+
+			[[nodiscard]]
+			inline vec3 right() const {
+				return vec4(RIGHT, 1.0) * m_local;
+			}
+
+			inline void translate(const vec3 change) {
+				m_origin += change;
+				update();
+			}
+
+			inline void origin(const vec3 pos) {
+				m_origin = pos;
+				update();
+			}
+
+			[[nodiscard]]
+			inline vec3 origin() const {
+				return m_origin;
+			}
+
+			inline void euler(vec3 angles) {
+				m_rotation = quat(angles);
+				update();
+			}
+
+			[[nodiscard]]
+			inline glm::vec3 euler() const {
+				return glm::eulerAngles(m_rotation);
+			}
+
+			inline mat4 model() const {
+				mat4 tmp(1.0f);
+				tmp = glm::translate(tmp, m_origin);
+				tmp = tmp * glm::toMat4(m_rotation);
+
+				return tmp;
+			}
 
 		private:
 			mat4 m_local; // us -> parent
@@ -100,7 +107,7 @@ namespace fggl::math {
 			inline void update() {
 				mat4 t(1.0f);
 				t *= glm::toMat4(m_rotation);
-				t = glm::translate( t, m_origin );
+				t = glm::translate(t, m_origin);
 				m_local = t;
 			}
 	};
@@ -110,11 +117,10 @@ namespace fggl::math {
 
 // feels a bit strange to be doing this...
 namespace glm {
-	inline bool operator<(const vec3& lhs, const vec3& rhs) {
-		return std::tie( lhs.x, lhs.y, lhs.z )
-		      < std::tie( rhs.x, rhs.y, rhs.z );
+	inline bool operator<(const vec3 &lhs, const vec3 &rhs) {
+		return std::tie(lhs.x, lhs.y, lhs.z)
+			< std::tie(rhs.x, rhs.y, rhs.z);
 	}
 }
 
-
 #endif
diff --git a/include/fggl/scenes/Scene.h b/include/fggl/scenes/Scene.h
index d4c9daf..0ca9987 100644
--- a/include/fggl/scenes/Scene.h
+++ b/include/fggl/scenes/Scene.h
@@ -11,38 +11,42 @@
 
 namespace fggl::scenes {
 
-    class Scene {
-        public:
-            virtual ~Scene() = default;
-
-            virtual void setup() = 0;
-            virtual void cleanup() = 0;
-
-            virtual void update() = 0;
-            virtual void render() = 0;
-    };
-
-    class SceneManager {
-        public:
-            SceneManager() = default;
-
-            void create(const std::string& name, std::shared_ptr<Scene> scene);
-            void activate(const std::string& name);
-
-            inline void update() {
-                if ( m_active == nullptr ) { return; }
-                m_active->update();
-            }
-
-            inline void render() {
-                if ( m_active == nullptr ) { return; }
-                m_active->render();
-            }
-
-        private:
-            std::shared_ptr<Scene> m_active;
-            std::unordered_map<std::string, std::shared_ptr<Scene>> m_scenes;
-    };
+	class Scene {
+		public:
+			virtual ~Scene() = default;
+
+			virtual void setup() = 0;
+			virtual void cleanup() = 0;
+
+			virtual void update() = 0;
+			virtual void render() = 0;
+	};
+
+	class SceneManager {
+		public:
+			SceneManager() = default;
+
+			void create(const std::string &name, std::shared_ptr<Scene> scene);
+			void activate(const std::string &name);
+
+			inline void update() {
+				if (m_active == nullptr) {
+					return;
+				}
+				m_active->update();
+			}
+
+			inline void render() {
+				if (m_active == nullptr) {
+					return;
+				}
+				m_active->render();
+			}
+
+		private:
+			std::shared_ptr<Scene> m_active;
+			std::unordered_map<std::string, std::shared_ptr<Scene>> m_scenes;
+	};
 
 }
 
diff --git a/include/fggl/scenes/menu.hpp b/include/fggl/scenes/menu.hpp
index 14cd63e..6e36489 100644
--- a/include/fggl/scenes/menu.hpp
+++ b/include/fggl/scenes/menu.hpp
@@ -11,28 +11,28 @@
 
 namespace fggl::scenes {
 
-    using callback = std::function<void(void)>;
+	using callback = std::function<void(void)>;
 
-    class BasicMenu : public AppState {
-        public:
-            BasicMenu(App& owner);
+	class BasicMenu : public AppState {
+		public:
+			BasicMenu(App &owner);
 
-            void update() override;
-            void render(gfx::Paint& paint) override;
+			void update() override;
+			void render(gfx::Paint &paint) override;
 
-            void activate() override;
-            void deactivate() override;
+			void activate() override;
+			void deactivate() override;
 
-            void add(const std::string& label, callback cb);
+			void add(const std::string &label, callback cb);
 
-        private:
-            std::shared_ptr<input::Input> m_inputs;
-            std::map<const std::string, callback> m_items;
+		private:
+			std::shared_ptr<input::Input> m_inputs;
+			std::map<const std::string, callback> m_items;
 
-            // menu state
-            std::string m_active;
-            math::vec2 m_cursorPos;
-    };
+			// menu state
+			std::string m_active;
+			math::vec2 m_cursorPos;
+	};
 
 } // namepace fggl::scenes
 
diff --git a/include/fggl/util/chrono.hpp b/include/fggl/util/chrono.hpp
index 64ca2e3..bca8312 100644
--- a/include/fggl/util/chrono.hpp
+++ b/include/fggl/util/chrono.hpp
@@ -4,7 +4,7 @@
 namespace fggl::util {
 
 	class Timer {
-		using time_t = unsigned long;
+			using time_t = unsigned long;
 		public:
 			inline void frequency(float freq) {
 				m_freq = freq;
diff --git a/include/fggl/util/service.h b/include/fggl/util/service.h
index 4fe8bd8..d7f6044 100644
--- a/include/fggl/util/service.h
+++ b/include/fggl/util/service.h
@@ -11,42 +11,42 @@
 
 namespace fggl::util {
 
-    class ServiceLocator {
-        inline static ServiceLocator *s_instance;
-        std::unordered_map<std::type_index, std::shared_ptr<void>> m_services;
-        ServiceLocator() = default;
-
-    public:
-        // don't allow copying or moving
-        ServiceLocator(ServiceLocator& other) = delete;
-        ServiceLocator(ServiceLocator&& other) = delete;
-
-        static ServiceLocator& instance() {
-            if ( s_instance == nullptr ) {
-                s_instance = new ServiceLocator();
-            }
-            return *s_instance;
-        }
-
-        template<typename T>
-        void supply(std::shared_ptr<T> ptr) {
-            auto info = std::type_index(typeid(T));
-            m_services[info] = ptr;
-        }
-
-        template<typename T>
-        std::shared_ptr<T> get() {
-            auto info = std::type_index(typeid(T));
-            return std::static_pointer_cast<T>(m_services.at(info));
-        }
-
-        template<typename T>
-        std::shared_ptr<T> providePtr() {
-            auto info = std::type_index(typeid(T));
-            return std::static_pointer_cast<T>(m_services.at(info));
-        }
-
-    };
+	class ServiceLocator {
+			inline static ServiceLocator *s_instance;
+			std::unordered_map<std::type_index, std::shared_ptr<void>> m_services;
+			ServiceLocator() = default;
+
+		public:
+			// don't allow copying or moving
+			ServiceLocator(ServiceLocator &other) = delete;
+			ServiceLocator(ServiceLocator &&other) = delete;
+
+			static ServiceLocator &instance() {
+				if (s_instance == nullptr) {
+					s_instance = new ServiceLocator();
+				}
+				return *s_instance;
+			}
+
+			template<typename T>
+			void supply(std::shared_ptr<T> ptr) {
+				auto info = std::type_index(typeid(T));
+				m_services[info] = ptr;
+			}
+
+			template<typename T>
+			std::shared_ptr<T> get() {
+				auto info = std::type_index(typeid(T));
+				return std::static_pointer_cast<T>(m_services.at(info));
+			}
+
+			template<typename T>
+			std::shared_ptr<T> providePtr() {
+				auto info = std::type_index(typeid(T));
+				return std::static_pointer_cast<T>(m_services.at(info));
+			}
+
+	};
 
 }
 
diff --git a/include/fggl/util/states.hpp b/include/fggl/util/states.hpp
index 29067a7..1eb2970 100644
--- a/include/fggl/util/states.hpp
+++ b/include/fggl/util/states.hpp
@@ -28,50 +28,50 @@
 
 namespace fggl::util {
 
-    template<typename S, typename I>
-    class StateMachine {
-        public:
-            using Identifer = I;
-            using StateType = S;
-
-            StateMachine() = default;
-            ~StateMachine() = default;
-
-            // class is non copy-able
-            StateMachine(const StateMachine& app) = delete;
-            StateMachine& operator=(StateMachine other) = delete;
-
-            template<typename T, typename... Args>
-            T* put(const Identifer& name, Args&&... args) {
-                static_assert( std::is_base_of<StateType,T>::value, "States must be AppStates");
-                m_states[name] = std::make_unique<T>( std::forward<Args...>(args...) );
-
-                // no active scene? first is the active one
-                if ( m_active.empty() ) {
-                    m_active = name;
-                }
-
-                return (T*)(m_states[name].get());
-            }
-
-            void change(const Identifer& name) {
-                assertm( m_states.find(name) != m_states.end(), "state does not exist");
-
-                active().deactivate();
-                m_active = name;
-                active().activate();
-            }
-
-            StateType& active() const {
-                assertm( m_states.find(m_active) != m_states.end(), "active state does not exist!");
-                return *(m_states.at( m_active ).get());
-            }
-
-        private:
-            Identifer m_active;
-            std::unordered_map<Identifer, std::unique_ptr<StateType>> m_states;
-
-    };
+	template<typename S, typename I>
+	class StateMachine {
+		public:
+			using Identifer = I;
+			using StateType = S;
+
+			StateMachine() = default;
+			~StateMachine() = default;
+
+			// class is non copy-able
+			StateMachine(const StateMachine &app) = delete;
+			StateMachine &operator=(StateMachine other) = delete;
+
+			template<typename T, typename... Args>
+			T *put(const Identifer &name, Args &&... args) {
+				static_assert(std::is_base_of<StateType, T>::value, "States must be AppStates");
+				m_states[name] = std::make_unique<T>(std::forward<Args...>(args...));
+
+				// no active scene? first is the active one
+				if (m_active.empty()) {
+					m_active = name;
+				}
+
+				return (T *) (m_states[name].get());
+			}
+
+			void change(const Identifer &name) {
+				assertm(m_states.find(name) != m_states.end(), "state does not exist");
+
+				active().deactivate();
+				m_active = name;
+				active().activate();
+			}
+
+			StateType &active() const {
+				assertm(m_states.find(m_active) != m_states.end(), "active state does not exist!");
+				return *(m_states.at(m_active).get());
+			}
+
+		private:
+			Identifer m_active;
+			std::unordered_map<Identifer, std::unique_ptr<StateType>> m_states;
+
+	};
 
 }
 
-- 
GitLab