.
[fishladder.git] / fishladder_resources.h
1 // FONTS
2 vg_tex2d tex_ubuntu = { .path = "textures/ubuntu.qoi" };
3
4 static Character characters_Ubuntu[] = {
5 {983, 90, 18, 18, 9, 9, 7},
6 {55, 90, 23, 40, 7, 31, 9},
7 {794, 90, 27, 26, 7, 33, 13},
8 {356, 49, 36, 40, 7, 31, 21},
9 {307, 0, 32, 46, 7, 34, 18},
10 {564, 0, 42, 41, 7, 31, 27},
11 {646, 0, 38, 41, 8, 31, 21},
12 {821, 90, 21, 26, 7, 33, 7},
13 {118, 0, 26, 49, 6, 34, 10},
14 {144, 0, 26, 49, 9, 34, 10},
15 {674, 90, 31, 31, 8, 31, 15},
16 {511, 90, 33, 34, 7, 26, 18},
17 {771, 90, 23, 27, 8, 12, 8},
18 {957, 90, 26, 21, 8, 20, 9},
19 {900, 90, 23, 22, 7, 13, 8},
20 {0, 0, 32, 49, 10, 34, 12},
21 {791, 0, 33, 41, 7, 32, 18},
22 {28, 90, 27, 40, 6, 31, 18},
23 {956, 0, 32, 41, 7, 32, 18},
24 {988, 0, 32, 41, 7, 32, 18},
25 {604, 49, 34, 40, 8, 31, 18},
26 {0, 49, 32, 41, 7, 31, 18},
27 {872, 49, 32, 40, 7, 31, 18},
28 {740, 49, 33, 40, 7, 31, 18},
29 {824, 0, 33, 41, 7, 31, 18},
30 {773, 49, 33, 40, 7, 31, 18},
31 {446, 90, 23, 35, 7, 25, 8},
32 {78, 90, 23, 40, 8, 26, 8},
33 {608, 90, 33, 33, 7, 26, 18},
34 {738, 90, 33, 27, 7, 23, 18},
35 {641, 90, 33, 33, 7, 26, 18},
36 {64, 49, 30, 41, 8, 31, 13},
37 {339, 0, 44, 45, 7, 31, 30},
38 {204, 49, 39, 40, 9, 31, 21},
39 {638, 49, 34, 40, 6, 31, 20},
40 {684, 0, 36, 41, 7, 31, 20},
41 {392, 49, 36, 40, 6, 31, 23},
42 {806, 49, 33, 40, 6, 31, 18},
43 {904, 49, 32, 40, 6, 31, 17},
44 {720, 0, 36, 41, 7, 31, 21},
45 {464, 49, 35, 40, 6, 31, 22},
46 {101, 90, 21, 40, 6, 31, 8},
47 {968, 49, 31, 40, 9, 31, 16},
48 {499, 49, 35, 40, 6, 31, 20},
49 {936, 49, 32, 40, 6, 31, 16},
50 {162, 49, 42, 40, 7, 31, 28},
51 {428, 49, 36, 40, 6, 31, 23},
52 {606, 0, 40, 41, 7, 31, 25},
53 {672, 49, 34, 40, 6, 31, 19},
54 {267, 0, 40, 46, 7, 31, 25},
55 {756, 0, 35, 41, 6, 31, 20},
56 {857, 0, 33, 41, 8, 32, 17},
57 {534, 49, 35, 40, 8, 31, 18},
58 {569, 49, 35, 40, 6, 31, 22},
59 {243, 49, 39, 40, 9, 31, 21},
60 {116, 49, 46, 40, 8, 31, 29},
61 {282, 49, 37, 40, 8, 31, 20},
62 {319, 49, 37, 40, 9, 31, 19},
63 {706, 49, 34, 40, 8, 31, 18},
64 {170, 0, 25, 49, 6, 34, 10},
65 {32, 0, 32, 49, 10, 34, 12},
66 {195, 0, 25, 49, 9, 34, 10},
67 {705, 90, 33, 30, 7, 31, 18},
68 {923, 90, 34, 21, 9, 6, 15},
69 {842, 90, 24, 24, 7, 34, 12},
70 {295, 90, 31, 35, 8, 26, 16},
71 {383, 0, 33, 43, 6, 34, 19},
72 {326, 90, 31, 35, 7, 26, 15},
73 {416, 0, 33, 43, 7, 34, 19},
74 {197, 90, 33, 35, 7, 26, 18},
75 {512, 0, 28, 43, 6, 34, 12},
76 {32, 49, 32, 41, 7, 26, 18},
77 {481, 0, 31, 43, 6, 34, 18},
78 {94, 49, 22, 41, 7, 32, 8},
79 {241, 0, 26, 47, 11, 32, 8},
80 {449, 0, 32, 43, 6, 34, 16},
81 {540, 0, 24, 43, 7, 34, 8},
82 {122, 90, 41, 35, 6, 26, 27},
83 {357, 90, 31, 35, 6, 26, 18},
84 {163, 90, 34, 35, 7, 26, 19},
85 {890, 0, 33, 41, 6, 26, 19},
86 {923, 0, 33, 41, 7, 26, 19},
87 {418, 90, 28, 35, 6, 26, 12},
88 {388, 90, 30, 35, 8, 26, 14},
89 {0, 90, 28, 40, 7, 31, 13},
90 {263, 90, 32, 35, 7, 25, 18},
91 {544, 90, 33, 34, 8, 25, 16},
92 {469, 90, 42, 34, 8, 25, 25},
93 {230, 90, 33, 35, 8, 26, 16},
94 {839, 49, 33, 40, 9, 25, 16},
95 {577, 90, 31, 34, 8, 25, 15},
96 {64, 0, 27, 49, 8, 34, 10},
97 {220, 0, 21, 49, 6, 34, 9},
98 {91, 0, 27, 49, 9, 34, 10},
99 {866, 90, 34, 23, 8, 21, 18},
100 };
101
102 static Font font_Ubuntu = { "Ubuntu", 32, 0, 0, 1024, 256, 95, characters_Ubuntu };
103
104 // TEXTURES
105 // ===========================================================================================================
106
107 vg_tex2d tex_tile_data = { .path = "textures/tileset.qoi" };
108 vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
109 vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
110 vg_tex2d tex_background = { .path = "textures/background.qoi" };
111 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
112 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
113 vg_tex2d tex_unkown = { .path = "textures/unkown.qoi" };
114 vg_tex2d tex_buttons = { .path = "textures/buttons.qoi" };
115
116 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_background, &tex_ball_noise, &tex_monofur, &tex_unkown, &tex_buttons, &tex_ubuntu };
117
118 // AUDIO
119 // ===========================================================================================================
120
121 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
122 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
123
124 sfx_system audio_system_sfx =
125 {
126 .vol = 1.f,
127 .ch = 1,
128 .vol_src = &audio_volume_sfx,
129 .name = "sfx"
130 };
131
132 sfx_set audio_tile_mod =
133 {
134 .sources = "\
135 sound/mod_01.ogg\0\
136 sound/mod_02.ogg\0\
137 sound/mod_03.ogg\0\
138 sound/mod_04.ogg\0\
139 sound/mod_05.ogg\0\
140 sound/mod_06.ogg\0",
141 .flags = 0
142 };
143
144 sfx_set audio_splitter =
145 {
146 .sources = "\
147 sound/splitter_01.ogg\0"
148 };
149
150 sfx_set audio_rolls =
151 {
152 .sources = "\
153 sound/rolling_01.ogg\0\
154 sound/rolling_02.ogg\0"
155 };
156
157 sfx_set audio_random =
158 {
159 .sources = "\
160 sound/random_01.ogg\0\
161 sound/random_02.ogg\0\
162 sound/random_03.ogg\0\
163 sound/random_04.ogg\0\
164 sound/random_05.ogg\0\
165 sound/random_06.ogg\0\
166 sound/random_07.ogg\0\
167 sound/random_08.ogg\0"
168 };
169
170 sfx_set audio_clicks =
171 {
172 .sources = "\
173 sound/click_a.ogg\0\
174 sound/click_b.ogg\0\
175 sound/click_c.ogg\0"
176 };
177
178 // One two or three layers of rolling noise
179 sfx_system audio_system_balls_rolling =
180 {
181 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
182 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT
183 };
184
185 // Various oneshots
186 sfx_system audio_system_balls_switching =
187 {
188 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
189 .name = "Balls Switching"
190 };
191
192 // Gameplay critical sounds eg. splitter sound rocking
193 sfx_system audio_system_balls_important =
194 {
195 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
196 .name = "Balls Gameplay"
197 };
198
199 // Suplemental sounds
200 sfx_system audio_system_balls_extra =
201 {
202 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
203 .name = "Balls Extra"
204 };
205
206 sfx_system audio_system_ui =
207 {
208 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
209 .name = "UI"
210 };
211
212 ui_colourset ui_fl_colours = {
213 .main = 0xff807373,
214 .hover = 0xff918484,
215 .active = 0xffad9f9e
216 };
217
218 ui_colourset ui_fl_colours_inactive = {
219 .main = 0xff655958,
220 .hover = 0xff655958,
221 .active = 0xff655958
222 };
223
224 static void resource_load_main(void)
225 {
226 // Textures
227 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
228
229 ui_override_font( tex_monofur.name, 7 );
230
231 ui_global_ctx.colours_main = &ui_fl_colours;
232 gui_reset_colours();
233
234 // Audio
235 sfx_set_init( &audio_tile_mod, NULL );
236 sfx_set_init( &audio_splitter, NULL );
237 sfx_set_init( &audio_rolls, NULL );
238 sfx_set_init( &audio_random, NULL );
239 sfx_set_init( &audio_clicks, NULL );
240 }
241
242 static void resource_free_main(void)
243 {
244 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
245
246 sfx_set_free( &audio_tile_mod );
247 sfx_set_free( &audio_splitter );
248 sfx_set_free( &audio_rolls );
249 sfx_set_free( &audio_random );
250 sfx_set_free( &audio_clicks );
251 }
252
253 // SHADERS
254 // ===========================================================================================================
255
256 SHADER_DEFINE( shader_tile_colour,
257
258 // VERTEX
259 "layout (location=0) in vec2 a_co;"
260 "uniform mat3 uPv;"
261 "uniform vec3 uOffset;"
262 ""
263 "void main()"
264 "{"
265 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
266 "}",
267
268 // FRAGMENT
269 "out vec4 FragColor;"
270 "uniform vec4 uColour;"
271 ""
272 "void main()"
273 "{"
274 "FragColor = uColour;"
275 "}"
276 ,
277 UNIFORMS({ "uPv", "uOffset", "uColour" })
278 )
279
280 SHADER_DEFINE( shader_ball,
281 // VERTEX
282 "layout (location=0) in vec2 a_co;"
283 "uniform vec3 uOffset;"
284 "uniform mat3 uPv;"
285 ""
286 "out vec4 aTexCoords;"
287 ""
288 "void main()"
289 "{"
290 // Vertex transform
291 "vec3 worldpos = vec3( (a_co * 0.5 - 0.25) * uOffset.z + uOffset.xy, 1.0 );"
292 "gl_Position = vec4( uPv * worldpos, 1.0 );"
293
294 // Create texture coords
295 "aTexCoords = vec4( a_co, worldpos.xy );"
296 "}",
297
298 // FRAGMENT
299 "out vec4 FragColor;"
300 ""
301 "uniform sampler2D uTexMain;"
302 "uniform vec3 uColour;"
303 "uniform vec2 uTexOffset;"
304 ""
305 "in vec4 aTexCoords;"
306 ""
307 "void main()"
308 "{"
309 "vec2 center_coords = aTexCoords.xy - 0.5;"
310 "vec2 center_coords_sqr = center_coords*center_coords;"
311 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
312
313 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
314 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
315 "vec4 noise_sample = texture( uTexMain, warped_coords );"
316
317 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
318
319 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
320 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
321 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
322
323 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
324 "vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
325
326 "FragColor = colour_comp;"
327 "}"
328 ,
329 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
330 )
331
332 SHADER_DEFINE( shader_tile_main,
333 // VERTEX
334 "layout (location=0) in vec2 a_co;"
335 "uniform vec4 uOffset;" // Tile x/y, uv x/y
336 "uniform mat3 uPv;"
337 "uniform mat2 uSubTransform;"
338 ""
339 "out vec4 aTexCoords;"
340 "out vec2 aWorldCoords;"
341 ""
342 "vec2 hash22(vec2 p)"
343 "{"
344 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
345 "p3 += dot(p3, p3.yzx+33.33);"
346 "return fract((p3.xx+p3.yz)*p3.zy);"
347 "}"
348 ""
349 "void main()"
350 "{"
351 // Vertex transform
352 "vec2 subtransform = uSubTransform * (a_co-0.5) + 0.5;"
353 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
354 "gl_Position = vec4( uPv * worldpos, 1.0 );"
355
356 // Create texture coords
357 "vec2 random_offset = floor(hash22(uOffset.xy) * 4.0) * 0.25;"
358 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
359 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
360 "aWorldCoords = worldpos.xy;"
361 "}",
362
363 // FRAGMENT
364 "out vec4 FragColor;"
365 ""
366 "uniform sampler2D uTexGlyphs;"
367 "uniform sampler2D uTexWood;"
368 "uniform float uGhost;"
369 "uniform float uForeground;"
370 "uniform vec2 uMousePos;"
371 "uniform vec4 uColour;"
372 ""
373 "in vec4 aTexCoords;"
374 "in vec2 aWorldCoords;"
375 ""
376 "void main()"
377 "{"
378 "vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 ) * 0.97;"
379 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
380 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
381 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
382 "vec3 wood_comp = mix( wood_secondary.rgb * shadowing_colour, wood.rgb, clamp( glyph.b * 2.0 - 1.0, 0.0, 1.0 ) );"
383
384 "vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
385
386 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
387
388 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
389 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
390
391 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
392 "}"
393 ,
394 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos", "uColour", "uForeground" })
395 )
396
397 SHADER_DEFINE( shader_background,
398 // VERTEX
399 "layout (location=0) in vec2 a_co;"
400 "uniform mat3 uPv;"
401 "uniform vec3 uOffset;"
402 ""
403 "out vec2 aTexCoords;"
404 ""
405 "void main()"
406 "{"
407 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
408 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
409 "aTexCoords = a_co;"
410 "}",
411
412 // FRAGMENT
413 "out vec4 FragColor;"
414 ""
415 "uniform sampler2D uTexMain;"
416 "uniform sampler2D uSamplerNoise;"
417 "uniform float uVariance;"
418 ""
419 "in vec2 aTexCoords;"
420 ""
421 "void main()"
422 "{"
423 "float ao_accum = 0.0;"
424 "for( int i=0; i<10; ++i )"
425 "{"
426 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
427 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
428 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
429 "}"
430 "ao_accum *= 0.15;"
431
432 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
433
434 "ao_accum -= data_this_tile.r;"
435
436 "vec3 colour_main = mix( vec3( 0.369768, 0.3654, 0.42 ),vec3( 0.275, 0.388, 0.553 ), data_this_tile.g );"
437
438 "vec2 square_coords = fract( aTexCoords * 64.0 );"
439 "vec2 grid_coords = abs( square_coords - 0.5 );"
440 "float edge_contrast = (1.0-ao_accum*0.2);"
441
442 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
443 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
444
445 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
446 "}"
447 ,
448 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise" })
449 )
450
451 SHADER_DEFINE( shader_wire,
452 // VERTEX
453 "layout (location=0) in vec2 a_co;"
454 "uniform vec3 uStart;"
455 "uniform vec3 uEnd;"
456 "uniform mat3 uPv;"
457 "uniform float uCurve;"
458 ""
459 "out vec2 aTexCoords;"
460 ""
461 "vec3 sample_curve_time( float t )"
462 "{"
463 "vec3 line_coord = mix( uStart, uEnd, t );"
464
465 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
466 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
467 "}"
468 ""
469 "void main()"
470 "{"
471 // Vertex transform
472 "vec3 p0 = sample_curve_time( a_co.x );"
473 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
474
475 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
476 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
477
478 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
479
480 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
481
482 // Create texture coords (todo: include stretch adjusted coords?)
483 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
484 "}",
485
486 // FRAGMENT
487 "out vec4 FragColor;"
488 ""
489 "uniform sampler2D uTexMain;"
490 "uniform vec4 uColour;"
491 "uniform float uTime;"
492 "uniform float uGlow;"
493 ""
494 "in vec2 aTexCoords;"
495 ""
496 "void main()"
497 "{"
498 // Compute shadowing
499 "float shadow = 1.0 - abs(aTexCoords.y - 0.5) * 2.0;"
500 "float masking = smoothstep( 0.5, 0.8, shadow );"
501
502 "vec3 colour_comp = mix( vec3(0.0,0.0,0.0), uColour.rgb, masking );"
503
504 "float flow_thing = fract( aTexCoords.x + uTime );"
505 "vec3 final_comp = colour_comp + flow_thing * uGlow;"
506
507 "FragColor = vec4( final_comp, max( shadow* 0.2, masking ) * uColour.a );"
508 "}"
509 ,
510 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve", "uTime", "uGlow" })
511 )
512
513 SHADER_DEFINE( shader_buttons,
514 // VERTEX
515 "layout (location=0) in vec2 a_co;"
516 "uniform vec4 uOffset;" // Tile x/y, uv x/y
517 "uniform mat3 uPv;"
518 ""
519 "out vec2 aTexCoords;"
520 ""
521 "void main()"
522 "{"
523 // Vertex transform
524 "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
525 "gl_Position = vec4( uPv * worldpos, 1.0 );"
526
527 // Create texture coords
528 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
529 "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
530 "}",
531
532 // FRAGMENT
533 "out vec4 FragColor;"
534 ""
535 "uniform sampler2D uTexMain;"
536 "uniform vec4 uColour;" // rgb, light amount
537 ""
538 "in vec2 aTexCoords;"
539 ""
540 "void main()"
541 "{"
542 "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
543
544 "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
545 "}"
546 ,
547 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
548 )
549
550
551 void vg_register(void)
552 {
553 SHADER_INIT( shader_tile_colour );
554 SHADER_INIT( shader_tile_main );
555 SHADER_INIT( shader_ball );
556 SHADER_INIT( shader_background );
557 SHADER_INIT( shader_wire );
558 SHADER_INIT( shader_buttons );
559 }
560
561 /*
562 0000 0 | 0001 1 | 0010 2 | 0011 3
563 | | | | |
564 X | X= | X | X=
565 | | |
566 0100 4 | 0101 5 | 0110 6 | 0111 7
567 | | | | |
568 =X | =X= | =X | =X=
569 | | |
570 1000 8 | 1001 9 | 1010 10 | 1011 11
571 | | | | |
572 X | X= | X | X=
573 | | | | | | |
574 1100 12 | 1101 13 | 1110 14 | 1111 15
575 | | | | |
576 =X | =X= | =X | =X=
577 | | | | | | |
578 */
579
580 float const MESH_NUMBER_0[] = {
581 #include "fonts/numbers/n0.h"
582 };
583
584 float const MESH_NUMBER_1[] = {
585 #include "fonts/numbers/n1.h"
586 };
587
588 float const MESH_NUMBER_2[] = {
589 #include "fonts/numbers/n2.h"
590 };
591
592 float const MESH_NUMBER_3[] = {
593 #include "fonts/numbers/n3.h"
594 };
595
596 float const MESH_NUMBER_4[] = {
597 #include "fonts/numbers/n4.h"
598 };
599
600 float const MESH_NUMBER_5[] = {
601 #include "fonts/numbers/n5.h"
602 };
603
604 float const MESH_NUMBER_6[] = {
605 #include "fonts/numbers/n6.h"
606 };
607
608 float const MESH_NUMBER_7[] = {
609 #include "fonts/numbers/n7.h"
610 };
611
612 float const MESH_NUMBER_8[] = {
613 #include "fonts/numbers/n8.h"
614 };
615
616 float const MESH_NUMBER_9[] = {
617 #include "fonts/numbers/n9.h"
618 };
619
620 float const MESH_NUMBERS_BUFFER[] =
621 {
622 #include "fonts/numbers/n0.h"
623 #include "fonts/numbers/n1.h"
624 #include "fonts/numbers/n2.h"
625 #include "fonts/numbers/n3.h"
626 #include "fonts/numbers/n4.h"
627 #include "fonts/numbers/n5.h"
628 #include "fonts/numbers/n6.h"
629 #include "fonts/numbers/n7.h"
630 #include "fonts/numbers/n8.h"
631 #include "fonts/numbers/n9.h"
632 };
633
634 #define MESH_NUMBER_DIVISOR 6
635
636 u32 const MESH_NUMBERS_OFFSETS[][2] =
637 {
638 {
639 0,
640 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR
641 },
642 {
643 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR,
644 vg_list_size( MESH_NUMBER_1 ) / MESH_NUMBER_DIVISOR
645 },
646 {
647 (
648 vg_list_size( MESH_NUMBER_0 ) +
649 vg_list_size( MESH_NUMBER_1 )
650 ) / MESH_NUMBER_DIVISOR,
651 vg_list_size( MESH_NUMBER_2 ) / MESH_NUMBER_DIVISOR
652 },
653 {
654 (
655 vg_list_size( MESH_NUMBER_0 ) +
656 vg_list_size( MESH_NUMBER_1 ) +
657 vg_list_size( MESH_NUMBER_2 )
658 ) / MESH_NUMBER_DIVISOR,
659 vg_list_size( MESH_NUMBER_3 ) / MESH_NUMBER_DIVISOR
660 },
661 {
662 (
663 vg_list_size( MESH_NUMBER_0 ) +
664 vg_list_size( MESH_NUMBER_1 ) +
665 vg_list_size( MESH_NUMBER_2 ) +
666 vg_list_size( MESH_NUMBER_3 )
667 ) / MESH_NUMBER_DIVISOR,
668 vg_list_size( MESH_NUMBER_4 ) / MESH_NUMBER_DIVISOR
669 },
670 {
671 (
672 vg_list_size( MESH_NUMBER_0 ) +
673 vg_list_size( MESH_NUMBER_1 ) +
674 vg_list_size( MESH_NUMBER_2 ) +
675 vg_list_size( MESH_NUMBER_3 ) +
676 vg_list_size( MESH_NUMBER_4 )
677 ) / MESH_NUMBER_DIVISOR,
678 vg_list_size( MESH_NUMBER_5 ) / MESH_NUMBER_DIVISOR
679 },
680 {
681 (
682 vg_list_size( MESH_NUMBER_0 ) +
683 vg_list_size( MESH_NUMBER_1 ) +
684 vg_list_size( MESH_NUMBER_2 ) +
685 vg_list_size( MESH_NUMBER_3 ) +
686 vg_list_size( MESH_NUMBER_4 ) +
687 vg_list_size( MESH_NUMBER_5 )
688 ) / MESH_NUMBER_DIVISOR,
689 vg_list_size( MESH_NUMBER_6 ) / MESH_NUMBER_DIVISOR
690 },
691 {
692 (
693 vg_list_size( MESH_NUMBER_0 ) +
694 vg_list_size( MESH_NUMBER_1 ) +
695 vg_list_size( MESH_NUMBER_2 ) +
696 vg_list_size( MESH_NUMBER_3 ) +
697 vg_list_size( MESH_NUMBER_4 ) +
698 vg_list_size( MESH_NUMBER_5 ) +
699 vg_list_size( MESH_NUMBER_6 )
700 ) / MESH_NUMBER_DIVISOR,
701 vg_list_size( MESH_NUMBER_7 ) / MESH_NUMBER_DIVISOR
702 },
703 {
704 (
705 vg_list_size( MESH_NUMBER_0 ) +
706 vg_list_size( MESH_NUMBER_1 ) +
707 vg_list_size( MESH_NUMBER_2 ) +
708 vg_list_size( MESH_NUMBER_3 ) +
709 vg_list_size( MESH_NUMBER_4 ) +
710 vg_list_size( MESH_NUMBER_5 ) +
711 vg_list_size( MESH_NUMBER_6 ) +
712 vg_list_size( MESH_NUMBER_7 )
713 ) / MESH_NUMBER_DIVISOR,
714 vg_list_size( MESH_NUMBER_8 ) / MESH_NUMBER_DIVISOR
715 },
716 {
717 (
718 vg_list_size( MESH_NUMBER_0 ) +
719 vg_list_size( MESH_NUMBER_1 ) +
720 vg_list_size( MESH_NUMBER_2 ) +
721 vg_list_size( MESH_NUMBER_3 ) +
722 vg_list_size( MESH_NUMBER_4 ) +
723 vg_list_size( MESH_NUMBER_5 ) +
724 vg_list_size( MESH_NUMBER_6 ) +
725 vg_list_size( MESH_NUMBER_7 ) +
726 vg_list_size( MESH_NUMBER_8 )
727 ) / MESH_NUMBER_DIVISOR,
728 vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
729 }
730 };
731
732 struct cmp_level
733 {
734 const char *map_name;
735 const char *title;
736 const char *description;
737
738 int unlocked;
739 int completed_score;
740
741 int _unlock, _linked; // When completed, unlock this level
742 struct cmp_level *unlock, *linked;
743
744 int serial_id;
745 int is_tutorial;
746
747 SteamLeaderboard_t steam_leaderboard;
748 };
749
750 static struct cmp_level cmp_levels_tutorials[] =
751 {
752 // r1
753 {
754 .serial_id = 0,
755 .title = "PRINCIPLE 1",
756 .map_name = "cmp_t01",
757 .description =
758 "Utilize basic transport methods",
759
760 ._unlock = 1,
761 .is_tutorial = 1
762 },
763 // r1
764 {
765 .serial_id = 1,
766 .title = "PRINCIPLE 2",
767 .map_name = "cmp_t02",
768 .description =
769 "Utilize the twisty turny(TM) piece to split the marble\n"
770 "stream into two",
771
772 ._unlock = 2,
773 .is_tutorial = 1,
774 },
775 // r1
776 {
777 .serial_id = 2,
778 .title = "PRINCIPLE 3",
779 .map_name = "cmp_t03",
780 .description =
781 "Merge transport into one path",
782
783 ._unlock = 12,
784 .is_tutorial = 1
785 },
786 // r1
787 {
788 .serial_id = 12,
789 .title = "PRINCIPLE 4",
790 .map_name = "cmp_t04",
791 .description =
792 "Some stages require multiple runs to succeed in order to\n"
793 "pass",
794
795 ._unlock = 6,
796 .is_tutorial = 1
797 }
798 };
799
800 static struct cmp_level cmp_levels_basic[] =
801 {
802 // r2 GM
803 {
804 .serial_id = 6,
805 .title = "PATCH",
806 .map_name = "cmp_b04",
807 .description =
808 "For some reason, the division module our intern built\n"
809 "for us is sending twice as many yellows as needed. Send\n"
810 "the excess to be recycled!",
811
812 ._unlock = 7,
813 ._linked = 3
814 },
815 // r1 GM
816 {
817 .serial_id = 3,
818 .title = "SUBDIVISION 1",
819 .map_name = "cmp_b01",
820 .description =
821 "Sometimes getting the desired amount takes dividing up\n"
822 "the input and recombining it.",
823
824 ._linked = 4,
825 ._unlock = 5
826 },
827 // r1 GM
828 {
829 .serial_id = 4,
830 .title = "SUBDIVISION 2",
831 .map_name = "cmp_b02",
832 .description =
833 "",
834
835 ._unlock = 7
836 },
837 // r1 GM
838 {
839 .serial_id = 5,
840 .title = "RESTRUCTURE",
841 .map_name = "cmp_b03",
842 .description =
843 "It is possible to swap these values using simple\n"
844 "division and addition.",
845
846 ._unlock = 8
847 },
848 // r2 GM
849 {
850 .serial_id = 7,
851 .title = "PATTERNS 1",
852 .map_name = "cmp_b05",
853 .description =
854 "Replicate the pattern",
855
856 ._linked = 8
857 },
858 // r2 GM
859 {
860 .serial_id = 8,
861 .title = "PATTERNS 2",
862 .map_name = "cmp_b06",
863 .description =
864 "Replicate MORE",
865
866 ._unlock = 15
867 },
868 // r2 GM
869 {
870 .serial_id = 15,
871 .title = "PRINCIPLE 5",
872 .map_name = "cmp_b10",
873 .description =
874 "The sharp engineers among you may have already spotted\n"
875 "and utilized this part of the system\n"
876 "\n"
877 "We forgot to include the relevant principle tasks as\n"
878 "of your training package, you will now be tasked to\n"
879 "complete them",
880
881 ._unlock = 16,
882 .is_tutorial = 1
883 },
884 // r2 GM
885 {
886 .serial_id = 16,
887 .title = "ROUTING PROBLEM",
888 .map_name = "cmp_routing",
889 .description =
890 "Things can get a little chaotic on tight boards, do your\n"
891 "best to utilize principle 5 to get the job done\n",
892
893 ._linked = 9
894 },
895 // r2 GM
896 {
897 .serial_id = 9,
898 .title = "MIGHTY CONSUMER",
899 .map_name = "cmp_b07",
900 .description =
901 "Build a greedy system",
902
903 ._linked = 10,
904 ._unlock = 11
905 },
906 {
907 .serial_id = 10,
908 .title = "SHIFT",
909 .map_name = "cmp_b08",
910 .description =
911 "",
912
913 ._unlock = 17
914 },
915 // r2 GM
916 {
917 .serial_id = 11,
918 .title = "REVERSE",
919 .map_name = "cmp_b09",
920 .description =
921 "Reverse the incoming order. Always length 4",
922
923 ._unlock = 17
924 },
925 // r2 GM
926 {
927 .serial_id = 17,
928 .title = "PRINCIPLE 6",
929 .map_name = "cmp_b11",
930 .description =
931 "Usually the splitter piece will flip flop between left\n"
932 "and right, however it can be forced to only rotate in\n"
933 "one direction if trigger wires are attached.\n"
934 "\n"
935 "Right click and drag from a regular block, and attach it\n"
936 "to a splitter. This creates a trigger.\n"
937 "The default state is left, and once a marble hits the\n"
938 "trigger it will switch to rotating that direction.",
939
940 ._unlock = 18,
941 .is_tutorial = 1
942 },
943 // r2 GM
944 {
945 .serial_id = 18,
946 .title = "NOT GATE",
947 .map_name = "cmp_not",
948 .description =
949 "Test your knowledge of triggers, build an 'NOT GATE'\n"
950 "emulated by marble logic.",
951
952 ._linked = 19,
953 ._unlock = 20
954 },
955 // r2 GM
956 {
957 .serial_id = 19,
958 .title = "AND GATE",
959 .map_name = "cmp_and",
960 .description =
961 "A slightly more complicated gate, but shouldn't be\n"
962 "too difficult for your skillset.",
963
964 ._unlock = 20
965 },
966 // r2 GM
967 {
968 .serial_id = 20,
969 .title = "QUALIFICATION PROJECT",
970 .map_name = "cmp_xor",
971 .description =
972 "Significantly more complicated than an AND or NOT gate,\n"
973 "but possible.",
974
975 ._unlock = 13
976 }
977 };
978
979 static struct cmp_level cmp_levels_grad[] =
980 {
981 // r2
982 {
983 .serial_id = 13,
984 .title = "SORT",
985 .map_name = "cmp_i01",
986 .description =
987 "Devise a scheme to filter and sort the inputs. If you\n"
988 "believe you lack the tools required to solve this one,\n"
989 "take a harder look at the inputs.",
990 ._linked = 14
991
992 },
993 // r2
994 {
995 .serial_id = 14,
996 .title = "THIRDS",
997 .map_name = "cmp_i02",
998 .description =
999 "Split the inputs up into a third of their values\n"
1000 "\n"
1001 "Is this possible? -HG",
1002 ._linked = 21
1003
1004 },
1005 // r2 GM
1006 {
1007 .serial_id = 21,
1008 .title = "SIMPLE ADDITION",
1009 .map_name = "cmp_grad",
1010 .description =
1011 "Take the amount of yellows coming in, and add them\n"
1012 "together. Send your result using the stream of blues.",
1013
1014 ._linked = 22
1015 },
1016 // r2 GM
1017 {
1018 .serial_id = 22,
1019 .title = "SECRET CODE",
1020 .map_name = "cmp_secret",
1021 .description =
1022 ""
1023 }
1024 };
1025
1026 #define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad ))
1027
1028 static struct serializable_set
1029 {
1030 struct cmp_level *pack;
1031 int count;
1032 }
1033 career_serializable[] =
1034 {
1035 {
1036 .pack = cmp_levels_tutorials,
1037 .count = vg_list_size( cmp_levels_tutorials )
1038 },
1039 {
1040 .pack = cmp_levels_basic,
1041 .count = vg_list_size( cmp_levels_basic )
1042 },
1043 {
1044 .pack = cmp_levels_grad,
1045 .count = vg_list_size( cmp_levels_grad )
1046 }
1047 };
1048
1049 // Setup pointers and that
1050 static void career_local_data_init(void)
1051 {
1052 struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
1053
1054 // COllect pointers
1055 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
1056 {
1057 struct serializable_set *set = &career_serializable[i];
1058
1059 for( int j = 0; j < set->count; j ++ )
1060 level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
1061 }
1062
1063 // Apply
1064 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
1065 {
1066 struct serializable_set *set = &career_serializable[i];
1067
1068 for( int j = 0; j < set->count; j ++ )
1069 {
1070 struct cmp_level *lvl = &set->pack[j];
1071 lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
1072 lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
1073 }
1074 }
1075 }