Initial commit

This commit is contained in:
2024-10-11 22:21:32 +02:00
commit 1bdd01e9b2
38 changed files with 11363 additions and 0 deletions

189
core/entity.jai Normal file
View File

@@ -0,0 +1,189 @@
Entity_Id :: #type, isa s64;
Entity_Flags :: enum_flags u8 {
NONE;
RENDERABLE;
COLLISION;
PHYSICS;
STATIC;
TRIGGER;
ANIMATED;
DONT_SAVE;
}
Renderable_Type :: enum {
MODEL;
}
Entity_Material :: struct {
base_color : Vector4;
}
MAX_NODES :: 256;
Node_Render_Data :: struct {
enabled : bool = true;
transform: Transform;
material : Entity_Material;
has_sampled_animation: bool;
// Buffers
transform_buffer: Buffer_Handle;
material_buffer: Buffer_Handle;
bone_buffers : [MAX_BONES] Buffer_Handle;
num_bones: s64;
}
Renderable :: struct {
visible: bool = true;
type : Renderable_Type;
model: *Model;
nodes: [MAX_NODES] Node_Render_Data;
num_nodes: s64;
}
MAX_CHILDREN :: 16;
Entity :: struct {
id: Entity_Id;
type : Type;
enabled: bool = true;
name: string;
parent: *Entity; @DontSerialize
children: [MAX_CHILDREN] *Entity; @DontSerialize
num_children: s64; @DontSerialize
attach_node_index: s64 = -1; @DontSerialize
flags : Entity_Flags;
transform: Transform;
grid_position: Vector3i;
snap_offset: Vector3;
renderable: Renderable; @DontSerialize
animator: Animator; @DontSerialize
// Physics
body : Physics_Body; @DontSerialize
collider : Collider; @DontSerialize
// End physics
remote_id: Entity_Id; @DontSerialize
is_proxy: bool; @DontSerialize
last_replication_time: float; @DontSerialize
_locator: Bucket_Locator; @DontSerialize
scene: *Scene; @DontSerialize
}
add_child :: (e: *Entity, child: *Entity, node_name: string = "") {
set_parent(child, e, node_name);
}
set_parent :: (e: *Entity, parent: *Entity, node_name: string = "") {
parent.children[parent.num_children] = e;
e.parent = parent;
parent.num_children += 1;
for node, index: parent.renderable.model.nodes {
if node.name == node_name {
e.attach_node_index = index;
break;
}
}
}
set_base_color :: (e: *Entity, color: Vector4, node_name: string = "") {
if e.renderable.type == .MODEL {
for i: 0..e.renderable.num_nodes-1 {
actual_node := e.renderable.model.nodes[i];
if node_name.count == 0 || node_name == actual_node.name {
data := *e.renderable.nodes[i];
if data.material_buffer > 0 {
material : Entity_Material = ---;
material.base_color = color;
upload_data_to_buffer(renderer, data.material_buffer, *material, size_of(Entity_Material));
}
}
}
}
}
set_node_enabled :: (e: *Entity, node_name: string, enabled : bool) {
if e.renderable.type == .MODEL {
for i: 0..e.renderable.num_nodes-1 {
actual_node := e.renderable.model.nodes[i];
if node_name.count == 0 || node_name == actual_node.name {
data := *e.renderable.nodes[i];
data.enabled = enabled;
}
}
}
}
load_model_into_entity :: (e: *Entity, model: *Model) {
e.renderable.type = .MODEL;
assert(model.nodes.count <= MAX_NODES);
e.renderable.num_nodes = model.nodes.count;
e.renderable.model = model;
for *model.nodes {
data : Node_Render_Data;
data.transform = it.transform;
update_matrix(*it.transform);
if it.meshes.count > 0 {
material : Entity_Material = ---;
material.base_color = it.material_defaults[0].base_color; // @Incomplete: What if there are multiple meshes?
data.material = material;
data.transform_buffer = create_constant_buffer(renderer, null, size_of(Matrix4), mappable=true);
data.material_buffer = create_constant_buffer(renderer, *material, size_of(Entity_Material), mappable=true);
data.num_bones = it.num_bones;
if it.num_bones > 0 {
for bone_index: 0..it.num_bones-1 {
data.bone_buffers[bone_index] = create_constant_buffer(renderer, null, size_of(Matrix4) * MAX_BONES, mappable=true);
}
}
}
e.renderable.nodes[it_index] = data;
}
}
destroy_entity :: (e: *Entity, remove_from_scene: bool = true) {
free(e.name);
for 0..e.renderable.num_nodes-1 {
node_data := e.renderable.nodes[it];
if node_data.transform_buffer > 0 {
destroy_buffer(renderer, node_data.transform_buffer);
}
if node_data.material_buffer > 0 {
destroy_buffer(renderer, node_data.material_buffer);
}
for bi: 0..node_data.num_bones-1 {
destroy_buffer(renderer, node_data.bone_buffers[bi]);
}
}
if remove_from_scene {
array_unordered_remove_by_value(*game_state.current_scene.entities, e);
if e.type == {
case Block; bucket_array_remove(*game_state.current_scene.by_type._Block, e._locator);
}
}
}