Merge branch 'main' of http://188.166.59.26/brossferatu/coven
This commit is contained in:
@@ -79,7 +79,7 @@ Entity :: struct {
|
||||
|
||||
// Physics
|
||||
body : Physics_Body; @DontSerialize
|
||||
collider : Collider; @DontSerialize
|
||||
collider : Collider;
|
||||
// End physics
|
||||
|
||||
#if NETWORKING {
|
||||
@@ -174,6 +174,10 @@ mark_entity_deleted :: (e: *Entity) {
|
||||
}
|
||||
|
||||
destroy_entity :: (e: *Entity) {
|
||||
if e.collider.mesh.vertices.data != null {
|
||||
array_free(e.collider.mesh.vertices);
|
||||
}
|
||||
|
||||
for 0..e.renderable.num_nodes-1 {
|
||||
node_data := e.renderable.nodes[it];
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#placeholder serialize_entity;
|
||||
#placeholder deserialize_entity;
|
||||
#placeholder duplicate_entity;
|
||||
#placeholder entity_ui;
|
||||
|
||||
MAX_CACHED_PILES :: 8;
|
||||
last_unnamed_scene_id := 0;
|
||||
@@ -123,6 +124,13 @@ unload_scene :: (scene: *Scene) {
|
||||
free(scene);
|
||||
}
|
||||
|
||||
switch_to_scene :: (scene_name: string) {
|
||||
new_scene := load_scene(scene_name);
|
||||
unload_scene(engine.current_scene);
|
||||
|
||||
engine.current_scene = new_scene;
|
||||
}
|
||||
|
||||
reload_scene :: (scene: *Scene) {
|
||||
name := copy_temporary_string(scene.name);
|
||||
unload_scene(engine.current_scene);
|
||||
@@ -262,6 +270,14 @@ update_entity_transform :: (e: *Entity, parent_matrix: Matrix4 = Matrix4_Identit
|
||||
}
|
||||
}
|
||||
|
||||
get_entity_with_id :: (scene: *Scene, id: s64) -> *Entity {
|
||||
for scene.entities {
|
||||
if it.id == id return it;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#scope_file
|
||||
next_entity_id: Entity_Id;
|
||||
@@ -229,6 +229,8 @@ editor_ui :: () {
|
||||
ui_vector_field("Scale", *entity.transform.scale);
|
||||
|
||||
update_matrix(*entity.transform);
|
||||
|
||||
entity_ui(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +81,42 @@ should_serialize :: (type: *Type_Info_Struct, member: Type_Info_Struct_Member) -
|
||||
return true;
|
||||
}
|
||||
|
||||
generate_member_ui :: (type: *Type_Info_Struct, builder: *String_Builder, path: string = "") {
|
||||
for type.members {
|
||||
if should_serialize(type, it) {
|
||||
new_path : string;
|
||||
if path.count == 0 {
|
||||
new_path = it.name;
|
||||
} else {
|
||||
new_path = tprint("%1.%2", path, it.name);
|
||||
}
|
||||
|
||||
if it.type.type == {
|
||||
case .STRUCT; {
|
||||
info_struct := cast(*Type_Info_Struct) it.type;
|
||||
if info_struct.name == "Vector3" {
|
||||
print_to_builder(builder, "\tui_vector_field(tprint(\"%\"), *e.%);\n", new_path, new_path);
|
||||
} else {
|
||||
generate_member_ui(info_struct, builder, new_path);
|
||||
}
|
||||
}
|
||||
//case .BOOL; #through;
|
||||
case .STRING; {
|
||||
print_to_builder(builder, "\tui_textfield(tprint(\"%\"), *e.%);\n", new_path, new_path);
|
||||
//ui_textfield :: (label: string, text: *string, identifier: s64 = 0, loc := #caller_location) {
|
||||
}
|
||||
case .FLOAT; {
|
||||
print_to_builder(builder, "\tui_float_field(tprint(\"%\"), *e.%);\n", new_path, new_path);
|
||||
}
|
||||
//case .ENUM; #through;
|
||||
case .INTEGER; {
|
||||
print_to_builder(builder, "\tui_int_field(tprint(\"%\"), *e.%);\n", new_path, new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generate_member_serialization :: (type: *Type_Info_Struct, builder: *String_Builder, path: string = "") {
|
||||
for type.members {
|
||||
if should_serialize(type, it) {
|
||||
@@ -96,6 +132,9 @@ generate_member_serialization :: (type: *Type_Info_Struct, builder: *String_Buil
|
||||
info_struct := cast(*Type_Info_Struct) it.type;
|
||||
generate_member_serialization(info_struct, builder, new_path);
|
||||
}
|
||||
case .STRING; {
|
||||
print_to_builder(builder, "\tprint_to_builder(builder, \"%: \%\\n\", e.%);\n", new_path, new_path);
|
||||
}
|
||||
case .BOOL; #through;
|
||||
case .FLOAT; #through;
|
||||
case .ENUM; #through;
|
||||
@@ -121,6 +160,10 @@ generate_member_deserialization :: (type: *Type_Info_Struct, builder: *String_Bu
|
||||
info_struct := cast(*Type_Info_Struct) it.type;
|
||||
generate_member_deserialization(info_struct, builder, new_path);
|
||||
}
|
||||
case .STRING; {
|
||||
print_to_builder(builder, "\t\t\t\tcase \"%\";\n", new_path);
|
||||
print_to_builder(builder, "\t\t\t\tif values[1].count > 0 { e.%1 = copy_string(trim(values[1])); }\n", new_path);
|
||||
}
|
||||
case .BOOL; #through;
|
||||
case .FLOAT; #through;
|
||||
case .ENUM; #through;
|
||||
@@ -159,6 +202,18 @@ generate_member_copy :: (type: *Type_Info_Struct, builder: *String_Builder, path
|
||||
}
|
||||
}
|
||||
|
||||
generate_ui_procedure_for_entity :: (code_struct: *Code_Struct) {
|
||||
name := code_struct.defined_type.name;
|
||||
|
||||
// Serialize
|
||||
ui : String_Builder;
|
||||
print_to_builder(*ui, "entity_ui_proc :: (e: *%) {\n", name);
|
||||
generate_member_ui(code_struct.defined_type, *ui);
|
||||
print_to_builder(*ui, "}\n");
|
||||
|
||||
array_add(*entity_serialize_proc_string, builder_to_string(*ui));
|
||||
}
|
||||
|
||||
generate_serialize_procedure_for_entity :: (code_struct: *Code_Struct) {
|
||||
name := code_struct.defined_type.name;
|
||||
|
||||
@@ -213,6 +268,7 @@ note_struct :: (code_struct: *Code_Struct) {
|
||||
print("Detected entity '%'.\n", name);
|
||||
|
||||
generate_serialize_procedure_for_entity(code_struct);
|
||||
generate_ui_procedure_for_entity(code_struct);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,6 +420,17 @@ generate_code :: (w: Workspace) {
|
||||
add_build_string(build_string, w);
|
||||
}
|
||||
|
||||
{
|
||||
builder: String_Builder;
|
||||
|
||||
for entity_type_names {
|
||||
print_to_builder(*builder, "\tcase %1; entity_ui_proc(cast(*%1)e);\n", it);
|
||||
}
|
||||
|
||||
build_string := sprint(ENTITY_UI, builder_to_string(*builder));
|
||||
add_build_string(build_string, w);
|
||||
}
|
||||
|
||||
{
|
||||
builder: String_Builder;
|
||||
|
||||
@@ -386,7 +453,7 @@ generate_code :: (w: Workspace) {
|
||||
add_build_string(build_string, w);
|
||||
|
||||
// We'll print out the added code just to show at compile-time what we are doing:
|
||||
print("Adding build string:\n%\n", build_string);
|
||||
//print("Adding build string:\n%\n", build_string);
|
||||
}
|
||||
|
||||
generated_code := false;
|
||||
@@ -470,6 +537,14 @@ duplicate_entity :: (e: *Entity) -> *Entity {
|
||||
}
|
||||
DONE
|
||||
|
||||
ENTITY_UI :: #string DONE
|
||||
entity_ui :: (e: *Entity) {
|
||||
if e.type == {
|
||||
%1
|
||||
}
|
||||
}
|
||||
DONE
|
||||
|
||||
INIT_SCENE :: #string DONE
|
||||
init_scene :: (scene: *Scene) {
|
||||
%1
|
||||
|
||||
@@ -36,6 +36,8 @@ Engine_Core :: struct {
|
||||
procs: struct {
|
||||
on_scene_loaded: (*Scene, Engine_Mode);
|
||||
on_pre_scene_loaded: (*Scene, Engine_Mode);
|
||||
on_trigger_enter: (*Entity, *Entity);
|
||||
on_trigger_exit: (*Entity, *Entity);
|
||||
}
|
||||
|
||||
paused: bool;
|
||||
@@ -115,6 +117,10 @@ coven_run :: (game_update_proc: (float), game_update_post_physics_proc: (float))
|
||||
update_physics(engine.current_scene, clamped_dt);
|
||||
game_update_post_physics_proc(clamped_dt);
|
||||
}
|
||||
} else {
|
||||
if engine.current_scene != null {
|
||||
update_trigger_mesh_colliders(engine.current_scene);
|
||||
}
|
||||
}
|
||||
|
||||
if engine.current_scene != null {
|
||||
|
||||
@@ -26,9 +26,6 @@ Trigger_Overlap :: struct {
|
||||
|
||||
MAX_TRIGGER_OVERLAPS :: 16;
|
||||
|
||||
on_trigger_enter_callback : (*Entity, *Entity);
|
||||
on_trigger_exit_callback : (*Entity, *Entity);
|
||||
|
||||
Collision_Layers :: enum_flags {
|
||||
NONE;
|
||||
|
||||
@@ -52,17 +49,17 @@ Collider :: struct {
|
||||
layer: Collision_Layers = .LAYER1;
|
||||
collides_with_layers: Collision_Layers = .LAYER1;
|
||||
|
||||
aabb: AABB;
|
||||
override_aabb: bool;
|
||||
aabb: AABB;
|
||||
union {
|
||||
sphere: Sphere;
|
||||
mesh : Mesh_Collider;
|
||||
sphere: Sphere; @DontSerialize
|
||||
mesh : Mesh_Collider; @DontSerialize
|
||||
}
|
||||
|
||||
overlaps: [MAX_TRIGGER_OVERLAPS] Trigger_Overlap;
|
||||
num_overlaps: s64;
|
||||
overlaps: [MAX_TRIGGER_OVERLAPS] Trigger_Overlap; @DontSerialize
|
||||
num_overlaps: s64; @DontSerialize
|
||||
|
||||
ignore: bool;
|
||||
ignore: bool; @DontSerialize
|
||||
}
|
||||
|
||||
Physics_Body :: struct {
|
||||
@@ -95,6 +92,16 @@ update_mesh_collider :: (e: *Entity) {
|
||||
e.collider.mesh.is_baked = true;
|
||||
}
|
||||
|
||||
update_trigger_mesh_colliders :: (scene: *Scene) {
|
||||
for e: scene.entities {
|
||||
if e.flags & .TRIGGER {
|
||||
if e.collider.type == .MESH {
|
||||
update_mesh_collider(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_mesh_colliders :: (scene: *Scene) {
|
||||
for e: scene.entities {
|
||||
if e.flags & .COLLISION {
|
||||
@@ -187,8 +194,8 @@ add_trigger_overlap_if_new :: (triggered_entity: *Entity, triggered_by_entity: *
|
||||
}
|
||||
}
|
||||
|
||||
if on_trigger_enter_callback != null {
|
||||
on_trigger_enter_callback(triggered_entity, triggered_by_entity);
|
||||
if engine.procs.on_trigger_enter != null {
|
||||
engine.procs.on_trigger_enter(triggered_entity, triggered_by_entity);
|
||||
}
|
||||
|
||||
triggered_entity.collider.overlaps[triggered_entity.collider.num_overlaps] = .{ triggered_by_entity, frame_index };
|
||||
@@ -288,8 +295,8 @@ update_physics :: (scene: *Scene, dt: float) {
|
||||
defer index += 1;
|
||||
|
||||
if e.collider.overlaps[index].frame_index < frame_index {
|
||||
if on_trigger_exit_callback != null {
|
||||
on_trigger_exit_callback(e, e.collider.overlaps[index].entity);
|
||||
if engine.procs.on_trigger_exit != null {
|
||||
engine.procs.on_trigger_exit(e, e.collider.overlaps[index].entity);
|
||||
}
|
||||
|
||||
if e.collider.num_overlaps > 1 {
|
||||
|
||||
113
ui/widgets.jai
113
ui/widgets.jai
@@ -184,6 +184,118 @@ ui_textfield :: (label: string, text: *string, identifier: s64 = 0, loc := #call
|
||||
ui_pop_parent();
|
||||
}
|
||||
|
||||
ui_int_field :: (label: string, value: *int, identifier: s64 = 0, loc := #caller_location) {
|
||||
ui_container_layout(identifier=identifier, loc=loc);
|
||||
ui_set_next_size_x(.CHILDREN_SUM);
|
||||
ui_push_parent(ui_state.last_box, .LEFT, .HORIZONTAL);
|
||||
{
|
||||
ui_label(label);
|
||||
|
||||
text_size := get_text_size(engine.renderer, tprint("%", <<value), ui_state.fonts.button);
|
||||
|
||||
ui_set_next_size_y(.PIXELS, text_size.y); // TODO
|
||||
ui_set_next_size_x(.CHILDREN_SUM);
|
||||
ui_set_next_padding(5);
|
||||
|
||||
//ui_set_next_text_alignment(.CENTER_VERTICALLY);
|
||||
outer := ui_box_make(.ANIMATE_ON_HOVER | .CLICKABLE | .DRAW_BORDER, get_hash(loc, identifier));
|
||||
|
||||
if outer.interaction.editing {
|
||||
outer.style.border_color = .{0.3,0.3,1.0,1.0};
|
||||
}
|
||||
|
||||
ui_push_parent(outer, alignment=.LEFT, axis=.HORIZONTAL);
|
||||
{
|
||||
ui_set_next_text_color(.{1,1,1,1});
|
||||
ui_set_next_text_alignment(.CENTER_VERTICALLY);
|
||||
ui_set_next_text_color(.{1,1,1,1});
|
||||
ui_set_next_size_x(.TEXT_DIM);
|
||||
ui_set_next_size_y(.TEXT_DIM);
|
||||
text_widget := ui_box_make(.DRAW_TEXT, get_hash(loc, identifier));
|
||||
|
||||
if outer.interaction.editing {
|
||||
text_widget.text = alloc_string(text_widget._number_text.count,, allocator=temp);
|
||||
memcpy(text_widget.text.data, text_widget._number_text.data.data, text_widget._number_text.count);
|
||||
|
||||
// Cursor
|
||||
ui_set_next_background_color(.{1.0,1.0,1.0,1.0});
|
||||
ui_set_next_size_x(.PIXELS, 2);
|
||||
ui_set_next_size_y(.PCT, 1);
|
||||
cursor := ui_box_make(.DRAW_BACKGROUND, get_hash(loc, identifier));
|
||||
|
||||
if key_down(.BACKSPACE) && text_widget._number_text.count > 0 {
|
||||
text_widget._number_text.count -= 1;
|
||||
}
|
||||
|
||||
if key_down(.RETURN) {
|
||||
// FORMAT IT BACK!
|
||||
temp_str : string;
|
||||
temp_str.data = text_widget._number_text.data.data;
|
||||
temp_str.count = text_widget._number_text.count;
|
||||
<<value = parse_int(*temp_str);
|
||||
outer.interaction.editing = false;
|
||||
engine.editor.focused_widget = null;
|
||||
}
|
||||
|
||||
if engine.input.has_char {
|
||||
text_str := alloc_string(1,, allocator=temp);
|
||||
text_str[0] = xx engine.input.current_char;
|
||||
|
||||
if text_str == {
|
||||
case "0";#through;
|
||||
case "1";#through;
|
||||
case "2";#through;
|
||||
case "3";#through;
|
||||
case "4";#through;
|
||||
case "5";#through;
|
||||
case "6";#through;
|
||||
case "7";#through;
|
||||
case "8";#through;
|
||||
case "9";
|
||||
{
|
||||
if !(text_str == "." && (array_contains(text_widget._number_text, #char ".") || text_widget._number_text.count == 0)) {
|
||||
text_widget._number_text.data[text_widget._number_text.count] = text_str[0];
|
||||
text_widget._number_text.count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ignore non-numeric characters
|
||||
} else {
|
||||
text_widget.text = copy_temporary_string(tprint("%", <<value));
|
||||
}
|
||||
|
||||
if outer.interaction.clicked {
|
||||
if engine.editor.focused_widget != null {
|
||||
engine.editor.focused_widget.interaction.editing = false;
|
||||
}
|
||||
|
||||
outer.interaction.editing = true;
|
||||
engine.editor.focused_widget = outer;
|
||||
formatted_text := copy_temporary_string(tprint("%", <<value));
|
||||
memcpy(text_widget._number_text.data.data, formatted_text.data, formatted_text.count);
|
||||
text_widget._number_text.count = formatted_text.count;
|
||||
}
|
||||
}
|
||||
ui_pop_parent();
|
||||
}
|
||||
ui_pop_parent();
|
||||
ui_set_next_background_color(.{0.0,1.0,1.0,0.0});
|
||||
ui_set_next_border_color(.{0.3,0.3,0.3,1.0});
|
||||
ui_set_next_size_x(.CHILDREN_SUM, 1);
|
||||
}
|
||||
|
||||
ui_float_field :: (label: string, value: *float, identifier: s64 = 0, loc := #caller_location) {
|
||||
ui_container_layout(identifier=identifier, loc=loc);
|
||||
ui_set_next_size_x(.CHILDREN_SUM);
|
||||
ui_push_parent(ui_state.last_box, .LEFT, .HORIZONTAL);
|
||||
{
|
||||
ui_label(label);
|
||||
ui_float_field(value, identifier);
|
||||
}
|
||||
ui_pop_parent();
|
||||
}
|
||||
|
||||
ui_float_field :: (value: *float, identifier: s64 = 0, loc := #caller_location) {
|
||||
ui_set_next_background_color(.{0.0,1.0,1.0,0.0});
|
||||
ui_set_next_border_color(.{0.3,0.3,0.3,1.0});
|
||||
@@ -249,6 +361,7 @@ ui_float_field :: (value: *float, identifier: s64 = 0, loc := #caller_location)
|
||||
case "7";#through;
|
||||
case "8";#through;
|
||||
case "9";#through;
|
||||
case "-";#through;
|
||||
case "."; {
|
||||
if !(text_str == "." && (array_contains(text_widget._number_text, #char ".") || text_widget._number_text.count == 0)) {
|
||||
text_widget._number_text.data[text_widget._number_text.count] = text_str[0];
|
||||
|
||||
Reference in New Issue
Block a user