+void vg_register(void)
+{
+ SHADER_INIT( shader_tile_colour );
+}
+
+void vg_start(void)
+{
+ glGenVertexArrays( 1, &world.tile_vao );
+ glGenBuffers( 1, &world.tile_vbo );
+
+ float quad_mesh[] =
+ {
+ 0.05f, 0.05f, 0.05f, 0.95f, 0.95f, 0.95f,
+ 0.05f, 0.05f, 0.95f, 0.95f, 0.95f, 0.05f
+ };
+
+ glBindVertexArray( world.tile_vao );
+ glBindBuffer( GL_ARRAY_BUFFER, world.tile_vbo );
+ glBufferData
+ (
+ GL_ARRAY_BUFFER,
+ sizeof( quad_mesh ),
+ quad_mesh,
+ GL_STATIC_DRAW
+ );
+
+ glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0 );
+ glEnableVertexAttribArray( 0 );
+
+ VG_CHECK_GL();
+
+ map_load
+ (
+ "#############;\n"
+ "###-#####-###;aaa,aa\n"
+ "## ##;\n"
+ "## ##;\n"
+ "## ##;\n"
+ "## ##;\n"
+ "## ##;\n"
+ "## ##;\n"
+ "###+#####+###;aa,aaa\n"
+ "#############;\n"
+ );
+}
+
+void vg_free(void)
+{
+ glDeleteVertexArrays( 1, &world.tile_vao );
+ glDeleteBuffers( 1, &world.tile_vbo );
+
+ map_free();
+}
+
+void vg_update(void)
+{
+ float ratio = (float)vg_window_y / (float)vg_window_x;
+ float const size = 9.5f;
+
+ v3f origin;
+ origin[0] = -0.5f * world.w;
+ origin[1] = -0.5f * world.h;
+ origin[2] = 0.0f;
+
+ m3x3_projection( m_projection, -size, size, size*ratio, -size*ratio );
+ m3x3_identity( m_view );
+ m3x3_translate( m_view, origin );
+ m3x3_mul( m_projection, m_view, vg_pv );
+ vg_projection_update();
+
+ v2f tile_pos;
+ v2_copy( vg_mouse_ws, tile_pos );
+
+ int tile_x = floorf( tile_pos[0] );
+ int tile_y = floorf( tile_pos[1] );
+
+ if( tile_x >= 2 && tile_x < world.w-2 && tile_y >= 2 && tile_y <= world.h-2 )
+ {
+ world.selected = tile_y * world.w + tile_x;
+
+ struct cell *cell = &world.data[tile_y*world.w+tile_x];
+ if( cell->state & (FLAG_WALL|FLAG_INPUT|FLAG_OUTPUT) )
+ {
+ world.selected = -1;
+ }
+ else
+ {
+ if( vg_get_button_down("primary") )
+ {
+ cell->state ^= FLAG_CANAL;
+ }
+ }
+ }
+ else
+ world.selected = -1;
+
+ for( int y = 1; y < world.h-1; y ++ )
+ {
+ for( int x = 1; x < world.w-1; x ++ )
+ {
+ struct cell *cell = &world.data[y*world.w+x];
+
+ if( !(cell->state & FLAG_CANAL) )
+ cell->water = 0;
+
+ if( cell->state & FLAG_INPUT )
+ cell->water = 8;
+
+ if( cell->water )
+ {
+ v2i dirs[] = {{1,0},{0,1},{-1,0},{0,-1}};
+
+ for( int i = 0; i < vg_list_size( dirs ); i ++ )
+ {
+ struct cell *neighbour = &world.data[(y+dirs[i][1])*world.w+x+dirs[i][0]];
+
+ if( neighbour->state & FLAG_CANAL )
+ {
+ neighbour->water = vg_max( neighbour->water, cell->water-1 );
+ }
+ }
+
+ cell->water --;
+ }
+ }
+ }
+}
+
+void vg_render(void)