use package opengles
use package glfw3
+Editor_Range :: struct {min, max: f32;}
+Editor_Disabled :: struct {}
+
editor_init :: () {
editor_font = font_lookup(.{"./assets/fonts/calibri.ttf", 18});
editor_big_font = font_lookup(.{"./assets/fonts/calibri.ttf", 24});
move_towards(^editor_openness, editor_target_openness, dt * 6);
handle_clicking_tab(dt);
- handle_entity_selction_and_dragging(dt);
+ switch active_tab {
+ case .Create do handle_placing_entities();
+ case .Edit do handle_entity_selction_and_dragging(dt);
+ }
}
#local handle_clicking_tab :: (dt: f32) {
clicked_tab = .None;
}
+#local handle_placing_entities :: () {
+ if active_index < 0 do return;
+
+ if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) {
+ entity_type := ^scene.entity_types.entries[active_index].value;
+ printf("ADDING {}\n", entity_type);
+
+ pos := mouse_get_position_vector();
+ entity := entity_type.make(^scene); // scene->make(entity_type);
+ entity.pos = pos;
+ }
+}
+
#local handle_entity_selction_and_dragging :: (dt: f32) {
mouse_pos := mouse_get_position_vector();
if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) && mouse_pos.x < ~~window_width - sidebar_width && mouse_pos.y > menubar_height {
+ if active_tab == .Edit do active_index = -1;
selected_entity_id = Entity_Nothing;
+
for scene.entities {
get_rect := scene.entity_types[it.type].get_rect;
if get_rect == null_proc do continue;
immediate_rectangle(r.x, r.y, r.w, r.h);
}
- background_color :: Color.{0.5, 0.5, 0.5, 0.7};
-
{ // Draw menu bar
x := 0.0f;
w := cast(f32) window_width;
h -= 4;
w = 100;
- for type_info.enum_values(Tabs) {
+ for^ type_info.enum_values(Tabs) {
// Don't draw the "None" item;
if it.value == 0 do continue;
switch active_tab {
case .Create {
-
+ render_create_sidebar(x, y, w, h);
}
case .Edit {
}
}
+#local render_create_sidebar :: (x, y, w, h: f32) {
+ i := 0;
+ for scene.entity_types.entries {
+ defer i += 1;
+
+ type := it.key;
+ info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(type);
+
+ if active_index == i {
+ immediate_set_color(.{.5,.5,.3});
+ } elseif Rect.contains(.{x, y, w, 36.0f}, mouse_get_position_vector()) {
+ immediate_set_color(.{.4,.4,.4});
+
+ if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) {
+ active_index = i;
+ }
+ } else {
+ immediate_set_color(.{.3,.3,.3});
+ }
+
+ immediate_rectangle(x, y, w, 36.0f);
+
+ y += 40.0f;
+ font_draw_centered(editor_font, x + 4, y - 18.0f, w, info.name);
+ }
+}
+
#local render_entity_fields :: (entity: ^Entity, x, y, w, h: f32) {
assert(entity != null, "entity is null");
assert(type_info.struct_inherits(entity.type, Entity), "entity is not an entity");
font_print(editor_big_font, x + 2, y + 24, info.name);
- render_struct_fields(any.{~~entity, entity.type}, 1, x, y + 4, w, h);
+ render_struct_fields(any.{~~entity, entity.type}, 0, x, y + 4, w, h);
}
#local render_struct_fields :: (v: any, i: i32, x, y, w, h: f32, depth := 0) -> (new_y: f32, new_i: i32) {
Field_Height :: 22.0f
info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(v.type);
- for info.members {
+ for^ info.members {
i += 1;
y += Field_Height;
- if i % 2 == 0 {
+ member_any := any.{cast(^u8) v.data + it.offset, it.type};
+
+ if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) {
+ if Rect.contains(.{x, y + 2, w, Field_Height + 2}, mouse_get_position_vector()) {
+ active_index = i - 1;
+ }
+ }
+
+ if active_index + 1 == i {
+ immediate_set_color(.{.4,.4,.2});
+ immediate_rectangle(x, y + 2, w, Field_Height + 2);
+
+ render_field_editor(member_any, y, it.name);
+
+ } elseif i % 2 == 0 {
immediate_set_color(.{.3,.3,.3});
immediate_rectangle(x, y + 2, w, Field_Height + 2);
}
font_print(editor_font, x + 2, y + Field_Height, it.name);
- member_any := any.{cast(^u8) v.data + it.offset, it.type};
-
#persist depth_colors := Color.[
Color.{0.4, 0.2, 0.2},
Color.{0.2, 0.4, 0.2},
return y, i;
}
+#local render_field_editor :: (v: any, y: f32, field_name: str) {
+ w := sidebar_width;
+ h := 200.0f;
+ x := ~~ window_width - sidebar_width * 2;
+ y = math.min(y, ~~ window_height - h);
+ immediate_set_color(.{.3,.3,.3});
+ immediate_rectangle(x, y, w, h);
+
+ y += 32;
+ font_print(editor_font, x, y, field_name);
+
+ switch v.type {
+ type_is(i32) {
+ font_print(editor_font, x, y + 32, "INT: {}\n", value);
+ }
+
+ type_is(f32) {
+ font_print(editor_font, x, y + 32, "FLOAT: {}\n", value);
+ }
+ }
+
+ type_is :: macro (T: type_expr, body: Code) {
+ case T {
+ value := *cast(^T) v.data;
+ #insert body;
+ }
+ }
+}
+
#local {
+ background_color :: Color.{0.5, 0.5, 0.5, 0.7};
+
editor_font: Font;
editor_big_font: Font;
active_tab := Tabs.Create;
clicked_tab := Tabs.None;
+
+ active_index := -1;
}
e.init(e, e.init_data.{}); // This constraint ensures that everything in the initialization data is given a default value.
}
-Entity_Handles :: struct {
+Entity_Info :: struct {
+ make : (scene: ^Entity_Manager) -> ^Entity = null_proc;
+
update : (entity: ^Entity, dt: f32) -> void = null_proc;
draw : (entity: ^Entity) -> void = null_proc;
get_rect : (entity: ^Entity) -> Rect = null_proc;
entities: [..] ^Entity;
entity_map: Map(Entity_ID, ^Entity);
- entity_types: Map(type_expr, Entity_Handles);
+ entity_types: Map(type_expr, Entity_Info);
next_entity_id: Entity_ID;
register :: entity_manager_register;
add :: entity_manager_add;
make :: entity_manager_make;
+ make_old :: entity_manager_make_old;
update :: entity_manager_update;
draw :: entity_manager_draw;
get :: entity_manager_get;
}
- handles := Entity_Handles.{};
+ info := Entity_Info.{};
+ info.make = #solidify entity_manager_make { entity_type=entity_type };
@CompilerFeatures // Maybe there should be data stored in the Type_Info_Struct about
// the functions/methods that are defined in the structs scope. I don't know if that
// would be worthwhile or if it would just be bulking up the type info data.
- #if #defined(entity_type.update) { handles.update = entity_type.update; if DEBUG do printf("{} has '{}'.\n", entity_type, "update"); }
- #if #defined(entity_type.draw) { handles.draw = entity_type.draw; if DEBUG do printf("{} has '{}'.\n", entity_type, "draw"); }
- #if #defined(entity_type.get_rect) { handles.get_rect = entity_type.get_rect; if DEBUG do printf("{} has '{}'.\n", entity_type, "get_rect"); }
- #if #defined(entity_type.interact) { handles.interact = entity_type.interact; if DEBUG do printf("{} has '{}'.\n", entity_type, "interact"); }
+ #if #defined(entity_type.update) { info.update = entity_type.update; if DEBUG do printf("{} has '{}'.\n", entity_type, "update"); }
+ #if #defined(entity_type.draw) { info.draw = entity_type.draw; if DEBUG do printf("{} has '{}'.\n", entity_type, "draw"); }
+ #if #defined(entity_type.get_rect) { info.get_rect = entity_type.get_rect; if DEBUG do printf("{} has '{}'.\n", entity_type, "get_rect"); }
+ #if #defined(entity_type.interact) { info.interact = entity_type.interact; if DEBUG do printf("{} has '{}'.\n", entity_type, "interact"); }
- entity_types[entity_type] = handles;
+ entity_types[entity_type] = info;
}
}
return entity.id;
}
-entity_manager_make :: (use this: ^Entity_Manager, $entity_type: type_expr, data: entity_type.init_data = .{}) -> ^entity_type where IsEntity(^entity_type) {
+entity_manager_make :: (use this: ^Entity_Manager, $entity_type: type_expr) -> ^entity_type where IsEntity(^entity_type) {
+ entity := new(entity_type, allocator=entity_allocator);
+ entity_type.init(entity, entity_type.init_data.{});
+ this->add(entity);
+ return entity;
+}
+
+entity_manager_make_old :: (use this: ^Entity_Manager, $entity_type: type_expr, data: entity_type.init_data = .{}) -> ^entity_type where IsEntity(^entity_type) {
entity := new(entity_type, allocator=entity_allocator);
entity_type.init(entity, data);
this->add(entity);
init_data :: struct {
pos := Vector2.{0, 0};
- size := Vector2.{0, 0};
+ size := Vector2.{10, 10};
}
init :: (use this: ^Door, data: init_data) {
texture: GLint;
texture_width, texture_height: i32;
chars: [] stbtt_packedchar;
+ em: f32;
}
font_make :: (fd: FontDescriptor) -> Font {
texture = texture,
texture_width = texture_size,
texture_height = texture_size,
- chars = char_data
+ chars = char_data,
+ em = ~~fd.size,
};
font_registry[fd] = font;
}
font_draw :: (font: Font, x, y: f32, msg: str) {
- // If this is being used in conjunction with the immediate
- // rendering system, make sure the immediate objects are flushed
- // before trying to render over them.
- #if #defined(immediate_flush) {
- immediate_flush();
+ quads: ^stbtt_aligned_quad = alloc.from_stack(msg.count * sizeof stbtt_aligned_quad);
+ quad_num := 0;
+
+ x_, y_ := x, y;
+
+ for msg {
+ if it == #char "\n" {
+ x_ = x;
+ y_ += font.em + 2;
+ }
+
+ stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
+ ~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
+
+ quad_num += 1;
}
+ font_render(font, quads[0 .. quad_num]);
+}
+
+font_draw_centered :: (font: Font, x, y, max_width: f32, msg: str) {
quads: ^stbtt_aligned_quad = alloc.from_stack(msg.count * sizeof stbtt_aligned_quad);
quad_num := 0;
+ width := font_get_width(font, msg);
x_, y_ := x, y;
+ x_ = (max_width - width) / 2 + x;
for msg {
+ if it == #char "\n" {
+ x_ = (max_width - width) / 2 + x;
+ y_ += font.em + 2;
+ }
+
stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
quad_num += 1;
}
+ font_render(font, quads[0 .. quad_num]);
+}
+
+#local font_render :: (font: Font, quads: [] stbtt_aligned_quad) {
+ // If this is being used in conjunction with the immediate
+ // rendering system, make sure the immediate objects are flushed
+ // before trying to render over them.
+ #if #defined(immediate_flush) {
+ immediate_flush();
+ }
+
glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
- glBufferSubData(GL_ARRAY_BUFFER, 0, quad_num * sizeof stbtt_aligned_quad, quads);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, quads.count * sizeof stbtt_aligned_quad, quads.data);
glBindBuffer(GL_ARRAY_BUFFER, -1);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_DEPTH_TEST);
glBindVertexArray(font_vao);
- glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quad_num);
+ glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quads.count);
glBindTexture(GL_TEXTURE_2D, -1);
glBindVertexArray(-1);
}
font_get_width :: (font: Font, msg: str) -> f32 {
x_, y_ := 0.0f, 0.0f;
+ width := 0.0f;
quad: stbtt_aligned_quad;
for msg {
+ if it == #char "\n" {
+ width = math.max(width, x_);
+ x_ = 0;
+ y_ += font.em + 2;
+ continue;
+ }
+
stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
~~(it - #char " "), ^x_, ^y_, ^quad, false);
}
- return x_;
+ return math.max(x_, width);
}
#if DEBUG { debug_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16}); }
scene = entity_manager_create();
- scene->make(Player, .{ pos = .{300, 300}, controls=player_1_controls });
- scene->make(Player, .{ pos = .{400, 300}, controls=player_2_controls, color=.{1,0,0} });
-
- scene->make(Wall, .{ .{100, 100}, .{400, 50} });
- // scene->make(Wall, .{ .{100, 100}, .{50, 400} });
- // scene->make(Wall, .{ .{450, 100}, .{50, 400} });
- // scene->make(Wall, .{ .{100, 450}, .{400, 50} });
-
- scene->make(Door, .{ .{150, 150}, .{50, 50} });
- scene->make(Door, .{ .{400, 150}, .{50, 50} });
- scene->make(Door, .{ .{400, 400}, .{50, 50} });
- scene->make(Door, .{ .{150, 400}, .{50, 50} });
-
- scene->make(Item, .{ pos=.{ 250, 250 }, color=.{1,0,0} });
- scene->make(Item, .{ pos=.{ 275, 250 }, color=.{0,1,0} });
- scene->make(Item, .{ pos=.{ 300, 250 }, color=.{0,0,1} });
+ scene->make_old(Player, .{ pos = .{300, 300}, controls=player_1_controls });
+ scene->make_old(Player, .{ pos = .{400, 300}, controls=player_2_controls, color=.{1,0,0} });
+
+ scene->make_old(Wall, .{ .{100, 100}, .{400, 50} });
+ // scene->make_old(Wall, .{ .{100, 100}, .{50, 400} });
+ // scene->make_old(Wall, .{ .{450, 100}, .{50, 400} });
+ // scene->make_old(Wall, .{ .{100, 450}, .{400, 50} });
+
+ scene->make_old(Door, .{ .{150, 150}, .{50, 50} });
+ scene->make_old(Door, .{ .{400, 150}, .{50, 50} });
+ scene->make_old(Door, .{ .{400, 400}, .{50, 50} });
+ scene->make_old(Door, .{ .{150, 400}, .{50, 50} });
+
+ scene->make_old(Item, .{ pos=.{ 250, 250 }, color=.{1,0,0} });
+ scene->make_old(Item, .{ pos=.{ 275, 250 }, color=.{0,1,0} });
+ scene->make_old(Item, .{ pos=.{ 300, 250 }, color=.{0,0,1} });
#if DEBUG {
println("Registered Entity types:");