diff --git a/demo/main.cpp b/demo/main.cpp
index d865c9897f0b5137a5038126b01ea69c34db7cb8..f68e2890cac0924d2b20a8857552291aca38ce5c 100644
--- a/demo/main.cpp
+++ b/demo/main.cpp
@@ -60,6 +60,114 @@ void loadShader(fggl::gfx::ShaderCache& cache, const char* name, bool hasGeom) {
 	cache.load(config);
 }
 
+void debugJoystickWindow( bool* visible, fggl::gfx::Input& input ) {
+	if ( ! *visible ) {
+		return;
+	}
+
+	ImGui::Begin("Joysticks", visible);
+	for ( int i=0; i<16; i++ ) {
+		bool present = input.hasJoystick(i);
+		std::string title = "Joystick " + std::to_string(i);
+
+		if ( ImGui::TreeNode(title.c_str()) ) {
+			ImGui::Text("present: %s", present ? "yes" : "no" );
+
+			if ( present ) {
+				const fggl::gfx::Joystick& joyData = input.joystick(i);
+				ImGui::Text( "%s", joyData.name );
+				ImGui::Text( "gamepad: %s", joyData.gamepad ? "yes" : "no" );
+				ImGui::Text( "axes: %d, buttons: %d, hats: %d",
+						joyData.axisCount,
+						joyData.buttonCount,
+						joyData.hatCount);
+
+				if (ImGui::TreeNode("axis##2")) {
+					// dump data
+					for ( int axid = 0; axid < joyData.axisCount; axid++ ) {
+						ImGui::Text("axis %d, value: %f", 
+								axid, joyData.axes[axid] );
+					}
+					ImGui::TreePop();
+				}
+
+				if (ImGui::TreeNode("buttons##2")) {
+					// dump data
+					for ( int btnid = 0; btnid < joyData.buttonCount; btnid++ ) {
+						ImGui::Text("button %d, value: %s", btnid,
+								joyData.buttons[btnid] == GLFW_PRESS
+								? "down" : "up" );
+					}
+					ImGui::TreePop();
+				}
+
+				if (ImGui::TreeNode("hats##2")) {
+					// dump data
+					for ( int btnid = 0; btnid < joyData.hatCount; btnid++ ) {
+						ImGui::Text("button %d, value: %d",
+								btnid, joyData.hats[btnid] );
+					}
+					ImGui::TreePop();
+				}
+			}
+
+			ImGui::TreePop();
+			ImGui::Separator();
+		}
+
+	}
+	ImGui::End();
+}
+
+void debugGamepadWindow( bool* visible, fggl::gfx::Input& input ) {
+	if ( ! *visible ) {
+		return;
+	}
+
+	ImGui::Begin("GamePad", visible);
+	for ( int i=0; i<16; i++ ) {
+		std::string title = "GamePad " + std::to_string(i);
+
+		bool present = input.hasJoystick(i);
+		if ( ImGui::TreeNode(title.c_str()) ) {
+			ImGui::Text("present: %s", present ? "yes" : "no" );
+
+			if ( present ) {
+
+				if ( ImGui::TreeNode("buttons##2") ) {
+					for ( auto& btn : fggl::gfx::PadButtons ) {
+						auto label = fggl::gfx::PadButtonLabels[ (int) btn ];
+						ImGui::Text( "%s: %i %i %i", label.c_str(), 
+								input.padDown(i, btn),
+								input.padPressed(i, btn),
+								input.padReleased(i, btn)
+							   );
+					}
+					ImGui::TreePop();
+				}
+
+				if ( ImGui::TreeNode("axes##2") ) {
+					for ( auto& axis : fggl::gfx::PadAxes ) {
+						auto label = fggl::gfx::PadAxisLabels[ (int) axis ];
+						ImGui::Text("%s: %f %f", label.c_str(),
+								input.padAxis(i, axis),
+								input.padAxisDelta(i, axis)
+							   );
+
+					}
+					ImGui::TreePop();
+				}
+
+			}
+
+			ImGui::TreePop();
+			ImGui::Separator();
+		}
+
+	}
+	ImGui::End();
+}
+
 int main(int argc, char* argv[]) {
 	fggl::gfx::Context ctx;
 
@@ -96,6 +204,7 @@ int main(int argc, char* argv[]) {
 	world.import<fggl::systems::OpenGL>();
 	world.import<fggl::systems::CameraInput>();
 
+	// NB until input handling and frame management is fixed, this singleton is needed...
 	world.ecs().set<fggl::components::GfxHacks>({ &win });
 
 	// make camera
@@ -179,107 +288,9 @@ int main(int argc, char* argv[]) {
 		// update step
 		time += dt;
 
-		// imgui joystick debug
-		if ( joystickWindow ) {
-			ImGui::Begin("Joysticks", &joystickWindow);
-			for ( int i=0; i<16; i++ ) {
-				bool present = input.hasJoystick(i);
-				std::string title = "Joystick " + std::to_string(i);
-
-				if ( ImGui::TreeNode(title.c_str()) ) {
-					ImGui::Text("present: %s", present ? "yes" : "no" );
-
-					if ( present ) {
-						const fggl::gfx::Joystick& joyData = input.joystick(i);
-						ImGui::Text( "%s", joyData.name );
-						ImGui::Text( "gamepad: %s", joyData.gamepad ? "yes" : "no" );
-						ImGui::Text( "axes: %d, buttons: %d, hats: %d",
-								joyData.axisCount,
-								joyData.buttonCount,
-								joyData.hatCount);
-
-						if (ImGui::TreeNode("axis##2")) {
-							// dump data
-							for ( int axid = 0; axid < joyData.axisCount; axid++ ) {
-								ImGui::Text("axis %d, value: %f", 
-										axid, joyData.axes[axid] );
-							}
-							ImGui::TreePop();
-						}
-
-						if (ImGui::TreeNode("buttons##2")) {
-							// dump data
-							for ( int btnid = 0; btnid < joyData.buttonCount; btnid++ ) {
-								ImGui::Text("button %d, value: %s", btnid,
-										joyData.buttons[btnid] == GLFW_PRESS
-										? "down" : "up" );
-							}
-							ImGui::TreePop();
-						}
-
-						if (ImGui::TreeNode("hats##2")) {
-							// dump data
-							for ( int btnid = 0; btnid < joyData.hatCount; btnid++ ) {
-								ImGui::Text("button %d, value: %d",
-										btnid, joyData.hats[btnid] );
-							}
-							ImGui::TreePop();
-						}
-					}
-
-					ImGui::TreePop();
-					ImGui::Separator();
-				}
-
-			}
-			ImGui::End();
-		}
-
-		// imgui gamepad debug
-		if ( gamepadWindow ) {
-			ImGui::Begin("GamePad", &gamepadWindow);
-			for ( int i=0; i<16; i++ ) {
-				std::string title = "GamePad " + std::to_string(i);
-
-				bool present = input.hasJoystick(i);
-				if ( ImGui::TreeNode(title.c_str()) ) {
-					ImGui::Text("present: %s", present ? "yes" : "no" );
-
-					if ( present ) {
-
-						if ( ImGui::TreeNode("buttons##2") ) {
-							for ( auto& btn : fggl::gfx::PadButtons ) {
-								auto label = fggl::gfx::PadButtonLabels[ (int) btn ];
-								ImGui::Text( "%s: %i %i %i", label.c_str(), 
-										input.padDown(i, btn),
-										input.padPressed(i, btn),
-										input.padReleased(i, btn)
-									   );
-							}
-							ImGui::TreePop();
-						}
-
-						if ( ImGui::TreeNode("axes##2") ) {
-							for ( auto& axis : fggl::gfx::PadAxes ) {
-								auto label = fggl::gfx::PadAxisLabels[ (int) axis ];
-								ImGui::Text("%s: %f %f", label.c_str(),
-										input.padAxis(i, axis),
-										input.padAxisDelta(i, axis)
-									   );
-
-							}
-							ImGui::TreePop();
-						}
-
-					}
-
-					ImGui::TreePop();
-					ImGui::Separator();
-				}
-
-			}
-			ImGui::End();
-		}
+		// imgui demos
+		debugJoystickWindow( &joystickWindow, input );
+		debugGamepadWindow( &gamepadWindow, input );
 
 		// render step
 		ogl.clear();