Initial commit
This commit is contained in:
189
core/entity.jai
Normal file
189
core/entity.jai
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user