From bd55fc66bf3b2440746622474469e37d9561490c Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Tue, 24 Dec 2019 16:59:13 +1100 Subject: [PATCH] Implemented duplicating selected entity in editor --- src/game/editor.c | 11 ++++++ src/game/scene.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++- src/game/scene.h | 1 + todo.txt | 8 ++--- 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/game/editor.c b/src/game/editor.c index a842179..e04e3b2 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -1217,6 +1217,15 @@ void editor_on_key_release(const struct Event* event) editor->selected_entity->flags |= EF_MARKED_FOR_DELETION; editor_entity_select(editor, NULL); } + + if(event->key.key == KEY_D && input_is_key_pressed(KEY_LCTRL) && editor->selected_entity && !editor->camera_looking_around) + { + struct Entity* new_entity = scene_entity_duplicate(game_state->scene, editor->selected_entity); + if(new_entity) + { + editor_entity_select(editor, new_entity); + } + } } void editor_tool_set(struct Editor* editor, int tool) @@ -2241,6 +2250,8 @@ void editor_entity_dialog(struct Editor* editor, struct nk_context* context) if(copy_entity_filename) { memset(entity_filename, '\0', MAX_FILENAME_LEN); + if(editor->selected_entity->archetype_index != -1) + strncpy(entity_filename, scene->entity_archetypes[editor->selected_entity->archetype_index], MAX_FILENAME_LEN); } int entity_filename_flags = NK_EDIT_SIG_ENTER | NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD; diff --git a/src/game/scene.c b/src/game/scene.c index d871c2f..085825f 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -576,7 +576,7 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* new_sound_source->source_buffer = sound_source_create(sound, filename, type); if(!new_sound_source->source_buffer) { - log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name); + log_error("scene:sound_source_create", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name); new_sound_source->source_instance = 0; return new_sound_source; } @@ -853,3 +853,88 @@ int scene_entity_archetype_add(struct Scene* scene, const char* filename) return index; } + +struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity) +{ + assert(scene && entity); + + struct Entity* new_entity = NULL; + if(entity->archetype_index != -1) + { + new_entity = entity_load(scene->entity_archetypes[entity->archetype_index], DIRT_INSTALL); + scene_entity_parent_set(scene, new_entity, entity->transform.parent); + return new_entity; + } + + switch(entity->type) + { + case ET_DEFAULT: + { + new_entity = scene_entity_create(scene, entity->name, entity->transform.parent); + } + break; + case ET_LIGHT: + { + struct Light* light = (struct Light*)entity; + struct Light* new_light = scene_light_create(scene, entity->name, entity->transform.parent, light->type); + new_light->inner_angle = light->inner_angle; + new_light->outer_angle = light->outer_angle; + new_light->falloff = light->falloff; + new_light->intensity = light->intensity; + new_light->cast_shadow = light->cast_shadow; + new_light->pcf_enabled = light->pcf_enabled; + new_light->valid = light->valid; + new_light->type = light->type; + new_light->radius = light->radius; + new_light->depth_bias = light->depth_bias; + vec3_assign(&new_light->color, &light->color); + memcpy(new_light->shadow_map, light->shadow_map, sizeof(int) * 4); // Fix this when we implement shadow mapping + new_entity = &new_light->base; + } + break; + case ET_STATIC_MESH: + { + struct Static_Mesh* mesh = (struct Static_Mesh*)entity; + struct Static_Mesh* new_mesh = scene_static_mesh_create(scene, entity->name, entity->transform.parent, geom_get(mesh->model.geometry_index)->filename, mesh->model.material->type); + memcpy(new_mesh->model.material_params, mesh->model.material_params, sizeof(struct Variant) * MMP_MAX); + new_entity = &new_mesh->base; + //Handle collision related information here! + } + break; + case ET_SOUND_SOURCE: + { + struct Sound_Source* sound_source = (struct Sound_Source*)entity; + struct Sound_Source* new_sound_source = scene_sound_source_create(scene, entity->name, entity->transform.parent, sound_source->source_buffer->filename, sound_source->type, sound_source->loop, sound_source->playing); + new_sound_source->min_distance = sound_source->min_distance; + new_sound_source->max_distance = sound_source->max_distance; + new_sound_source->rolloff_factor = sound_source->rolloff_factor; + new_sound_source->volume = sound_source->volume; + new_sound_source->attenuation_type = sound_source->attenuation_type; + + struct Sound* sound = game_state_get()->sound; + sound_source_instance_attenuation_set(sound, new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor); + sound_source_instance_min_max_distance_set(sound, new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance); + sound_source_instance_volume_set(sound, new_sound_source->source_instance, new_sound_source->volume); + new_entity = &new_sound_source->base; + } + break; + default: + { + log_message("Cannot duplicate unsupported entity type: %s", entity_type_name_get(entity)); + } + break; + } + + transform_copy(new_entity, entity, false); + + for(int i = 0; i < array_len(entity->transform.children); i++) + { + struct Entity* child_entity = entity->transform.children[i]; + struct Entity* new_child_entity = scene_entity_duplicate(scene, child_entity); + if(new_child_entity) + scene_entity_parent_set(scene, new_child_entity, new_entity); + else + log_error("scene:entity_duplicate", "Failed to create child entity from %s", child_entity->name); + } + return new_entity; +} diff --git a/src/game/scene.h b/src/game/scene.h index 4227434..40eccad 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -34,6 +34,7 @@ void scene_destroy(struct Scene* scene); void scene_update(struct Scene* scene, float dt); void scene_post_update(struct Scene* scene); +struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity); struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent); struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type); struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height); diff --git a/todo.txt b/todo.txt index 58f73dd..a21f9cd 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,5 @@ Todo: - - For entities that have archetypes, check read/write them to the file they were loaded from when showing the save entity dialog - When loading entities, show an additional optional textfield where user can enter the name they want for the entity after it is loaded - - Implelement contextual actions for entites that are shown in scene hierarchy - Add editor undo for transformation operations - Decide how to handle scale when checking sphere-ray intersection - Add material export for blender exporter? @@ -35,7 +33,6 @@ Todo: ? Maybe remove physics engine and ode all together if we're not using it or investigate the memory leaks that it causes if we're going to keep it? - Disable editor event recievers on game mode change - Editor Undo - - Duplicate with Ctrl-D - Color picker - Color palette, picker and dropper - Key binding and function to snap editor camera to selected entity @@ -380,4 +377,7 @@ Done: * Console command help * Use actual selected entity's mesh for tool mesh when the entity already has a mesh and use a placeholder like a sphere when there is not mesh * Implmented dialog for loading entities into the scene via editor - * Implement behaviour that avoids writing normal entities that do not have children or parent to file to avoid inconsistencies when loading them \ No newline at end of file + * Implement behaviour that avoids writing normal entities that do not have children or parent to file to avoid inconsistencies when loading them + * Implelement contextual actions for entites that are shown in scene hierarchy + * For entities that have archetypes, check read/write them to the file they were loaded from when showing the save entity dialog + * Duplicate with Ctrl-D \ No newline at end of file