Reverse order
New things to program:
- UI text element renderer (SDF)
- Particle system thing for ball collision
- Level descriptions / titles
+ UI text element renderer (SDF) DONE(sorta)
+ Particle system thing for ball collision
+ Level descriptions / titles HALF
Row Gridlines for I/O
Play button / Speed controller
int num_fishes;
- char map_name[128];
+ char map_name[64];
struct career_level *ptr_career_level;
u32 score;
// Scan for width
for(;; world.w ++)
{
- if( str[world.w] == ';' )
+ if( c[world.w] == ';' )
break;
- else if( !str[world.w] )
+ else if( !c[world.w] )
{
vg_error( "Unexpected EOF when parsing level\n" );
return 0;
}
+ // Level title
+ ui_begin( &ui_global_ctx, 512, 256 );
+
+ ui_global_ctx.override_colour = 0xff9a8a89;
+ //ui_text( &ui_global_ctx, world.map_title, 6, 0 );
+ ui_global_ctx.override_colour = 0xffffffff;
+
+ ui_resolve( &ui_global_ctx );
+
+ m3x3f world_text;
+ m3x3_copy( vg_pv, world_text );
+ m3x3_translate( world_text, (v3f){ 1.55f, 1.9f, 0.0f } );
+ m3x3_rotate( world_text, VG_PIf*0.5f );
+ m3x3_scale( world_text, (v3f){0.01f,-0.01f,0.01f} );
+
+ ui_draw( &ui_global_ctx, world_text );
+
+ // Main
+ // =========================================================================================
+
+ use_mesh( &world.tile );
SHADER_USE( shader_tile_main );
m2x2f subtransform;
level_ui_space[1] -= 0.01f;
draw_numbers( level_ui_space, i );
}
-
- //use_mesh( &world.numbers );
- //draw_numbers( (v3f){ 0.0f, -0.5f, 0.1f }, 128765 );
}
void vg_ui(void)
{
+ ui_global_ctx.cursor[0] = 0;
+ ui_global_ctx.cursor[1] = 0;
+ ui_global_ctx.cursor[2] = 256;
+
+ ui_fill_y( &ui_global_ctx );
+ ui_new_node( &ui_global_ctx );
+ {
+ ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0xff5577ff );
+
+ ui_text( &ui_global_ctx, "MARBLE COMPUTING", 4, 0 );
+
+ ui_global_ctx.cursor[1] += 45;
+ ui_global_ctx.cursor[3] = 709;
+
+ // Level scroll view
+ ui_new_node( &ui_global_ctx );
+ {
+ ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0xffff7729 );
+ ui_set_clip( &ui_global_ctx, ui_global_ctx.cursor );
+
+ ui_global_ctx.cursor[3] = 50;
+ ui_global_ctx.cursor[2] = 240;
+
+ for( int i = 0; i < vg_list_size(cmp_levels_basic); i ++ )
+ {
+ struct cmp_level *lvl_info = &cmp_levels_basic[i];
+
+ ui_new_node( &ui_global_ctx );
+ {
+ ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, i&0x1?0xff23fce45:0xff8722f8 );
+ ui_text( &ui_global_ctx, lvl_info->title, 3, 0 );
+ }
+ ui_end_down( &ui_global_ctx );
+ }
+
+ ui_release_clip( &ui_global_ctx );
+ }
+ ui_end_down( &ui_global_ctx );
+ }
+ ui_end( &ui_global_ctx );
}
vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
vg_tex2d tex_background = { .path = "textures/background.qoi" };
vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
-vg_tex2d tex_monofur = { .path = "textures/ascii.qoi" };
+vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_background, &tex_ball_noise, &tex_monofur };
// Textures
vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
- ui_override_font( tex_monofur.name, 3 );
+ ui_override_font( tex_monofur.name, 7 );
// Audio
sfx_set_init( &audio_tile_mod, NULL );
vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
}
};
+
+struct cmp_level
+{
+ const char *map_name;
+ const char *title;
+ const char *description;
+
+ int serial_id;
+};
+
+struct cmp_level cmp_levels_tutorials[] =
+{
+ {
+ .title = "PRINCIPLE 1",
+ .map_name = "cmp_t01",
+ .description = "Utilize basic transport methods",
+
+ .serial_id = 0
+ },
+ {
+ .title = "PRINCIPLE 2",
+ .map_name = "cmp_t02",
+ .description = "Utilize the twisty turny(TM) piece",
+
+ .serial_id = 1
+ },
+ {
+ .title = "PRINCIPLE 3",
+ .map_name = "cmp_t03",
+ .description = "Merge transport into one",
+
+ .serial_id = 2
+ },
+ {
+ .title = "PRINCIPLE 4",
+ .map_name = "cmp_t04",
+ .description = "Some stages require multiple runs to succeed in order to pass",
+
+ .serial_id = 12
+ }
+};
+
+struct cmp_level cmp_levels_basic[] =
+{
+ {
+ .title = "SUBDIVISION 1",
+ .map_name = "cmp_b01",
+ .description = "Simple maths, branching required.",
+
+ .serial_id = 3
+ },
+ {
+ .title = "SUBDIVISION 2",
+ .map_name = "cmp_b02",
+ .description = "Simple maths. Futher.",
+
+ .serial_id = 4
+ },
+ {
+ .title = "RESTRUCTURE",
+ .map_name = "cmp_b03",
+ .description = "Not so simple swap",
+
+ .serial_id = 5
+ },
+ {
+ .title = "SERIALIZE",
+ .map_name = "cmp_b04",
+ .description = "Merge and sort",
+
+ .serial_id = 6
+ },
+ {
+ .title = "PATTERNS 1",
+ .map_name = "cmp_b05",
+ .description = "Replicate",
+
+ .serial_id = 7
+ },
+ {
+ .title = "PATTERNS 2",
+ .map_name = "cmp_b06",
+ .description = "Replicate MORE",
+
+ .serial_id = 8
+ },
+ {
+ .title = "MIGHTY CONSUMER",
+ .map_name = "cmp_b07",
+ .description = "Build a greedy system",
+
+ .serial_id = 9
+ },
+ {
+ .title = "ENCRYPTED 1",
+ .map_name = "cmp_b08",
+ .description = "Some configurations may not be valid",
+
+ .serial_id = 10
+ },
+ {
+ .title = "REVERSE",
+ .map_name = "cmp_b09",
+ .description = "Reverse the incoming order. Always length 4",
+
+ .serial_id = 11
+ },
+ {
+ .title = "PRINCIPLE 5",
+ .map_name = "cmp_b10",
+ .description =
+ "The competent engineers among you may have already\n"
+ "spotted and utilized these parts of the system\n"
+ "\n"
+ "We forgot to include the relevant principle tasks\n"
+ "as part of your training package, you will now be\n"
+ "tasked to complete them",
+
+ .serial_id = 15
+ },
+ {
+ .title = "ROUTING PROBLEM",
+ .map_name = "cmp_routing",
+ .description =
+ "Things can get a little chaotic on tight boards,\n"
+ "Do your best to utilize principle 5 to get the job\n"
+ "done.",
+
+ .serial_id = 16
+ },
+ {
+ .title = "PRINCIPLE 6",
+ .map_name = "cmp_b11",
+ .description =
+ "While hovering over a simple tile peice, right click\n"
+ "and drag to start creating a wire. These can be\n"
+ "connected to the left, or right recieving pins of a\n"
+ "Twisty Turny(TM) peice.\n"
+ "\n"
+ "Once connected, the Twisty Turny(TM) will no longer\n"
+ "'flip flop' as marbles run through them, but instead\n"
+ "be set to left or right rotating only. As indicated\n"
+ "by the status arrow beneath them\n"
+ "\n"
+ "When the left or right slot is triggered, the Twisty\n"
+ "Turny(TM) will switch modes according to that input.\n"
+ "\n"
+ "Trigger wires apply instantaneously, however if both\n"
+ "the left and right inputs are recieved at the same\n"
+ "time, this results in no operation being performed,\n"
+ "and no state changes take place in the Twisty Turny(TM)\n",
+
+ .serial_id = 17
+ },
+ {
+ .title = "NOT GATE",
+ .map_name = "cmp_not",
+ .description =
+ "Test your knowledge of triggers, build an 'NOT GATE'\n"
+ "emulated by marble logic.",
+
+ .serial_id = 18
+ },
+ {
+ .title = "AND GATE",
+ .map_name = "cmp_and",
+ .description =
+ "A slightly more complicated gate, but shouldn't be\n"
+ "too difficult for your skillset.",
+
+ .serial_id = 19
+ },
+ {
+ .title = "QUALIFICATION PROJECT",
+ .map_name = "cmp_grad",
+ .description =
+ "There's no instructions here, resolve and complete this\n"
+ "task to qualify yourself as an official marble engineer",
+ .serial_id = 20
+ }
+};
+
+struct cmp_level cmp_levels_grad[] =
+{
+ {
+ .title = "SORT",
+ .map_name = "cmp_i01",
+ .description =
+ "Device a scheme to filter and sort the inputs. If you\n"
+ "believe you lack the tools required to solve this one,\n"
+ "take a harder look at the inputs.",
+
+ .serial_id = 13
+ },
+ {
+ .title = "THIRDS",
+ .map_name = "cmp_i02",
+ .description =
+ "Spit your inputs up into a third of its value\n"
+ "Is this possible? -HG",
+
+ .serial_id = 14
+ },
+ {
+ .title = "XOR CHIP",
+ .map_name = "cmp_xor",
+ .description =
+ "Significantly more complicated than an AND or NOT gate,\n"
+ "but possible.",
+ .serial_id = 21
+ },
+ {
+ .title = "SECRET CODE",
+ .map_name = "cmp_secret",
+ .description =
+ "Only one input should send an unlock signal marble to\n"
+ "the output.\n"
+ "The code: 100110",
+ .serial_id = 22
+ }
+};
+PRINCIPLE 1
#########;
###-#####;acac
## ##;
vg_debugtools_draw();
ui_resolve( &ui_global_ctx );
- ui_draw( &ui_global_ctx );
+ ui_draw( &ui_global_ctx, NULL );
}
glfwSwapBuffers( vg_window );
{
temp[i] = '\0';
in_token = 0;
+
+ if( arg_count == vg_list_size( args ) )
+ break;
}
else
{
"layout (location=0) in vec2 a_co;" // i16, i16, .. ?
"layout (location=1) in vec2 a_uv;" // i8, i8
"layout (location=2) in vec4 a_colour;" // u32
+ "layout (location=3) in vec4 a_clip;" // i16, i16, i16, i16
"uniform mat3 uPv;"
""
"out vec2 aTexCoords;"
"out vec4 aColour;"
+ "out vec2 aWsp;"
+ "out vec4 aClip;"
""
"void main()"
"{"
"gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
- "aTexCoords = a_uv * 0.01388888888;"
+ "aTexCoords = a_uv * 0.0078125;"
"aColour = a_colour;"
+
+ "aWsp = a_co;"
+ "aClip = a_clip;"
"}",
// FRAGMENT
"in vec2 aTexCoords;"
"in vec4 aColour;"
""
+ "in vec2 aWsp;"
+ "in vec4 aClip;"
+ ""
"void main()"
"{"
+ "float clip_blend = step( aWsp.x, aClip.z ) * step( aWsp.y, aClip.w ) * step( aClip.x, aWsp.x ) * step( aClip.y, aWsp.y );"
+
"vec4 glyph = texture( uTexGlyphs, aTexCoords );"
- "FragColor = aColour * vec4( 1.0, 1.0, 1.0, glyph.r );"
+ "FragColor = aColour * vec4( 1.0, 1.0, 1.0, glyph.r * clip_blend );"
"}"
,
UNIFORMS({ "uPv", "uTexGlyphs" })
#pragma pack(push,1)
struct ui_vert
{
- ui_px co[2];
- u8 uv[2];
- u32 colour;
+ ui_px co[2]; //32 4
+ u8 uv[2]; //16 2
+ u32 colour; //32 4
+ ui_rect clip; //64 8
}
*verts;
#pragma pack(pop)
+ u32 override_colour;
+
u32 num_verts;
u16 *indices;
u32 num_indices;
+ ui_rect clipping;
ui_rect cursor;
u32 stack_count;
u32 capture_mouse_id;
u32 const stride = sizeof( struct ui_vert );
// XY
- glVertexAttribPointer( 0, 2, GL_UNSIGNED_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, co ) );
+ glVertexAttribPointer( 0, 2, GL_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, co ) );
glEnableVertexAttribArray( 0 );
// UV
// COLOUR
glVertexAttribPointer( 2, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)offsetof( struct ui_vert, colour ) );
glEnableVertexAttribArray( 2 );
+
+ // CLIPPING
+ glVertexAttribPointer( 3, 4, GL_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, clip ) );
+ glEnableVertexAttribArray( 3 );
}
// Initialize default context
free( ui_global_ctx.indices );
}
-static void ui_draw( ui_ctx *ctx )
+static void ui_draw( ui_ctx *ctx, m3x3f view_override )
{
glBindVertexArray( ui_vao );
SHADER_USE( shader_ui );
m3x3f view = M3X3_IDENTITY;
- m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
- m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f), -1.0f/((float)vg_window_y*0.5f), 1.0f } );
- glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, GL_FALSE, (float *)view );
+
+ if( !view_override )
+ {
+ view_override = view;
+
+ m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
+ m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f), -1.0f/((float)vg_window_y*0.5f), 1.0f } );
+ }
+
+ glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, GL_FALSE, (float *)view_override );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
}
}
+static void ui_set_clip( ui_ctx *ctx, ui_rect clip )
+{
+ ctx->clipping[0] = clip[0];
+ ctx->clipping[1] = clip[1];
+ ctx->clipping[2] = clip[0] + clip[2];
+ ctx->clipping[3] = clip[1] + clip[3];
+}
+
+static void ui_release_clip( ui_ctx *ctx )
+{
+ ctx->clipping[0] = -32000;
+ ctx->clipping[1] = -32000;
+ ctx->clipping[2] = 32000;
+ ctx->clipping[3] = 32000;
+}
+
// Drawing
// ===========================================================================================================
u16 ind_start = ctx->num_verts;
u16 *indices = &ctx->indices[ ctx->num_indices ];
+ ui_rect_copy( ctx->clipping, vertices[0].clip );
+ ui_rect_copy( ctx->clipping, vertices[1].clip );
+ ui_rect_copy( ctx->clipping, vertices[2].clip );
+ ui_rect_copy( ctx->clipping, vertices[3].clip );
+
indices[0] = ind_start+0;
indices[1] = ind_start+2;
indices[2] = ind_start+1;
static struct ui_vert *ui_fill_rect( ui_ctx *ctx, ui_rect rect, u32 colour )
{
- return ui_fill_rect_uv( ctx, rect, colour, (ui_px[4]){ 66, 72-66, 66, 72-66 } );
+ return ui_fill_rect_uv( ctx, rect, colour, (ui_px[4]){ 4,124,4,124 } );
}
static void ui_text( ui_ctx *ctx, const char *str, ui_px scale, int alignment )
text_cursor[0] = ctx->cursor[0];
text_cursor[1] = ctx->cursor[1];
- text_cursor[2] = 7*scale;
- text_cursor[3] = 7*scale;
+ text_cursor[2] = scale*8;
+ text_cursor[3] = scale*8;
- u32 current_colour = 0xffffffff;
+ u32 current_colour = ctx->override_colour;
const char *_c = str;
char c;
{
u8 glyph_base[2];
u8 glyph_index = c - 32;
- glyph_base[0] = glyph_index%10;
- glyph_base[1] = (glyph_index-glyph_base[0])/10;
+ glyph_base[0] = glyph_index&0xf;
+ glyph_base[1] = (glyph_index-glyph_base[0])>>4;
- glyph_base[0] *= 7;
- glyph_base[1] *= 7;
+ glyph_base[0] *= 8;
+ glyph_base[1] *= 8;
- ui_fill_rect_uv( ctx, text_cursor, current_colour, (ui_px[4]){glyph_base[0],72-glyph_base[1],glyph_base[0]+7,72-(glyph_base[1]+7)} );
+ ui_fill_rect_uv( ctx, text_cursor, current_colour,
+ (ui_px[4]){
+ glyph_base[0],
+ 128-glyph_base[1],
+ glyph_base[0]+8,
+ 128-(glyph_base[1]+8)
+ });
}
else if( c == '\x1B' )
{
break;
}
}
+ continue;
}
- text_cursor[0] += ui_glyph_spacing_x*scale;
+ text_cursor[0] += (ui_glyph_spacing_x*scale)/2;
}
}
ctx->num_verts = 0;
ctx->num_indices = 0;
+
+ ui_release_clip( ctx );
}
static void ui_resolve( ui_ctx *ctx )