+ // Shadow layer
+ glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.5f, 0.5f, 0.5f, 1.0f );
+ for( int y = 0; y < world.h; y ++ )
+ for( int x = 0; x < world.w; x ++ )
+ {
+ struct cell *cell = pcell((v2i){x,y});
+
+ if( cell->state & FLAG_CANAL )
+ {
+ continue;
+ }
+
+ glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)x - 0.2f, (float)y - 0.15f, 1.0f );
+ draw_mesh( 0, 2 );
+ }
+
+ for( int y = 0; y < world.h; y ++ )
+ {
+ for( int x = 0; x < world.w; x ++ )
+ {
+ struct cell *cell = pcell((v2i){x,y});
+ int selected = world.selected == y*world.w + x;
+
+ if( cell->state & FLAG_SPLIT )
+ {
+ glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.9f, 0.9f, 0.9f, 1.0f );
+ glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)x, (float)y, 1.0f );
+
+ struct mesh *splitter = cell->state & FLAG_FLIP_FLOP? &world.splitter_r: &world.splitter_l;
+
+ use_mesh( splitter );
+ draw_mesh( 0, splitter->elements );
+ use_mesh( &world.tile );
+ }
+
+ if( (cell->state & FLAG_CANAL) && !selected )
+ continue;
+
+ glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)x, (float)y, 1.0f );
+
+ v4f colour;
+
+ if( cell->state & FLAG_WALL ) { v4_copy( (v4f){ 0.2f, 0.2f, 0.2f, 1.0f }, colour ); }
+ else if( cell->state & FLAG_CANAL ) { v4_copy( (v4f){ 0.6f, 0.6f, 0.6f, 1.0f }, colour ); }
+ else if( cell->state & FLAG_INPUT ) { v4_copy( (v4f){ 0.5f, 0.5f, 0.5f, 1.0f }, colour ); }
+ else if( cell->state & FLAG_OUTPUT ) { v4_copy( (v4f){ 0.2f, 0.7f, 0.3f, 1.0f }, colour ); }
+ else v4_copy( (v4f){ 0.9f, 0.9f, 0.9f, 1.0f }, colour );
+
+ //if( cell->water[world.frame&0x1] )
+ // v4_copy( (v4f){ 0.2f, 0.3f, 0.7f * (float)(cell->water[world.frame&0x1]) * (1.0f/16.0f), 1.0f }, colour );
+
+ if( selected )
+ v3_muls( colour, sinf( vg_time )*0.25f + 0.5f, colour );
+
+ //if( cell->state & (FLAG_SPLIT) )
+ // v4_copy( (v4f){ 0.75f, 0.75f, 0.02f, 1.0f }, colour );
+ //if( cell->state & (FLAG_MERGER) )
+ // v4_copy( (v4f){ 0.75f, 0.02f, 0.75f, 1.0f }, colour );
+
+ glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, colour );
+
+ draw_mesh( 0, 2 );
+ }
+ }
+
+ use_mesh( &world.circle );
+
+ // Draw i/o arrays
+ for( int i = 0; i < arrlen( world.io ); i ++ )
+ {
+ struct cell_terminal *term = &world.io[ i ];
+ int posx = term->id % world.w;
+ int posy = (term->id - posx)/world.w;
+ int is_input = world.data[ term->id ].state & FLAG_INPUT;
+
+ int const filled_start = 0;
+ int const filled_count = 32;
+ int const empty_start = 32;
+ int const empty_count = 32*2;
+
+ v4f dot_colour = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ for( int j = 0; j < arrlen( term->conditions ); j ++ )
+ {
+ glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + 0.2f, 0.1f );
+
+ if( is_input )
+ {
+ colour_code_v3( term->conditions[j], dot_colour );
+ glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour );
+
+ // Draw filled if tick not passed, draw empty if empty
+ if( world.sim_frame > j )
+ draw_mesh( empty_start, empty_count );
+ else
+ draw_mesh( filled_start, filled_count );
+ }
+ else
+ {
+ if( term->recv_count > j )
+ {
+ colour_code_v3( term->recv[j], dot_colour );
+ v3_muls( dot_colour, 0.8f, dot_colour );
+ glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour );
+
+ draw_mesh( filled_start, filled_count );
+ }
+
+ colour_code_v3( term->conditions[j], dot_colour );
+ glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour );
+
+ draw_mesh( empty_start, empty_count );
+ }
+ }
+ }
+
+ // Draw 'fish'
+ if( world.simulating )
+ {
+ float scaled_time = (vg_time-world.sim_start)*2.0f;
+ float lerp = 1.0f-(scaled_time - (float)world.sim_frame);
+
+ v4f dot_colour = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ for( int i = 0; i < world.num_fishes; i ++ )
+ {
+ struct fish *fish = &world.fishes[i];
+
+ if( !fish->alive )
+ continue;
+
+ colour_code_v3( fish->payload, dot_colour );
+ glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour );
+
+ glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)fish->pos[0] + 0.5f - (float)fish->dir[0]*lerp, (float)fish->pos[1] + 0.25f - (float)fish->dir[1]*lerp, 0.25f );
+ draw_mesh( 0, 32 );
+ }
+ }