diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ecb7244b..8db81172 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: run: | set VULKAN_SDK=C:\VulkanSDK\1.3.224.1 cd $GITHUB_WORKSPACE - cd scripts + cd tools python gen_build.py python gen_examples.py cd ../src @@ -68,13 +68,14 @@ jobs: if not exist ../out/pl_ref_renderer_ext.dll exit 1 if not exist ../out/pl_draw_ext.dll exit 1 if not exist ../out/pl_ui_ext.dll exit 1 + if not exist ../out/pl_camera_script.dll exit 1 if not exist ../out/pilotlight.lib exit 1 - name: Package Pilot Light shell: cmd run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python package.py - name: Upload Pilot Light @@ -100,7 +101,7 @@ jobs: - name: Build Pilot Light run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 gen_build.py python3 gen_examples.py cd ../src @@ -132,12 +133,13 @@ jobs: test -f ./out/pl_ref_renderer_ext.dylib || exit 1 test -f ./out/pl_draw_ext.dylib || exit 1 test -f ./out/pl_ui_ext.dylib || exit 1 + test -f ./out/pl_camera_script.dylib || exit 1 test -f ./out/pilotlight.a || exit 1 - name: Package Pilot Light run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 package.py - name: Upload Pilot Light @@ -177,7 +179,7 @@ jobs: - name: Build Pilot Light run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 gen_build.py python3 gen_examples.py cd ../src @@ -209,12 +211,13 @@ jobs: test -f ./out/pl_ref_renderer_ext.so || exit 1 test -f ./out/pl_draw_ext.so || exit 1 test -f ./out/pl_ui_ext.so || exit 1 + test -f ./out/pl_camera_script.so || exit 1 test -f ./out/pilotlight.a || exit 1 - name: Package Pilot Light run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 package.py pwd diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 95c4a77d..323504e2 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -60,7 +60,7 @@ jobs: echo "You may use a free license. More information at https://www.viva64.com/en/b/0457/" exit 0 fi - cd scripts + cd tools python3 gen_build.py cd ../src chmod +x build.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4b90ce56..2d8ff384 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,7 +33,7 @@ jobs: shell: cmd run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python gen_tests.py cd ../tests call build.bat -c debug @@ -58,7 +58,7 @@ jobs: - name: Run Tests run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 gen_tests.py cd ../tests chmod +x build.sh @@ -94,7 +94,7 @@ jobs: - name: Run Tests run: | cd $GITHUB_WORKSPACE - cd scripts + cd tools python3 gen_tests.py cd ../tests chmod +x build.sh diff --git a/apps/app.c b/apps/app.c index 1631332b..13a1a663 100644 --- a/apps/app.c +++ b/apps/app.c @@ -240,6 +240,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) ptAppData->tMainCamera = gptEcs->create_perspective_camera(ptMainComponentLibrary, "main camera", (plVec3){-9.6f, 2.096f, 0.86f}, PL_PI_3, ptIO->afMainViewportSize[0] / ptIO->afMainViewportSize[1], 0.1f, 30.0f, &ptMainCamera); gptCamera->set_pitch_yaw(ptMainCamera, -0.245f, 1.816f); gptCamera->update(ptMainCamera); + gptEcs->attach_script(ptMainComponentLibrary, "pl_camera_script", PL_SCRIPT_FLAG_PLAYING, ptAppData->tMainCamera, NULL); // create cull camera plCameraComponent* ptCullCamera = NULL; @@ -386,33 +387,6 @@ pl_app_update(plAppData* ptAppData) plCameraComponent* ptCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera); plCameraComponent* ptCullCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tCullCamera); - - static const float fCameraTravelSpeed = 4.0f; - static const float fCameraRotationSpeed = 0.005f; - - // camera space - bool bOwnKeyboard = ptIO->bWantCaptureKeyboard; - if(!bOwnKeyboard) - { - if(gptIO->is_key_down(PL_KEY_W)) gptCamera->translate(ptCamera, 0.0f, 0.0f, fCameraTravelSpeed * ptIO->fDeltaTime); - if(gptIO->is_key_down(PL_KEY_S)) gptCamera->translate(ptCamera, 0.0f, 0.0f, -fCameraTravelSpeed* ptIO->fDeltaTime); - if(gptIO->is_key_down(PL_KEY_A)) gptCamera->translate(ptCamera, -fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f, 0.0f); - if(gptIO->is_key_down(PL_KEY_D)) gptCamera->translate(ptCamera, fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f, 0.0f); - - // world space - if(gptIO->is_key_down(PL_KEY_F)) { gptCamera->translate(ptCamera, 0.0f, -fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f); } - if(gptIO->is_key_down(PL_KEY_R)) { gptCamera->translate(ptCamera, 0.0f, fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f); } - } - - bool bOwnMouse = ptIO->bWantCaptureMouse; - if(!bOwnMouse && gptIO->is_mouse_dragging(PL_MOUSE_BUTTON_LEFT, 1.0f)) - { - const plVec2 tMouseDelta = gptIO->get_mouse_drag_delta(PL_MOUSE_BUTTON_LEFT, 1.0f); - gptCamera->rotate(ptCamera, -tMouseDelta.y * fCameraRotationSpeed, -tMouseDelta.x * fCameraRotationSpeed); - gptIO->reset_mouse_drag_delta(PL_MOUSE_BUTTON_LEFT); - } - - gptCamera->update(ptCamera); gptCamera->update(ptCullCamera); // run ecs system diff --git a/examples/README.md b/examples/README.md index ce7049fa..7b7e9abf 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,7 +8,7 @@ Next: ### Windows Example for running example 0: ```bash -cd pilotlight/scripts +cd pilotlight/tools python gen_examples.py cd ../examples build.bat @@ -19,7 +19,7 @@ pilot_light.exe -a example_0 ### MacOS & Linux Example for running example 0: ```bash -cd pilotlight/scripts +cd pilotlight/tools python3 gen_examples.py cd ../examples chmod +x build.sh diff --git a/extensions/pl_draw_ext.c b/extensions/pl_draw_ext.c index 64a1b796..7c9eb7cc 100644 --- a/extensions/pl_draw_ext.c +++ b/extensions/pl_draw_ext.c @@ -1848,6 +1848,8 @@ pl_cleanup_font_atlas(void) } pl_sb_free(gptCtx->tFontAtlas.sbtCustomRects); pl_sb_free(gptCtx->tFontAtlas.sbtFonts); + pl_sb_free(gptCtx->tFontAtlas.sbtFontFreeIndices); + pl_sb_free(gptCtx->tFontAtlas.sbtFontGenerations); pl_sb_free(gptCtx->tFontAtlas._sbtPrepData); PL_FREE(gptCtx->tFontAtlas.pucPixelsAsAlpha8); PL_FREE(gptCtx->tFontAtlas.pucPixelsAsRGBA32); diff --git a/extensions/pl_ecs_ext.c b/extensions/pl_ecs_ext.c index 52e7f681..9aa1dad3 100644 --- a/extensions/pl_ecs_ext.c +++ b/extensions/pl_ecs_ext.c @@ -28,6 +28,7 @@ Index of this file: // extensions #include "pl_job_ext.h" +#include "pl_script_ext.h" //----------------------------------------------------------------------------- // [SECTION] structs @@ -44,7 +45,10 @@ typedef struct _plComponentLibraryData static uint32_t uLogChannel = UINT32_MAX; -static const plJobI* gptJob = NULL; +// apis +static const plJobI* gptJob = NULL; +static const plApiRegistryI* gptApiRegistry = NULL; +static const plExtensionRegistryI* gptExtensionRegistry = NULL; //----------------------------------------------------------------------------- // [SECTION] internal api @@ -76,6 +80,8 @@ static plEntity pl_ecs_create_perspective_camera (plComponentLibrary*, const cha static plEntity pl_ecs_create_orthographic_camera(plComponentLibrary*, const char* pcName, plVec3 tPos, float fWidth, float fHeight, float fNearZ, float fFarZ, plCameraComponent**); static plEntity pl_ecs_create_directional_light (plComponentLibrary*, const char* pcName, plVec3 tDirection, plLightComponent**); static plEntity pl_ecs_create_point_light (plComponentLibrary*, const char* pcName, plVec3 tPosition, plLightComponent**); +static plEntity pl_ecs_create_script (plComponentLibrary*, const char* pcFile, plScriptFlags, plScriptComponent**); +static void pl_ecs_attach_script (plComponentLibrary*, const char* pcFile, plScriptFlags, plEntity, plScriptComponent**); // heirarchy @@ -89,6 +95,7 @@ static void pl_run_skin_update_system (plComponentLibrary* ptLibrar static void pl_run_hierarchy_update_system (plComponentLibrary* ptLibrary); static void pl_run_animation_update_system (plComponentLibrary* ptLibrary, float fDeltaTime); static void pl_run_inverse_kinematics_update_system(plComponentLibrary* ptLibrary); +static void pl_run_script_update_system (plComponentLibrary* ptLibrary); // misc. static void pl_calculate_normals (plMeshComponent* atMeshes, uint32_t uComponentCount); @@ -126,62 +133,6 @@ pl_ecs_has_entity(plComponentManager* ptManager, plEntity tEntity) // [SECTION] public api implementation //----------------------------------------------------------------------------- -static const plEcsI* -pl_load_ecs_api(void) -{ - static const plEcsI tApi = { - .init_component_library = pl_ecs_init_component_library, - .cleanup_component_library = pl_ecs_cleanup_component_library, - .create_entity = pl_ecs_create_entity, - .remove_entity = pl_ecs_remove_entity, - .get_entity = pl_ecs_get_entity, - .is_entity_valid = pl_ecs_is_entity_valid, - .get_index = pl_ecs_get_index, - .get_component = pl_ecs_get_component, - .add_component = pl_ecs_add_component, - .create_tag = pl_ecs_create_tag, - .create_mesh = pl_ecs_create_mesh, - .create_perspective_camera = pl_ecs_create_perspective_camera, - .create_orthographic_camera = pl_ecs_create_orthographic_camera, - .create_object = pl_ecs_create_object, - .create_transform = pl_ecs_create_transform, - .create_material = pl_ecs_create_material, - .create_skin = pl_ecs_create_skin, - .create_animation = pl_ecs_create_animation, - .create_animation_data = pl_ecs_create_animation_data, - .create_directional_light = pl_ecs_create_directional_light, - .create_point_light = pl_ecs_create_point_light, - .attach_component = pl_ecs_attach_component, - .deattach_component = pl_ecs_deattach_component, - .calculate_normals = pl_calculate_normals, - .calculate_tangents = pl_calculate_tangents, - .run_object_update_system = pl_run_object_update_system, - .run_transform_update_system = pl_run_transform_update_system, - .run_hierarchy_update_system = pl_run_hierarchy_update_system, - .run_skin_update_system = pl_run_skin_update_system, - .run_animation_update_system = pl_run_animation_update_system, - .run_inverse_kinematics_update_system = pl_run_inverse_kinematics_update_system - }; - return &tApi; -} - -static const plCameraI* -pl_load_camera_api(void) -{ - static const plCameraI tApi = { - .set_fov = pl_camera_set_fov, - .set_clip_planes = pl_camera_set_clip_planes, - .set_aspect = pl_camera_set_aspect, - .set_pos = pl_camera_set_pos, - .set_pitch_yaw = pl_camera_set_pitch_yaw, - .translate = pl_camera_translate, - .rotate = pl_camera_rotate, - .update = pl_camera_update, - .look_at = pl_camera_look_at, - }; - return &tApi; -} - //----------------------------------------------------------------------------- // [SECTION] internal api implementation //----------------------------------------------------------------------------- @@ -226,6 +177,9 @@ pl_ecs_init_component_library(plComponentLibrary* ptLibrary) ptLibrary->tLightComponentManager.tComponentType = PL_COMPONENT_TYPE_LIGHT; ptLibrary->tLightComponentManager.szStride = sizeof(plLightComponent); + ptLibrary->tScriptComponentManager.tComponentType = PL_COMPONENT_TYPE_SCRIPT; + ptLibrary->tScriptComponentManager.szStride = sizeof(plScriptComponent); + ptLibrary->_ptManagers[0] = &ptLibrary->tTagComponentManager; ptLibrary->_ptManagers[1] = &ptLibrary->tTransformComponentManager; ptLibrary->_ptManagers[2] = &ptLibrary->tMeshComponentManager; @@ -238,6 +192,7 @@ pl_ecs_init_component_library(plComponentLibrary* ptLibrary) ptLibrary->_ptManagers[9] = &ptLibrary->tAnimationDataComponentManager; ptLibrary->_ptManagers[10] = &ptLibrary->tInverseKinematicsComponentManager; ptLibrary->_ptManagers[11] = &ptLibrary->tLightComponentManager; + ptLibrary->_ptManagers[12] = &ptLibrary->tScriptComponentManager; for(uint32_t i = 0; i < PL_COMPONENT_TYPE_COUNT; i++) ptLibrary->_ptManagers[i]->ptParentLibrary = ptLibrary; @@ -451,6 +406,13 @@ pl_ecs_remove_entity(plComponentLibrary* ptLibrary, plEntity tEntity) pl_sb_del_swap(sbComponents, uEntityValue); break; } + + case PL_COMPONENT_TYPE_SCRIPT: + { + plScriptComponent* sbComponents = ptLibrary->_ptManagers[i]->pComponents; + pl_sb_del_swap(sbComponents, uEntityValue); + break; + } } } } @@ -691,6 +653,19 @@ pl_ecs_add_component(plComponentLibrary* ptLibrary, plComponentType tType, plEnt return &sbComponents[uComponentIndex]; } + case PL_COMPONENT_TYPE_SCRIPT: + { + plScriptComponent* sbComponents = ptManager->pComponents; + if(bAddSlot) + pl_sb_add(sbComponents); + ptManager->pComponents = sbComponents; + sbComponents[uComponentIndex] = (plScriptComponent){ + .tFlags = PL_SCRIPT_FLAG_NONE, + .acFile = {0} + }; + return &sbComponents[uComponentIndex]; + } + } return NULL; @@ -757,6 +732,72 @@ pl_ecs_create_point_light(plComponentLibrary* ptLibrary, const char* pcName, plV return tNewEntity; } +static plEntity +pl_ecs_create_script(plComponentLibrary* ptLibrary, const char* pcFile, plScriptFlags tFlags, plScriptComponent** pptCompOut) +{ + pl_log_debug_to_f(uLogChannel, "created script: '%s'", pcFile); + plEntity tNewEntity = pl_ecs_create_tag(ptLibrary, pcFile); + plScriptComponent* ptScript = pl_ecs_add_component(ptLibrary, PL_COMPONENT_TYPE_SCRIPT, tNewEntity); + ptScript->tFlags = tFlags; + strncpy(ptScript->acFile, pcFile, PL_MAX_NAME_LENGTH); + + gptExtensionRegistry->load(pcFile, "pl_load_script", "pl_unload_script", tFlags & PL_SCRIPT_FLAG_RELOADABLE); + + const plScriptI* ptScriptApi = gptApiRegistry->first(PL_API_SCRIPT); + if(strncmp(pcFile, ptScriptApi->name(), PL_MAX_NAME_LENGTH) != 0) + { + while(ptScriptApi) + { + ptScriptApi = gptApiRegistry->next(ptScriptApi); + if(strncmp(pcFile, ptScriptApi->name(), PL_MAX_NAME_LENGTH) == 0) + { + break; + } + } + } + ptScript->_ptApi = ptScriptApi; + PL_ASSERT(ptScriptApi); + + if(ptScriptApi->setup) + ptScriptApi->setup(ptLibrary, tNewEntity); + + if(pptCompOut) + *pptCompOut = ptScript; + return tNewEntity; +} + +static void +pl_ecs_attach_script(plComponentLibrary* ptLibrary, const char* pcFile, plScriptFlags tFlags, plEntity tEntity, plScriptComponent** pptCompOut) +{ + pl_log_debug_to_f(uLogChannel, "attach script: '%s'", pcFile); + plScriptComponent* ptScript = pl_ecs_add_component(ptLibrary, PL_COMPONENT_TYPE_SCRIPT, tEntity); + ptScript->tFlags = tFlags; + strncpy(ptScript->acFile, pcFile, PL_MAX_NAME_LENGTH); + + gptExtensionRegistry->load(pcFile, "pl_load_script", "pl_unload_script", tFlags & PL_SCRIPT_FLAG_RELOADABLE); + + const plScriptI* ptScriptApi = gptApiRegistry->first(PL_API_SCRIPT); + if(strncmp(pcFile, ptScriptApi->name(), PL_MAX_NAME_LENGTH) != 0) + { + while(ptScriptApi) + { + ptScriptApi = gptApiRegistry->next(ptScriptApi); + if(strncmp(pcFile, ptScriptApi->name(), PL_MAX_NAME_LENGTH) == 0) + { + break; + } + } + } + ptScript->_ptApi = ptScriptApi; + PL_ASSERT(ptScriptApi); + + if(ptScriptApi->setup) + ptScriptApi->setup(ptLibrary, tEntity); + + if(pptCompOut) + *pptCompOut = ptScript; +} + static plEntity pl_ecs_create_object(plComponentLibrary* ptLibrary, const char* pcName, plObjectComponent** pptCompOut) { @@ -1072,6 +1113,28 @@ pl_run_hierarchy_update_system(plComponentLibrary* ptLibrary) pl_end_profile_sample(); } +static void +pl_run_script_update_system(plComponentLibrary* ptLibrary) +{ + pl_begin_profile_sample(__FUNCTION__); + + plScriptComponent* sbtComponents = ptLibrary->tScriptComponentManager.pComponents; + + const uint32_t uComponentCount = pl_sb_size(sbtComponents); + for(uint32_t i = 0; i < uComponentCount; i++) + { + const plEntity tEnitity = ptLibrary->tScriptComponentManager.sbtEntities[i]; + if(sbtComponents[i].tFlags) + continue; + + if(sbtComponents[i].tFlags & PL_SCRIPT_FLAG_PLAYING) + sbtComponents[i]._ptApi->run(ptLibrary, tEnitity); + if(sbtComponents[i].tFlags & PL_SCRIPT_FLAG_PLAY_ONCE) + sbtComponents[i].tFlags = PL_SCRIPT_FLAG_NONE; + } + pl_end_profile_sample(); +} + static void pl_run_animation_update_system(plComponentLibrary* ptLibrary, float fDeltaTime) { @@ -1640,9 +1703,69 @@ pl_calculate_tangents(plMeshComponent* atMeshes, uint32_t uComponentCount) // [SECTION] extension loading //----------------------------------------------------------------------------- +static const plEcsI* +pl_load_ecs_api(void) +{ + static const plEcsI tApi = { + .init_component_library = pl_ecs_init_component_library, + .cleanup_component_library = pl_ecs_cleanup_component_library, + .create_entity = pl_ecs_create_entity, + .remove_entity = pl_ecs_remove_entity, + .get_entity = pl_ecs_get_entity, + .is_entity_valid = pl_ecs_is_entity_valid, + .get_index = pl_ecs_get_index, + .get_component = pl_ecs_get_component, + .add_component = pl_ecs_add_component, + .create_tag = pl_ecs_create_tag, + .create_mesh = pl_ecs_create_mesh, + .create_perspective_camera = pl_ecs_create_perspective_camera, + .create_orthographic_camera = pl_ecs_create_orthographic_camera, + .create_object = pl_ecs_create_object, + .create_transform = pl_ecs_create_transform, + .create_material = pl_ecs_create_material, + .create_skin = pl_ecs_create_skin, + .create_animation = pl_ecs_create_animation, + .create_animation_data = pl_ecs_create_animation_data, + .create_directional_light = pl_ecs_create_directional_light, + .create_point_light = pl_ecs_create_point_light, + .create_script = pl_ecs_create_script, + .attach_script = pl_ecs_attach_script, + .attach_component = pl_ecs_attach_component, + .deattach_component = pl_ecs_deattach_component, + .calculate_normals = pl_calculate_normals, + .calculate_tangents = pl_calculate_tangents, + .run_object_update_system = pl_run_object_update_system, + .run_transform_update_system = pl_run_transform_update_system, + .run_hierarchy_update_system = pl_run_hierarchy_update_system, + .run_skin_update_system = pl_run_skin_update_system, + .run_animation_update_system = pl_run_animation_update_system, + .run_inverse_kinematics_update_system = pl_run_inverse_kinematics_update_system, + .run_script_update_system = pl_run_script_update_system + }; + return &tApi; +} + +static const plCameraI* +pl_load_camera_api(void) +{ + static const plCameraI tApi = { + .set_fov = pl_camera_set_fov, + .set_clip_planes = pl_camera_set_clip_planes, + .set_aspect = pl_camera_set_aspect, + .set_pos = pl_camera_set_pos, + .set_pitch_yaw = pl_camera_set_pitch_yaw, + .translate = pl_camera_translate, + .rotate = pl_camera_rotate, + .update = pl_camera_update, + .look_at = pl_camera_look_at, + }; + return &tApi; +} + PL_EXPORT void pl_load_ext(plApiRegistryI* ptApiRegistry, bool bReload) { + gptApiRegistry = ptApiRegistry; const plDataRegistryI* ptDataRegistry = ptApiRegistry->first(PL_API_DATA_REGISTRY); pl_set_memory_context(ptDataRegistry->get_data(PL_CONTEXT_MEMORY)); pl_set_profile_context(ptDataRegistry->get_data("profile")); @@ -1653,6 +1776,7 @@ pl_load_ext(plApiRegistryI* ptApiRegistry, bool bReload) ptExtensionRegistry->load("pl_job_ext", NULL, NULL, false); // load required contexts + gptExtensionRegistry = ptApiRegistry->first(PL_API_EXTENSION_REGISTRY); gptJob = ptApiRegistry->first(PL_API_JOB); if(bReload) diff --git a/extensions/pl_ecs_ext.h b/extensions/pl_ecs_ext.h index 5613cba0..d3b954ec 100644 --- a/extensions/pl_ecs_ext.h +++ b/extensions/pl_ecs_ext.h @@ -77,12 +77,14 @@ typedef struct _plAnimationComponent plAnimationComponent; typedef struct _plAnimationDataComponent plAnimationDataComponent; typedef struct _plInverseKinematicsComponent plInverseKinematicsComponent; typedef struct _plLightComponent plLightComponent; +typedef struct _plScriptComponent plScriptComponent; // enums typedef int plShaderType; typedef int plComponentType; typedef int plTextureSlot; typedef int plMaterialFlags; +typedef int plScriptFlags; typedef int plBlendMode; typedef int plCameraType; typedef int plAnimationMode; @@ -136,6 +138,10 @@ typedef struct _plEcsI plEntity (*create_directional_light) (plComponentLibrary*, const char* pcName, plVec3 tDirection, plLightComponent**); plEntity (*create_point_light) (plComponentLibrary*, const char* pcName, plVec3 tPosition, plLightComponent**); + // scripts + plEntity (*create_script)(plComponentLibrary*, const char* pcFile, plScriptFlags, plScriptComponent**); + void (*attach_script)(plComponentLibrary*, const char* pcFile, plScriptFlags, plEntity tEntity, plScriptComponent**); + // hierarchy void (*attach_component) (plComponentLibrary*, plEntity tEntity, plEntity tParent); void (*deattach_component) (plComponentLibrary*, plEntity); @@ -151,6 +157,7 @@ typedef struct _plEcsI void (*run_hierarchy_update_system) (plComponentLibrary*); void (*run_animation_update_system) (plComponentLibrary*, float fDeltaTime); void (*run_inverse_kinematics_update_system)(plComponentLibrary*); + void (*run_script_update_system) (plComponentLibrary*); } plEcsI; typedef struct _plCameraI @@ -184,6 +191,7 @@ enum _plComponentType PL_COMPONENT_TYPE_ANIMATION_DATA, PL_COMPONENT_TYPE_INVERSE_KINEMATICS, PL_COMPONENT_TYPE_LIGHT, + PL_COMPONENT_TYPE_SCRIPT, PL_COMPONENT_TYPE_COUNT }; @@ -263,6 +271,14 @@ enum _plAnimationFlags PL_ANIMATION_FLAG_LOOPED = 1 << 1 }; +enum _plScriptFlags +{ + PL_SCRIPT_FLAG_NONE = 0, + PL_SCRIPT_FLAG_PLAYING = 1 << 0, + PL_SCRIPT_FLAG_PLAY_ONCE = 1 << 1, + PL_SCRIPT_FLAG_RELOADABLE = 1 << 2 +}; + enum _plMeshFormatFlags { PL_MESH_FORMAT_FLAG_NONE = 0, @@ -361,6 +377,7 @@ typedef struct _plComponentLibrary plComponentManager tAnimationDataComponentManager; plComponentManager tInverseKinematicsComponentManager; plComponentManager tLightComponentManager; + plComponentManager tScriptComponentManager; plComponentManager* _ptManagers[PL_COMPONENT_TYPE_COUNT]; // just for internal convenience void* pInternal; @@ -514,4 +531,11 @@ typedef struct _plInverseKinematicsComponent uint32_t uIterationCount; } plInverseKinematicsComponent; +typedef struct _plScriptComponent +{ + plScriptFlags tFlags; + char acFile[PL_MAX_NAME_LENGTH]; + const struct _plScriptI* _ptApi; +} plScriptComponent; + #endif // PL_ECS_EXT_H \ No newline at end of file diff --git a/extensions/pl_ref_renderer_ext.c b/extensions/pl_ref_renderer_ext.c index 2fded182..c9ad4b10 100644 --- a/extensions/pl_ref_renderer_ext.c +++ b/extensions/pl_ref_renderer_ext.c @@ -2757,6 +2757,7 @@ pl_refr_run_ecs(uint32_t uSceneHandle) { pl_begin_profile_sample(__FUNCTION__); plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + gptECS->run_script_update_system(&ptScene->tComponentLibrary); gptECS->run_animation_update_system(&ptScene->tComponentLibrary, gptIO->get_io()->fDeltaTime); gptECS->run_transform_update_system(&ptScene->tComponentLibrary); gptECS->run_hierarchy_update_system(&ptScene->tComponentLibrary); diff --git a/extensions/pl_script_ext.h b/extensions/pl_script_ext.h new file mode 100644 index 00000000..a7799753 --- /dev/null +++ b/extensions/pl_script_ext.h @@ -0,0 +1,56 @@ +/* + pl_script_ext.h + - this is the interface script components must implement +*/ + +/* +Index of this file: +// [SECTION] header mess +// [SECTION] apis +// [SECTION] forward declarations +// [SECTION] public api structs +*/ + +//----------------------------------------------------------------------------- +// [SECTION] header mess +//----------------------------------------------------------------------------- + +#ifndef PL_SCRIPT_EXT_H +#define PL_SCRIPT_EXT_H + +#define PL_SCRIPT_EXT_VERSION "1.0.0" +#define PL_SCRIPT_EXT_VERSION_NUM 100000 + +//----------------------------------------------------------------------------- +// [SECTION] apis +//----------------------------------------------------------------------------- + +#define PL_API_SCRIPT "PL_API_SCRIPT" +typedef struct _plScriptI plScriptI; + +//----------------------------------------------------------------------------- +// [SECTION] forward declarations +//----------------------------------------------------------------------------- + +// external +typedef struct _plComponentLibrary plComponentLibrary; // pl_ecs_ext.h +typedef union _plEntity plEntity; // pl_ecs_ext.h + +//----------------------------------------------------------------------------- +// [SECTION] public api structs +//----------------------------------------------------------------------------- + +typedef struct _plScriptI +{ + // ran when creating a new script component (optional) + void (*setup)(plComponentLibrary*, plEntity); + + // ran every frame + void (*run)(plComponentLibrary*, plEntity); + + // used by entity component system to differentiate between implmentations + // of this interface and must be the dll/so name without an extension + const char* (*name)(void); +} plScriptI; + +#endif // PL_SCRIPT_EXT_H \ No newline at end of file diff --git a/scripts/pl_camera_script.c b/scripts/pl_camera_script.c new file mode 100644 index 00000000..422b9c4c --- /dev/null +++ b/scripts/pl_camera_script.c @@ -0,0 +1,119 @@ +/* + pl_camera_script.c +*/ + +/* +Index of this file: +// [SECTION] includes +// [SECTION] global data & APIs +// [SECTION] implementation +// [SECTION] script loading +*/ + +//----------------------------------------------------------------------------- +// [SECTION] includes +//----------------------------------------------------------------------------- + +#include "pilotlight.h" +#include "pl_script_ext.h" + +// extensions +#include "pl_ecs_ext.h" + +//----------------------------------------------------------------------------- +// [SECTION] global data & APIs +//----------------------------------------------------------------------------- + +// required APIs +const plIOI* gptIO = NULL; +const plCameraI* gptCamera = NULL; +const plEcsI* gptEcs = NULL; + +//----------------------------------------------------------------------------- +// [SECTION] implementation +//----------------------------------------------------------------------------- + +// static void +// pl_script_run(plComponentLibrary* ptLibrary, plEntity tEntity) +// { + +// } + +static void +pl_script_run(plComponentLibrary* ptLibrary, plEntity tEntity) +{ + plCameraComponent* ptCamera = gptEcs->get_component(ptLibrary, PL_COMPONENT_TYPE_CAMERA, tEntity); + + plIO* ptIO = gptIO->get_io(); + + static const float fCameraTravelSpeed = 4.0f; + static const float fCameraRotationSpeed = 0.005f; + + // camera space + bool bOwnKeyboard = ptIO->bWantCaptureKeyboard; + if(!bOwnKeyboard) + { + if(gptIO->is_key_down(PL_KEY_W)) gptCamera->translate(ptCamera, 0.0f, 0.0f, fCameraTravelSpeed * ptIO->fDeltaTime); + if(gptIO->is_key_down(PL_KEY_S)) gptCamera->translate(ptCamera, 0.0f, 0.0f, -fCameraTravelSpeed* ptIO->fDeltaTime); + if(gptIO->is_key_down(PL_KEY_A)) gptCamera->translate(ptCamera, -fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f, 0.0f); + if(gptIO->is_key_down(PL_KEY_D)) gptCamera->translate(ptCamera, fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f, 0.0f); + + // world space + if(gptIO->is_key_down(PL_KEY_F)) { gptCamera->translate(ptCamera, 0.0f, -fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f); } + if(gptIO->is_key_down(PL_KEY_R)) { gptCamera->translate(ptCamera, 0.0f, fCameraTravelSpeed * ptIO->fDeltaTime, 0.0f); } + } + + bool bOwnMouse = ptIO->bWantCaptureMouse; + if(!bOwnMouse && gptIO->is_mouse_dragging(PL_MOUSE_BUTTON_LEFT, 1.0f)) + { + const plVec2 tMouseDelta = gptIO->get_mouse_drag_delta(PL_MOUSE_BUTTON_LEFT, 1.0f); + gptCamera->rotate(ptCamera, -tMouseDelta.y * fCameraRotationSpeed, -tMouseDelta.x * fCameraRotationSpeed); + gptIO->reset_mouse_drag_delta(PL_MOUSE_BUTTON_LEFT); + } + + gptCamera->update(ptCamera); +} + +static const char* +pl_script_name(void) +{ + return "pl_camera_script"; +} + +//----------------------------------------------------------------------------- +// [SECTION] script loading +//----------------------------------------------------------------------------- + +static const plScriptI* +pl_load_script_api(void) +{ + static const plScriptI tApi = { + .setup = NULL, + .run = pl_script_run, + .name = pl_script_name + }; + return &tApi; +} + +PL_EXPORT void +pl_load_script(plApiRegistryI* ptApiRegistry, bool bReload) +{ + const plDataRegistryI* ptDataRegistry = ptApiRegistry->first(PL_API_DATA_REGISTRY); + pl_set_memory_context(ptDataRegistry->get_data(PL_CONTEXT_MEMORY)); + + // load apis + gptEcs = ptApiRegistry->first(PL_API_ECS); + gptCamera = ptApiRegistry->first(PL_API_CAMERA); + gptIO = ptApiRegistry->first(PL_API_IO); + + if(bReload) + ptApiRegistry->replace(ptApiRegistry->first(PL_API_SCRIPT), pl_load_script_api()); + else + ptApiRegistry->add(PL_API_SCRIPT, pl_load_script_api()); +} + +PL_EXPORT void +pl_unload_script(plApiRegistryI* ptApiRegistry) +{ + +} diff --git a/scripts/download_assets.py b/tools/download_assets.py similarity index 100% rename from scripts/download_assets.py rename to tools/download_assets.py diff --git a/scripts/gen_build.py b/tools/gen_build.py similarity index 98% rename from scripts/gen_build.py rename to tools/gen_build.py index 63dba4e3..48fba915 100644 --- a/scripts/gen_build.py +++ b/tools/gen_build.py @@ -141,6 +141,10 @@ def add_plugin_to_metal_app(name, reloadable, objc = False, binary_name = None, add_plugin_to_metal_app("pl_ref_renderer_ext", True) add_plugin_to_metal_app("pl_ui_ext", True, False, None, "../ui/") + # scripts + add_plugin_to_vulkan_app("pl_camera_script", False, None, "../scripts/") + add_plugin_to_metal_app("pl_camera_script", False, False, None, "../scripts/") + pl.pop_target_links() ############################################################################### diff --git a/scripts/gen_examples.py b/tools/gen_examples.py similarity index 100% rename from scripts/gen_examples.py rename to tools/gen_examples.py diff --git a/scripts/gen_tests.py b/tools/gen_tests.py similarity index 100% rename from scripts/gen_tests.py rename to tools/gen_tests.py diff --git a/scripts/package.py b/tools/package.py similarity index 98% rename from scripts/package.py rename to tools/package.py index 5107d90c..81748c6d 100644 --- a/scripts/package.py +++ b/tools/package.py @@ -56,6 +56,7 @@ # copy extension headers for extension in extensions: shutil.copy("../extensions/" + extension + ".h", target_directory + "/include/" + extension + ".h") +shutil.copy("../extensions/pl_script_ext.h", target_directory + "/include/pl_script_ext.h") shutil.copy("../ui/pl_ui_ext.h", target_directory + "/include/pl_ui_ext.h") # copy pilotlight-lib headers