#!/bin/sh
-onyx src/main.onyx && onyx doc src/main.onyx
+onyx -V src/main.onyx
package ttf_font
use package core
+use package core.intrinsics.wasm { sqrt_f32 }
use package vecmath
// Very proud of how small this function can be using slices
return ~~val / cast(f32) (1 << 16);
}
-#private_file read_string :: proc (use br: ^BinaryReader, len: i32) -> string {
+#private_file read_string :: proc (use br: ^BinaryReader, len: i32) -> str {
ret := data.data[pos .. pos + len];
pos += len;
return ret;
entry_selector : u16;
range_shift : u16;
- table_map : i32map.I32Map(TTTableInfo);
+ table_map : map.Map(i32, TTTableInfo);
char_maps : [..] TTCmap;
version : u32;
ttf_create :: proc (ttf_data: [] u8) -> TrueTypeFont {
ttf : TrueTypeFont;
ttf.reader = binary_reader_create(ttf_data);
- i32map.init(^ttf.table_map);
+ map.init(^ttf.table_map);
array.init(^ttf.char_maps);
ttf_read_offset_table(^ttf);
ttf_read_head_table(^ttf);
table_info.offset = read_u32(^reader);
table_info.length = read_u32(^reader);
- i32map.put(^table_map, tag_int, table_info);
+ map.put(^table_map, tag_int, table_info);
- if !str.equal(tag, "head") {
+ if !string.equal(tag, "head") {
csum := ttf_calc_table_checksum(^reader, table_info.offset, table_info.length);
if table_info.checksum != csum {
print("WARNING: Checksum for table '");
ttf_read_head_table :: proc (use ttf: ^TrueTypeFont) {
empty_table_hack := TTTableInfo.{};
- head_table_info := i32map.get(^table_map, string_to_beu32("head"), empty_table_hack);
+ head_table_info := map.get(^table_map, string_to_beu32("head"), empty_table_hack);
seek(^reader, head_table_info.offset);
version = read_u32(^reader);
ttf_lookup_glyph_offset :: proc (use ttf: ^TrueTypeFont, glyph_index: i32) -> u32 {
empty_table_hack := TTTableInfo.{};
- loca_table_info := i32map.get(^table_map, string_to_beu32("loca"), empty_table_hack);
- glyf_table_info := i32map.get(^table_map, string_to_beu32("glyf"), empty_table_hack);
+ loca_table_info := map.get(^table_map, string_to_beu32("loca"), empty_table_hack);
+ glyf_table_info := map.get(^table_map, string_to_beu32("glyf"), empty_table_hack);
old: u32;
defer seek(^reader, old);
offset := ttf_lookup_glyph_offset(ttf, glyph_index);
empty_table_hack := TTTableInfo.{};
- glyf_table_info := i32map.get(^table_map, string_to_beu32("glyf"), empty_table_hack);
+ glyf_table_info := map.get(^table_map, string_to_beu32("glyf"), empty_table_hack);
if offset >= glyf_table_info.offset + glyf_table_info.length do return null;
ttf_glyph_count :: proc (use ttf: ^TrueTypeFont) -> u32 {
empty_table_hack := TTTableInfo.{};
- maxp_table_info := i32map.get(^table_map, string_to_beu32("maxp"), empty_table_hack);
+ maxp_table_info := map.get(^table_map, string_to_beu32("maxp"), empty_table_hack);
old := seek(^reader, maxp_table_info.offset + 4);
defer seek(^reader, old);
ttf_read_cmap_table :: proc (use ttf: ^TrueTypeFont) {
empty_table_hack := TTTableInfo.{};
- cmap_table_info := i32map.get(^table_map, string_to_beu32("cmap"), empty_table_hack);
+ cmap_table_info := map.get(^table_map, string_to_beu32("cmap"), empty_table_hack);
seek(^reader, cmap_table_info.offset);
version := read_u16(^reader);
range_shift : u16;
segments : [..] TTSegment;
- cache : i32map.I32Map(i32);
+ cache : map.Map(i32, i32);
}
TTSegment :: struct {
ttf_read_cmap4 :: proc (use ttf: ^TrueTypeFont) {
cmap : TTCmap;
cmap.cmap4.format = TTCmapFormat.Segmented;
- map := ^cmap.cmap4;
- i32map.init(^map.cache);
+ imap := ^cmap.cmap4;
+ map.init(^imap.cache);
- map.seg_count = read_u16(^reader) >> ~~1;
- map.search_range = read_u16(^reader);
- map.entry_selector = read_u16(^reader);
- map.range_shift = read_u16(^reader);
+ imap.seg_count = read_u16(^reader) >> ~~1;
+ imap.search_range = read_u16(^reader);
+ imap.entry_selector = read_u16(^reader);
+ imap.range_shift = read_u16(^reader);
- array.init(^map.segments, ~~map.seg_count);
- map.segments.count = cast(u32) map.seg_count;
+ array.init(^imap.segments, ~~imap.seg_count);
+ imap.segments.count = cast(u32) imap.seg_count;
- for ^seg: map.segments do seg.end_code = read_u16(^reader);
+ for ^seg: imap.segments do seg.end_code = read_u16(^reader);
read_u16(^reader); // Reserved and unused
- for ^seg: map.segments do seg.start_code = read_u16(^reader);
- for ^seg: map.segments do seg.id_delta = read_u16(^reader);
- for ^seg: map.segments {
+ for ^seg: imap.segments do seg.start_code = read_u16(^reader);
+ for ^seg: imap.segments do seg.id_delta = read_u16(^reader);
+ for ^seg: imap.segments {
seg.id_range_offset = read_u16(^reader);
if seg.id_range_offset != ~~0 do seg.id_range_offset += ~~(tell(^reader) - 2);
}
#private_file
ttf_lookup_in_cmap4 :: proc (use ttf: ^TrueTypeFont, cmap: ^TTCmap4, charcode: u32) -> u32 {
- if i32map.has(^cmap.cache, charcode) do return i32map.get(^cmap.cache, charcode);
+ if map.has(^cmap.cache, charcode) do return map.get(^cmap.cache, charcode);
index := 0;
for ^seg: cmap.segments {
}
}
- i32map.put(^cmap.cache, charcode, index);
+ map.put(^cmap.cache, charcode, index);
return index;
}
ttf_read_hhea_table :: proc (use ttf: ^TrueTypeFont) {
empty_table_hack := TTTableInfo.{};
- hhea_table_info := i32map.get(^table_map, string_to_beu32("hhea"), empty_table_hack);
+ hhea_table_info := map.get(^table_map, string_to_beu32("hhea"), empty_table_hack);
seek(^reader, hhea_table_info.offset);
hhea.version = read_u32(^reader);
ttf_lookup_horizontal_metrics :: proc (use ttf: ^TrueTypeFont, glyph_index: u32) -> TTHorizontalMetrics {
empty_table_hack := TTTableInfo.{};
- hmtx_table_info := i32map.get(^table_map, string_to_beu32("hmtx"), empty_table_hack);
+ hmtx_table_info := map.get(^table_map, string_to_beu32("hmtx"), empty_table_hack);
offset := hmtx_table_info.offset;
hmtx : TTHorizontalMetrics;
}
#private_file
-string_to_beu32 :: proc (s: string) -> u32 {
+string_to_beu32 :: proc (s: str) -> u32 {
return (cast(u32) s[0] << 24)
| (cast(u32) s[1] << 16)
| (cast(u32) s[2] << 8)
Atlas :: struct {
texture : ^texture.Texture;
- map : i32map.I32Map(AtlasSprite);
+ texmap : map.Map(i32, AtlasSprite);
}
AtlasSprite :: struct {
create :: proc (tex: ^texture.Texture) -> Atlas {
atlas : Atlas;
atlas.texture = tex;
- i32map.init(^atlas.map);
+ map.init(^atlas.texmap);
return atlas;
}
map :: proc (use atlas: ^Atlas, id: i32, sprite: AtlasSprite) {
- i32map.put(^map, id, sprite);
+ map.put(^texmap, id, sprite);
}
lookup :: proc (use atlas: ^Atlas, id: i32, offset := 0) -> AtlasSprite {
- sprite := i32map.get(^map, id, AtlasSprite.{});
+ sprite := map.get(^texmap, id, AtlasSprite.{});
if offset != 0 {
sprite.x += ~~offset * sprite.w;
}
apply_to_quad :: proc (use atlas: ^Atlas, id: i32, quad: ^Quad) {
- sprite := i32map.get(^map, id, AtlasSprite.{});
+ sprite := map.get(^texmap, id, AtlasSprite.{});
quad.tex_size.x = sprite.w / ~~texture.width;
quad.tex_size.y = sprite.h / ~~texture.height;
quad.tex_pos.x = sprite.x / ~~texture.width;
return loc;
}
-draw_text :: proc (renderer: ^RenderContext, s: string, pos: V2f, scale := 1.0f) {
+draw_text :: proc (renderer: ^RenderContext, s: str, pos: V2f, scale := 1.0f) {
x := pos.x;
y := pos.y;
color : Color4f32 = Color4f32.{ 0f, 0f, 0f, 0f };
}
-init :: proc (use qr: ^QuadRenderer, initial_quads := 10) {
+init :: proc (use qr: ^QuadRenderer, initial_quads := 10) #export "QUAD_INIT" {
vertexArray = gl.createVertexArray();
gl.bindVertexArray(vertexArray);
// Set up vertex and index data
- vertex_data : [4] V2f;
- vertex_data[0] = V2f.{ 0.0f, 0.0f };
- vertex_data[1] = V2f.{ 0.0f, 1.0f };
- vertex_data[2] = V2f.{ 1.0f, 1.0f };
- vertex_data[3] = V2f.{ 1.0f, 0.0f };
+ vertex_data := V2f.[
+ V2f.{ 0.0f, 0.0f },
+ V2f.{ 0.0f, 1.0f },
+ V2f.{ 1.0f, 1.0f },
+ V2f.{ 1.0f, 0.0f },
+ ];
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
+ gl.bufferData(gl.ARRAY_BUFFER, (#type [] void).{
count = sizeof [4] V2f,
data = cast(^void) vertex_data
}, gl.STATIC_DRAW);
quadBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
+ gl.bufferData(gl.ARRAY_BUFFER, (#type [] void).{
count = sizeof Quad * quad_data.count,
data = cast(^void) quad_data.data,
}, gl.DYNAMIC_DRAW);
gl.vertexAttribPointer(5, 4, gl.FLOAT, false, sizeof Quad, 8 * sizeof f32);
gl.bindBuffer(gl.ARRAY_BUFFER, -1);
- index_data : [6] gl.GLubyte;
- index_data[0] = cast(gl.GLubyte) 0;
- index_data[1] = cast(gl.GLubyte) 1;
- index_data[2] = cast(gl.GLubyte) 2;
- index_data[3] = cast(gl.GLubyte) 0;
- index_data[4] = cast(gl.GLubyte) 2;
- index_data[5] = cast(gl.GLubyte) 3;
-
- // index_data := { 0, 1, 2, 0, 2, 3 };
+ index_data := gl.GLubyte.[ 0, 1, 2, 0, 2, 3 ];
indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, Buffer.{
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (#type [] void).{
count = sizeof [6] gl.GLubyte,
data = cast(^void) index_data,
}, gl.STATIC_DRAW);
rebuffer_data :: proc (use qr: ^QuadRenderer) {
if !is_data_dirty do return;
+ println("Rebuffering DATA!!");
+
gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
- gl.bufferSubData(gl.ARRAY_BUFFER, 0, Buffer.{
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, (#type [] void).{
count = quad_data.count * sizeof Quad,
data = cast(^void) quad_data.data,
});
*rc = RenderContext.{
quads = aqr,
- max_quad_idx = qr.quad_data.count,
+ max_quad_idx = aqr.quad_data.count,
};
}
}
if simulating {
- quad_scratch : allocator.ScratchState;
- quad_alloc : Allocator;
- allocator.scratch_state_init(^quad_scratch, ~~quad_scratch_buffer, 512 * 1024);
- allocator.scratch_alloc_init(^quad_alloc, ^quad_scratch);
+ quad_scratch := alloc.ring.make(~~quad_scratch_buffer, 512 * 1024);
+ quad_alloc := alloc.ring.make_allocator(^quad_scratch);
quadtree_init(^dude_tree, AABB.{ 0.0f, 0.0f, ~~tilemap.width * TILE_SIZE, ~~tilemap.height * TILE_SIZE});
for ^d: dudes do quadtree_insert(^dude_tree, d, quad_alloc);
+
for ^d: dudes do dude_update(d, dt, ^dude_tree);
for ^d: dudes {
if d.can_move_x do d.pos.x += d.vel.x * dt;
// draw_quad_tree(^dude_tree);
dude_sprite := atlas.lookup(^main_atlas, 0);
+
for ^d: dudes {
aabb := dude_get_aabb(d);
renderer.color = d.color;
draw();
}
-main :: proc (args: [] cstring) {
+main :: proc (args: [] cstr) {
println("Setting up WebGL2 canvas...");
time_now :: proc () -> u32 #foreign "time" "now" ---;
tilemap_init :: proc (use tm: ^Tilemap, w := 10, h := 10) {
width = w;
height = h;
- allocator.alloc_slice(^tiles, width * height);
+ alloc.alloc_slice(^tiles, width * height);
printf("The tilemap takes up %i kibibytes.\n", (width * height * sizeof Tile) >> 10);
hw := region.w / ~~ 2;
hh := region.h / ~~ 2;
- qt.nw = alloc(a, sizeof QuadTree(T));
- qt.ne = alloc(a, sizeof QuadTree(T));
- qt.sw = alloc(a, sizeof QuadTree(T));
- qt.se = alloc(a, sizeof QuadTree(T));
+ qt.nw = raw_alloc(a, sizeof QuadTree(T));
+ qt.ne = raw_alloc(a, sizeof QuadTree(T));
+ qt.sw = raw_alloc(a, sizeof QuadTree(T));
+ qt.se = raw_alloc(a, sizeof QuadTree(T));
quadtree_init(qt.nw, AABB.{ region.x, region.y, hw, hh });
quadtree_init(qt.ne, AABB.{ region.x + hw, region.y, hw, hh });
package gl_utils
-use package core.str { make as string_make }
+use package core.string { make as string_make }
use package gl as gl
-compile_shader :: proc (shader_type: gl.GLenum, source: string) -> gl.GLShader {
+compile_shader :: proc (shader_type: gl.GLenum, source: str) -> gl.GLShader {
shader := gl.createShader(shader_type);
gl.shaderSource(shader, source);
gl.compileShader(shader);