├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ ├── doc.yml │ ├── feature_request.yml │ └── maintenance.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── scripts │ └── get_latest_changelog.py └── workflows │ ├── auto_approve.yml │ ├── code_quality.yml │ ├── codeql.yml │ ├── release_bump.yml │ └── release_publish.yml ├── .gitignore ├── .semantic_release └── CHANGELOG.md.j2 ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOPMENT.md ├── LICENSE ├── NOTICE ├── README.md ├── SETUP_SUBMITTER_CMF.md ├── auto-update-plugin.bat ├── depsBundle.py ├── depsBundle.sh ├── docs ├── Makefile ├── make.bat └── source │ ├── _templates │ ├── module.rst_t │ ├── package.rst_t │ └── toc.rst_t │ ├── conf.py │ ├── docs_api │ ├── api.rst │ ├── unreal_adaptor.UnrealAdaptor.rst │ ├── unreal_adaptor.UnrealClient.rst │ ├── unreal_adaptor.UnrealClient.step_handlers.rst │ ├── unreal_adaptor.rst │ ├── unreal_logger.rst │ ├── unreal_perforce_utils.rst │ ├── unreal_submitter.rst │ └── unreal_submitter.unreal_open_job.rst │ ├── docs_usage │ ├── configure.rst │ ├── data_assets.rst │ ├── p4_credentials_management.rst │ ├── py_use_cases │ │ ├── py_submission_general.rst │ │ ├── py_submit_custom_job.rst │ │ ├── py_submit_p4_render_job.rst │ │ ├── py_submit_render_job.rst │ │ ├── py_submit_ugs_render_job.rst │ │ └── py_use_cases.rst │ ├── usage.rst │ └── use_cases │ │ ├── check_parameters_consistency.rst │ │ ├── create_p4_render_job.rst │ │ ├── create_render_job.rst │ │ ├── create_ugs_render_job.rst │ │ ├── hide_parameters.rst │ │ ├── submit_custom_job_from_bp.rst │ │ ├── submit_job.rst │ │ ├── submit_predefined_render_job.rst │ │ ├── submit_render_job_from_bp.rst │ │ └── use_cases.rst │ ├── images │ ├── consistency_check_0.png │ ├── consistency_check_1.png │ ├── consistency_check_2.png │ ├── consistency_check_3.png │ ├── consistency_check_4.png │ ├── create_data_asset_0.png │ ├── create_data_asset_1.png │ ├── create_data_asset_2.png │ ├── create_p4_render_job_0.png │ ├── create_p4_render_job_1.png │ ├── create_p4_render_job_2.png │ ├── create_p4_render_job_3.png │ ├── create_render_job_0.png │ ├── create_render_job_1.png │ ├── create_render_job_10.png │ ├── create_render_job_2.png │ ├── create_render_job_3.png │ ├── create_render_job_4.png │ ├── create_render_job_5.png │ ├── create_render_job_6.png │ ├── create_render_job_7.png │ ├── create_render_job_8.png │ ├── create_render_job_9.png │ ├── create_ugs_render_job_0.png │ ├── create_ugs_render_job_1.png │ ├── create_ugs_render_job_2.png │ ├── create_ugs_render_job_3.png │ ├── create_ugs_render_job_4.png │ ├── deadline_cloud_settings.png │ ├── hide_params_0.png │ ├── hide_params_1.png │ ├── hide_params_2.png │ ├── hide_params_3.png │ ├── hide_params_4.png │ ├── mrq_plugin_settings_0.png │ ├── mrq_plugin_settings_1.png │ ├── submit_custom_bp_0.png │ ├── submit_custom_bp_1.png │ ├── submit_custom_bp_2.png │ ├── submit_job_0.png │ ├── submit_job_1.png │ ├── submit_job_2.png │ ├── submit_job_3.png │ ├── submit_job_4.png │ ├── submit_job_5.png │ ├── submit_predefined_job_0.png │ ├── submit_predefined_job_1.png │ ├── submit_render_bp_0.png │ ├── submit_render_bp_1.png │ ├── submit_render_bp_2.png │ └── submit_render_bp_3.png │ ├── index.rst │ └── resources │ └── logs_policy_example.sh ├── hatch.toml ├── hatch_custom_hook.py ├── install_builder └── deadline-cloud-for-unreal-engine.xml ├── pipeline ├── CODEOWNERS ├── build.sh ├── integ.sh └── publish.sh ├── pyproject.toml ├── requirements-docs.txt ├── requirements-release.txt ├── requirements-testing.txt ├── scripts ├── __init__.py ├── add_copyright_headers.sh ├── build_plugin.py └── clean_test_resources.py ├── src ├── deadline │ ├── unreal_adaptor │ │ ├── UnrealAdaptor │ │ │ ├── __init__.py │ │ │ ├── __main__.py │ │ │ ├── adaptor.py │ │ │ ├── common.py │ │ │ ├── py.typed │ │ │ └── schemas │ │ │ │ ├── init_data.schema.json │ │ │ │ └── run_data.schema.json │ │ ├── UnrealClient │ │ │ ├── __init__.py │ │ │ ├── py.typed │ │ │ ├── step_handlers │ │ │ │ ├── __init__.py │ │ │ │ ├── base_step_handler.py │ │ │ │ ├── unreal_custom_step_handler.py │ │ │ │ └── unreal_render_step_handler.py │ │ │ └── unreal_client.py │ │ └── __init__.py │ ├── unreal_logger │ │ ├── __init__.py │ │ ├── handlers.py │ │ └── logger.py │ ├── unreal_perforce_utils │ │ ├── __init__.py │ │ ├── app.py │ │ ├── cli.py │ │ ├── exceptions.py │ │ ├── perforce.py │ │ ├── secret_manager.py │ │ └── unreal_source_control.py │ └── unreal_submitter │ │ ├── __init__.py │ │ ├── common.py │ │ ├── exceptions.py │ │ ├── settings.py │ │ ├── submitter.py │ │ ├── unreal_dependency_collector.py │ │ └── unreal_open_job │ │ ├── __init__.py │ │ ├── unreal_open_job.py │ │ ├── unreal_open_job_entity.py │ │ ├── unreal_open_job_environment.py │ │ ├── unreal_open_job_parameters_consistency.py │ │ ├── unreal_open_job_shared_settings.py │ │ ├── unreal_open_job_step.py │ │ └── unreal_open_job_step_host_requirements.py └── unreal_plugin │ ├── Config │ └── DefaultUnrealDeadlineCloudService.ini │ ├── Content │ ├── OpenJD_DataAssets │ │ ├── Perforce │ │ │ ├── OpenJD_P4_Environment_LaunchEditor.uasset │ │ │ ├── OpenJD_P4_Environment_SyncCmf.uasset │ │ │ ├── OpenJD_P4_Job_Render.uasset │ │ │ └── OpenJD_P4_Step_Render.uasset │ │ ├── Render │ │ │ ├── OpenJD_Environment_ApplyP4Secrets.uasset │ │ │ ├── OpenJD_Environment_LaunchEditor.uasset │ │ │ ├── OpenJD_Job_Render.uasset │ │ │ └── OpenJD_Step_Render.uasset │ │ └── UGS │ │ │ ├── OpenJD_UGS_Environment_LaunchEditor.uasset │ │ │ ├── OpenJD_UGS_Environment_SyncCmf.uasset │ │ │ ├── OpenJD_UGS_Job_Render.uasset │ │ │ ├── OpenJD_UGS_Job_Render_P4Secrets.uasset │ │ │ └── OpenJD_UGS_Step_Render.uasset │ ├── Python │ │ ├── init_unreal.py │ │ ├── job_library.py │ │ ├── open_job_template_api.py │ │ ├── openjd_templates │ │ │ ├── custom │ │ │ │ ├── custom_job.yml │ │ │ │ └── custom_step.yml │ │ │ ├── launch_ue_environment.yml │ │ │ ├── p4 │ │ │ │ ├── p4_apply_secrets_environment.yml │ │ │ │ ├── p4_launch_ue_environment.yml │ │ │ │ ├── p4_render_job.yml │ │ │ │ ├── p4_render_step.yml │ │ │ │ ├── p4_sync_cmf_environment.yml │ │ │ │ └── p4_sync_smf_environment.yml │ │ │ ├── render_job.yml │ │ │ ├── render_step.yml │ │ │ ├── render_step_mpq.yml │ │ │ └── ugs │ │ │ │ ├── ugs_launch_ue_environment.yml │ │ │ │ ├── ugs_render_job.yml │ │ │ │ ├── ugs_render_step.yml │ │ │ │ ├── ugs_sync_cmf_environment.yml │ │ │ │ └── ugs_sync_smf_environment.yml │ │ ├── remote_executor.py │ │ ├── settings.py │ │ └── submit_actions │ │ │ ├── custom_job_submission.py │ │ │ ├── custom_script.py │ │ │ ├── p4_render_job_submission.py │ │ │ ├── render_job_submission.py │ │ │ └── ugs_render_job_submission.py │ └── Widgets │ │ ├── DeadlineJobSubmitter.uasset │ │ └── DeadlinePathSelector.uasset │ ├── DEVELOPMENT.md │ ├── Documentation │ ├── Doxyfile │ ├── doxygen-awesome-sidebar-only.css │ ├── doxygen-awesome.LICENSE │ └── doxygen-awesome.css │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── Resources │ └── Icon128.png │ ├── Source │ └── UnrealDeadlineCloudService │ │ ├── Private │ │ ├── DeadlineCloudJobSettings │ │ │ ├── DeadlineCloudDetailsWidgetsHelper.cpp │ │ │ ├── DeadlineCloudDeveloperSettings.cpp │ │ │ ├── DeadlineCloudEnvironment.cpp │ │ │ ├── DeadlineCloudEnvironmentDetails.cpp │ │ │ ├── DeadlineCloudInputValidationHelper.cpp │ │ │ ├── DeadlineCloudJob.cpp │ │ │ ├── DeadlineCloudJobDetails.cpp │ │ │ ├── DeadlineCloudJobPresetDetailsCustomization.cpp │ │ │ ├── DeadlineCloudRenderStep.cpp │ │ │ ├── DeadlineCloudSettingsDetails.cpp │ │ │ ├── DeadlineCloudStatusHandler.cpp │ │ │ ├── DeadlineCloudStep.cpp │ │ │ └── DeadlineCloudStepDetails.cpp │ │ ├── MovieRenderPipeline │ │ │ ├── DeadlineCloudRenderStepSetting.cpp │ │ │ ├── DeadlineCloudStepBaseSetting.cpp │ │ │ ├── DeadlineExecutorImplementationLibrary.cpp │ │ │ └── MoviePipelineDeadlineCloudExecutorJob.cpp │ │ ├── PythonAPILibraries │ │ │ ├── DeadlineCloudJobBundleLibrary.cpp │ │ │ ├── DeadlineCloudSettingsLibrary.cpp │ │ │ ├── PythonAPILibrary.cpp │ │ │ └── PythonGameThreadExecutor.cpp │ │ ├── Tests │ │ │ ├── DeadlinePluginTest_Environment.spec.cpp │ │ │ ├── DeadlinePluginTest_Job.spec.cpp │ │ │ ├── DeadlinePluginTest_Step.spec.cpp │ │ │ ├── DeadlinePluginTest_UI.spec.cpp │ │ │ ├── Integration │ │ │ │ └── DeadlinePluginTest_CreateJobTest.cpp │ │ │ └── openjd_templates │ │ │ │ ├── launch_ue_environment.yml │ │ │ │ ├── launch_ue_environment_UI.yml │ │ │ │ ├── render_job.yml │ │ │ │ ├── render_job_UI.yml │ │ │ │ ├── render_step.yml │ │ │ │ └── render_step_UI.yml │ │ └── UnrealDeadlineCloudServiceModule.cpp │ │ ├── Public │ │ ├── DeadlineCloudJobSettings │ │ │ ├── DeadlineCloudDetailsWidgetsHelper.h │ │ │ ├── DeadlineCloudDeveloperSettings.h │ │ │ ├── DeadlineCloudEnvironment.h │ │ │ ├── DeadlineCloudEnvironmentDetails.h │ │ │ ├── DeadlineCloudInputValidationHelper.h │ │ │ ├── DeadlineCloudJob.h │ │ │ ├── DeadlineCloudJobDetails.h │ │ │ ├── DeadlineCloudJobPresetDetailsCustomization.h │ │ │ ├── DeadlineCloudJobPythonLibrary.h │ │ │ ├── DeadlineCloudPerforceEnvironment.h │ │ │ ├── DeadlineCloudRenderJob.h │ │ │ ├── DeadlineCloudRenderStep.h │ │ │ ├── DeadlineCloudSettingsDetails.h │ │ │ ├── DeadlineCloudStatusHandler.h │ │ │ ├── DeadlineCloudStep.h │ │ │ ├── DeadlineCloudStepDetails.h │ │ │ └── DeadlineCloudUgsEnvironment.h │ │ ├── MovieRenderPipeline │ │ │ ├── DeadlineCloudCustomScriptStepSetting.h │ │ │ ├── DeadlineCloudRenderStepSetting.h │ │ │ ├── DeadlineCloudStepBaseSetting.h │ │ │ ├── DeadlineExecutorImplementationLibrary.h │ │ │ └── MoviePipelineDeadlineCloudExecutorJob.h │ │ ├── PythonAPILibraries │ │ │ ├── DeadlineCloudJobBundleLibrary.h │ │ │ ├── DeadlineCloudSettingsLibrary.h │ │ │ ├── PythonAPILibrary.h │ │ │ ├── PythonGameThreadExecutor.h │ │ │ ├── PythonParametersConsistencyChecker.h │ │ │ └── PythonYamlLibrary.h │ │ └── UnrealDeadlineCloudServiceModule.h │ │ └── UnrealDeadlineCloudService.Build.cs │ └── UnrealDeadlineCloudService.uplugin └── test ├── __init__.py ├── deadline_adaptor_for_unreal ├── __init__.py └── unit │ ├── UnrealAdaptor │ ├── __init__.py │ └── test_adaptor.py │ ├── UnrealClient │ ├── __init__.py │ ├── step_handlers │ │ ├── __init__.py │ │ ├── custom_scripts │ │ │ ├── existed_not_valid_script.py │ │ │ └── valid_script.py │ │ ├── test_custom_step_handler.py │ │ └── test_render_step_handler.py │ └── test_client.py │ └── __init__.py ├── deadline_logger_for_unreal ├── __init__.py └── test_logger.py ├── deadline_perforce_utils_for_unreal ├── __init__.py ├── test_app.py ├── test_perforce.py ├── test_secret_manager.py └── test_unreal_source_control.py ├── deadline_submitter_for_unreal ├── __init__.py ├── fixtures.py └── unit │ ├── __init__.py │ ├── test_common.py │ ├── test_submitter.py │ └── test_unreal_open_job │ ├── __init__.py │ ├── test_parameters_consistency.py │ ├── test_unreal_open_job.py │ ├── test_unreal_open_job_entity.py │ ├── test_unreal_open_job_environment.py │ ├── test_unreal_open_job_shared_settings.py │ └── test_unreal_open_job_step.py ├── end_to_end ├── conftest.py ├── test_create_job.py └── test_worker_agent.py └── test_copyright_headers.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.uasset filter=lfs diff=lfs merge=lfs -text 2 | *.umap filter=lfs diff=lfs merge=lfs -text 3 | *.dll filter=lfs diff=lfs merge=lfs -text 4 | *.dylib filter=lfs diff=lfs merge=lfs -text 5 | *.so filter=lfs diff=lfs merge=lfs -text 6 | *.pdb filter=lfs diff=lfs merge=lfs -text 7 | *.png filter=lfs diff=lfs merge=lfs -text 8 | *.lib filter=lfs diff=lfs merge=lfs -text 9 | *.zip filter=lfs diff=lfs merge=lfs -text 10 | *.mp4 filter=lfs diff=lfs merge=lfs -text 11 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @aws-deadline/unreal-engine-developers -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F41B Bug Report" 2 | description: Report a bug 3 | title: "Bug: (short bug description)" 4 | labels: ["bug", "needs triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for taking the time to fill out this bug report! 10 | 11 | ⚠️ If the bug that you are reporting is a security-related issue or security vulnerability, 12 | then please do not create a report via this template. Instead please 13 | notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) 14 | or directly via email to [AWS Security](aws-security@amazon.com). 15 | 16 | - type: textarea 17 | id: description 18 | attributes: 19 | label: Describe the bug 20 | description: What is the problem? A clear and concise description of the bug. 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | id: expected_behaviour 26 | attributes: 27 | label: Expected Behaviour 28 | description: What did you expect to happen? 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | id: current_behaviour 34 | attributes: 35 | label: Current Behaviour 36 | description: What actually happened? Please include as much detail as you can. 37 | validations: 38 | required: true 39 | 40 | - type: textarea 41 | id: reproduction_steps 42 | attributes: 43 | label: Reproduction Steps 44 | description: | 45 | Please provide as much detail as you can to help us understand how we can reproduce the bug. 46 | Step by step instructions and self-contained code snippets are ideal. 47 | validations: 48 | required: true 49 | 50 | - type: textarea 51 | id: environment 52 | attributes: 53 | label: Environment 54 | description: Please provide information on the environment and software versions that you are using to reproduce the bug. 55 | value: | 56 | At minimum: 57 | 1. Operating system (e.g. Windows Server 2022; Amazon Linux 2023; etc.) 58 | 2. Version of Unreal Engine 59 | 3. Version of this package 60 | 4. If this is from a version installed by the Deadline Cloud Submitter installer, then what version of the submitter installer? 61 | 62 | Please share other details about your environment that you think might be relevant to reproducing the bug. 63 | validations: 64 | required: true 65 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/doc.yml: -------------------------------------------------------------------------------- 1 | name: "📕 Documentation Issue" 2 | description: Issue in the documentation 3 | title: "Docs: (short description of the issue)" 4 | labels: ["documentation", "needs triage"] 5 | body: 6 | - type: textarea 7 | id: documentation_issue 8 | attributes: 9 | label: Documentation Issue 10 | description: Describe the issue 11 | validations: 12 | required: true 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "\U0001F680 Feature Request" 2 | description: Request a new feature 3 | title: "Feature request: (short description of the feature)" 4 | labels: ["enhancement", "needs triage"] 5 | body: 6 | - type: textarea 7 | id: problem 8 | attributes: 9 | label: Describe the problem 10 | description: | 11 | Help us understand the problem that you are trying to solve, and why it is important to you. 12 | Provide as much detail as you are able. 13 | validations: 14 | required: true 15 | 16 | - type: textarea 17 | id: proposed_solution 18 | attributes: 19 | label: Proposed Solution 20 | description: | 21 | Describe your proposed feature that you see solving this problem for you. If you have a 22 | full or partial prototype implementation then please open a draft pull request and link to 23 | it here as well. 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | id: use_case 29 | attributes: 30 | label: Example Use Cases 31 | description: | 32 | Provide some sample code snippets or shell scripts that show how **you** would use this feature as 33 | you have proposed it. 34 | validations: 35 | required: true 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/maintenance.yml: -------------------------------------------------------------------------------- 1 | name: "🛠️ Maintenance" 2 | description: Some type of improvement 3 | title: "Maintenance: (short description of the issue)" 4 | labels: ["maintenance", "needs triage"] 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Description 10 | description: Describe the improvement and why it is important to do. 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: solution 15 | attributes: 16 | label: Solution 17 | description: Provide any ideas you have for how the suggestion can be implemented. 18 | validations: 19 | required: true 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *delete text starting here* 2 | Please ensure that you have read through the [contributing guidelines](https://github.com/aws-deadline/deadline-cloud-for-unreal-engine/blob/mainline/CONTRIBUTING.md#contributing-via-pull-requests) before continuing. 3 | *delete text ending here* 4 | 5 | Fixes: ** 6 | 7 | ### What was the problem/requirement? (What/Why) 8 | 9 | ### What was the solution? (How) 10 | 11 | ### What is the impact of this change? 12 | 13 | ### How was this change tested? 14 | 15 | *delete text starting here* 16 | See [DEVELOPMENT.md](https://github.com/aws-deadline/deadline-cloud-for-unreal-engine/blob/mainline/DEVELOPMENT.md) for information on running tests. 17 | 18 | - Have you run the unit tests? 19 | *delete text ending here* 20 | 21 | ### Have you run a render job successfully with these changes? 22 | 23 | *delete text starting here* 24 | See the "Submit a Test Render" section of [this guide](https://github.com/aws-deadline/deadline-cloud-for-unreal-engine/blob/mainline/SETUP_SUBMITTER_CMF.md#submit-a-test-render-optional) 25 | *delete text ending here* 26 | 27 | ### Was this change documented? 28 | 29 | *delete text starting here* 30 | - Did you update all relevant docstrings for Python functions that you modified? 31 | - Should the README.md, DEVELOPMENT.md, or other documents in the repository's docs/ directory be updated along with your change? 32 | - Should the schema files for the adaptor's init-data or run-data be updated? 33 | *delete text ending here* 34 | 35 | ### Is this a breaking change? 36 | 37 | *delete text starting here* 38 | A breaking change is one that modifies a public contract in some way or otherwise changes functionality of this application in a way 39 | that is not backwards compatible. Examples of changes that are breaking include: 40 | 41 | 1. Adding a new required value to the init-data or run-data of the adaptor; 42 | 2. Deleting or renaming a value in the init-data or run-data of the adaptor; and 43 | 3. Otherwise modifying the interface of the adaptor such that a job submitted with an older version of the Unreal submitter plug-in 44 | will not work with a version of the adaptor that includes your modification. 45 | 46 | If so, then please describe the changes that users of this package must make to update their scripts, or Python applications. Also, 47 | please ensure that the title of your commit follows our conventional commit guidelines in 48 | [CONTRIBUTING.md](https://github.com/aws-deadline/deadline-cloud-for-unreal-engine/blob/mainline/CONTRIBUTING.md#conventional-commits) for breaking changes. 49 | *delete text ending here* 50 | 51 | ---- 52 | 53 | *By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.* -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | commit-message: 13 | prefix: "chore(deps):" 14 | - package-ecosystem: "github-actions" 15 | directory: "/" # Location of package manifests 16 | schedule: 17 | interval: "daily" -------------------------------------------------------------------------------- /.github/scripts/get_latest_changelog.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | """ 3 | This script gets the changelog notes for the latest version of this package. It makes the following assumptions 4 | 1. A file called CHANGELOG.md is in the current directory that has the changelog 5 | 2. The changelog file is formatted in a way such that level 2 headers are: 6 | a. The only indication of the beginning of a version's changelog notes. 7 | b. Always begin with `## ` 8 | 3. The changelog file contains the newest version's changelog notes at the top of the file. 9 | 10 | Example CHANGELOG.md: 11 | ``` 12 | ## 1.0.0 (2024-02-06) 13 | 14 | ### BREAKING CHANGES 15 | * **api**: rename all APIs 16 | 17 | ## 0.1.0 (2024-02-06) 18 | 19 | ### Features 20 | * **api**: add new api 21 | ``` 22 | 23 | Running this script on the above CHANGELOG.md should return the following contents: 24 | ``` 25 | ## 1.0.0 (2024-02-06) 26 | 27 | ### BREAKING CHANGES 28 | * **api**: rename all APIs 29 | 30 | ``` 31 | """ 32 | import re 33 | 34 | h2 = r"^##\s.*$" 35 | with open("CHANGELOG.md") as f: 36 | contents = f.read() 37 | matches = re.findall(h2, contents, re.MULTILINE) 38 | changelog = contents[: contents.find(matches[1]) - 1] if len(matches) > 1 else contents 39 | print(changelog) 40 | -------------------------------------------------------------------------------- /.github/workflows/auto_approve.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-approve 2 | on: pull_request 3 | 4 | permissions: 5 | pull-requests: write 6 | 7 | jobs: 8 | dependabot: 9 | runs-on: ubuntu-latest 10 | if: ${{ github.actor == 'dependabot[bot]' }} 11 | steps: 12 | - name: Dependabot metadata 13 | id: metadata 14 | uses: dependabot/fetch-metadata@v2 15 | with: 16 | github-token: "${{ secrets.GITHUB_TOKEN }}" 17 | - name: Approve a PR 18 | run: gh pr review --approve "$PR_URL" 19 | env: 20 | PR_URL: ${{ github.event.pull_request.html_url }} 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/code_quality.yml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | pull_request: 5 | branches: [ mainline, release ] 6 | workflow_call: 7 | inputs: 8 | branch: 9 | required: false 10 | type: string 11 | 12 | jobs: 13 | Test: 14 | name: Python 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, windows-latest, macos-latest] 18 | python-version: ['3.9', '3.10', '3.11'] 19 | uses: aws-deadline/.github/.github/workflows/reusable_python_build.yml@mainline 20 | with: 21 | os: ${{ matrix.os }} 22 | python-version: ${{ matrix.python-version }} -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "mainline" ] 6 | pull_request: 7 | branches: [ "mainline" ] 8 | schedule: 9 | - cron: '0 8 * * MON' 10 | 11 | jobs: 12 | Analysis: 13 | name: Analysis 14 | uses: aws-deadline/.github/.github/workflows/reusable_codeql.yml@mainline 15 | -------------------------------------------------------------------------------- /.github/workflows/release_bump.yml: -------------------------------------------------------------------------------- 1 | name: "Release: Bump" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | force_version_bump: 7 | required: false 8 | default: "" 9 | type: choice 10 | options: 11 | - "" 12 | - patch 13 | - minor 14 | - major 15 | 16 | concurrency: 17 | group: release 18 | 19 | jobs: 20 | UnitTests: 21 | name: Unit Tests 22 | uses: ./.github/workflows/code_quality.yml 23 | with: 24 | branch: mainline 25 | 26 | Bump: 27 | name: Version Bump 28 | needs: UnitTests 29 | uses: aws-deadline/.github/.github/workflows/reusable_bump.yml@mainline 30 | secrets: inherit 31 | with: 32 | force_version_bump: ${{ inputs.force_version_bump }} -------------------------------------------------------------------------------- /.github/workflows/release_publish.yml: -------------------------------------------------------------------------------- 1 | name: "Release: Publish" 2 | run-name: "Release: ${{ github.event.head_commit.message }}" 3 | 4 | on: 5 | push: 6 | branches: 7 | - mainline 8 | paths: 9 | - CHANGELOG.md 10 | 11 | concurrency: 12 | group: release 13 | 14 | jobs: 15 | Publish: 16 | name: Publish Release 17 | permissions: 18 | id-token: write 19 | contents: write 20 | uses: aws-deadline/.github/.github/workflows/reusable_publish.yml@mainline 21 | secrets: inherit 22 | # PyPI does not support reusable workflows yet 23 | # # See https://github.com/pypi/warehouse/issues/11096 24 | PublishToPyPI: 25 | needs: Publish 26 | runs-on: ubuntu-latest 27 | environment: release 28 | permissions: 29 | id-token: write 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | with: 34 | ref: release 35 | fetch-depth: 0 36 | - name: Set up Python 37 | uses: actions/setup-python@v5 38 | with: 39 | python-version: '3.9' 40 | - name: Install dependencies 41 | run: | 42 | pip install --upgrade hatch 43 | - name: Build 44 | run: hatch -v build 45 | # # See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-pypi 46 | - name: Publish to PyPI 47 | uses: pypa/gh-action-pypi-publish@release/v1 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | __pycache__ 3 | .coverage 4 | .tox 5 | .venv 6 | .vscode 7 | *_version.py 8 | 9 | /dependency_bundle 10 | /dist 11 | /docs/build/ 12 | /htmlcov 13 | /wheels/ 14 | 15 | **/test_job_bundle/ 16 | **/test-job-bundle-results.txt 17 | 18 | .DS_Store 19 | 20 | # Visual Studio user specific files 21 | .vs/ 22 | .vsconfig 23 | 24 | # Builds 25 | Build/* 26 | !Builds/* 27 | Build/*/** 28 | 29 | # Don't ignore icon files in Build 30 | !Build/**/*.ico 31 | 32 | # Rider 33 | .idea/ 34 | _ReSharper.Caches/* 35 | Plugins/*/RiderLink/* 36 | 37 | # Compiled Object files 38 | *.slo 39 | *.lo 40 | *.o 41 | *.obj 42 | 43 | # Precompiled Headers 44 | *.gch 45 | *.pch 46 | 47 | # Fortran module files 48 | *.mod 49 | 50 | # Compiled Static libraries 51 | #*.lai 52 | #*.la 53 | #*.a 54 | #*.lib 55 | 56 | # Executables 57 | *.exe 58 | *.out 59 | *.app 60 | *.ipa 61 | 62 | # These project files can be generated by the engine 63 | *.xcodeproj 64 | *.xcworkspace 65 | *.sln 66 | *.suo 67 | *.opensdf 68 | *.sdf 69 | *.VC.db 70 | *.VC.opendb 71 | 72 | # Precompiled Assets 73 | SourceArt/**/*.png 74 | SourceArt/**/*.tga 75 | 76 | # Binary Files 77 | Plugins/*/Binaries/* 78 | 79 | # Built data for maps 80 | *_BuiltData.uasset 81 | 82 | # Configuration files generated by the Editor 83 | Saved/* 84 | Logs/* 85 | 86 | # Compiled source files for the engine to use 87 | Intermediate/* 88 | Plugins/*/Intermediate/* 89 | 90 | # Cache files for the editor to use 91 | DerivedDataCache/* 92 | 93 | # Visual Studio user specific files 94 | .vs/ 95 | .vsconfig 96 | 97 | 98 | 99 | # Doxygen documentation 100 | gen 101 | -------------------------------------------------------------------------------- /.semantic_release/CHANGELOG.md.j2: -------------------------------------------------------------------------------- 1 | {% for version, release in context.history.released.items() %} 2 | ## {{ version.as_tag() }} ({{ release.tagged_date.strftime("%Y-%m-%d") }}) 3 | 4 | {% if "breaking" in release["elements"] %} 5 | ### BREAKING CHANGES 6 | {% for commit in release["elements"]["breaking"] %} 7 | * {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.commit.summary[commit.commit.summary.find(": ")+1:].strip() }} ([`{{ commit.short_hash }}`]({{ commit.commit.hexsha | commit_hash_url }})) 8 | {% endfor %} 9 | {% endif %} 10 | 11 | {% if "features" in release["elements"] %} 12 | ### Features 13 | {% for commit in release["elements"]["features"] %} 14 | * {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.commit.summary[commit.commit.summary.find(": ")+1:].strip() }} ([`{{ commit.short_hash }}`]({{ commit.commit.hexsha | commit_hash_url }})) 15 | {% endfor %} 16 | {% endif %} 17 | 18 | {% if "bug fixes" in release["elements"] %} 19 | ### Bug Fixes 20 | {% for commit in release["elements"]["bug fixes"] %} 21 | * {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.commit.summary[commit.commit.summary.find(":")+1:].strip() }} ([`{{ commit.short_hash }}`]({{ commit.commit.hexsha | commit_hash_url }})) 22 | {% endfor %} 23 | {% endif %} 24 | 25 | {% endfor %} -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /depsBundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -xeuo pipefail 3 | 4 | python depsBundle.py 5 | 6 | rm -f dependency_bundle/deadline_cloud_for_unreal_engine_submitter-deps-windows.zip 7 | 8 | cp dependency_bundle/deadline_cloud_for_unreal_engine_submitter-deps.zip dependency_bundle/deadline_cloud_for_unreal_engine_submitter-deps-windows.zip 9 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/_templates/module.rst_t: -------------------------------------------------------------------------------- 1 | {%- if show_headings %} 2 | {{- submodule | e | heading(2) }} 3 | 4 | {% endif -%} 5 | .. automodule:: {{ qualname }} 6 | {%- for option in automodule_options %} 7 | :{{ option }}: 8 | {%- endfor %} 9 | 10 | -------------------------------------------------------------------------------- /docs/source/_templates/package.rst_t: -------------------------------------------------------------------------------- 1 | {%- macro automodule(modname, options) -%} 2 | .. automodule:: {{ modname }} 3 | {%- for option in options %} 4 | :{{ option }}: 5 | {%- endfor %} 6 | {%- endmacro %} 7 | 8 | {%- macro toctree(docnames) -%} 9 | .. toctree:: 10 | :maxdepth: {{ maxdepth }} 11 | {% for docname in docnames %} 12 | {{ docname }} 13 | {%- endfor %} 14 | {%- endmacro %} 15 | 16 | {%- if is_namespace %} 17 | {{- pkgname | e | heading }} 18 | {% else %} 19 | {{- pkgname | e | heading }} 20 | {% endif %} 21 | 22 | {%- if is_namespace %} 23 | .. py:module:: {{ pkgname }} 24 | {% endif %} 25 | 26 | {%- if modulefirst and not is_namespace %} 27 | {{ automodule(pkgname, automodule_options) }} 28 | {% endif %} 29 | 30 | {%- if subpackages %} 31 | Subpackages 32 | ----------- 33 | 34 | {{ toctree(subpackages) }} 35 | {% endif %} 36 | 37 | {%- if submodules %} 38 | Submodules 39 | ---------- 40 | {% if separatemodules %} 41 | {{ toctree(submodules) }} 42 | {% else %} 43 | {%- for submodule in submodules %} 44 | {% if show_headings %} 45 | {{- submodule | e | heading(2) }} 46 | {% endif %} 47 | {{ automodule(submodule, automodule_options) }} 48 | {% endfor %} 49 | {%- endif %} 50 | {%- endif %} 51 | 52 | {%- if not modulefirst and not is_namespace %} 53 | Module contents 54 | --------------- 55 | 56 | {{ automodule(pkgname, automodule_options) }} 57 | {% endif %} 58 | -------------------------------------------------------------------------------- /docs/source/_templates/toc.rst_t: -------------------------------------------------------------------------------- 1 | {{ header | heading }} 2 | 3 | .. toctree:: 4 | :maxdepth: {{ maxdepth }} 5 | {% for docname in docnames %} 6 | {{ docname }} 7 | {%- endfor %} 8 | 9 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | 4 | src_deadline_path = str(Path(__file__).parent.parent.parent) + "/src" 5 | sys.path.insert(0, src_deadline_path) 6 | 7 | project = "deadline-cloud-for-unreal-engine" 8 | copyright = "2025, Amazon.com" 9 | author = "Amazon.com" 10 | release = "0.4.0" 11 | 12 | # -- General configuration --------------------------------------------------- 13 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 14 | 15 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon"] 16 | 17 | templates_path = ["_templates"] 18 | exclude_patterns = [] 19 | autodoc_mock_imports = ["unreal", "deadline.client", "deadline.job_attachments", "openjd", "P4"] 20 | autodoc_member_order = "bysource" 21 | autodoc_default_options = {"members": True, "undoc-members": True, "private-members": True} 22 | 23 | 24 | # -- Options for HTML output ------------------------------------------------- 25 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 26 | 27 | html_theme = "sphinx_rtd_theme" 28 | -------------------------------------------------------------------------------- /docs/source/docs_api/api.rst: -------------------------------------------------------------------------------- 1 | Submitter and Adaptor API 2 | ========================= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | unreal_adaptor 8 | unreal_logger 9 | unreal_submitter 10 | unreal_perforce_utils 11 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_adaptor.UnrealAdaptor.rst: -------------------------------------------------------------------------------- 1 | unreal\_adaptor.UnrealAdaptor 2 | ===================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | unreal\_adaptor.UnrealAdaptor.adaptor 8 | -------------------------------------------- 9 | 10 | .. automodule:: deadline.unreal_adaptor.UnrealAdaptor.adaptor 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | unreal\_adaptor.UnrealAdaptor.common 16 | ------------------------------------------- 17 | 18 | .. automodule:: deadline.unreal_adaptor.UnrealAdaptor.common 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_adaptor.UnrealClient.rst: -------------------------------------------------------------------------------- 1 | unreal\_adaptor.UnrealClient 2 | ==================================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | unreal_adaptor.UnrealClient.step_handlers 11 | 12 | Submodules 13 | ---------- 14 | 15 | unreal\_adaptor.UnrealClient.unreal\_client 16 | -------------------------------------------------- 17 | 18 | .. automodule:: deadline.unreal_adaptor.UnrealClient.unreal_client 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_adaptor.UnrealClient.step_handlers.rst: -------------------------------------------------------------------------------- 1 | unreal\_adaptor.UnrealClient.step\_handlers 2 | =================================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | unreal\_adaptor.UnrealClient.step\_handlers.base\_step\_handler 8 | ---------------------------------------------------------------------- 9 | 10 | .. automodule:: deadline.unreal_adaptor.UnrealClient.step_handlers.base_step_handler 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | unreal\_adaptor.UnrealClient.step\_handlers.unreal\_custom\_step\_handler 16 | -------------------------------------------------------------------------------- 17 | 18 | .. automodule:: deadline.unreal_adaptor.UnrealClient.step_handlers.unreal_custom_step_handler 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | unreal\_adaptor.UnrealClient.step\_handlers.unreal\_render\_step\_handler 24 | -------------------------------------------------------------------------------- 25 | 26 | .. automodule:: deadline.unreal_adaptor.UnrealClient.step_handlers.unreal_render_step_handler 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_adaptor.rst: -------------------------------------------------------------------------------- 1 | unreal\_adaptor 2 | ======================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | unreal_adaptor.UnrealAdaptor 11 | unreal_adaptor.UnrealClient 12 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_logger.rst: -------------------------------------------------------------------------------- 1 | unreal\_logger 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | unreal\_logger.handlers 8 | ------------------------------ 9 | 10 | .. automodule:: deadline.unreal_logger.handlers 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | unreal\_logger.logger 16 | ---------------------------- 17 | 18 | .. automodule:: deadline.unreal_logger.logger 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_perforce_utils.rst: -------------------------------------------------------------------------------- 1 | unreal\_perforce\_utils 2 | ======================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | unreal\_perforce\_utils.app 8 | --------------------------- 9 | 10 | .. automodule:: deadline.unreal_perforce_utils.app 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | unreal\_perforce\_utils.exceptions 16 | ----------------------------------- 17 | 18 | .. automodule:: deadline.unreal_perforce_utils.exceptions 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | unreal\_perforce\_utils.cli 24 | --------------------------- 25 | 26 | .. automodule:: deadline.unreal_perforce_utils.cli 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | unreal\_perforce\_utils.perforce 32 | -------------------------------- 33 | 34 | .. automodule:: deadline.unreal_perforce_utils.perforce 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_submitter.rst: -------------------------------------------------------------------------------- 1 | unreal\_submitter 2 | ========================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | unreal_submitter.unreal_open_job 11 | 12 | Submodules 13 | ---------- 14 | 15 | unreal\_submitter.common 16 | ------------------------------- 17 | 18 | .. automodule:: deadline.unreal_submitter.common 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | unreal\_submitter.exceptions 24 | ----------------------------------- 25 | 26 | .. automodule:: deadline.unreal_submitter.exceptions 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | unreal\_submitter.settings 32 | --------------------------------- 33 | 34 | .. automodule:: deadline.unreal_submitter.settings 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | unreal\_submitter.submitter 40 | ---------------------------------- 41 | 42 | .. automodule:: deadline.unreal_submitter.submitter 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | unreal\_submitter.unreal\_dependency\_collector 48 | ------------------------------------------------------ 49 | 50 | .. automodule:: deadline.unreal_submitter.unreal_dependency_collector 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | -------------------------------------------------------------------------------- /docs/source/docs_api/unreal_submitter.unreal_open_job.rst: -------------------------------------------------------------------------------- 1 | unreal\_submitter.unreal\_open\_job 2 | =========================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job 8 | ------------------------------------------------------------ 9 | 10 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_entity 16 | -------------------------------------------------------------------- 17 | 18 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_entity 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_environment 24 | ------------------------------------------------------------------------- 25 | 26 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_environment 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_parameters\_consistency 32 | ------------------------------------------------------------------------------------- 33 | 34 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_parameters_consistency 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_shared\_settings 40 | ------------------------------------------------------------------------------ 41 | 42 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_shared_settings 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_step 48 | ------------------------------------------------------------------ 49 | 50 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_step 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | unreal\_submitter.unreal\_open\_job.unreal\_open\_job\_step\_host\_requirements 56 | -------------------------------------------------------------------------------------- 57 | 58 | .. automodule:: deadline.unreal_submitter.unreal_open_job.unreal_open_job_step_host_requirements 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | -------------------------------------------------------------------------------- /docs/source/docs_usage/configure.rst: -------------------------------------------------------------------------------- 1 | Configure Movie Render Pipeline and Unreal Deadline Cloud plugins 2 | ================================================================= 3 | 4 | 5 | Configure Movie Render Pipeline Plugin 6 | ************************************** 7 | 8 | #. Go to "Edit" > "Project Settings …" 9 | #. Find "Movie Render Pipeline" plugin in "Plugins" section on the left side 10 | 11 | .. image:: /images/mrq_plugin_settings_0.png 12 | 13 | #. Set “Default Remote Executor” as “MoviePipelineDeadlineCloudRemoteExecutor” 14 | and “Default Executor Job” as “MoviePipelineDeadlineCloudExecutorJob” 15 | 16 | .. image:: /images/mrq_plugin_settings_1.png 17 | 18 | 19 | Configure Unreal Deadline Cloud Plugin 20 | ************************************** 21 | 22 | #. Go to "Edit" > "Project Settings …" 23 | #. Find "Deadline Cloud" plugin in "Plugins" section on the left side 24 | #. Login into Deadline Cloud if needed 25 | #. Configure Default Farm, Queue, Storage Profile and other settings 26 | 27 | .. image:: /images/deadline_cloud_settings.png -------------------------------------------------------------------------------- /docs/source/docs_usage/data_assets.rst: -------------------------------------------------------------------------------- 1 | Create DeadlineCloud data assets 2 | ================================ 3 | 4 | #. In the content browser click RMB -> Miscellaneous -> Data Asset or type “data asset” in the search bar 5 | 6 | .. image:: /images/create_data_asset_0.png 7 | 8 | #. Type “deadline”. Here you can see bunch of DeadlineCloud assets: 9 | 10 | .. image:: /images/create_data_asset_1.png 11 | 12 | a. Deadline Cloud Job - Basic implementation of OpenJob 13 | #. Deadline Cloud Render Job - OpenJob for submitting jobs from MRQ plugin 14 | #. Deadline Cloud Step - Basic implementation of OpenJob Step 15 | #. Deadline Cloud Render Step - Specific class for Unreal Render actions script 16 | #. Deadline Cloud Environment - Basic implementation of OpenJob Environment 17 | #. Deadline Cloud Ugs Environment - Specific class for OpenJob Environment if you want to use Unreal Game Sync VCS 18 | 19 | #. Each Data Asset (Job, Step, Environment) has a common field “Path to Template”. 20 | Prepared in advance templates located in **Plugins/UnrealDeadlineCloudService/Content/Python/openjd_templates** 21 | (**src/unreal_plugin/Content/Python/openjd_templates**) 22 | 23 | .. image:: /images/create_data_asset_2.png 24 | 25 | a. render_job.yml - Render Job template 26 | #. launch_ue_environment.yml - Environment that launch the UE on env enter and close it on env exit 27 | #. render_step.yml - Step with script that runs UE rendering 28 | #. ugs 29 | 30 | i. ugs_render_job.yml - Render Job template for UGS jobs 31 | #. ugs_sync_cmf_environment.yml - Environment that sync UGS workspace before render. Use for CMF render farm 32 | #. ugs_sync_smf_environment.yml - Environment that sync UGS workspace before render. Use for SMF render farm 33 | #. ugs_launch_ue_environment.yml - Environment that launch the UE for UGS jobs 34 | #. ugs_render_step.yml - Step with script that runs UE rendering for UGS jobs 35 | #. p4 36 | 37 | i. p4_render_job.yml - Render Job template for P4 jobs 38 | #. p4_sync_cmf_environment.yml - Environment that sync P4 workspace before render. Use for CMF render farm 39 | #. p4_sync_smf_environment.yml - Environment that sync P4 workspace before render. Use for SMF render farm 40 | #. p4_launch_ue_environment.yml - Environment that launch the UE for P4 jobs 41 | #. p4_render_step.yml - Step with script that runs UE rendering for P4 jobs 42 | #. custom 43 | 44 | i. custom_job.yml - Job template for executing custom actions 45 | #. custom_step.yml - Step template for executing custom python scripts with "custom" handler -------------------------------------------------------------------------------- /docs/source/docs_usage/py_use_cases/py_submit_custom_job.rst: -------------------------------------------------------------------------------- 1 | Submit Custom Unreal OpenJob from Python 2 | ======================================== 3 | 4 | Example of submission process described in **Content/Python/submit_actions/custom_job_submission.py** 5 | in Plugin folder: 6 | 7 | .. literalinclude:: ../../../../src/unreal_plugin/Content/Python/submit_actions/custom_job_submission.py 8 | :language: python 9 | :linenos: 10 | 11 | 12 | Example of custom script to pass as ``--script_path`` parameter and execute on render node described in 13 | **Content/Python/submit_actions/custom_script.py** in Plugin folder: 14 | 15 | .. literalinclude:: ../../../../src/unreal_plugin/Content/Python/submit_actions/custom_script.py 16 | :language: python 17 | :linenos: -------------------------------------------------------------------------------- /docs/source/docs_usage/py_use_cases/py_submit_p4_render_job.rst: -------------------------------------------------------------------------------- 1 | Submit Render Unreal OpenJob from Python in Perforce pipeline 2 | ============================================================= 3 | 4 | .. note:: Before creating the UGS jobs, please refer to :ref:`p4-credentials-management` to see 5 | how to set up/pass P4 credentials on your workers fleet 6 | 7 | Example of submission process described in **Content/Python/submit_actions/p4_render_job_submission.py** 8 | in Plugin folder: 9 | 10 | .. literalinclude:: ../../../../src/unreal_plugin/Content/Python/submit_actions/p4_render_job_submission.py 11 | :language: python 12 | :linenos: 13 | -------------------------------------------------------------------------------- /docs/source/docs_usage/py_use_cases/py_submit_render_job.rst: -------------------------------------------------------------------------------- 1 | Submit Render Unreal OpenJob from Python 2 | ======================================== 3 | 4 | Example of submission process described in **Content/Python/submit_actions/render_job_submission.py** 5 | in Plugin folder: 6 | 7 | .. literalinclude:: ../../../../src/unreal_plugin/Content/Python/submit_actions/render_job_submission.py 8 | :language: python 9 | :linenos: 10 | -------------------------------------------------------------------------------- /docs/source/docs_usage/py_use_cases/py_submit_ugs_render_job.rst: -------------------------------------------------------------------------------- 1 | Submit Render Unreal OpenJob from Python in Unreal Game Sync pipeline 2 | ===================================================================== 3 | 4 | .. note:: Before creating the UGS jobs, please refer to :ref:`p4-credentials-management` to see 5 | how to set up/pass P4 credentials on your workers fleet 6 | 7 | Example of submission process described in **Content/Python/submit_actions/usg_render_job_submission.py** 8 | in Plugin folder: 9 | 10 | .. literalinclude:: ../../../../src/unreal_plugin/Content/Python/submit_actions/ugs_render_job_submission.py 11 | :language: python 12 | :linenos: 13 | -------------------------------------------------------------------------------- /docs/source/docs_usage/py_use_cases/py_use_cases.rst: -------------------------------------------------------------------------------- 1 | How To create, configure and submit Jobs, Steps, Environments from Python 2 | ========================================================================= 3 | 4 | Examples of the submission from Unreal Python located in **Content/Python/submit_actions**: 5 | 6 | #. **render_job_submission.py** - submit default Render Job using S3 to transfer project files 7 | #. **ugs_render_job_submission.py** - submit Render Job using UGS to transfer project files 8 | #. **custom_job_submission.py** - submit custom Job with **custom_script.py** to execute 9 | 10 | .. toctree:: 11 | :maxdepth: 1 12 | 13 | py_submission_general 14 | py_submit_render_job 15 | py_submit_ugs_render_job 16 | py_submit_p4_render_job 17 | py_submit_custom_job -------------------------------------------------------------------------------- /docs/source/docs_usage/usage.rst: -------------------------------------------------------------------------------- 1 | How To Use 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | configure 8 | data_assets 9 | use_cases/use_cases 10 | py_use_cases/py_use_cases 11 | p4_credentials_management -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/check_parameters_consistency.rst: -------------------------------------------------------------------------------- 1 | Check Parameters Consistency 2 | ============================ 3 | 4 | The plugin allows you to check consistency of the parameters of Step, Job parameters and 5 | variables of Environment while editing the data asset and submitting the Job. 6 | 7 | Parameter is **consistent** if its **name** and **type** are the same in the YAML and Data Asset. 8 | 9 | Environment Variable is **consistent** if its **name** is the same in the YAML and Data Asset. 10 | 11 | That means consistency check failed if: 12 | 13 | #. YAML parameter missed in data asset parameters list 14 | #. Data asset parameter missed in YAML parameters list 15 | #. YAML/Data asset parameters with the same name have different type (only for Job and Step) 16 | 17 | Check consistency while editing the Data Asset 18 | ********************************************** 19 | 20 | #. Create new DeadlineCloud Job data asset, select the YAML template for it, save and close it 21 | 22 | .. image:: /images/consistency_check_0.png 23 | 24 | #. Open that YAML in any text editor and add/remove some parameter to/from **parameterDefinitions** list 25 | 26 | .. image:: /images/consistency_check_1.png 27 | 28 | #. Open DeadlineCloud Job data asset. You will see the warning message and fix button 29 | 30 | .. image:: /images/consistency_check_2.png 31 | 32 | #. Click "OK" button to fix the parameters. YAML parameters have the priority on the Data Asset's ones, and 33 | Fix affect only the data asset parameters, so the fix logic is: 34 | a. If YAML parameter missed in Data Asset, it will be added 35 | #. If Data Asset parameter missed in YAML, it will be removed 36 | #. If parameter in both sources have same **name** but different **types**, 37 | it will be removed and same YAML parameter will be added 38 | #. All of the values of added parameters will be empty or equal to **default** described in YAML 39 | 40 | .. image:: /images/consistency_check_3.png 41 | 42 | 43 | Check consistency while submitting 44 | ********************************** 45 | 46 | #. Create new Job in MRQ widget, select you prepared DeadlineCloud Job data asset and click **Render (Remote)** button 47 | #. You will see the warning message and submission will be aborted 48 | 49 | .. image:: /images/consistency_check_4.png -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/create_render_job.rst: -------------------------------------------------------------------------------- 1 | Create Default Render Job 2 | ========================= 3 | 4 | Render Step data asset 5 | ********************** 6 | 7 | #. Select “Deadline Cloud Render Step”. Name an asset, for example “RenderStep” and open it for editing. 8 | 9 | .. image:: /images/create_render_job_0.png 10 | 11 | #. Select **Content/Python/openjd_templates/render_step.yml** 12 | 13 | .. image:: /images/create_render_job_1.png 14 | 15 | #. Task Parameter Definitions and Name from YAML will be loaded to data asset 16 | 17 | .. image:: /images/create_render_job_2.png 18 | 19 | a. Handler - specify which UnrealAdaptor’s handler will process the script commands. Handler "render" used for usual pipeline of MRQ render **Filled automatically during the submission** 20 | #. QueueManifestPath - path to the serialized MRQ manifest where render job is described. **Filled automatically during the submission** 21 | #. TaskChunkSize - Number of shots of Level Sequence to render per OpenJob Task. Set this value according to what number of tasks you want Deadline Cloud to generate 22 | For example, if Level Sequence has 10 shots and TaskChunkSize = 3 that means 4 OpenJob Tasks will be introduced: 23 | 24 | i. Task 0 - shots 0, 1, 2 25 | #. Task 1 - shots 3, 4, 5 26 | #. Task 2 - shots 6, 7, 8 27 | #. Task 3 - shot 9 28 | 29 | #. TaskChunkId - list of chunk ids. This example will consist of 0, 1, 2, 3 (task ids). **Filled automatically during the submission** 30 | 31 | 32 | Launch UE Environment data asset 33 | ******************************** 34 | 35 | #. Select "Deadline Cloud Environment". Name an asset, for example "LaunchUnrealEnvironment" and open it for editing. 36 | 37 | .. image:: /images/create_render_job_3.png 38 | 39 | #. Select **Content/Python/openjd_templates/launch_ue_environment.yml** 40 | #. Environment variables and Name from YAML will be loaded to data asset 41 | 42 | .. image:: /images/create_render_job_4.png 43 | 44 | a. REMOTE_EXECUTION=True - indicates that Unreal will be launched on the remote machine 45 | and plugin should do/don’t some specific operations 46 | 47 | 48 | Render Job data asset 49 | ********************* 50 | 51 | #. Select "Deadline Cloud Render Job". Name an asset, for example "RenderJob" and open it for editing. 52 | 53 | .. image:: /images/create_render_job_5.png 54 | 55 | #. Select **Content/Python/openjd_templates/render_job.yml** 56 | #. Parameter Definitions from YAML will be loaded to data asset 57 | 58 | .. image:: /images/create_render_job_6.png 59 | 60 | a. Executable - Unreal executable name to launch on render node 61 | #. ExtraCmdArgs - Additional CMD arguments to launch Unreal executable with 62 | #. ExtraCmdArgsFile - Specific file parameter where **ExtraCmdArgs** will be stored. 63 | Need to avoid **1024 chars limit** on **STRING** parameter. **Filled automatically during the submission** 64 | #. ProjectFilePath - Local path of the current Unreal Project. **Filled automatically during the submission** 65 | 66 | #. Configure Job Shared Settings, Host Requirements and Job Attachments if needed 67 | 68 | .. image:: /images/create_render_job_7.png 69 | 70 | #. Add “RenderStep” and “LaunchUnrealEnvironment” assets in appropriate fields 71 | 72 | .. image:: /images/create_render_job_8.png 73 | .. image:: /images/create_render_job_9.png 74 | 75 | #. Final state of the DeadlineCloud Render Job 76 | 77 | .. image:: /images/create_render_job_10.png -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/hide_parameters.rst: -------------------------------------------------------------------------------- 1 | Hide Job and Step parameters in Data Asset 2 | ========================================== 3 | 4 | Plugin provide ability to configure, which Job and Step parameters should be hidden from User in 5 | Data Asset and MRQ Deadline Cloud Job widget. 6 | 7 | Each parameter has "opened eye" button 8 | 9 | .. image:: /images/hide_params_0.png 10 | 11 | To make parameter hidden, click eye button. Its icon will be replaced with "closed eye" 12 | 13 | .. image:: /images/hide_params_1.png 14 | 15 | Additionally, info message about that some parameters hidden will appear 16 | 17 | .. image:: /images/hide_params_2.png 18 | 19 | By clicking "Hide" button, you will hide parameters with "closed eye" icon in Data Asset and MRQ Job Widget. 20 | Button "Hide" converts to "Show" that reveals the parameters from Data Asset and MRQ Job Widget. 21 | 22 | .. image:: /images/hide_params_3.png 23 | .. image:: /images/hide_params_4.png -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/submit_custom_job_from_bp.rst: -------------------------------------------------------------------------------- 1 | Submit Custom Job from Editor Utility Widget 2 | ============================================ 3 | 4 | Plugin provide the ability to submit custom jobs to DeadlineCloud farm via Editor Utility Widgets. 5 | As an example, we add the simple submitter that allows to select python script to execute on the 6 | render node within Unreal Engine session. 7 | 8 | #. Check if **Show Plugin Content** is enabled in **Content Browser Settings** 9 | 10 | .. image:: /images/submit_render_bp_0.png 11 | 12 | #. Find **DeadlinePathSelector** in **All/Plugins/UnrealDeadlineCloudServiceContent/Widgets** 13 | 14 | .. image:: /images/submit_custom_bp_0.png 15 | 16 | #. Right-click on this file and select **Run Editor Utility Widget**. You will see the UI of Blueprint Submitter 17 | 18 | .. image:: /images/submit_custom_bp_1.png 19 | 20 | #. Select path to the Python script to execute. As an example, we prepare script **Content/Python/submit_actions/custom_script.py** 21 | and click "Submit" button 22 | 23 | .. image:: /images/submit_custom_bp_2.png 24 | -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/submit_job.rst: -------------------------------------------------------------------------------- 1 | Submit Job from Movie Render Queue 2 | ================================== 3 | 4 | To submit DeadlineCloud Job from Movie Render Queue, follow next steps: 5 | 6 | #. Go to "Window" > "Cinematics" > "Movie Render Queue" 7 | #. Select Level Sequence to render 8 | 9 | .. image:: /images/submit_job_0.png 10 | 11 | #. Set "Job Preset" as created DeadlineCloud Render Job data asset 12 | 13 | .. image:: /images/submit_job_1.png 14 | 15 | #. Name of the OpenJob will be set as one of the next parameters by next priority 16 | 17 | a. MRQ Job Preset Overrides 18 | 19 | .. image:: /images/submit_job_2.png 20 | 21 | #. DeadlineCloudJob Job Shared Settings 22 | 23 | .. image:: /images/submit_job_3.png 24 | 25 | #. Name from YAML 26 | 27 | .. image:: /images/submit_job_4.png 28 | 29 | #. MRQ Job name (shot name) 30 | 31 | .. image:: /images/submit_job_5.png 32 | 33 | #. Update parameters in Preset Overrides if needed 34 | #. Click “Render (Remote)” button -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/submit_predefined_render_job.rst: -------------------------------------------------------------------------------- 1 | Submit Predefined Render Job from Movie Render Queue 2 | ==================================================== 3 | 4 | Deadline Cloud plugin provide the ability to submit predefined Render Job: 5 | 6 | * Render Job (**Deadline Cloud Render Job**) 7 | 8 | * Launch Unreal Environment (**Deadline Cloud Environment**) 9 | 10 | * Render Step (**Deadline Cloud Render Step**) 11 | 12 | To submit predefined job, follow these steps: 13 | 14 | #. Go to "Window" > "Cinematics" > "Movie Render Queue" 15 | #. Select Level Sequence to render 16 | 17 | .. image:: /images/submit_job_0.png 18 | 19 | #. Do not set "Job Preset" as some Data Asset, because its already filled with transient Data Asset 20 | 21 | .. image:: /images/submit_predefined_job_0.png 22 | 23 | #. Update parameters in Preset, Steps and Environments Overrides if needed 24 | 25 | .. image:: /images/submit_predefined_job_1.png 26 | 27 | #. Click “Render (Remote)” button -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/submit_render_job_from_bp.rst: -------------------------------------------------------------------------------- 1 | Submit Render Job from Editor Utility Widget 2 | ============================================ 3 | 4 | Plugin provide the ability to submit render jobs to DeadlineCloud farm via Editor Utility Widgets. 5 | 6 | #. Check if **Show Plugin Content** is enabled in **Content Browser Settings** 7 | 8 | .. image:: /images/submit_render_bp_0.png 9 | 10 | #. Find **DeadlineJobSubmitter** in **All/Plugins/UnrealDeadlineCloudServiceContent/Widgets** 11 | 12 | .. image:: /images/submit_render_bp_1.png 13 | 14 | #. Right-click on this file and select **Run Editor Utility Widget**. You will see the UI of Blueprint Submitter 15 | 16 | .. image:: /images/submit_render_bp_2.png 17 | 18 | #. Select DeadlineCloud Job Preset, Level Sequence, Level and MRQ Job Configuration 19 | how do you usually do it in the MRQ plugin and click "Render" button 20 | 21 | .. image:: /images/submit_render_bp_3.png 22 | -------------------------------------------------------------------------------- /docs/source/docs_usage/use_cases/use_cases.rst: -------------------------------------------------------------------------------- 1 | How To create, configure and submit Jobs, Steps, Environments from UI 2 | ===================================================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | create_render_job 8 | create_ugs_render_job 9 | create_p4_render_job 10 | submit_job 11 | submit_predefined_render_job 12 | submit_render_job_from_bp 13 | submit_custom_job_from_bp 14 | check_parameters_consistency 15 | hide_parameters 16 | -------------------------------------------------------------------------------- /docs/source/images/consistency_check_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cfe3e22c134e0d8e9ac0890ea2dada056222964bae129cc63f5cade1b0d489cb 3 | size 15672 4 | -------------------------------------------------------------------------------- /docs/source/images/consistency_check_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8046dd58d0b1f2cea9af7ab39a751a90db161ed2e33f8fbc6acfe53855e3d7a6 3 | size 46656 4 | -------------------------------------------------------------------------------- /docs/source/images/consistency_check_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:55b2359bedc11daf36afefad108d16462f381c65c283176f542898729a81331a 3 | size 19680 4 | -------------------------------------------------------------------------------- /docs/source/images/consistency_check_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:737392faf7bb1012f3e095486b8b80b9bd581630fdb764d52e781913004614e0 3 | size 17337 4 | -------------------------------------------------------------------------------- /docs/source/images/consistency_check_4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:83f4f6da150264c4975ee9c175de72e77b865ce5ed5482cb57dcd7f3b73b7d34 3 | size 18961 4 | -------------------------------------------------------------------------------- /docs/source/images/create_data_asset_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5e433b4ba94bff9704b72eaf40a11f0a98f45d1e6aafbb402cea1989151fd747 3 | size 119660 4 | -------------------------------------------------------------------------------- /docs/source/images/create_data_asset_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:de2794edd9ec12effc083136ebeb6eeb5aa191b317d2c69d4c7c500dfbdf9151 3 | size 35605 4 | -------------------------------------------------------------------------------- /docs/source/images/create_data_asset_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:54322d70510f176497b88297bdea84ba4d86016b7c349e16c3e12bfa5d5031dc 3 | size 29518 4 | -------------------------------------------------------------------------------- /docs/source/images/create_p4_render_job_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2227662c7ecbf2dae27c81241f79641c53e0ee26b2915d59f4675a1570b96fb7 3 | size 41840 4 | -------------------------------------------------------------------------------- /docs/source/images/create_p4_render_job_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:76681c5edba9322add7850206e7926765ae0f35d642a8e6b6c853d839278e942 3 | size 15064 4 | -------------------------------------------------------------------------------- /docs/source/images/create_p4_render_job_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fdd1552b2911523d9a1d64fb29164d7aba232c16b8e4a9b0ad7d9c508334fd86 3 | size 24793 4 | -------------------------------------------------------------------------------- /docs/source/images/create_p4_render_job_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ccbe08c1b4c9640b47aaa2ad9de3cc725bb3e19ff05887e3dc6c647f05fd56c8 3 | size 37855 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:abc479ee82a5f2ffe38e2dce87f54d355beee4bde037207e7f830e35f79ce1ad 3 | size 37633 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5cc9e3a6348230ff3b5dfea9eb35ccae76f9f9691df3f14fba7fb7f79f653bd1 3 | size 16944 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_10.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8d84efea3a0411e3a82e69be2555e65ab6238988996745e8cf608430d2a22792 3 | size 52690 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2d0ec30f030f112fd13216ead263b67760a45ea3f37df0d88791a26cd3fb9d0d 3 | size 28407 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c080cc56615104b37932d90fc9fd81136de6405b17ca9e7d13018adcefb23599 3 | size 37743 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c8726c6643d5cd764cd2b52e7d8a7e5522baf8b3019fd33bca31f277c0d06235 3 | size 26137 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_5.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:28e7eb4dbac75b8b325a6d444b96f341d43ea9fb8befb71bc53b93b20401d3b9 3 | size 37561 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_6.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78d0a7735db3caef9fe281cabb6e739e5977a61ea4f7ed95759a1f305e85e8ed 3 | size 37136 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_7.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6192abe638e36a21649af68a3aab4a41d6ce70ca432140583a7fb2034fa00c30 3 | size 24930 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_8.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a6d7dfd98fbc2b0d4ea975e314de71852784dc402350e927894d6b8bab60d444 3 | size 29094 4 | -------------------------------------------------------------------------------- /docs/source/images/create_render_job_9.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8dfdd675daf3c096cf922c067001b480f8aa12dd7ff5abb9e3d3a7384ce5154c 3 | size 23904 4 | -------------------------------------------------------------------------------- /docs/source/images/create_ugs_render_job_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1763ee69b8caa9dec41ec8674ddf840f938766963b10bb5ec75051f98ccba113 3 | size 21088 4 | -------------------------------------------------------------------------------- /docs/source/images/create_ugs_render_job_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:539dbcf6c1fbe50071f8bae455e98fee35a1715085b0dd8ff19f255c62eb5cc6 3 | size 37446 4 | -------------------------------------------------------------------------------- /docs/source/images/create_ugs_render_job_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:852b03c238cd8d3a0e02a45d7c7e5e33511adcd572b37ee4ffb92610b5e36ffb 3 | size 24152 4 | -------------------------------------------------------------------------------- /docs/source/images/create_ugs_render_job_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b163290f1eb1dfdb8f781d0b8eb8648584ad74a2eb240decf3a0579176682260 3 | size 18580 4 | -------------------------------------------------------------------------------- /docs/source/images/create_ugs_render_job_4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:613ab12924bc2455079faac3fc64a1211b6e0f80fdb48f794a220f0dff123151 3 | size 58049 4 | -------------------------------------------------------------------------------- /docs/source/images/deadline_cloud_settings.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f317a92b5a14fbb95b38b951a2aee51511afb899dfcd67e98308ab2e67bf122e 3 | size 67757 4 | -------------------------------------------------------------------------------- /docs/source/images/hide_params_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0c34bc176c72f4b83a5ade5131b63cd0a0302821df1e32ecbe0f24a2db61ae44 3 | size 17595 4 | -------------------------------------------------------------------------------- /docs/source/images/hide_params_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff8959cf04c25dc751e73aade38699c24b71b94d9b302d212fd4b9123d53b374 3 | size 9528 4 | -------------------------------------------------------------------------------- /docs/source/images/hide_params_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f981a33fdcc3d826b1a7b44e50a63814a466a87ed0c81db4592abc9d9071a79a 3 | size 29148 4 | -------------------------------------------------------------------------------- /docs/source/images/hide_params_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ab3d5dd14607a22f7e347dc08fa5af06d7553546f2e8cce775cd80d3a81ad24d 3 | size 23182 4 | -------------------------------------------------------------------------------- /docs/source/images/hide_params_4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2d6fab250e224d2a039cf08b5a8525a7069be77957413014fa95d2d8a5704ebe 3 | size 18509 4 | -------------------------------------------------------------------------------- /docs/source/images/mrq_plugin_settings_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:18bad4378bcd04da6063be4119ee715bbf3621eac040b31be11154be8c9ff76e 3 | size 144560 4 | -------------------------------------------------------------------------------- /docs/source/images/mrq_plugin_settings_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:08ab4911c4e346416c2a1ad44d6eecc642a681999b6633293dfc61af0d51ceb6 3 | size 75475 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_custom_bp_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:343a5c354c015438c69b7fde89de5569748524d52ed17e49b80776bd99d0263f 3 | size 57950 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_custom_bp_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e030dc08a1db3993877ab4d1e13162407cf50ba6ff3d5a24d1e23d464879ea2c 3 | size 11333 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_custom_bp_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:deb8debde6f96c5520965bcf0be87c9c8e6842f0404e2d0f0fe0c50593bda4af 3 | size 22865 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:848f6492318b7983afe0c2fd5628bbb4add2e6b57321c9fc5bf1058d041430a0 3 | size 42766 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fb80219a86bbd5f12c7f839594412e850bf4746093ac0efef5761d3444247d11 3 | size 58047 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f0c14c1b7717ba465ece367caec491bdd767e82cf560e0620dcbd0e133923774 3 | size 15384 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2c152b9b2499676f3b78a21c24417f17cd78d995386eba267d790f2e38ad8373 3 | size 29764 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2a16dfdf67be301b0a0d5b409ee5cf2b30795a2c4891c546def52e768845ebe8 3 | size 10159 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_job_5.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2e2ae37aa6992d3cde1088451a6c9299bef56401756da7d1b739bb32609c0d09 3 | size 17985 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_predefined_job_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e356ba5dfa3a6f9137ab37f61c3fc83739041be5fefa6d03f8ad79989fa57d4d 3 | size 9295 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_predefined_job_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0dc021c36dc2a62fbd64886cc00ba7e9b32c68d79c26cd4637c621864fb3c3e1 3 | size 73706 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_render_bp_0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2554b7de54276813be3960569a1634d206deb18095999f1d7e663db7ad590df5 3 | size 91862 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_render_bp_1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78de6f9b8fffa3b863ab4b61328f03c7fef9bda21b324b163e411cb61c4d5e55 3 | size 55723 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_render_bp_2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8aff6ce4675d4a8e158e89f07be323a3e9eccfd71164bcd2029688d9252a09b4 3 | size 29960 4 | -------------------------------------------------------------------------------- /docs/source/images/submit_render_bp_3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:596ca50878203283d8cb80bfaf542a4991fadfda5e2e285c621789e6d2e33983 3 | size 48118 4 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to deadline-cloud-for-unreal-engine's documentation! 2 | ============================================================ 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | docs_api/api 9 | docs_usage/usage 10 | -------------------------------------------------------------------------------- /docs/source/resources/logs_policy_example.sh: -------------------------------------------------------------------------------- 1 | aws logs put-account-policy 2 | --policy-name "MaskOpenJDEnvSecrets" 3 | --policy-type DATA_PROTECTION_POLICY 4 | --scope ALL 5 | --policy-document '{ 6 | "Name": "openjd_data_protection", 7 | "Description": "Hides openjd_env log line data which may be setting sensitive info", 8 | "Version": "2021-06-01", 9 | "Configuration": { 10 | "CustomDataIdentifier": [ 11 | {"Name": "OpenjdEnv", "Regex": "openjd_env:\s*[^=]+=.*"} 12 | ] 13 | }, 14 | "Statement": [ 15 | { 16 | "Sid": "audit-policy", 17 | "DataIdentifier": [ 18 | "OpenjdEnv" 19 | ], 20 | "Operation": { 21 | "Audit": { 22 | "NoFindingsDestination": {} 23 | } 24 | } 25 | }, 26 | { 27 | "Sid": "redact-policy", 28 | "DataIdentifier": [ 29 | "OpenjdEnv" 30 | ], 31 | "Operation": { 32 | "Deidentify": { 33 | "MaskConfig": {} 34 | } 35 | } 36 | } 37 | ] 38 | }' -------------------------------------------------------------------------------- /hatch.toml: -------------------------------------------------------------------------------- 1 | [envs.default] 2 | pre-install-commands = [ 3 | "pip install -r requirements-testing.txt" 4 | ] 5 | 6 | [envs.default.scripts] 7 | sync = "pip install -r requirements-testing.txt" 8 | test = "pytest test/ --cov-config pyproject.toml --ignore=test/end_to_end {args}" 9 | e2e = "pytest test/end_to_end --no-cov {args}" 10 | typing = "mypy {args:src test}" 11 | style = [ 12 | "ruff check {args:.}", 13 | "black --check --diff {args:.}", 14 | ] 15 | fmt = [ 16 | "black {args:.}", 17 | "style", 18 | ] 19 | lint = [ 20 | "style", 21 | "typing", 22 | ] 23 | 24 | [[envs.all.matrix]] 25 | python = ["3.8", "3.9", "3.10", "3.11"] 26 | 27 | [envs.default.env-vars] 28 | SKIP_BOOTSTRAP_TEST_RESOURCES="True" 29 | 30 | [envs.codebuild.scripts] 31 | build = "hatch build" 32 | 33 | [envs.codebuild.env-vars] 34 | SKIP_BOOTSTRAP_TEST_RESOURCES="True" 35 | 36 | [envs.release] 37 | detached = true 38 | 39 | [envs.release.scripts] 40 | deps = "pip install -r requirements-release.txt" 41 | bump = "semantic-release -v --strict version --no-push --no-commit --no-tag --skip-build {args}" 42 | version = "semantic-release -v --strict version --print {args}" -------------------------------------------------------------------------------- /hatch_custom_hook.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import shutil 4 | 5 | from hatchling.builders.hooks.plugin.interface import BuildHookInterface 6 | from typing import Any 7 | 8 | 9 | class HatchCustomBuildHook(BuildHookInterface): 10 | """ 11 | This class implements Hatch's [custom build hook] (https://hatch.pypa.io/1.6/plugins/build-hook/custom/) 12 | for a copy_version_py operation that copies the _version.py file generated by the hatch-vcs build hook into 13 | specified destination directories. See the `[[tool.hatch.build.hooks.custom]]` section in `pyproject.toml`. 14 | """ 15 | 16 | def _validate_config(self): 17 | if sorted(self.config) != ["copy_version_py", "path"] or list( 18 | self.config["copy_version_py"] 19 | ) != ["destinations"]: 20 | raise RuntimeError( 21 | "Configuration of the custom build hook must be like { 'copy_version_py': {'destinations': ['path1', ...]}}." 22 | + f" Received:\n{self.config}" 23 | ) 24 | 25 | def initialize(self, version: str, build_data: dict[str, Any]) -> None: 26 | self._validate_config() 27 | 28 | for destination in self.config["copy_version_py"]["destinations"]: 29 | print(f"Copying _version.py to {destination}") 30 | shutil.copy( 31 | os.path.join(self.root, "_version.py"), 32 | os.path.join(self.root, destination), 33 | ) 34 | 35 | def clean(self, versions: list[str]) -> None: 36 | self._validate_config() 37 | 38 | cleaned_count = 0 39 | for destination in self.config["copy_version_py"]["destinations"]: 40 | print(f"Cleaning _version.py from {destination}") 41 | clean_path = os.path.join(self.root, destination, "_version.py") 42 | try: 43 | os.remove(clean_path) 44 | cleaned_count += 1 45 | except FileNotFoundError: 46 | pass 47 | print(f"Cleaned {cleaned_count} items") 48 | -------------------------------------------------------------------------------- /pipeline/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @aws-deadline/Admin -------------------------------------------------------------------------------- /pipeline/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Set the -e option 3 | set -e 4 | 5 | pip install --upgrade pip 6 | pip install --upgrade hatch 7 | pip install --upgrade twine 8 | hatch -v run codebuild:lint 9 | hatch run codebuild:test 10 | hatch -v run codebuild:build -------------------------------------------------------------------------------- /pipeline/integ.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Set the -e option 3 | set -e 4 | 5 | pip install --upgrade pip 6 | pip install --upgrade hatch 7 | hatch run integ:test -------------------------------------------------------------------------------- /pipeline/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Set the -e option 3 | set -e 4 | 5 | ./pipeline/build.sh 6 | twine upload --repository codeartifact dist/* --verbose -------------------------------------------------------------------------------- /requirements-docs.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-rtd-theme -------------------------------------------------------------------------------- /requirements-release.txt: -------------------------------------------------------------------------------- 1 | python-semantic-release == 9.21.* -------------------------------------------------------------------------------- /requirements-testing.txt: -------------------------------------------------------------------------------- 1 | coverage[toml] == 7.* 2 | pytest == 8.* 3 | pytest-cov == 6.* 4 | pytest-xdist == 3.* 5 | twine == 6.* 6 | mypy == 1.* 7 | black == 25.* 8 | ruff == 0.11.* 9 | types-pyyaml == 6.* 10 | psutil >= 5.9.0 11 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /scripts/add_copyright_headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | 4 | set -euxo pipefail 5 | 6 | if [ $# -eq 0 ]; then 7 | echo "Usage: add-copyright-headers ..." >&2 8 | exit 1 9 | fi 10 | 11 | for file in "$@"; do 12 | if ! head -1 | grep 'Copyright ' "$file" >/dev/null; then 13 | case "$file" in 14 | *.java) 15 | CONTENT=$(cat "$file") 16 | cat > "$file" </dev/null; then 25 | CONTENT=$(tail -n +2 "$file") 26 | cat > "$file" < 29 | $CONTENT 30 | EOF 31 | else 32 | CONTENT=$(cat "$file") 33 | cat > "$file" < 35 | $CONTENT 36 | EOF 37 | fi 38 | ;; 39 | *.py) 40 | CONTENT=$(cat "$file") 41 | cat > "$file" < "$file" < "$file" < "$file" <&2 73 | exit 1 74 | ;; 75 | esac 76 | fi 77 | done -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | from .__main__ import main 4 | from .adaptor import UnrealAdaptor 5 | 6 | 7 | __all__ = ["UnrealAdaptor", "main"] 8 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/__main__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import os 4 | import sys 5 | import logging 6 | 7 | from openjd.adaptor_runtime import EntryPoint 8 | 9 | from .adaptor import UnrealAdaptor 10 | 11 | __all__ = ["main"] 12 | _logger = logging.getLogger(__name__) 13 | 14 | 15 | def main(reentry_exe=None) -> int: 16 | _logger.info("About to start the UnrealAdaptor") 17 | 18 | package_name = vars(sys.modules[__name__])["__package__"] 19 | if not package_name: 20 | raise RuntimeError(f"Must be run as a module. Do not run {__file__} directly") 21 | 22 | timeout_in_seconds = float(os.getenv("ADAPTOR_DAEMON_TIMEOUT_IN_SECONDS", 3600.0)) 23 | try: 24 | EntryPoint(UnrealAdaptor).start( 25 | reentry_exe=reentry_exe, timeout_in_seconds=timeout_in_seconds # type: ignore 26 | ) 27 | except Exception as e: 28 | _logger.error(f"Entrypoint failed: {e}") 29 | return 1 30 | 31 | _logger.info("Done UnrealAdaptor main") 32 | return 0 33 | 34 | 35 | if __name__ == "__main__": 36 | sys.exit(main()) 37 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/common.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import os 4 | 5 | from openjd.adaptor_runtime.adaptors import AdaptorDataValidators 6 | 7 | 8 | def add_module_to_pythonpath(module_path: str): 9 | """ 10 | Extend or create env variable PYTHONPATH and add there the given path 11 | """ 12 | 13 | # can be passed the __init__.py file or the parent directory 14 | module_directory = os.path.dirname(module_path) if os.path.isfile(module_path) else module_path 15 | 16 | if "PYTHONPATH" in os.environ: 17 | os.environ["PYTHONPATH"] = f'{os.environ["PYTHONPATH"]}{os.pathsep}{module_directory}' 18 | else: 19 | os.environ["PYTHONPATH"] = module_directory 20 | 21 | 22 | class DataValidation: 23 | """ 24 | Common class for validating init and run data 25 | """ 26 | 27 | def __init__(self): 28 | cur_dir = os.path.dirname(__file__) 29 | schema_dir = os.path.join(cur_dir, "schemas") 30 | self.validators = AdaptorDataValidators.for_adaptor(schema_dir) 31 | 32 | def validate_init_data(self, init_data: dict): 33 | """ 34 | Validate the given init data 35 | 36 | :param init_data: Initial adaptor data 37 | :type init_data: dict 38 | 39 | :raises jsonschema.exceptions.ValidationError: if the instance is invalid 40 | :raises jsonschema.exceptions.SchemaError: if the schema itself is invalid 41 | """ 42 | self.validators.init_data.validate(init_data) 43 | 44 | def validate_run_data(self, run_data: dict): 45 | """ 46 | Validate the given run data 47 | 48 | :param run_data: Run adaptor data 49 | :type run_data: dict 50 | 51 | :raises jsonschema.exceptions.ValidationError: if the instance is invalid 52 | :raises jsonschema.exceptions.SchemaError: if the schema itself is invalid 53 | """ 54 | 55 | self.validators.run_data.validate(run_data) 56 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/py.typed: -------------------------------------------------------------------------------- 1 | # Marker file that indicates this package supports typing 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/schemas/init_data.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "type": "object", 4 | "properties": { 5 | "project_path": { "type": "string" }, 6 | "extra_cmd_args": { "type": [ "string", "null" ] }, 7 | "extra_cmd_args_file": { "type": "string" }, 8 | "executable": {"type": "string"}, 9 | "job_dependencies_descriptor": {"type": "string"} 10 | }, 11 | "required": [ 12 | "project_path" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealAdaptor/schemas/run_data.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "type": "object", 4 | "properties": { 5 | "handler": { "type": "string" }, 6 | "level_path": { "type": "string" }, 7 | "level_sequence_path": { "type": "string" }, 8 | "job_configuration_path": { "type": "string" }, 9 | "queue_manifest_path": { "type": "string" }, 10 | "queue_path": { "type": "string" }, 11 | "script_path": { "type": "string" }, 12 | "script_args": { "type": "string" }, 13 | "chunk_size": { "type": "integer" }, 14 | "chunk_id": { "type": "integer" }, 15 | "output_path": { "type": "string" } 16 | }, 17 | "required": [ 18 | "handler" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealClient/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealClient/py.typed: -------------------------------------------------------------------------------- 1 | # Marker file that indicates this package supports typing 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealClient/step_handlers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | from typing import Type, Union 4 | 5 | from .base_step_handler import BaseStepHandler 6 | from .unreal_render_step_handler import UnrealRenderStepHandler 7 | from .unreal_custom_step_handler import UnrealCustomStepHandler 8 | 9 | __all__ = ["BaseStepHandler", "get_step_handler_class"] 10 | 11 | 12 | def get_step_handler_class( 13 | handler: str = "base", 14 | ) -> Type[Union[BaseStepHandler, UnrealCustomStepHandler, UnrealRenderStepHandler]]: 15 | """ 16 | Returns the step handler instance for the given handler name. 17 | 18 | Args: 19 | handler (str, optional): The handler name to get the handler instance of. 20 | Defaults to "BaseStepHandler". 21 | 22 | Returns the BaseStepHandler instance for the given handler name. 23 | """ 24 | 25 | handlers_map = dict( 26 | base=BaseStepHandler, render=UnrealRenderStepHandler, custom=UnrealCustomStepHandler 27 | ) 28 | 29 | print( 30 | f'Trying to get step handler class, defined as "{handler}" in the handlers map: {handlers_map}' 31 | ) 32 | handler_class = handlers_map.get(handler, BaseStepHandler) 33 | print(f"Got step handler class: {handler_class}") 34 | 35 | return handler_class 36 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/UnrealClient/step_handlers/base_step_handler.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import re 4 | from typing import Optional 5 | from abc import abstractmethod, ABC 6 | 7 | 8 | class BaseStepHandler(ABC): 9 | def __init__(self): 10 | self.action_dict = dict(run_script=self.run_script, wait_result=self.wait_result) 11 | 12 | @abstractmethod 13 | def run_script(self, args: dict) -> bool: 14 | """ 15 | :param args: A dictionary that contains the arguments for running the script. 16 | :return: boolean indicating the script run successfully or not. 17 | 18 | This method is an abstract method that needs to be implemented by the extending class. 19 | It is responsible for executing a script using the provided arguments. 20 | """ 21 | raise NotImplementedError("Abstract method, need to be implemented") # pragma: no cover 22 | 23 | @abstractmethod 24 | def wait_result(self, args: Optional[dict] = None) -> None: 25 | """ 26 | :param args: A dictionary that contains the arguments for waiting. 27 | :return: None 28 | 29 | This method is an abstract method that needs to be implemented by the extending class. 30 | It is responsible for waiting result of the 31 | :meth:`deadline.unreal_adaptor.UnrealClient.step_handlers.base_step_handler.BaseStepHandler.run_script()`. 32 | """ 33 | raise NotImplementedError("Abstract method, need to be implemented") # pragma: no cover 34 | 35 | @staticmethod 36 | @abstractmethod 37 | def regex_pattern_progress() -> list[re.Pattern]: 38 | """Returns a list of regex Patterns that match the progress messages""" 39 | raise NotImplementedError("Abstract method, need to be implemented") # pragma: no cover 40 | 41 | @staticmethod 42 | @abstractmethod 43 | def regex_pattern_complete() -> list[re.Pattern]: 44 | """Returns a list of regex Patterns that match the complete messages""" 45 | raise NotImplementedError("Abstract method, need to be implemented") # pragma: no cover 46 | 47 | @staticmethod 48 | @abstractmethod 49 | def regex_pattern_error() -> list[re.Pattern]: 50 | """Returns a list of regex Patterns that match the errors messages""" 51 | raise NotImplementedError("Abstract method, need to be implemented") # pragma: no cover 52 | -------------------------------------------------------------------------------- /src/deadline/unreal_adaptor/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_logger/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | from deadline.unreal_logger.logger import get_logger 4 | 5 | __all__ = ["get_logger"] 6 | -------------------------------------------------------------------------------- /src/deadline/unreal_logger/handlers.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import logging 4 | 5 | 6 | class UnrealLogHandler(logging.Handler): 7 | """ 8 | Logging handler which writes records using unreal.log methods 9 | """ 10 | 11 | def __init__(self, unreal_module): 12 | super().__init__() 13 | self._unreal_mod = unreal_module 14 | 15 | def emit(self, record): 16 | """ 17 | Log the specified logging record. 18 | Calls the unreal log method corresponding to the record level name: 19 | - WARNING - unreal.log_warning 20 | - ERROR, CRITICAL - unreal.log_error 21 | - DEBUG, INFO and other custom levels - unreal.log 22 | """ 23 | 24 | if self._unreal_mod is None: 25 | return 26 | 27 | msg = self.format(record) 28 | 29 | if record.levelname == "WARNING": 30 | self._unreal_mod.log_warning(msg) 31 | elif record.levelname in ["ERROR", "CRITICAL"]: 32 | self._unreal_mod.log_error(msg) 33 | else: 34 | self._unreal_mod.log(msg) # DEBUG, INFO and other custom levels 35 | -------------------------------------------------------------------------------- /src/deadline/unreal_logger/logger.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import logging 4 | 5 | from deadline.unreal_logger.handlers import UnrealLogHandler 6 | 7 | try: 8 | import unreal # noqa: F401 9 | 10 | UNREAL_INITIALIZED = True 11 | except ModuleNotFoundError: 12 | unreal = None 13 | UNREAL_INITIALIZED = False 14 | 15 | 16 | UNREAL_HANDLER_ADDED = False 17 | 18 | 19 | def add_unreal_handler(logger: logging.Logger) -> None: 20 | """ 21 | Attach :class:`deadline.unreal_logger.handlers.UnrealLogHandler` to given logger 22 | 23 | :param logger: Logger instance 24 | :type logger: logging.Logger 25 | """ 26 | 27 | unreal_log_handler = UnrealLogHandler(unreal) 28 | unreal_log_handler.setLevel(logging.DEBUG) 29 | logger.addHandler(unreal_log_handler) 30 | 31 | 32 | def get_logger() -> logging.Logger: 33 | """ 34 | Returns an instance of logging.Handler. 35 | Attach handler :class:`deadline.unreal_logger.handlers.UnrealLogHandler` if unreal module is 36 | available for the first time 37 | """ 38 | 39 | unreal_logger = logging.getLogger("unreal_logger") 40 | unreal_logger.setLevel(logging.DEBUG) 41 | 42 | global UNREAL_HANDLER_ADDED 43 | 44 | # can be called outside UE so need to check before adding UE specific handler 45 | if not UNREAL_HANDLER_ADDED and UNREAL_INITIALIZED: 46 | add_unreal_handler(unreal_logger) 47 | UNREAL_HANDLER_ADDED = True 48 | 49 | return unreal_logger 50 | -------------------------------------------------------------------------------- /src/deadline/unreal_perforce_utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_perforce_utils/cli.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import argparse 4 | 5 | from deadline.unreal_perforce_utils import app 6 | 7 | 8 | def parse_args(): 9 | argparser = argparse.ArgumentParser("unreal-perforce-utils") 10 | argparser.add_argument( 11 | "command", choices=["create_workspace", "delete_workspace", "apply_perforce_secrets"] 12 | ) 13 | argparser.add_argument("-UnrealProjectName", required=False, help="Unreal Project Name") 14 | argparser.add_argument( 15 | "-UnrealProjectRelativePath", required=False, help="Relative path to the workspace root" 16 | ) 17 | argparser.add_argument( 18 | "-OverriddenWorkspaceRoot", required=False, help="New workspace root to create (Optional)" 19 | ), 20 | argparser.add_argument( 21 | "-PerforceWorkspaceSpecificationTemplate", required=False, help="P4 spec JSON file path" 22 | ) 23 | argparser.add_argument( 24 | "-PerforceChangelistNumber", type=str, required=False, help="Changelist number to sync to" 25 | ), 26 | argparser.add_argument( 27 | "-PerforceWorkspaceName", type=int, required=False, help="Changelist number to sync to" 28 | ), 29 | 30 | return argparser.parse_args() 31 | 32 | 33 | def main(): 34 | 35 | args = parse_args() 36 | 37 | if args.command == "create_workspace": 38 | app.create_workspace( 39 | perforce_specification_template_path=args.PerforceWorkspaceSpecificationTemplate, 40 | unreal_project_relative_path=args.UnrealProjectRelativePath, 41 | unreal_project_name=args.UnrealProjectName, 42 | overridden_workspace_root=args.OverriddenWorkspaceRoot, 43 | changelist=args.PerforceChangelistNumber, 44 | ) 45 | 46 | if args.command == "delete_workspace": 47 | app.delete_workspace( 48 | workspace_name=args.PerforceWorkspaceName, project_name=args.UnrealProjectName 49 | ) 50 | 51 | if args.command == "apply_perforce_secrets": 52 | app.apply_perforce_secrets() 53 | 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /src/deadline/unreal_perforce_utils/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | class UnrealSourceControlNotAvailableError(Exception): 5 | """Raised whenn Unreal Source Control Provider is not available""" 6 | 7 | pass 8 | 9 | 10 | class PerforceWorkspaceNotFoundError(Exception): 11 | """Raised when a workspace with the given parameters was not found""" 12 | 13 | 14 | class PerforceConnectionError(Exception): 15 | """Raised when failed to connect to the Perforce with given credentials""" 16 | 17 | pass 18 | 19 | 20 | class SecretsManagerError(Exception): 21 | """Raised when failed to get secret from Boto3 SecretsManager""" 22 | 23 | pass 24 | -------------------------------------------------------------------------------- /src/deadline/unreal_submitter/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/deadline/unreal_submitter/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | class DeadlineCloudSubmitterException(Exception): 5 | """Base exception for all deadline-cloud-for-unreal-engine custom exceptions""" 6 | 7 | pass 8 | 9 | 10 | class ParametersAreNotConsistentError(DeadlineCloudSubmitterException): 11 | """Raised when OpenJD parameters/variables are not consistent""" 12 | 13 | pass 14 | 15 | 16 | class RenderStepCountConstraintError(DeadlineCloudSubmitterException): 17 | """Raised when the number of Render Steps in a Render Job is different from 1.""" 18 | 19 | pass 20 | 21 | 22 | class MrqJobIsMissingError(DeadlineCloudSubmitterException): 23 | """Raised when the Render Job or Render step missed the required MRQ job""" 24 | 25 | pass 26 | 27 | 28 | class RenderArgumentsTypeNotSetError(DeadlineCloudSubmitterException): 29 | """Raised when the render arguments type is not set""" 30 | 31 | pass 32 | 33 | 34 | class PathContainsNonValidCharacters(DeadlineCloudSubmitterException): 35 | """Raised when the path contains not allowed characters""" 36 | 37 | pass 38 | 39 | 40 | class FailedToDetectFilesTransferStrategy(DeadlineCloudSubmitterException): 41 | """Raised when its failed to detect which strategy to use for transfer files to render""" 42 | 43 | 44 | class ProjectIsNotUnderWorkspaceError(Exception): 45 | """Raised when current Unreal Project is not under the current Workspace""" 46 | -------------------------------------------------------------------------------- /src/deadline/unreal_submitter/settings.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import os 4 | 5 | 6 | JOB_TEMPLATE_VERSION = os.getenv("OPEN_JOB_TEMPLATE_VERSION", "jobtemplate-2023-09") 7 | ENVIRONMENT_VERSION = os.getenv("OPEN_JOB_ENVIRONMENT_TEMPLATE_VERSION", "environment-2023-09") 8 | 9 | OPENJD_TEMPLATES_DIRECTORY = os.getenv("OPENJD_TEMPLATES_DIRECTORY", "") 10 | 11 | RENDER_JOB_TEMPLATE_DEFAULT_PATH = "render_job.yml" 12 | RENDER_STEP_TEMPLATE_DEFAULT_PATH = "render_step.yml" 13 | LAUNCH_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "launch_ue_environment.yml" 14 | 15 | UGS_RENDER_JOB_TEMPLATE_DEFAULT_PATH = "ugs/ugs_render_job.yml" 16 | UGS_RENDER_STEP_TEMPLATE_DEFAULT_PATH = "ugs/ugs_render_step.yml" 17 | UGS_LAUNCH_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "ugs/ugs_launch_ue_environment.yml" 18 | UGS_SYNC_CMF_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "ugs/ugs_sync_cmf_environment.yml" 19 | UGS_SYNC_SMF_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "ugs/ugs_sync_smf_environment.yml" 20 | 21 | P4_RENDER_JOB_TEMPLATE_DEFAULT_PATH = "p4/p4_render_job.yml" 22 | P4_RENDER_STEP_TEMPLATE_DEFAULT_PATH = "p4/p4_render_step.yml" 23 | P4_LAUNCH_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "p4/p4_launch_ue_environment.yml" 24 | P4_SYNC_CMF_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "p4/p4_sync_cmf_environment.yml" 25 | P4_SYNC_SMF_ENVIRONMENT_TEMPLATE_DEFAULT_PATH = "p4/p4_sync_smf_environment.yml" 26 | -------------------------------------------------------------------------------- /src/deadline/unreal_submitter/unreal_open_job/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/unreal_plugin/Config/DefaultUnrealDeadlineCloudService.ini: -------------------------------------------------------------------------------- 1 | [CoreRedirects] 2 | +FunctionRedirects=(OldName="/Script/UnrealDeadlineCloudService.DeadlineCloudDeveloperSettings.get_aws_profiles",NewName="/Script/UnrealDeadlineCloudService.DeadlineCloudDeveloperSettings.Get_Aws_Profiles") 3 | +ClassRedirects=(OldName="/Script/UnrealDeadlineCloudService.DeadlineCloudSettings",NewName="/Script/UnrealDeadlineCloudService.DeadlineCloudSettingsLibrary") 4 | +StructRedirects=(OldName="/Script/UnrealDeadlineCloudService.DeadlineCloudAutoDetectedFileAttachmentsStruct",NewName="/Script/UnrealDeadlineCloudService.DeadlineCloudFileAttachmentsArray") -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Perforce/OpenJD_P4_Environment_LaunchEditor.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c9ee5cc0ae873a294c01d864025ebb50dff5589285597a766f31586047e28111 3 | size 2202 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Perforce/OpenJD_P4_Environment_SyncCmf.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2d33f28bb0dc75a435b5996a84824957c5cf8c2e816480eec270fa849740ec1a 3 | size 2235 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Perforce/OpenJD_P4_Job_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:daf757091f2a630941a91b22bc3d0ca4de23435f3d51a8138db78a2de550cc2f 3 | size 4685 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Perforce/OpenJD_P4_Step_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:47fd017264ecde8cc7572cdb7203d25c81e413e8860ccfa7b36f8868647bd88f 3 | size 3311 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Render/OpenJD_Environment_ApplyP4Secrets.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca0a903f2f27969d42465b6af0896de593a3451cb43d0b0d3f23d33e57e8dc02 3 | size 2183 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Render/OpenJD_Environment_LaunchEditor.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3796e453019ae2b9a84d767b7e01c2e4293b4873ef649e2e013e3dedf1b691f6 3 | size 2171 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Render/OpenJD_Job_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d604bba8f8b8e1052360c0fa8d3413edbf820f6f61609791e398c8bfc669a178 3 | size 3566 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/Render/OpenJD_Step_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4af4d7acc3e749f295b1cd5f216cdc20958f853ae7c7f99bbcb4b895007d60e3 3 | size 3101 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/UGS/OpenJD_UGS_Environment_LaunchEditor.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1d64dae126f57411f6a64a3789eea9d0dd03e435b3d9651985f0b93771ae8c88 3 | size 2200 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/UGS/OpenJD_UGS_Environment_SyncCmf.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3554cd0d0a96e454f4188539508a366c30d1d499eec0e7945776588053efad99 3 | size 2187 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/UGS/OpenJD_UGS_Job_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c65906aa1c16121aeaffacc0edd212fc50e55a48715072b05fef92120793b4ae 3 | size 4616 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/UGS/OpenJD_UGS_Job_Render_P4Secrets.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f039b385deda8b3fcfb1748afc142ac581f523b37ed2dcbdf80ab7cc8d4655a6 3 | size 4887 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/OpenJD_DataAssets/UGS/OpenJD_UGS_Step_Render.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d928c2b99c942e193f8448b634ee7d4d81eb97771465a6cca22cd58caf9bc384 3 | size 3308 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/job_library.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import os 4 | import unreal 5 | 6 | from deadline.unreal_submitter import common 7 | from deadline.unreal_logger import get_logger 8 | from deadline.unreal_submitter.unreal_dependency_collector import ( 9 | DependencyCollector, 10 | DependencyFilters, 11 | ) 12 | 13 | 14 | logger = get_logger() 15 | 16 | 17 | @unreal.uclass() 18 | class DeadlineCloudJobBundleLibraryImplementation(unreal.DeadlineCloudJobBundleLibrary): 19 | @unreal.ufunction(override=True) 20 | def get_job_dependencies(self, mrq_job): 21 | level_sequence_path = common.soft_obj_path_to_str(mrq_job.sequence) 22 | level_path = common.soft_obj_path_to_str(mrq_job.map) 23 | 24 | level_sequence_path, _ = os.path.splitext(level_sequence_path) 25 | level_path, _ = os.path.splitext(level_path) 26 | 27 | dependency_collector = DependencyCollector() 28 | logger.info("Level sequence: " + level_sequence_path) 29 | logger.info("Level: " + level_path) 30 | 31 | unreal_dependencies = dependency_collector.collect( 32 | asset_path=level_sequence_path, 33 | filter_method=DependencyFilters.dependency_in_game_folder, 34 | ) 35 | 36 | unreal_dependencies += dependency_collector.collect( 37 | asset_path=level_path, filter_method=DependencyFilters.dependency_in_game_folder 38 | ) 39 | 40 | unreal_dependencies += [level_sequence_path, level_path] 41 | 42 | logger.info( 43 | f"Converted level path: " 44 | f"{common.os_path_from_unreal_path(level_sequence_path, with_ext=True)}" 45 | ) 46 | 47 | unreal_dependencies = list(set(unreal_dependencies)) 48 | 49 | return [common.os_path_from_unreal_path(d, with_ext=True) for d in unreal_dependencies] 50 | 51 | @unreal.ufunction(override=True) 52 | def get_cpu_architectures(self): 53 | return ["x86_64", "arm64"] 54 | 55 | @unreal.ufunction(override=True) 56 | def get_operating_systems(self): 57 | return ["linux", "macos", "windows"] 58 | 59 | @unreal.ufunction(override=True) 60 | def get_job_initial_state_options(self): 61 | return ["READY", "SUSPENDED"] 62 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/custom/custom_job.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: CustomJob 3 | parameterDefinitions: 4 | - name: ProjectFilePath 5 | type: PATH 6 | objectType: FILE 7 | dataFlow: IN 8 | - name: ExtraCmdArgs 9 | type: STRING 10 | default: '-log' 11 | - name: ExtraCmdArgsFile 12 | type: PATH 13 | objectType: FILE 14 | dataFlow: IN 15 | - name: Executable 16 | type: STRING 17 | default: 'UnrealEditor-Cmd' 18 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/custom/custom_step.yml: -------------------------------------------------------------------------------- 1 | name: CustomScript 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: Handler 5 | type: STRING 6 | range: ['custom'] 7 | - name: ScriptPath 8 | type: PATH 9 | range: [] 10 | script: 11 | embeddedFiles: 12 | - name: runData 13 | filename: run-data.yaml 14 | type: TEXT 15 | data: | 16 | handler: {{Task.Param.Handler}} 17 | script_path: {{Task.Param.ScriptPath}} 18 | actions: 19 | onRun: 20 | command: unreal-engine-openjd 21 | args: 22 | - daemon 23 | - run 24 | - --connection-file 25 | - '{{Session.WorkingDirectory}}/connection.json' 26 | - --run-data 27 | - file://{{ Task.File.runData }} 28 | cancelation: 29 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/launch_ue_environment.yml: -------------------------------------------------------------------------------- 1 | name: LaunchUnrealEditor 2 | variables: 3 | REMOTE_EXECUTION: 'True' 4 | script: 5 | embeddedFiles: 6 | - name: initData 7 | filename: init-data.yaml 8 | type: TEXT 9 | data: | 10 | executable: {{Param.Executable}} 11 | project_path: {{Param.ProjectFilePath}} 12 | extra_cmd_args: {{Param.ExtraCmdArgs}} 13 | extra_cmd_args_file: {{Param.ExtraCmdArgsFile}} 14 | actions: 15 | onEnter: 16 | command: unreal-engine-openjd 17 | args: 18 | - daemon 19 | - start 20 | - --connection-file 21 | - '{{Session.WorkingDirectory}}/connection.json' 22 | - --init-data 23 | - file://{{Env.File.initData}} 24 | cancelation: 25 | mode: NOTIFY_THEN_TERMINATE 26 | onExit: 27 | command: unreal-engine-openjd 28 | args: 29 | - daemon 30 | - stop 31 | - --connection-file 32 | - '{{Session.WorkingDirectory}}/connection.json' 33 | cancelation: 34 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_apply_secrets_environment.yml: -------------------------------------------------------------------------------- 1 | # OpenJD Environment for getting Perforce credentials from AWS SecretManager and applying them for connection. 2 | # When using environment variables to connect to Perforce, they will appear in the logs with 3 | # the prefix "openjd_env". Use with caution because sensitive data, such as the password, port, 4 | # and user, will be reflected in the job execution history." 5 | 6 | name: P4ApplySecrets 7 | variables: 8 | AWS_SECRET_P4INFO: "" 9 | script: 10 | actions: 11 | onEnter: 12 | command: unreal-engine-p4-utils 13 | args: 14 | - apply_perforce_secrets 15 | cancelation: 16 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_launch_ue_environment.yml: -------------------------------------------------------------------------------- 1 | name: LaunchUnrealEditorWithP4 2 | variables: 3 | REMOTE_EXECUTION: 'True' 4 | script: 5 | embeddedFiles: 6 | - name: initData 7 | filename: init-data.yaml 8 | type: TEXT 9 | data: | 10 | project_path: "%P4_CLIENT_DIRECTORY%/{{Param.ProjectRelativePath}}" 11 | extra_cmd_args: {{Param.ExtraCmdArgs}} 12 | extra_cmd_args_file: {{Param.ExtraCmdArgsFile}} 13 | job_dependencies_descriptor: {{Param.MrqJobDependenciesDescriptor}} 14 | actions: 15 | onEnter: 16 | command: unreal-engine-openjd 17 | args: 18 | - daemon 19 | - start 20 | - --connection-file 21 | - '{{Session.WorkingDirectory}}/connection.json' 22 | - --init-data 23 | - file://{{Env.File.initData}} 24 | cancelation: 25 | mode: NOTIFY_THEN_TERMINATE 26 | onExit: 27 | command: unreal-engine-openjd 28 | args: 29 | - daemon 30 | - stop 31 | - --connection-file 32 | - '{{Session.WorkingDirectory}}/connection.json' 33 | cancelation: 34 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_render_job.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: RenderJob 3 | parameterDefinitions: 4 | - name: ProjectRelativePath 5 | type: STRING 6 | - name: ProjectName 7 | type: STRING 8 | - name: PerforceChangelistNumber 9 | type: STRING 10 | - name: PerforceWorkspaceSpecificationTemplate 11 | type: PATH 12 | objectType: FILE 13 | dataFlow: IN 14 | - name: MrqJobDependenciesDescriptor 15 | type: PATH 16 | objectType: FILE 17 | dataFlow: IN 18 | - name: ExtraCmdArgs 19 | type: STRING 20 | default: '-log' 21 | - name: ExtraCmdArgsFile 22 | type: PATH 23 | objectType: FILE 24 | dataFlow: IN 25 | - name: Executable 26 | type: STRING 27 | default: 'UnrealEditor-Cmd' 28 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_render_step.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: ChunkId 5 | type: INT 6 | range: [] 7 | - name: Handler 8 | type: STRING 9 | range: [] 10 | - name: QueueManifestPath 11 | type: PATH 12 | range: [] 13 | - name: ChunkSize 14 | type: INT 15 | range: [1] 16 | - name: OutputPath 17 | type: PATH 18 | range: [] 19 | script: 20 | embeddedFiles: 21 | - name: runData 22 | filename: run-data.yaml 23 | type: TEXT 24 | data: | 25 | handler: {{Task.Param.Handler}} 26 | queue_manifest_path: {{Task.Param.QueueManifestPath}} 27 | chunk_size: {{Task.Param.ChunkSize}} 28 | chunk_id: {{Task.Param.ChunkId}} 29 | output_path: {{Task.Param.OutputPath}} 30 | actions: 31 | onRun: 32 | command: unreal-engine-openjd 33 | args: 34 | - daemon 35 | - run 36 | - --connection-file 37 | - '{{Session.WorkingDirectory}}/connection.json' 38 | - --run-data 39 | - file://{{Task.File.runData}} 40 | cancelation: 41 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_sync_cmf_environment.yml: -------------------------------------------------------------------------------- 1 | name: P4SyncCmf 2 | variables: 3 | P4_CLIENTS_ROOT_DIRECTORY: 'D:\projects' 4 | AWS_SECRET_P4INFO: '' 5 | script: 6 | actions: 7 | onEnter: 8 | command: unreal-engine-p4-utils 9 | args: 10 | - create_workspace 11 | - -UnrealProjectRelativePath 12 | - '{{Param.ProjectRelativePath}}' 13 | - -UnrealProjectName 14 | - '{{Param.ProjectName}}' 15 | - -PerforceWorkspaceSpecificationTemplate 16 | - '{{Param.PerforceWorkspaceSpecificationTemplate}}' 17 | - -PerforceChangelistNumber 18 | - '{{Param.PerforceChangelistNumber}}' 19 | cancelation: 20 | mode: NOTIFY_THEN_TERMINATE 21 | onExit: 22 | command: unreal-engine-p4-utils 23 | args: 24 | - delete_workspace 25 | - -UnrealProjectName 26 | - '{{Param.ProjectName}}' 27 | cancelation: 28 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/p4/p4_sync_smf_environment.yml: -------------------------------------------------------------------------------- 1 | name: P4SyncSmf 2 | variables: 3 | AWS_SECRET_P4INFO: '' 4 | script: 5 | actions: 6 | onEnter: 7 | command: unreal-engine-p4-utils 8 | args: 9 | - create_workspace 10 | - -UnrealProjectRelativePath 11 | - '{{Param.ProjectRelativePath}}' 12 | - -UnrealProjectName 13 | - '{{Param.ProjectName}}' 14 | - -PerforceWorkspaceSpecificationTemplate 15 | - '{{Param.PerforceWorkspaceSpecificationTemplate}}' 16 | - -PerforceChangelistNumber 17 | - '{{Param.PerforceChangelistNumber}}' 18 | cancelation: 19 | mode: NOTIFY_THEN_TERMINATE 20 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/render_job.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: RenderJob 3 | parameterDefinitions: 4 | - name: ProjectFilePath 5 | type: PATH 6 | objectType: FILE 7 | dataFlow: IN 8 | - name: ExtraCmdArgs 9 | type: STRING 10 | default: '-log' 11 | - name: ExtraCmdArgsFile 12 | type: PATH 13 | objectType: FILE 14 | dataFlow: IN 15 | - name: Executable 16 | type: STRING 17 | default: 'UnrealEditor-Cmd' -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/render_step.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: ChunkId 5 | type: INT 6 | range: [] 7 | - name: Handler 8 | type: STRING 9 | range: [] 10 | - name: QueueManifestPath 11 | type: PATH 12 | range: [] 13 | - name: ChunkSize 14 | type: INT 15 | range: [1] 16 | script: 17 | embeddedFiles: 18 | - name: runData 19 | filename: run-data.yaml 20 | type: TEXT 21 | data: | 22 | handler: {{Task.Param.Handler}} 23 | queue_manifest_path: {{Task.Param.QueueManifestPath}} 24 | chunk_size: {{Task.Param.ChunkSize}} 25 | chunk_id: {{Task.Param.ChunkId}} 26 | actions: 27 | onRun: 28 | command: unreal-engine-openjd 29 | args: 30 | - daemon 31 | - run 32 | - --connection-file 33 | - '{{Session.WorkingDirectory}}/connection.json' 34 | - --run-data 35 | - file://{{Task.File.runData}} 36 | cancelation: 37 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/render_step_mpq.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: ChunkId 5 | type: INT 6 | range: [] 7 | - name: Handler 8 | type: STRING 9 | range: [] 10 | - name: MoviePipelineQueuePath 11 | type: PATH 12 | range: [] 13 | - name: ChunkSize 14 | type: INT 15 | range: [1] 16 | script: 17 | embeddedFiles: 18 | - name: runData 19 | filename: run-data.yaml 20 | type: TEXT 21 | data: | 22 | handler: {{Task.Param.Handler}} 23 | queue_path: {{Task.Param.MoviePipelineQueuePath}} 24 | chunk_size: {{Task.Param.ChunkSize}} 25 | chunk_id: {{Task.Param.ChunkId}} 26 | actions: 27 | onRun: 28 | command: unreal-engine-openjd 29 | args: 30 | - daemon 31 | - run 32 | - --connection-file 33 | - '{{Session.WorkingDirectory}}/connection.json' 34 | - --run-data 35 | - file://{{Task.File.runData}} 36 | cancelation: 37 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/ugs/ugs_launch_ue_environment.yml: -------------------------------------------------------------------------------- 1 | name: LaunchUnrealEditorWithUgs 2 | variables: 3 | REMOTE_EXECUTION: 'True' 4 | script: 5 | embeddedFiles: 6 | - name: initData 7 | filename: init-data.yaml 8 | type: TEXT 9 | data: | 10 | executable: "%P4_CLIENT_DIRECTORY%/{{Param.ExecutableRelativePath}}" 11 | project_path: "%P4_CLIENT_DIRECTORY%/{{Param.ProjectRelativePath}}" 12 | extra_cmd_args: {{Param.ExtraCmdArgs}} 13 | extra_cmd_args_file: {{Param.ExtraCmdArgsFile}} 14 | actions: 15 | onEnter: 16 | command: unreal-engine-openjd 17 | args: 18 | - daemon 19 | - start 20 | - --connection-file 21 | - '{{Session.WorkingDirectory}}/connection.json' 22 | - --init-data 23 | - file://{{Env.File.initData}} 24 | cancelation: 25 | mode: NOTIFY_THEN_TERMINATE 26 | onExit: 27 | command: unreal-engine-openjd 28 | args: 29 | - daemon 30 | - stop 31 | - --connection-file 32 | - '{{Session.WorkingDirectory}}/connection.json' 33 | cancelation: 34 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/ugs/ugs_render_job.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: RenderJob 3 | parameterDefinitions: 4 | - name: ProjectRelativePath 5 | type: STRING 6 | - name: ProjectName 7 | type: STRING 8 | - name: PerforceStreamPath 9 | type: STRING 10 | - name: ExecutableRelativePath 11 | type: STRING 12 | - name: PerforceChangelistNumber 13 | type: STRING 14 | - name: ExtraCmdArgs 15 | type: STRING 16 | default: '-log' 17 | - name: ExtraCmdArgsFile 18 | type: PATH 19 | objectType: FILE 20 | dataFlow: IN 21 | - name: Executable 22 | type: STRING 23 | default: 'UnrealEditor-Cmd' 24 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/ugs/ugs_render_step.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: ChunkId 5 | type: INT 6 | range: [] 7 | - name: Handler 8 | type: STRING 9 | range: [] 10 | - name: QueueManifestPath 11 | type: PATH 12 | range: [] 13 | - name: ChunkSize 14 | type: INT 15 | range: [1] 16 | - name: OutputPath 17 | type: PATH 18 | range: [] 19 | script: 20 | embeddedFiles: 21 | - name: runData 22 | filename: run-data.yaml 23 | type: TEXT 24 | data: | 25 | handler: {{Task.Param.Handler}} 26 | queue_manifest_path: {{Task.Param.QueueManifestPath}} 27 | chunk_size: {{Task.Param.ChunkSize}} 28 | chunk_id: {{Task.Param.ChunkId}} 29 | output_path: {{Task.Param.OutputPath}} 30 | actions: 31 | onRun: 32 | command: unreal-engine-openjd 33 | args: 34 | - daemon 35 | - run 36 | - --connection-file 37 | - '{{Session.WorkingDirectory}}/connection.json' 38 | - --run-data 39 | - file://{{Task.File.runData}} 40 | cancelation: 41 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/ugs/ugs_sync_cmf_environment.yml: -------------------------------------------------------------------------------- 1 | name: UgsSyncCmf 2 | variables: 3 | P4_CLIENTS_ROOT_DIRECTORY: 'D:\projects' 4 | script: 5 | embeddedFiles: 6 | - name: UgsSync 7 | filename: UgsSync.bat 8 | type: TEXT 9 | data: | 10 | :: Go to the directory where all workspaces live 11 | set "WorkspaceName=%USERNAME%_%COMPUTERNAME%_{{Param.ProjectName}}" 12 | if defined DEADLINE_WORKER_ID ( 13 | set "WorkspaceName=%WorkspaceName%_%DEADLINE_WORKER_ID%" 14 | ) 15 | set "WorkspaceDir=%P4_CLIENTS_ROOT_DIRECTORY%\%WorkspaceName%" 16 | mkdir %WorkspaceDir% 17 | cd /d %WorkspaceDir% 18 | 19 | :: Get or Create P4 workspace with UGS 20 | :: ugs switch {{Param.PerforceStreamPath}} 21 | ugs init {{Param.PerforceStreamPath}} -client=%WorkspaceName% -project={{Param.ProjectRelativePath}} 22 | 23 | :: Find workspace root folder named as Stream path with "/" replaced by "+" (UGS CLI does it by default) 24 | set "WorkspaceFolderName={{Param.PerforceStreamPath}}" 25 | set "WorkspaceFolderName=%WorkspaceFolderName:/=+%" 26 | 27 | :: Go to this directory 28 | cd /d %WorkspaceFolderName% 29 | 30 | :: Sync to given changelist, no generate proj files, overwrite clobber files, sync binaries 31 | ugs sync {{Param.PerforceChangelistNumber}} -nogpf -clobber -binaries 32 | echo Sync completed successfully 33 | 34 | :: Store this path to Env variable for future using while launching the Unreal Editor and Project within 35 | echo openjd_env: P4_CLIENT_DIRECTORY=%CD% 36 | 37 | :: Error handling 38 | IF ERRORLEVEL NEQ 0 ( 39 | echo Error detected! Code: %ERRORLEVEL% 40 | exit /b !ERRORCODE! 41 | ) ELSE ( 42 | echo Command succeeded! 43 | ) 44 | - name: RemovePerforceWorkspace 45 | filename: RemovePerforceWorkspace.bat 46 | type: TEXT 47 | data: | 48 | :: Remove env variable 49 | echo openjd_unset_env: P4_CLIENT_DIRECTORY 50 | actions: 51 | onEnter: 52 | command: '{{Env.File.UgsSync}}' 53 | cancelation: 54 | mode: NOTIFY_THEN_TERMINATE 55 | onExit: 56 | command: '{{Env.File.RemovePerforceWorkspace}}' 57 | cancelation: 58 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/openjd_templates/ugs/ugs_sync_smf_environment.yml: -------------------------------------------------------------------------------- 1 | name: UgsSyncSmf 2 | script: 3 | embeddedFiles: 4 | - name: UgsSync 5 | filename: UgsSync.bat 6 | type: TEXT 7 | data: | 8 | :: Get or Create P4 workspace with UGS 9 | :: ugs switch {{Param.PerforceStreamPath}} 10 | set "WorkspaceName=%USERNAME%_%COMPUTERNAME%_{{Param.ProjectName}}" 11 | if defined DEADLINE_WORKER_ID ( 12 | set "WorkspaceName=%WorkspaceName%_%DEADLINE_WORKER_ID%" 13 | ) 14 | ugs init {{Param.PerforceStreamPath}} -client=%WorkspaceName% -project={{Param.ProjectRelativePath}} 15 | 16 | :: Find workspace root folder named as Stream path with "/" replaced by "+" (UGS CLI does it by default) 17 | set "WorkspaceFolderName={{Param.PerforceStreamPath}}" 18 | set "WorkspaceFolderName=%WorkspaceFolderName:/=+%" 19 | 20 | :: Go to this directory 21 | cd /d %WorkspaceFolderName% 22 | 23 | :: Sync to given changelist, no generate proj files, overwrite clobber files, sync binaries 24 | ugs sync {{Param.PerforceChangelistNumber}} -nogpf -clobber -binaries 25 | echo Sync completed successfuly 26 | 27 | :: Store this path to Env variable for future using while launching the Unreal Editor and Project within 28 | echo openjd_env: P4_CLIENT_DIRECTORY=%CD% 29 | :: Store WorkspaceName env variable to use it in RemovePerforceWorkspace 30 | echo openjd_env: WorkspaceName=%WorkspaceName% 31 | 32 | :: Error handling 33 | IF ERRORLEVEL NEQ 0 ( 34 | echo Error detected! Code: %ERRORLEVEL% 35 | exit /b !ERRORCODE! 36 | ) ELSE ( 37 | echo Command succeeded! 38 | ) 39 | - name: RemovePerforceWorkspace 40 | filename: RemovePerforceWorkspace.bat 41 | type: TEXT 42 | data: | 43 | :: Clear workspace files 44 | p4 sync -f %P4_CLIENT_DIRECTORY%/...#0 45 | 46 | :: Delete workspace 47 | p4 client -d -f %WorkspaceName% 48 | 49 | :: Remove env variable 50 | echo openjd_unset_env: P4_CLIENT_DIRECTORY 51 | actions: 52 | onEnter: 53 | command: '{{Env.File.UgsSync}}' 54 | cancelation: 55 | mode: NOTIFY_THEN_TERMINATE 56 | onExit: 57 | command: '{{Env.File.RemovePerforceWorkspace}}' 58 | cancelation: 59 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/submit_actions/custom_job_submission.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import argparse 4 | 5 | # Required imports 6 | from deadline.unreal_submitter import settings 7 | from deadline.unreal_submitter.submitter import ( 8 | UnrealOpenJobSubmitter, 9 | ) 10 | 11 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job import ( 12 | UnrealOpenJob, 13 | ) 14 | 15 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_step import ( 16 | UnrealOpenJobStep, 17 | UnrealOpenJobStepParameterDefinition, 18 | ) 19 | 20 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_environment import ( 21 | LaunchEditorUnrealOpenJobEnvironment, 22 | ) 23 | from deadline.unreal_logger import get_logger 24 | 25 | 26 | logger = get_logger() 27 | 28 | 29 | # Add default location of predefined YAML templates to env to allow OpenJob entities 30 | # load them without declaring full path to templates 31 | if "OPENJD_TEMPLATES_DIRECTORY" not in os.environ: 32 | os.environ["OPENJD_TEMPLATES_DIRECTORY"] = ( 33 | f"{os.path.dirname(os.path.dirname(__file__))}" 34 | f"/src/unreal_plugin/Content/Python/openjd_templates" 35 | ) 36 | 37 | 38 | def main(script_path: str): 39 | # Create default Unreal OpenJob entity to customize it 40 | custom_open_job = UnrealOpenJob( 41 | # Set its custom name, will be taken from template otherwise 42 | name="CustomJobFromPython", 43 | # Since UnrealOpenJob has no default template, we need to pass it 44 | file_path=f"{settings.OPENJD_TEMPLATES_DIRECTORY}/custom/custom_job.yml", 45 | steps=[ 46 | # Set single Custom Step 47 | UnrealOpenJobStep( 48 | # Set its custom name, will be taken from template otherwise 49 | name="CustomStepFromPython", 50 | # Since UnrealOpenJobStep has no default template, we need to pass it 51 | file_path=f"{settings.OPENJD_TEMPLATES_DIRECTORY}/custom/custom_step.yml", 52 | extra_parameters=[ 53 | # Override ScriptPath parameter value 54 | UnrealOpenJobStepParameterDefinition("ScriptPath", "PATH", [script_path]) 55 | ], 56 | ), 57 | ], 58 | # Set single Launch UE Environment 59 | environments=[LaunchEditorUnrealOpenJobEnvironment()], 60 | ) 61 | 62 | # Create Submitter for OpenJobs in silent mode (without UI notifications) 63 | submitter = UnrealOpenJobSubmitter(silent_mode=True) 64 | 65 | # Add Custom Unreal OpenJob to submission queue 66 | submitter.add_job(custom_open_job) 67 | 68 | # Sumit jobs and log their IDs 69 | submitted_job_ids = submitter.submit_jobs() 70 | for job_id in submitted_job_ids: 71 | logger.info(f"Job submitted: {job_id}") 72 | 73 | 74 | if __name__ == "__main__": 75 | logger.info("Executing test script") 76 | 77 | parser = argparse.ArgumentParser(description="Submits test script") 78 | parser.add_argument("--script_path", type=str, help="Python script path") 79 | 80 | arguments = parser.parse_args() 81 | 82 | main(arguments.script_path) 83 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/submit_actions/custom_script.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | # Simple script that just execute computation of unreal Vectors 4 | 5 | 6 | def main(): 7 | import unreal 8 | 9 | unreal.log("Executing Custom Script ...") 10 | 11 | v1 = unreal.Vector() 12 | v1.x = 10 13 | unreal.log(f"Vector 1: {v1.x}, {v1.y}, {v1.z}") 14 | 15 | v2 = unreal.Vector(10, 20, 30) 16 | unreal.log(f"Vector 2: {v2.x}, {v2.y}, {v2.z}") 17 | 18 | v3 = (v1 + v2) * 2 19 | unreal.log(f"Resulted Vector 3: {v3.x}, {v3.y}, {v3.z}") 20 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/submit_actions/p4_render_job_submission.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import unreal 4 | 5 | # Required imports 6 | from deadline.unreal_submitter.submitter import ( 7 | UnrealRenderOpenJobSubmitter, 8 | ) 9 | 10 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job import ( 11 | P4RenderUnrealOpenJob, 12 | ) 13 | 14 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_step import ( 15 | P4RenderUnrealOpenJobStep, 16 | UnrealOpenJobStepParameterDefinition, 17 | ) 18 | 19 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_environment import ( 20 | P4LaunchEditorUnrealOpenJobEnvironment, 21 | P4SyncCmfUnrealOpenJobEnvironment, 22 | ) 23 | from deadline.unreal_logger import get_logger 24 | 25 | 26 | logger = get_logger() 27 | 28 | 29 | # Add default location of predefined YAML templates to env to allow OpenJob entities 30 | # load them without declaring full path to templates 31 | if "OPENJD_TEMPLATES_DIRECTORY" not in os.environ: 32 | os.environ["OPENJD_TEMPLATES_DIRECTORY"] = ( 33 | f"{os.path.dirname(os.path.dirname(__file__))}" 34 | f"/src/unreal_plugin/Content/Python/openjd_templates" 35 | ) 36 | 37 | 38 | def main(): 39 | # Create Submitter for Render OpenJobs in silent mode (without UI notifications) 40 | render_job_submitter = UnrealRenderOpenJobSubmitter(silent_mode=False) 41 | 42 | # Get jobs from Render Queue or you can create your own 43 | queue = unreal.get_editor_subsystem(unreal.MoviePipelineQueueSubsystem).get_queue() 44 | 45 | # From each MRQ job create Render Unreal OpenJob 46 | for job in queue.get_jobs(): 47 | default_render_job = P4RenderUnrealOpenJob( 48 | # Set single Render step 49 | steps=[ 50 | P4RenderUnrealOpenJobStep( 51 | extra_parameters=[ 52 | # Override ChunkSize parameter value 53 | UnrealOpenJobStepParameterDefinition("ChunkSize", "INT", [10]) 54 | ] 55 | ) 56 | ], 57 | # Set environments exactly in that order: 58 | # 1. Environment for syncing UGS workspace before render 59 | # 2. Environment for launch UE 60 | environments=[ 61 | P4SyncCmfUnrealOpenJobEnvironment(), 62 | P4LaunchEditorUnrealOpenJobEnvironment(), 63 | ], 64 | # Set MRQ Job to retrieve render data and OpenJob overrides from 65 | mrq_job=job, 66 | ) 67 | print(default_render_job._extra_parameters) 68 | 69 | # Add Render Unreal OpenJob to submission queue 70 | render_job_submitter.add_job(default_render_job) 71 | 72 | # Sumit jobs and log their IDs 73 | submitted_job_ids = render_job_submitter.submit_jobs() 74 | for job_id in submitted_job_ids: 75 | logger.info(f"Job submitted: {job_id}") 76 | 77 | 78 | if __name__ == "__main__": 79 | main() 80 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/submit_actions/render_job_submission.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import unreal 4 | 5 | # Required imports 6 | from deadline.unreal_submitter.submitter import ( 7 | UnrealRenderOpenJobSubmitter, 8 | ) 9 | 10 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job import ( 11 | RenderUnrealOpenJob, 12 | ) 13 | 14 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_step import ( 15 | RenderUnrealOpenJobStep, 16 | UnrealOpenJobStepParameterDefinition, 17 | ) 18 | 19 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_environment import ( 20 | LaunchEditorUnrealOpenJobEnvironment, 21 | ) 22 | from deadline.unreal_logger import get_logger 23 | 24 | 25 | logger = get_logger() 26 | 27 | 28 | # Add default location of predefined YAML templates to env to allow OpenJob entities 29 | # load them without declaring full path to templates 30 | if "OPENJD_TEMPLATES_DIRECTORY" not in os.environ: 31 | os.environ["OPENJD_TEMPLATES_DIRECTORY"] = ( 32 | f"{os.path.dirname(os.path.dirname(__file__))}" 33 | f"/src/unreal_plugin/Content/Python/openjd_templates" 34 | ) 35 | 36 | 37 | def main(): 38 | # Create Submitter for Render OpenJobs in silent mode (without UI notifications) 39 | render_job_submitter = UnrealRenderOpenJobSubmitter(silent_mode=True) 40 | 41 | # Get jobs from Render Queue or you can create your own 42 | queue = unreal.get_editor_subsystem(unreal.MoviePipelineQueueSubsystem).get_queue() 43 | 44 | # From each MRQ job create Render Unreal OpenJob 45 | for job in queue.get_jobs(): 46 | default_render_job = RenderUnrealOpenJob( 47 | # Set single Render step 48 | steps=[ 49 | RenderUnrealOpenJobStep( 50 | extra_parameters=[ 51 | # Override ChunkSize parameter value 52 | UnrealOpenJobStepParameterDefinition("ChunkSize", "INT", [10]) 53 | ] 54 | ) 55 | ], 56 | # Set single Launch UE Environment 57 | environments=[LaunchEditorUnrealOpenJobEnvironment()], 58 | # Set MRQ Job to retrieve render data and OpenJob overrides from 59 | mrq_job=job, 60 | ) 61 | 62 | # Add Render Unreal OpenJob to submission queue 63 | render_job_submitter.add_job(default_render_job) 64 | 65 | # Sumit jobs and log their IDs 66 | submitted_job_ids = render_job_submitter.submit_jobs() 67 | for job_id in submitted_job_ids: 68 | logger.info(f"Job submitted: {job_id}") 69 | 70 | 71 | if __name__ == "__main__": 72 | main() 73 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Python/submit_actions/ugs_render_job_submission.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import unreal 4 | 5 | # Required imports 6 | from deadline.unreal_submitter.submitter import ( 7 | UnrealRenderOpenJobSubmitter, 8 | ) 9 | 10 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job import ( 11 | UgsRenderUnrealOpenJob, 12 | ) 13 | 14 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_step import ( 15 | UgsRenderUnrealOpenJobStep, 16 | UnrealOpenJobStepParameterDefinition, 17 | ) 18 | 19 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_environment import ( 20 | UgsLaunchEditorUnrealOpenJobEnvironment, 21 | UgsSyncCmfUnrealOpenJobEnvironment, 22 | ) 23 | from deadline.unreal_logger import get_logger 24 | 25 | 26 | logger = get_logger() 27 | 28 | 29 | # Add default location of predefined YAML templates to env to allow OpenJob entities 30 | # load them without declaring full path to templates 31 | if "OPENJD_TEMPLATES_DIRECTORY" not in os.environ: 32 | os.environ["OPENJD_TEMPLATES_DIRECTORY"] = ( 33 | f"{os.path.dirname(os.path.dirname(__file__))}" 34 | f"/src/unreal_plugin/Content/Python/openjd_templates" 35 | ) 36 | 37 | 38 | def main(): 39 | # Create Submitter for Render OpenJobs in silent mode (without UI notifications) 40 | render_job_submitter = UnrealRenderOpenJobSubmitter(silent_mode=True) 41 | 42 | # Get jobs from Render Queue or you can create your own 43 | queue = unreal.get_editor_subsystem(unreal.MoviePipelineQueueSubsystem).get_queue() 44 | 45 | # From each MRQ job create Render Unreal OpenJob 46 | for job in queue.get_jobs(): 47 | default_render_job = UgsRenderUnrealOpenJob( 48 | # Set single Render step 49 | steps=[ 50 | UgsRenderUnrealOpenJobStep( 51 | extra_parameters=[ 52 | # Override ChunkSize parameter value 53 | UnrealOpenJobStepParameterDefinition("ChunkSize", "INT", [10]) 54 | ] 55 | ) 56 | ], 57 | # Set environments exactly in that order: 58 | # 1. Environment for syncing UGS workspace before render 59 | # 2. Environment for launch UE 60 | environments=[ 61 | UgsSyncCmfUnrealOpenJobEnvironment(), 62 | UgsLaunchEditorUnrealOpenJobEnvironment(), 63 | ], 64 | # Set MRQ Job to retrieve render data and OpenJob overrides from 65 | mrq_job=job, 66 | ) 67 | 68 | # Add Render Unreal OpenJob to submission queue 69 | render_job_submitter.add_job(default_render_job) 70 | 71 | # Sumit jobs and log their IDs 72 | submitted_job_ids = render_job_submitter.submit_jobs() 73 | for job_id in submitted_job_ids: 74 | logger.info(f"Job submitted: {job_id}") 75 | 76 | 77 | if __name__ == "__main__": 78 | main() 79 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Widgets/DeadlineJobSubmitter.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ffd4e1d5da338562a93000fe97736bc45abe53ab31b92a5d707f19fd13c7f08d 3 | size 217784 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Content/Widgets/DeadlinePathSelector.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2608b1358b23b8695128789497e3f5948d5041e5647b2d339d67470301f43fe5 3 | size 154646 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # UnrealDeadlineCloudService 2 | 3 | ## Development pipeline 4 | 5 | ### Adding UnrealSubmitter to the UE plugin 6 | Approach: CI/CD build UE plugin with unreal_submitter with .bat file 7 | 1. Remove all files from Content/Python/libraries 8 | 2. cloning deadline-cloud-for-unreal, deadline-cloud 9 | 3. pip install deadline-cloud/ --target=Content/Python/libraries 10 | 4. Copy deadline-cloud-for-unreal/src/deadline/unreal_submitter to Content/Python/libraries folder 11 | 5. Delete cloned repos. 12 | 6. Delete pull_submitter.bat from release plugin package (via CI/CD) 13 | 14 | ### Generating C++ code documentation 15 | C++ documentation is generated with [Doxygen](https://www.doxygen.nl/) 16 | 1. Install Doxygen. Add doxygen exe to system path 17 | 2. cd UnrealDeadlineCloudService/Documentation 18 | 3. Generate documentation by running ```doxygen``` command in command line -------------------------------------------------------------------------------- /src/unreal_plugin/Documentation/doxygen-awesome-sidebar-only.css: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | html { 31 | /* side nav width. MUST be = `TREEVIEW_WIDTH`. 32 | * Make sure it is wide enought to contain the page title (logo + title + version) 33 | */ 34 | --side-nav-fixed-width: 340px; 35 | --menu-display: none; 36 | 37 | --top-height: 120px; 38 | } 39 | 40 | 41 | @media screen and (min-width: 768px) { 42 | html { 43 | --searchbar-background: var(--page-background-color); 44 | } 45 | 46 | #side-nav { 47 | min-width: var(--side-nav-fixed-width); 48 | max-width: var(--side-nav-fixed-width); 49 | top: var(--top-height); 50 | overflow: visible; 51 | } 52 | 53 | #nav-tree, #side-nav { 54 | height: calc(100vh - var(--top-height)) !important; 55 | } 56 | 57 | #nav-tree { 58 | padding: 0; 59 | } 60 | 61 | #top { 62 | display: block; 63 | border-bottom: none; 64 | height: var(--top-height); 65 | margin-bottom: calc(0px - var(--top-height)); 66 | max-width: var(--side-nav-fixed-width); 67 | background: var(--side-nav-background); 68 | } 69 | #main-nav { 70 | float: left; 71 | padding-right: 0; 72 | } 73 | 74 | .ui-resizable-handle { 75 | cursor: default; 76 | width: 1px !important; 77 | box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color); 78 | } 79 | 80 | #nav-path { 81 | position: fixed; 82 | right: 0; 83 | left: var(--side-nav-fixed-width); 84 | bottom: 0; 85 | width: auto; 86 | } 87 | 88 | #doc-content { 89 | height: calc(100vh - 31px) !important; 90 | padding-bottom: calc(3 * var(--spacing-large)); 91 | padding-top: calc(var(--top-height) - 80px); 92 | box-sizing: border-box; 93 | margin-left: var(--side-nav-fixed-width) !important; 94 | } 95 | 96 | #MSearchBox { 97 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium))); 98 | } 99 | 100 | #MSearchField { 101 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px); 102 | } 103 | 104 | #MSearchResultsWindow { 105 | left: var(--spacing-medium) !important; 106 | right: auto; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/unreal_plugin/Documentation/doxygen-awesome.LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 jothepro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/unreal_plugin/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /src/unreal_plugin/README.md: -------------------------------------------------------------------------------- 1 | # UnrealDeadlineCloudService 2 | 3 | - Provides a UI and API for submitting render jobs on the artist machine.\ 4 | - Executes rendering on Worker Node 5 | 6 | 7 | ## Requirements 8 | - Unreal Engine 5.2 9 | 10 | 11 | ## Installation 12 | Should be placed in the "Plugins" folder of the UE project. 13 | 14 | ## Development 15 | See the [DEVELOPMENT](DEVELOPMENT.md) file for development pipelines 16 | 17 | ## Telemetry 18 | 19 | This library collects telemetry data by default. Telemetry events contain non-personally-identifiable information that helps us understand how users interact with our software so we know what features our customers use, and/or what existing pain points are. 20 | 21 | You can opt out of telemetry data collection by either: 22 | 23 | 1. Setting the environment variable: `DEADLINE_CLOUD_TELEMETRY_OPT_OUT=true` 24 | 2. Setting the config file: `deadline config set telemetry.opt_out true` 25 | 26 | Note that setting the environment variable supersedes the config file setting. 27 | 28 | ## License 29 | This project is licensed under the Apache-2.0 License. 30 | -------------------------------------------------------------------------------- /src/unreal_plugin/Resources/Icon128.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f7239efaeefbd82de33ebe18518e50de075ea4188a468a9e4991396433d2275f 3 | size 12699 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/DeadlineCloudJobSettings/DeadlineCloudRenderStep.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #include "DeadlineCloudJobSettings/DeadlineCloudRenderStep.h" 4 | 5 | 6 | UDeadlineCloudRenderStep::UDeadlineCloudRenderStep() 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/DeadlineCloudJobSettings/DeadlineCloudStatusHandler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | #include "DeadlineCloudJobSettings/DeadlineCloudStatusHandler.h" 5 | #include "DeadlineCloudJobSettings/DeadlineCloudDeveloperSettings.h" 6 | #include "DirectoryWatcherModule.h" 7 | #include "IDirectoryWatcher.h" 8 | 9 | FDeadlineCloudStatusHandler::FDeadlineCloudStatusHandler(TWeakObjectPtr InSettings) 10 | : Settings(InSettings) 11 | { 12 | } 13 | 14 | FDeadlineCloudStatusHandler::~FDeadlineCloudStatusHandler() 15 | { 16 | StopDirectoryWatch(); 17 | } 18 | 19 | void FDeadlineCloudStatusHandler::StopDirectoryWatch() 20 | { 21 | FDirectoryWatcherModule& DirectoryWatcherModule = FModuleManager::LoadModuleChecked(NAME_DirectoryWatcher); 22 | if (const auto DirectoryWatcher = DirectoryWatcherModule.Get()) 23 | { 24 | for (auto& WatchedDirectory : WatchedDirectories) 25 | { 26 | if (WatchedDirectory.DirectoryWatcherHandle.IsValid()) 27 | { 28 | DirectoryWatcher->UnregisterDirectoryChangedCallback_Handle( 29 | WatchedDirectory.FolderPath, WatchedDirectory.DirectoryWatcherHandle); 30 | WatchedDirectory.FolderPath.Empty(); 31 | } 32 | } 33 | } 34 | } 35 | 36 | void FDeadlineCloudStatusHandler::StartDirectoryWatch() 37 | { 38 | FDirectoryWatcherModule& DirectoryWatcherModule = 39 | FModuleManager::LoadModuleChecked(NAME_DirectoryWatcher); 40 | if (IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get()) 41 | { 42 | const FString UserDocDir = FPlatformProcess::UserDir(); 43 | FDirectoryPath DirectoryPath; 44 | 45 | FString DocDir; 46 | const FString UserDir = FPaths::GetPath(UserDocDir.TrimChar('/')); 47 | TArray AwsCredPaths = { 48 | UserDir / FString(".aws"), 49 | UserDir / FString(".aws") / FString("sso") / FString("cache"), 50 | // }; 51 | // TArray DeadlineConfigPaths = { 52 | UserDir / FString(".deadline") 53 | }; 54 | 55 | // StopDirectoryWatch(); 56 | for (auto AwsCredPath : AwsCredPaths) 57 | { 58 | FConfigWatchedDirInfo WatchedDirectory; 59 | WatchedDirectory.FolderPath = MoveTemp(AwsCredPath); 60 | { 61 | DirectoryWatcher->RegisterDirectoryChangedCallback_Handle( 62 | WatchedDirectory.FolderPath, 63 | IDirectoryWatcher::FDirectoryChanged::CreateLambda([this](const TArray& FileChanges) 64 | { 65 | Settings->RefreshState(); 66 | }), 67 | WatchedDirectory.DirectoryWatcherHandle, 68 | /*Flags*/ 0 69 | ); 70 | } 71 | WatchedDirectories.Emplace(WatchedDirectory); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/MovieRenderPipeline/DeadlineCloudRenderStepSetting.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | #include "MovieRenderPipeline/DeadlineCloudRenderStepSetting.h" 5 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/MovieRenderPipeline/DeadlineCloudStepBaseSetting.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #include "MovieRenderPipeline/DeadlineCloudStepBaseSetting.h" 4 | #include "MoviePipelineUtils.h" 5 | 6 | #if UE_VERSION_NEWER_THAN(5, 2, -1) 7 | #define MOVIE_PIPELINE_CONFIG_CLASS UMoviePipelinePrimaryConfig 8 | #else 9 | #define MOVIE_PIPELINE_CONFIG_CLASS UMoviePipelineMasterConfig 10 | #endif 11 | 12 | TArray GetStepOptionsImplementation(UObject* Object) 13 | { 14 | TArray DeadlineCloudStepOptions; 15 | if (const auto Config = Cast(Object->GetOuter())) 16 | { 17 | for (const auto Setting : Config->GetAllSettings()) 18 | { 19 | const auto SettingClass = Setting->GetClass(); 20 | if (const auto DeadlineCloudSetting = Cast(SettingClass->ClassDefaultObject)) 21 | { 22 | DeadlineCloudStepOptions.Add(DeadlineCloudSetting->GetDisplayText().ToString()); 23 | } 24 | else if (const auto _ = Cast(SettingClass->ClassDefaultObject)) 25 | { 26 | // Iterate through containers to find struct properties 27 | for (TFieldIterator ItProp(SettingClass, EFieldIterationFlags::IncludeAll); ItProp; ++ItProp) 28 | { 29 | const FArrayProperty* ArrayProperty = CastField(*ItProp); 30 | if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) 31 | { 32 | if (StructProperty->Struct->IsChildOf(FDeadlineCloudCompositeStepParameters::StaticStruct())) 33 | { 34 | FScriptArrayHelper ArrayHelper(ArrayProperty, ArrayProperty->ContainerPtrToValuePtr(Setting)); 35 | for (int32 ValueIdx = 0; ValueIdx < ArrayHelper.Num(); ++ValueIdx) 36 | { 37 | const auto StepParameter = reinterpret_cast(ArrayHelper.GetRawPtr(ValueIdx)); 38 | if (StepParameter && !StepParameter->Name.IsEmpty()) 39 | { 40 | DeadlineCloudStepOptions.Add(StepParameter->Name); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | return DeadlineCloudStepOptions; 50 | } 51 | 52 | TArray UDeadlineCloudStepBaseSetting::GetStepOptions() 53 | { 54 | return GetStepOptionsImplementation(this); 55 | } 56 | 57 | TArray UDeadlineCloudCompositeStepBaseSetting::GetStepOptions() 58 | { 59 | return GetStepOptionsImplementation(this); 60 | } 61 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/MovieRenderPipeline/DeadlineExecutorImplementationLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | #include "MovieRenderPipeline/DeadlineExecutorImplementationLibrary.h" 3 | 4 | #define LOCTEXT_NAMESPACE "DeadlineExecutor" 5 | 6 | TSubclassOf UDeadlineExecutorImplementationLibrary::GetDefaultDeadlineExecutor() 7 | { 8 | UMoviePipelineQueueSubsystem* Subsystem = GEditor->GetEditorSubsystem(); 9 | check(Subsystem); 10 | 11 | const UMovieRenderPipelineProjectSettings* ProjectSettings = GetDefault(); 12 | TSubclassOf ExecutorClass = ProjectSettings->DefaultRemoteExecutor.TryLoadClass(); 13 | return ExecutorClass; 14 | } 15 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/PythonAPILibraries/DeadlineCloudJobBundleLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | #include "PythonAPILibraries/DeadlineCloudJobBundleLibrary.h" 5 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/PythonAPILibraries/DeadlineCloudSettingsLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #include "PythonAPILibraries/DeadlineCloudSettingsLibrary.h" 4 | #include "DeadlineCloudJobSettings/DeadlineCloudDeveloperSettings.h" 5 | 6 | void UDeadlineCloudSettingsLibrary::InitFromPython() 7 | { 8 | if (!bInitialized) 9 | { 10 | bInitialized = true; 11 | UDeadlineCloudDeveloperSettings* Settings = UDeadlineCloudDeveloperSettings::GetMutable(); 12 | if (Settings) 13 | { 14 | Settings->Refresh(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/PythonAPILibraries/PythonAPILibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #include "PythonAPILibraries/PythonAPILibrary.h" 4 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/PythonAPILibraries/PythonGameThreadExecutor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #include "PythonAPILibraries/PythonGameThreadExecutor.h" 4 | 5 | void UPythonGameThreadExecutor::Tick(float DeltaTime) 6 | { 7 | Execute(DeltaTime); 8 | } 9 | 10 | bool UPythonGameThreadExecutor::IsTickable() const 11 | { 12 | return true; 13 | } 14 | 15 | TStatId UPythonGameThreadExecutor::GetStatId() const 16 | { 17 | RETURN_QUICK_DECLARE_CYCLE_STAT(UICToolsGameThreadExecutor, STATGROUP_Tickables); 18 | } 19 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/launch_ue_environment.yml: -------------------------------------------------------------------------------- 1 | name: LaunchUnrealEditor 2 | variables: 3 | REMOTE_EXECUTION: 'True' 4 | script: 5 | embeddedFiles: 6 | - name: initData 7 | filename: init-data.yaml 8 | type: TEXT 9 | data: | 10 | executable: {{Param.Executable}} 11 | project_path: {{Param.ProjectFilePath}} 12 | extra_cmd_args: {{Param.ExtraCmdArgs}} 13 | extra_cmd_args_file: {{Param.ExtraCmdArgsFile}} 14 | actions: 15 | onEnter: 16 | command: unreal-engine-openjd 17 | args: 18 | - daemon 19 | - start 20 | - --connection-file 21 | - '{{Session.WorkingDirectory}}/connection.json' 22 | - --init-data 23 | - file://{{Env.File.initData}} 24 | cancelation: 25 | mode: NOTIFY_THEN_TERMINATE 26 | onExit: 27 | command: unreal-engine-openjd 28 | args: 29 | - daemon 30 | - stop 31 | - --connection-file 32 | - '{{Session.WorkingDirectory}}/connection.json' 33 | cancelation: 34 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/launch_ue_environment_UI.yml: -------------------------------------------------------------------------------- 1 | name: LaunchUnrealEditor 2 | variables: 3 | Variable1: 'True' 4 | Variable2: 'ThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidation' 5 | Variable3: 'Test' 6 | script: 7 | embeddedFiles: 8 | - name: initData 9 | filename: init-data.yaml 10 | type: TEXT 11 | data: | 12 | executable: {{Param.Executable}} 13 | project_path: {{Param.ProjectFilePath}} 14 | extra_cmd_args: {{Param.ExtraCmdArgs}} 15 | extra_cmd_args_file: {{Param.ExtraCmdArgsFile}} 16 | actions: 17 | onEnter: 18 | command: unreal-engine-openjd 19 | args: 20 | - daemon 21 | - start 22 | - --connection-file 23 | - '{{Session.WorkingDirectory}}/connection.json' 24 | - --init-data 25 | - file://{{Env.File.initData}} 26 | cancelation: 27 | mode: NOTIFY_THEN_TERMINATE 28 | onExit: 29 | command: unreal-engine-openjd 30 | args: 31 | - daemon 32 | - stop 33 | - --connection-file 34 | - '{{Session.WorkingDirectory}}/connection.json' 35 | cancelation: 36 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/render_job.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: RenderJob 3 | parameterDefinitions: 4 | - name: ProjectFilePath 5 | type: PATH 6 | objectType: FILE 7 | dataFlow: IN 8 | - name: ExtraCmdArgs 9 | type: STRING 10 | default: '-log' 11 | - name: ExtraCmdArgsFile 12 | type: PATH 13 | objectType: FILE 14 | dataFlow: IN 15 | - name: Executable 16 | type: STRING 17 | default: 'UnrealEditor-Cmd' 18 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/render_job_UI.yml: -------------------------------------------------------------------------------- 1 | specificationVersion: jobtemplate-2023-09 2 | name: RenderJob 3 | parameterDefinitions: 4 | - name: PathParameter 5 | type: PATH 6 | default: 'ThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidation' 7 | objectType: FILE 8 | dataFlow: IN 9 | - name: StringParameter 10 | type: STRING 11 | default: 'ThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidation' 12 | - name: FloatParameter 13 | type: FLOAT 14 | default: '3.5' 15 | - name: IntParameter 16 | type: INT 17 | default: '5' 18 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/render_step.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: Handler 5 | type: STRING 6 | range: [] 7 | - name: QueueManifestPath 8 | type: PATH 9 | range: [] 10 | - name: ChunkSize 11 | type: INT 12 | range: [] 13 | - name: ChunkId 14 | type: INT 15 | range: [] 16 | script: 17 | embeddedFiles: 18 | - name: runData 19 | filename: run-data.yaml 20 | type: TEXT 21 | data: | 22 | handler: {{Task.Param.Handler}} 23 | queue_manifest_path: {{Task.Param.QueueManifestPath}} 24 | chunk_size: {{Task.Param.ChunkSize}} 25 | chunk_id: {{Task.Param.ChunkId}} 26 | actions: 27 | onRun: 28 | command: unreal-engine-openjd 29 | args: 30 | - daemon 31 | - run 32 | - --connection-file 33 | - '{{Session.WorkingDirectory}}/connection.json' 34 | - --run-data 35 | - file://{{Task.File.runData}} 36 | cancelation: 37 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Private/Tests/openjd_templates/render_step_UI.yml: -------------------------------------------------------------------------------- 1 | name: Render 2 | parameterSpace: 3 | taskParameterDefinitions: 4 | - name: StringParameters 5 | type: STRING 6 | range: [ 7 | ThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidation 8 | ] 9 | - name: PathParameters 10 | type: PATH 11 | range: [ 12 | ThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidationThisInputIsWayTooLongForValidation 13 | ] 14 | - name: FloatParameters 15 | type: FLOAT 16 | range: [ 17 | 1.5 18 | ] 19 | - name: IntParameters 20 | type: INT 21 | range: [ 22 | 3 23 | ] 24 | script: 25 | embeddedFiles: 26 | - name: runData 27 | filename: run-data.yaml 28 | type: TEXT 29 | data: | 30 | handler: {{Task.Param.Handler}} 31 | queue_manifest_path: {{Task.Param.QueueManifestPath}} 32 | chunk_size: {{Task.Param.ChunkSize}} 33 | chunk_id: {{Task.Param.ChunkId}} 34 | actions: 35 | onRun: 36 | command: unreal-engine-openjd 37 | args: 38 | - daemon 39 | - run 40 | - --connection-file 41 | - '{{Session.WorkingDirectory}}/connection.json' 42 | - --run-data 43 | - file://{{Task.File.runData}} 44 | cancelation: 45 | mode: NOTIFY_THEN_TERMINATE -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudEnvironment.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "PythonAPILibraries/PythonYamlLibrary.h" 5 | #include "DeadlineCloudEnvironment.generated.h" 6 | 7 | USTRUCT(BlueprintType) 8 | struct UNREALDEADLINECLOUDSERVICE_API FDeadlineCloudEnvironmentVariablesMap 9 | { 10 | GENERATED_BODY() 11 | 12 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Parameters") 13 | TMap Variables; 14 | }; 15 | 16 | USTRUCT(BlueprintType) 17 | struct UNREALDEADLINECLOUDSERVICE_API FDeadlineCloudEnvironmentOverride 18 | { 19 | GENERATED_BODY() 20 | 21 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Parameters") 22 | FString Name; 23 | 24 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Parameters") 25 | FDeadlineCloudEnvironmentVariablesMap Variables; 26 | }; 27 | 28 | UCLASS(BlueprintType, Blueprintable) 29 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudEnvironment : public UDataAsset 30 | { 31 | GENERATED_BODY() 32 | public: 33 | 34 | UDeadlineCloudEnvironment(); 35 | 36 | FSimpleDelegate OnPathChanged; 37 | 38 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Parameters") 39 | FString Name; 40 | 41 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Parameters") 42 | FFilePath PathToTemplate; 43 | 44 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Parameters") 45 | FDeadlineCloudEnvironmentVariablesMap Variables; 46 | 47 | /** Read path */ 48 | UFUNCTION() 49 | void OpenEnvFile(const FString& Path); 50 | 51 | UFUNCTION() 52 | FParametersConsistencyCheckResult CheckEnvironmentVariablesConsistency(const UDeadlineCloudEnvironment* Env); 53 | 54 | UFUNCTION() 55 | void FixEnvironmentVariablesConsistency(UDeadlineCloudEnvironment* Env); 56 | 57 | FDeadlineCloudEnvironmentOverride GetEnvironmentData(); 58 | 59 | bool IsDefaultVariables(); 60 | void ResetVariables(); 61 | 62 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; 63 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudInputValidationHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "CoreMinimal.h" 5 | #include "DeadlineCloudJobSettings/DeadlineCloudDetailsWidgetsHelper.h" 6 | 7 | using FValidatorFunc = TFunction; 8 | 9 | class FDeadlineCloudInputValidationHelper 10 | { 11 | public: 12 | 13 | static FOnVerifyTextChanged GetStringValidationFunction(EValueValidationType ValidationType); 14 | static FOnVerifyTextChanged GetPathValidationFunction(EValueValidationType ValidationType); 15 | 16 | /** Basic length validation */ 17 | static bool IsValidLength(const FString& InStr, int32 Min, int32 Max); 18 | 19 | /** Length validation with error reporting */ 20 | static bool IsValidLength(const FString& InStr, int32 Min, int32 Max, FText& OutError, const FText& FieldName = FText::FromString(TEXT("Value"))); 21 | 22 | /** Disallows Cc (control) characters (C0/C1 Unicode ranges) */ 23 | static bool ContainsNoControlCharacters(const FString& InStr, const TSet& ExcludeList); 24 | 25 | /** Disallows control characters and provides error message */ 26 | static bool ContainsNoControlCharacters(const FString& InStr, FText& OutError, 27 | const TSet& ExcludeList, const FText& FieldName = FText::FromString(TEXT("Value"))); 28 | 29 | /** Validates identifier: starts with [A-Za-z_] and contains only [A-Za-z0-9_] */ 30 | static bool IsValidIdentifier(const FString& InStr); 31 | 32 | /** Identifier with error message */ 33 | static bool IsValidIdentifier(const FString& InStr, FText& OutError, const FText& FieldName = FText::FromString(TEXT("Identifier"))); 34 | 35 | private: 36 | 37 | static FValidatorFunc CreateLengthValidator(int32 Min, int32 Max); 38 | static FValidatorFunc CreateLengthAndIdentifierValidator(int32 Min, int32 Max); 39 | static FValidatorFunc CreateLengthAndControlValidator(int32 Min, int32 Max, TSet ExcludeList); 40 | 41 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudJobPythonLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "CoreMinimal.h" 5 | #include "CoreMinimal.h" 6 | #include "UObject/Object.h" 7 | #include "PythonAPILibraries/PythonYamlLibrary.h" 8 | #include "DeadlineCloudJobPythonLibrary.generated.h" 9 | 10 | UCLASS() 11 | class UNREALDEADLINECLOUDSERVICE_API UOpenJobPythonLibrary : public UObject, public TPythonAPILibraryBase 12 | { 13 | GENERATED_BODY() 14 | public: 15 | 16 | UOpenJobPythonLibrary() {}; 17 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudPerforceEnvironment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PythonAPILibraries/PythonYamlLibrary.h" 4 | #include "DeadlineCloudEnvironment.h" 5 | #include "DeadlineCloudPerforceEnvironment.generated.h" 6 | 7 | 8 | UCLASS(BlueprintType) 9 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudPerforceEnvironment : public UDeadlineCloudEnvironment 10 | { 11 | GENERATED_BODY() 12 | public: 13 | 14 | UDeadlineCloudPerforceEnvironment() {}; 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudRenderJob.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "PythonAPILibraries/PythonYamlLibrary.h" 5 | #include "DeadlineCloudJob.h" 6 | #include "DeadlineCloudRenderJob.generated.h" 7 | 8 | UCLASS(BlueprintType) 9 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudRenderJob : public UDeadlineCloudJob 10 | { 11 | GENERATED_BODY() 12 | public: 13 | 14 | UDeadlineCloudRenderJob() {}; 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudRenderStep.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "DeadlineCloudStep.h" 5 | #include "DeadlineCloudRenderStep.generated.h" 6 | 7 | 8 | UCLASS(BlueprintType, Blueprintable) 9 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudRenderStep : public UDeadlineCloudStep 10 | { 11 | GENERATED_BODY() 12 | public: 13 | 14 | UDeadlineCloudRenderStep(); 15 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudSettingsDetails.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "DeadlineCloudStatusHandler.h" 5 | #include "DetailLayoutBuilder.h" 6 | #include "IDetailCustomization.h" 7 | 8 | class UDeadlineCloudDeveloperSettings; 9 | 10 | /** 11 | * Deadline Cloud settings details UI customization 12 | */ 13 | class FDeadlineCloudSettingsDetails : public IDetailCustomization 14 | { 15 | private: 16 | TWeakObjectPtr Settings; 17 | TUniquePtr DeadlineCloudStatusHandler; 18 | public: 19 | /** Makes a new instance of this detail layout class for a specific detail view requesting it */ 20 | static TSharedRef MakeInstance(); 21 | 22 | 23 | /** IDetailCustomization interface */ 24 | virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; 25 | }; 26 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudStatusHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | class UDeadlineCloudDeveloperSettings; 8 | /** 9 | * Deadline Cloud status handler 10 | */ 11 | class UNREALDEADLINECLOUDSERVICE_API FDeadlineCloudStatusHandler 12 | { 13 | inline static const FName NAME_DirectoryWatcher = "DirectoryWatcher"; 14 | /** Help struct to keep a list of config directory watch handlers */ 15 | struct FConfigWatchedDirInfo 16 | { 17 | FDelegateHandle DirectoryWatcherHandle; 18 | FString FolderPath; 19 | }; 20 | 21 | /** List of config directory watch handlers */ 22 | TArray WatchedDirectories; 23 | 24 | /** Reference to Deadline Cloud settings */ 25 | TWeakObjectPtr Settings; 26 | 27 | public: 28 | /** Starts tracking directories updates */ 29 | void StartDirectoryWatch(); 30 | 31 | /** Stops tracking directories updates */ 32 | void StopDirectoryWatch(); 33 | 34 | /** 35 | * @param InSettings Deadline Cloud plugin settings 36 | */ 37 | explicit FDeadlineCloudStatusHandler(TWeakObjectPtr InSettings); 38 | ~FDeadlineCloudStatusHandler(); 39 | }; 40 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/DeadlineCloudJobSettings/DeadlineCloudUgsEnvironment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PythonAPILibraries/PythonYamlLibrary.h" 4 | #include "DeadlineCloudEnvironment.h" 5 | #include "DeadlineCloudUgsEnvironment.generated.h" 6 | 7 | 8 | UCLASS(BlueprintType) 9 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudUgsEnvironment : public UDeadlineCloudEnvironment 10 | { 11 | GENERATED_BODY() 12 | public: 13 | 14 | UDeadlineCloudUgsEnvironment() {}; 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/MovieRenderPipeline/DeadlineCloudCustomScriptStepSetting.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "MovieRenderPipeline/DeadlineCloudStepBaseSetting.h" 7 | #include "DeadlineCloudCustomScriptStepSetting.generated.h" 8 | 9 | /** 10 | * Custom script step settings parameters 11 | */ 12 | USTRUCT(BlueprintType) 13 | struct UNREALDEADLINECLOUDSERVICE_API FDeadlineCloudCustomScriptStepParameters : public FDeadlineCloudCompositeStepParameters 14 | { 15 | GENERATED_BODY() 16 | 17 | /** Path to custom python script to execute */ 18 | UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(RelativeToGameDir, Category=Rendering)) 19 | FFilePath Script; 20 | }; 21 | 22 | /** 23 | * UDeadlineCloudCompositeStepBaseSetting -- should always include property DeadlineCloudSteps, 24 | * which should be array of structs inherited from FDeadlineCloudCompositeStepParameters 25 | * UDeadlineCloudCompositeStepBaseSetting 26 | */ 27 | UCLASS(Blueprintable) 28 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudCustomScriptStepSetting : public UDeadlineCloudCompositeStepBaseSetting 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | /** List of custom script steps */ 34 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Rendering) 35 | TArray DeadlineCloudSteps; 36 | 37 | #if WITH_EDITOR 38 | virtual FText GetDisplayText() const override { return NSLOCTEXT("MovieRenderPipeline", "DeadlineCloudRenderStepSettingDisplayName", "Custom Scripts"); } 39 | #endif 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/MovieRenderPipeline/DeadlineCloudRenderStepSetting.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "MovieRenderPipeline/DeadlineCloudStepBaseSetting.h" 7 | #include "DeadlineCloudRenderStepSetting.generated.h" 8 | 9 | /** 10 | * Deadline Cloud Render step setting 11 | */ 12 | UCLASS() 13 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudRenderStepSetting : public UDeadlineCloudStepBaseSetting 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | #if WITH_EDITOR 19 | virtual FText GetDisplayText() const override { return NSLOCTEXT("MovieRenderPipeline", "DeadlineCloudRenderStepSettingDisplayName", "Render"); } 20 | #endif 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/MovieRenderPipeline/DeadlineCloudStepBaseSetting.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "MoviePipelineSetting.h" 7 | #include "Misc/EngineVersionComparison.h" 8 | #include "DeadlineCloudStepBaseSetting.generated.h" 9 | 10 | /** 11 | * Base class for Deadline Cloud MRQ setting. 12 | * Unreal DeadlineCloud submitter creates an OpenJob step for each setting inherited from this class 13 | */ 14 | UCLASS(Blueprintable, Abstract) 15 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudStepBaseSetting : public UMoviePipelineSetting 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | /** List of Deadline Cloud step names this step depends on */ 21 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Rendering", meta = (GetOptions = "GetStepOptions")) 22 | TArray DependsOn; 23 | 24 | virtual bool IsValidOnShots() const override { return true; } 25 | 26 | #if UE_VERSION_NEWER_THAN(5, 2, -1) 27 | virtual bool IsValidOnPrimary() const override { return true; } 28 | #else 29 | virtual bool IsValidOnMaster() const override { return true; } 30 | #endif 31 | 32 | #if WITH_EDITOR 33 | virtual FText GetCategoryText() const override { return NSLOCTEXT("MovieRenderPipeline", "DeadlineCloudCategoryName_Text", "DeadlineCloud"); } 34 | #endif 35 | 36 | /** Returns a list of all currently available Deadline Cloud step names */ 37 | UFUNCTION() 38 | TArray GetStepOptions(); 39 | }; 40 | 41 | /** 42 | * Base parameters structure for Deadline Cloud composite MRQ Setting 43 | */ 44 | USTRUCT(BlueprintType) 45 | struct UNREALDEADLINECLOUDSERVICE_API FDeadlineCloudCompositeStepParameters 46 | { 47 | GENERATED_BODY() 48 | 49 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Rendering) 50 | FString Name = ""; 51 | 52 | UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (GetOptions = "GetStepOptions", Category=Rendering)) 53 | TArray DependsOn; 54 | }; 55 | 56 | /** 57 | * Intended to be mapped to multiple steps of the OpenJob 58 | * Should always have property TArray DeadlineCloudSteps when inherited 59 | * An array of structs inherited from FDeadlineCloudCompositeStepParameters 60 | * Each array element of the property will be mapped to a step in OpenJob 61 | * We don't add this property to base class since in Unreal we can't define UPROPERTY of generic type 62 | */ 63 | UCLASS(Blueprintable, Abstract) 64 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudCompositeStepBaseSetting : public UMoviePipelineSetting 65 | { 66 | GENERATED_BODY() 67 | 68 | public: 69 | 70 | // When extended should include property: 71 | // UPROPERTY(EditAnywhere, BlueprintReadWrite) 72 | // TArray DeadlineCloudSteps; 73 | 74 | virtual bool IsValidOnShots() const override { return true; } 75 | 76 | #if UE_VERSION_NEWER_THAN(5, 2, -1) 77 | virtual bool IsValidOnPrimary() const override { return true; } 78 | #else 79 | virtual bool IsValidOnMaster() const override { return true; } 80 | #endif 81 | 82 | #if WITH_EDITOR 83 | virtual FText GetCategoryText() const override { return NSLOCTEXT("MovieRenderPipeline", "DeadlineCloudCategoryName_Text", "DeadlineCloud"); } 84 | #endif 85 | 86 | /** Returns a list of all currently available Deadline Cloud step names */ 87 | UFUNCTION() 88 | TArray GetStepOptions(); 89 | }; 90 | 91 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/MovieRenderPipeline/DeadlineExecutorImplementationLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | #include "MoviePipelineQueue.h" 8 | #include "MoviePipelinePrimaryConfig.h" 9 | #include "MovieRenderPipelineEditor/Public/MoviePipelineQueueSubsystem.h" 10 | #include "MovieRenderPipelineEditor/Public/MovieRenderPipelineSettings.h" 11 | #include "MovieRenderPipelineCore/Public/MoviePipelineExecutor.h" 12 | #include "MovieRenderPipelineCore/Public/MoviePipelineQueue.h" 13 | 14 | #include "Editor.h" 15 | #include "EditorSubsystem.h" 16 | #include "Subsystems/ImportSubsystem.h" 17 | #include "Subsystems/AssetEditorSubsystem.h" 18 | 19 | #include "Misc/Paths.h" 20 | #include "UObject/NoExportTypes.h" 21 | 22 | #include "Kismet/BlueprintFunctionLibrary.h" 23 | #include "UObject/Object.h" 24 | #include "DeadlineExecutorImplementationLibrary.generated.h" 25 | 26 | 27 | UCLASS() 28 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineExecutorImplementationLibrary : public UObject 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | UFUNCTION(BlueprintCallable, Category = "Deadline Executor") 34 | static TSubclassOf GetDefaultDeadlineExecutor(); 35 | 36 | }; 37 | 38 | UCLASS(Blueprintable) 39 | class ULevelSelector : public UObject 40 | { 41 | GENERATED_BODY() 42 | 43 | public: 44 | 45 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Level Selection", meta = (AllowedClasses = "/Script/Engine.World")) 46 | TSoftObjectPtr Map; 47 | }; 48 | 49 | UCLASS(Blueprintable) 50 | class UPathSelector : public UObject 51 | { 52 | GENERATED_BODY() 53 | 54 | public: 55 | 56 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Path Selection") 57 | FFilePath FilePath; 58 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/PythonAPILibraries/DeadlineCloudJobBundleLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "PythonAPILibrary.h" 7 | #include "MovieRenderPipeline/MoviePipelineDeadlineCloudExecutorJob.h" 8 | #include "UObject/Object.h" 9 | #include "DeadlineCloudJobBundleLibrary.generated.h" 10 | 11 | /** 12 | * Deadline Cloud "Job Bundle" function library. Intended to be implemented in Python: Content/Python/job_library.py 13 | * see: DeadlineCloudJobBundleLibraryImplementation 14 | */ 15 | UCLASS() 16 | class UNREALDEADLINECLOUDSERVICE_API UDeadlineCloudJobBundleLibrary : public UObject, public TPythonAPILibraryBase 17 | { 18 | GENERATED_BODY() 19 | 20 | public: 21 | /** 22 | * Collect list of rendered Level and Level Sequence assets 23 | * @param MrqJob Unreal MRQ job 24 | * @return List of the Level and LevelSequence job dependencies 25 | */ 26 | UFUNCTION(BlueprintImplementableEvent) 27 | TArray GetJobDependencies(const UMoviePipelineDeadlineCloudExecutorJob *MrqJob); 28 | 29 | /** @return list of CPU architectures */ 30 | UFUNCTION(BlueprintImplementableEvent) 31 | TArray GetCpuArchitectures(); 32 | 33 | /** @return list of Operating Systems */ 34 | UFUNCTION(BlueprintImplementableEvent) 35 | TArray GetOperatingSystems(); 36 | 37 | /** @return list of Possible job initial states */ 38 | UFUNCTION(BlueprintImplementableEvent) 39 | TArray GetJobInitialStateOptions(); 40 | }; 41 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/PythonAPILibraries/PythonAPILibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | /** 6 | * Base class for singleton uobject implemented in python. 7 | * See @ref UDeadlineCloudDeveloperSettings, @ref UDeadlineCloudJobBundleLibrary, @ref UPythonGameThreadExecutor 8 | * @tparam T uobject class type 9 | */ 10 | template 11 | class UNREALDEADLINECLOUDSERVICE_API TPythonAPILibraryBase 12 | { 13 | public: 14 | static T* Get() 15 | { 16 | TArray PythonAPIClasses; 17 | GetDerivedClasses(T::StaticClass(), PythonAPIClasses); 18 | if (PythonAPIClasses.Num() > 0) 19 | { 20 | return Cast(PythonAPIClasses[PythonAPIClasses.Num() - 1]->GetDefaultObject()); 21 | } 22 | return nullptr; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/PythonAPILibraries/PythonGameThreadExecutor.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "PythonAPILibraries/PythonAPILibrary.h" 7 | #include "UObject/Object.h" 8 | #include "PythonGameThreadExecutor.generated.h" 9 | 10 | /** 11 | * Python Game thread executor. Intended to execute python code in main thread in Unreal on Editor tick. 12 | * See implementation: OnTickThreadExecutorImplementation 13 | * in deadline-cloud-for-unreal: src/deadline/unreal_adaptor/UnrealClient/unreal_client.py 14 | */ 15 | UCLASS(Blueprintable) 16 | class UNREALDEADLINECLOUDSERVICE_API UPythonGameThreadExecutor : public UObject, public TPythonAPILibraryBase, public FTickableEditorObject 17 | { 18 | GENERATED_BODY() 19 | public: 20 | 21 | /** This method is called in Tick method. This way the code it runs will be executed in Editor Main thread */ 22 | UFUNCTION(BlueprintImplementableEvent, Category = Python) 23 | void Execute(float DeltaTime) const; 24 | 25 | private: 26 | 27 | /** FTickableEditorObject interface */ 28 | virtual void Tick(float DeltaTime) override; 29 | virtual bool IsTickable() const override; 30 | virtual TStatId GetStatId() const override; 31 | }; 32 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/PythonAPILibraries/PythonParametersConsistencyChecker.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "PythonAPILibrary.h" 7 | #include "PythonYamlLibrary.h" 8 | #include "UObject/Object.h" 9 | #include "PythonParametersConsistencyChecker.generated.h" 10 | 11 | USTRUCT(BlueprintType) 12 | struct FParametersConsistencyCheckResult 13 | 14 | { 15 | GENERATED_BODY() 16 | 17 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Checker") 18 | bool Passed = false; 19 | 20 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Checker") 21 | FString Reason; 22 | 23 | }; 24 | 25 | 26 | 27 | UCLASS() 28 | class UNREALDEADLINECLOUDSERVICE_API UPythonParametersConsistencyChecker : public UObject, public TPythonAPILibraryBase 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | UFUNCTION(BlueprintImplementableEvent) 34 | FParametersConsistencyCheckResult CheckJobParametersConsistency(const UDeadlineCloudJob* Job); 35 | 36 | UFUNCTION(BlueprintImplementableEvent) 37 | void FixJobParametersConsistency (UDeadlineCloudJob* Job); 38 | 39 | UFUNCTION(BlueprintImplementableEvent) 40 | FParametersConsistencyCheckResult CheckStepParametersConsistency(const UDeadlineCloudStep* Step); 41 | 42 | UFUNCTION(BlueprintImplementableEvent) 43 | void FixStepParametersConsistency (UDeadlineCloudStep* Step); 44 | 45 | UFUNCTION(BlueprintImplementableEvent) 46 | FParametersConsistencyCheckResult CheckEnvironmentVariablesConsistency(const UDeadlineCloudEnvironment* Environment); 47 | 48 | UFUNCTION(BlueprintImplementableEvent) 49 | void FixEnvironmentVariablesConsistency(UDeadlineCloudEnvironment* Environment); 50 | 51 | }; -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/Public/UnrealDeadlineCloudServiceModule.h: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | /** 9 | * This is the module definition for the editor mode. You can implement custom functionality 10 | * as your plugin module starts up and shuts down. See IModuleInterface for more extensibility options. 11 | */ 12 | class FUnrealDeadlineCloudServiceModule : public IModuleInterface 13 | { 14 | public: 15 | 16 | /** IModuleInterface implementation */ 17 | virtual void StartupModule() override; 18 | virtual void ShutdownModule() override; 19 | }; 20 | -------------------------------------------------------------------------------- /src/unreal_plugin/Source/UnrealDeadlineCloudService/UnrealDeadlineCloudService.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using UnrealBuildTool.Rules; 5 | 6 | public class UnrealDeadlineCloudService : ModuleRules 7 | { 8 | public UnrealDeadlineCloudService(ReadOnlyTargetRules Target) : base(Target) 9 | { 10 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 11 | 12 | PublicIncludePaths.AddRange( 13 | new string[] { 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | } 21 | ); 22 | 23 | 24 | PublicDependencyModuleNames.AddRange( 25 | new string[] 26 | { 27 | "AutomationDriver", 28 | "UnrealEd", 29 | "EditorSubsystem", 30 | "Slate", 31 | "SlateCore", 32 | "EditorWidgets", 33 | "Core", 34 | "CoreUObject", 35 | "Engine", 36 | "MovieRenderPipelineCore", 37 | "MovieRenderPipelineEditor", 38 | "InputCore", 39 | "DesktopWidgets", 40 | } 41 | ); 42 | 43 | 44 | PrivateDependencyModuleNames.AddRange( 45 | new string[] 46 | { 47 | "Core", 48 | "CoreUObject", 49 | "Engine", 50 | "Slate", 51 | "SlateCore", 52 | "InputCore", 53 | "EditorFramework", 54 | "EditorStyle", 55 | "EditorWidgets", 56 | "DesktopWidgets", 57 | "DesktopPlatform", 58 | "UnrealEd", 59 | "LevelEditor", 60 | "InteractiveToolsFramework", 61 | "EditorInteractiveToolsFramework", 62 | "MovieRenderPipelineCore", 63 | "PropertyEditor", 64 | "DeveloperSettings", 65 | "JsonUtilities", 66 | "AssetTools", 67 | "Projects", 68 | "AssetRegistry", 69 | "LevelSequence" 70 | } 71 | ); 72 | 73 | 74 | DynamicallyLoadedModuleNames.AddRange( 75 | new string[] 76 | { 77 | } 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/unreal_plugin/UnrealDeadlineCloudService.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "UnrealDeadlineCloudService", 6 | "Description": "", 7 | "Category": "Other", 8 | "CreatedBy": "", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "CanContainContent": true, 13 | "IsBetaVersion": false, 14 | "IsExperimentalVersion": true, 15 | "Installed": false, 16 | "EnabledByDefault": true, 17 | "Plugins": 18 | [ 19 | { 20 | "Name": "PythonScriptPlugin", 21 | "Enabled": true 22 | }, 23 | { 24 | "Name": "MovieRenderPipeline", 25 | "Enabled": true 26 | }, 27 | { 28 | "Name": "EditorScriptingUtilities", 29 | "Enabled": true 30 | } 31 | ], 32 | "Modules": [ 33 | { 34 | "Name": "UnrealDeadlineCloudService", 35 | "Type" : "UncookedOnly" 36 | } 37 | ], 38 | "PythonRequirements": 39 | [ 40 | { 41 | 42 | "Platform": "All", 43 | "Requirements": 44 | [ 45 | "deadline-cloud-for-unreal-engine>=0.5.0" 46 | ] 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealAdaptor/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealClient/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealClient/step_handlers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealClient/step_handlers/custom_scripts/existed_not_valid_script.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | def not_main(): 5 | pass 6 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealClient/step_handlers/custom_scripts/valid_script.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | def main(**kwargs): 5 | return f"Im valid, get next kwargs: {kwargs}" 6 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/UnrealClient/step_handlers/test_render_step_handler.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import sys 4 | import pytest 5 | from unittest.mock import MagicMock, patch 6 | 7 | 8 | unreal_mock = MagicMock() 9 | unreal_mock.log = MagicMock() 10 | sys.modules["unreal"] = unreal_mock 11 | 12 | 13 | @pytest.fixture() 14 | def unreal_render_step_handler(): 15 | from deadline.unreal_adaptor.UnrealClient.step_handlers.unreal_render_step_handler import ( 16 | UnrealRenderStepHandler, 17 | ) 18 | 19 | return UnrealRenderStepHandler() 20 | 21 | 22 | class ShotInfoMock: 23 | 24 | def __init__(self, enabled: bool, outer_name: str, inner_name: str): 25 | self.enabled = enabled 26 | self.outer_name = outer_name 27 | self.inner_name = inner_name 28 | 29 | 30 | class RenderJobMock: 31 | 32 | def __init__(self, shot_info: list[ShotInfoMock]): 33 | self.shot_info = shot_info 34 | 35 | 36 | class TestUnrealRenderStepHandler: 37 | 38 | @pytest.mark.parametrize( 39 | "shots_count, enabled_shots_count, task_chunk_size, task_chunk_id", 40 | [ 41 | (29, 15, 5, 0), 42 | (29, 29, 5, 1), 43 | (1, 1, 10, 0), 44 | (1500, 1, 1501, 0), 45 | (10, 9, 3, 2), 46 | ], 47 | ) 48 | def test_enable_shots_by_chunk( 49 | self, 50 | unreal_render_step_handler, 51 | shots_count, 52 | enabled_shots_count, 53 | task_chunk_size, 54 | task_chunk_id, 55 | ): 56 | # GIVEN 57 | enabled_shots = [ 58 | ShotInfoMock(enabled=True, outer_name=f"Enabled{i}", inner_name=f"Enabled{i}") 59 | for i in range(enabled_shots_count) 60 | ] 61 | disabled_shots = [ 62 | ShotInfoMock(enabled=False, outer_name=f"Disabled{i}", inner_name=f"Disabled{i}") 63 | for i in range(shots_count - enabled_shots_count) 64 | ] 65 | render_job_mock = RenderJobMock(shot_info=enabled_shots + disabled_shots) 66 | 67 | enabled_job_shots = [shot for shot in render_job_mock.shot_info if shot.enabled] 68 | chunked = enabled_job_shots[ 69 | task_chunk_id * task_chunk_size : (task_chunk_id + 1) * task_chunk_size 70 | ] 71 | chunked_names = [shot.outer_name for shot in chunked] 72 | 73 | # WHEN 74 | with patch( 75 | "deadline.unreal_adaptor.UnrealClient.step_handlers." 76 | "unreal_render_step_handler.logger.info" 77 | ) as log_mock: 78 | unreal_render_step_handler.enable_shots_by_chunk( 79 | render_job_mock, task_chunk_size, task_chunk_id 80 | ) 81 | 82 | # THEN 83 | enabled_shots = [shot for shot in render_job_mock.shot_info if shot.enabled] 84 | assert all([shot.enabled for shot in enabled_shots]) 85 | assert all([shot.outer_name.startswith("Enabled") for shot in chunked]) 86 | assert len(enabled_shots) <= task_chunk_size and len(enabled_shots) <= shots_count 87 | 88 | disabled_shots = [ 89 | shot for shot in render_job_mock.shot_info if shot.outer_name not in chunked_names 90 | ] 91 | for shot in disabled_shots: 92 | assert not shot.enabled 93 | 94 | log_mock.assert_called_with( 95 | f"Shots in task: {[shot.outer_name for shot in enabled_shots]}" 96 | ) 97 | -------------------------------------------------------------------------------- /test/deadline_adaptor_for_unreal/unit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_logger_for_unreal/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_logger_for_unreal/test_logger.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import pytest 4 | from unittest.mock import Mock, MagicMock, patch 5 | 6 | from deadline.unreal_logger import get_logger 7 | from deadline.unreal_logger.logger import add_unreal_handler 8 | from deadline.unreal_logger.handlers import UnrealLogHandler 9 | 10 | 11 | class TestUnrealLogHandler: 12 | 13 | @pytest.mark.parametrize( 14 | "log_level, expected_method", 15 | [ 16 | ("WARNING", "log_warning"), 17 | ("ERROR", "log_error"), 18 | ("CRITICAL", "log_error"), 19 | ("INFO", "log"), 20 | ("DEBUG", "log"), 21 | ("CUSTOM_LEVEL", "log"), 22 | ], 23 | ) 24 | @patch("logging.Handler.format") 25 | def test_emit(self, mock_format: Mock, log_level: str, expected_method: str): 26 | # GIVEN 27 | unreal_module = MagicMock() 28 | setattr(unreal_module, expected_method, MagicMock()) 29 | 30 | record = MagicMock() 31 | record.levelname = log_level 32 | mock_format.return_value = record 33 | 34 | handler = UnrealLogHandler(unreal_module) 35 | 36 | # WHEN 37 | handler.emit(record) 38 | 39 | # THEN 40 | mocked_method: MagicMock = getattr(unreal_module, expected_method) 41 | mocked_method.assert_called_once_with(record) 42 | 43 | def test_emit_with_invalid_unreal_module(self): 44 | # GIVEN 45 | unreal_module = Mock(return_value=None) 46 | handler = UnrealLogHandler(unreal_module) 47 | 48 | # WHEN 49 | handler.emit(MagicMock()) 50 | 51 | # THEN 52 | assert unreal_module.call_count == 0 53 | 54 | 55 | class TestUnrealLogger: 56 | 57 | @pytest.mark.parametrize( 58 | "unreal_initialized, handler_added, add_handler_calls", 59 | [ 60 | (True, True, 0), 61 | (False, True, 0), 62 | (False, False, 0), 63 | (True, False, 1), 64 | ], 65 | ) 66 | @patch("deadline.unreal_logger.logger.add_unreal_handler") 67 | def test_get_logger( 68 | self, 69 | add_unreal_handler_mock: Mock, 70 | unreal_initialized: bool, 71 | handler_added: bool, 72 | add_handler_calls: int, 73 | ): 74 | # GIVEN 75 | with patch("deadline.unreal_logger.logger.UNREAL_INITIALIZED", unreal_initialized): 76 | with patch("deadline.unreal_logger.logger.UNREAL_HANDLER_ADDED", handler_added): 77 | # WHEN 78 | get_logger() 79 | 80 | # THEN 81 | assert add_unreal_handler_mock.call_count == add_handler_calls 82 | 83 | def test_add_unreal_handler(self): 84 | # GIVEN 85 | logger = get_logger() 86 | logger.handlers.clear() 87 | 88 | # WHEN 89 | add_unreal_handler(logger) 90 | 91 | # THEN 92 | assert len(logger.handlers) == 1 93 | assert isinstance(logger.handlers[0], UnrealLogHandler) 94 | -------------------------------------------------------------------------------- /test/deadline_perforce_utils_for_unreal/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_perforce_utils_for_unreal/test_app.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | import os 3 | import socket 4 | import pytest 5 | import getpass 6 | from unittest.mock import MagicMock, Mock, patch, mock_open 7 | 8 | from deadline.unreal_perforce_utils import app 9 | 10 | 11 | class TestUnrealP4UtilsApp: 12 | 13 | @pytest.mark.parametrize( 14 | "project_name, env", 15 | [ 16 | ("MockedProject", {}), 17 | ("", {}), 18 | (None, {}), 19 | ("MockedProject", {"DEADLINE_WORKER_ID": "worker-1"}), 20 | ("", {"DEADLINE_WORKER_ID": "worker-1"}), 21 | (None, {"DEADLINE_WORKER_ID": "worker-1"}), 22 | ], 23 | ) 24 | @patch("getpass.getuser", return_value="j.doe") 25 | @patch("socket.gethostname", return_value="WORKER-1") 26 | def test_get_workspace_name( 27 | self, get_host_name_mock: Mock, getuser_mock: Mock, project_name: str, env: dict[str, str] 28 | ): 29 | # GIVEN 30 | expected = f"{getpass.getuser()}_{socket.gethostname()}_{project_name}" 31 | 32 | # WHEN 33 | with patch.dict(os.environ, env, clear=True): 34 | workspace_name = app.get_workspace_name(project_name) 35 | 36 | # THEN 37 | if "DEADLINE_WORKER_ID" in os.environ: 38 | assert workspace_name == f"{expected}_{os.environ['DEADLINE_WORKER_ID']}" 39 | else: 40 | assert workspace_name == expected 41 | 42 | @patch("os.path.exists", return_value=True) 43 | @patch("builtins.open", new_callable=mock_open) 44 | def test_get_workspace_specification_template_from_file( 45 | self, mock_exists: Mock, mock_open_file: Mock 46 | ): 47 | # GIVEN 48 | expected_template = {"Spec": "Value"} 49 | 50 | # GIVEN & WHEN 51 | with patch("json.load", MagicMock(side_effect=[expected_template])): 52 | template = app.get_workspace_specification_template_from_file("filename.json") 53 | 54 | # THEN 55 | assert template == expected_template 56 | 57 | def test_get_workspace_specification_template_from_non_existing_file(self): 58 | # GIVEN & WHEN 59 | with pytest.raises(FileNotFoundError) as exc_info: 60 | app.get_workspace_specification_template_from_file("not_existed_template.json") 61 | 62 | # THEN 63 | assert exc_info 64 | 65 | @pytest.mark.parametrize( 66 | "p4_info, openjd_env_output", 67 | [ 68 | ( 69 | {"P4PORT": "port", "P4USER": "user", "P4PASSWD": "pass"}, 70 | ["openjd_env: P4PORT=port", "openjd_env: P4USER=user", "openjd_env: P4PASSWD=pass"], 71 | ), 72 | ({}, []), 73 | ], 74 | ) 75 | @patch("deadline.unreal_perforce_utils.secret_manager.get_perforce_info") 76 | def test_apply_perforce_secrets( 77 | self, get_perforce_info_mock: Mock, p4_info: dict[str, str], openjd_env_output: list[str] 78 | ): 79 | 80 | # GIVEN 81 | get_perforce_info_mock.return_value = p4_info 82 | 83 | # WHEN 84 | with patch("builtins.print") as print_mock: 85 | app.apply_perforce_secrets() 86 | 87 | # THEN 88 | assert len(print_mock.mock_calls) == len(openjd_env_output) 89 | for i, call in enumerate(print_mock.mock_calls): 90 | assert call.args[0] == openjd_env_output[i] 91 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/fixtures.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | 4 | def f_job_template_default() -> dict: 5 | return { 6 | "specificationVersion": "jobtemplate-2023-09", 7 | "name": "JobA", 8 | "parameterDefinitions": [ 9 | { 10 | "name": "ParamA", 11 | "type": "PATH", 12 | "objectType": "FILE", 13 | "dataFlow": "IN", 14 | "default": "path/to/file", 15 | }, 16 | {"name": "ParamB", "type": "STRING", "default": "foo"}, 17 | {"name": "ParamC", "type": "INT", "default": 1}, 18 | {"name": "ParamD", "type": "FLOAT", "default": 1.0}, 19 | ], 20 | } 21 | 22 | 23 | def f_step_template_default() -> dict: 24 | return { 25 | "name": "StepA", 26 | "parameterSpace": { 27 | "taskParameterDefinitions": [ 28 | {"name": "ParamA", "type": "PATH", "range": ["path/to/file"]}, 29 | {"name": "ParamB", "type": "STRING", "range": ["foo"]}, 30 | {"name": "ParamC", "type": "INT", "range": [1]}, 31 | {"name": "ParamD", "type": "FLOAT", "range": [1.0]}, 32 | ] 33 | }, 34 | "script": { 35 | "embeddedFiles": [ 36 | { 37 | "name": "Run", 38 | "filename": "run.bat", 39 | "runnable": True, 40 | "type": "TEXT", 41 | "data": "echo {{Task.Param.ParamA}}\necho {{Task.Param.ParamB}}\necho {{Task.Param.ParamC}}\necho {{Task.Param.ParamD}}\n", 42 | } 43 | ], 44 | "actions": { 45 | "onRun": { 46 | "command": "{{Task.File.Run}}", 47 | "cancelation": {"mode": "NOTIFY_THEN_TERMINATE"}, 48 | } 49 | }, 50 | }, 51 | } 52 | 53 | 54 | def f_environment_template_default() -> dict: 55 | return { 56 | "name": "EnvironmentA", 57 | "variables": {"VARIABLE_A": "VALUE_A", "VARIABLE_B": "VALUE_B"}, 58 | "script": { 59 | "embeddedFiles": [ 60 | { 61 | "name": "Init", 62 | "filename": "init.bat", 63 | "runnable": True, 64 | "type": "TEXT", 65 | "data": "echo {{Param.ParamA}}\necho {{Param.ParamB}}\necho {{Param.ParamC}}\necho {{Param.ParamD}}\n", 66 | }, 67 | { 68 | "name": "Exit", 69 | "filename": "exit.bat", 70 | "runnable": True, 71 | "type": "TEXT", 72 | "data": "echo {{Param.ParamD}}\necho {{Param.ParamC}}\necho {{Param.ParamB}}\necho {{Param.ParamA}}\n", 73 | }, 74 | ], 75 | "actions": { 76 | "onEnter": { 77 | "command": "{{Env.File.Init}}", 78 | "cancelation": {"mode": "NOTIFY_THEN_TERMINATE"}, 79 | }, 80 | "onExit": { 81 | "command": "{{Env.File.Exit}}", 82 | "cancelation": {"mode": "NOTIFY_THEN_TERMINATE"}, 83 | }, 84 | }, 85 | }, 86 | } 87 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/unit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/unit/test_unreal_open_job/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/unit/test_unreal_open_job/test_unreal_open_job_entity.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import sys 4 | import pytest 5 | from unittest.mock import Mock, MagicMock, PropertyMock, patch 6 | 7 | from openjd.model.v2023_09 import JobTemplate, StepTemplate 8 | 9 | from test.deadline_submitter_for_unreal import fixtures 10 | 11 | unreal_mock = MagicMock() 12 | sys.modules["unreal"] = unreal_mock 13 | 14 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_entity import ( # noqa: E402 15 | UnrealOpenJobEntity, 16 | ) 17 | 18 | 19 | class TestUnrealOpenJobEntity: 20 | 21 | @patch.object(UnrealOpenJobEntity, "_check_parameters_consistency") 22 | def test__validate_parameters_passed(self, check_consistency_mock: Mock): 23 | # GIVEN 24 | unreal_open_job_entity = UnrealOpenJobEntity(template_class=JobTemplate, file_path="") 25 | 26 | return_value = Mock() 27 | return_value.passed = True 28 | check_consistency_mock.return_value = return_value 29 | 30 | # WHEN 31 | is_valid = unreal_open_job_entity._validate_parameters() 32 | 33 | # THEN 34 | assert is_valid 35 | 36 | @patch.object(UnrealOpenJobEntity, "_check_parameters_consistency") 37 | def test__validate_parameters_failed(self, check_consistency_mock: Mock): 38 | # GIVEN 39 | unreal_open_job_entity = UnrealOpenJobEntity(template_class=JobTemplate, file_path="") 40 | fail_reason = "Mocked reason" 41 | 42 | return_value = Mock() 43 | return_value.passed = False 44 | return_value.reason = fail_reason 45 | check_consistency_mock.return_value = return_value 46 | 47 | # WHEN 48 | with pytest.raises(Exception) as exception_info: 49 | unreal_open_job_entity._validate_parameters() 50 | 51 | # THEN 52 | assert str(exception_info.value) == fail_reason 53 | 54 | @patch( 55 | "deadline.unreal_submitter.unreal_open_job.unreal_open_job_entity." 56 | "UnrealOpenJobEntity.file_path", 57 | new_callable=PropertyMock, 58 | ) 59 | def test_get_template_object_not_existed(self, file_path_mock: PropertyMock): 60 | # GIVEN 61 | file_path = "not_existed_template.yml" 62 | unreal_open_job_entity = UnrealOpenJobEntity(JobTemplate, file_path) 63 | file_path_mock.side_effect = [file_path] * 4 64 | 65 | # WHEN 66 | with pytest.raises(FileNotFoundError) as exc_info: 67 | print(unreal_open_job_entity.get_template_object()) 68 | 69 | # THEN 70 | assert str(exc_info.value) == f'Descriptor file "{file_path}" not found' 71 | 72 | @patch( 73 | "deadline.unreal_submitter.unreal_open_job.unreal_open_job_entity." 74 | "UnrealOpenJobEntity.get_template_object", 75 | return_value=fixtures.f_step_template_default(), 76 | ) 77 | def test_build_template(self, get_template_object_mock: Mock): 78 | # GIVEN 79 | template_cls = StepTemplate 80 | openjd_entity = UnrealOpenJobEntity(template_class=template_cls, file_path="") 81 | template = fixtures.f_step_template_default() 82 | 83 | # WHEN 84 | openjd_template = openjd_entity.build_template() 85 | 86 | # THEN 87 | assert isinstance(openjd_template, template_cls) 88 | assert set(template.keys()).issubset(set(openjd_template.__fields__.keys())) 89 | -------------------------------------------------------------------------------- /test/deadline_submitter_for_unreal/unit/test_unreal_open_job/test_unreal_open_job_shared_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import sys 4 | from unittest.mock import MagicMock, patch 5 | 6 | unreal_mock = MagicMock() 7 | sys.modules["unreal"] = unreal_mock 8 | 9 | from deadline.unreal_submitter.unreal_open_job.unreal_open_job_shared_settings import ( # noqa: E402 10 | JobSharedSettings, 11 | ) 12 | 13 | 14 | class TestJobSharedSettings: 15 | 16 | @patch("unreal.DeadlineCloudJobSharedSettingsStruct") 17 | def test_from_u_deadline_cloud_job_shared_settings(self, u_settings_mock: MagicMock): 18 | # GIVEN 19 | u_settings_mock.initial_state = "READY" 20 | u_settings_mock.maximum_failed_tasks_count = 50 21 | u_settings_mock.maximum_retries_per_task = 50 22 | u_settings_mock.priority = 100 23 | 24 | # WHEN 25 | settings = JobSharedSettings.from_u_deadline_cloud_job_shared_settings(u_settings_mock) 26 | 27 | # THEN 28 | assert settings.get_initial_state() == u_settings_mock.initial_state 29 | assert settings.get_max_failed_tasks_count() == u_settings_mock.maximum_failed_tasks_count 30 | assert settings.get_max_retries_per_task() == u_settings_mock.maximum_retries_per_task 31 | assert settings.get_priority() == u_settings_mock.priority 32 | -------------------------------------------------------------------------------- /test/end_to_end/test_create_job.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import logging 4 | from conftest import extract_job_info_from_test_output, wait_for_job_state, cancel_job 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | def test_create_job(deadline_client, build_plugin, create_readonly_test_project, run_unreal_test): 10 | """Run CreateJob automation test from within Unreal and monitor job status until READY, then cancel it""" 11 | 12 | _, uproject_file = create_readonly_test_project 13 | 14 | logger.info(f"Creating job from project {uproject_file}") 15 | success, output_lines = run_unreal_test("DeadlineCloud.Integration.CreateJob", uproject_file) 16 | assert success, "Create job test failed" 17 | 18 | # Extract job ID and farm ID from the output 19 | job_id, farm_id, queue_id = extract_job_info_from_test_output(output_lines) 20 | 21 | assert job_id 22 | assert farm_id 23 | assert queue_id 24 | 25 | # For checking if a job is in READY state: 26 | success, status, message = wait_for_job_state( 27 | deadline_client=deadline_client, 28 | farm_id=farm_id, 29 | job_id=job_id, 30 | queue_id=queue_id, 31 | expected_states=["READY"], 32 | max_wait_time=30, 33 | wait_interval=5, 34 | ) 35 | assert success 36 | 37 | # Once the job is in READY state, cancel it since test_worker_agent.py will handle the full job execution 38 | logger.info(f"Job {job_id} is in READY state, canceling it...") 39 | cancel_job(deadline_client, farm_id, queue_id, job_id) 40 | -------------------------------------------------------------------------------- /test/end_to_end/test_worker_agent.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import logging 4 | from conftest import extract_job_info_from_test_output, wait_for_job_state 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | def test_create_job_with_worker_agent( 10 | deadline_client, 11 | build_plugin, 12 | create_readonly_test_project, 13 | run_unreal_test, 14 | deadline_worker_agent, 15 | ): 16 | """ 17 | Run CreateJob automation test from within Unreal with a local worker agent running. 18 | This test verifies that the job is processed by the local worker agent. 19 | """ 20 | 21 | # The deadline_worker_agent fixture will start the worker agent before this test runs 22 | # and will stop it after the test completes 23 | 24 | _, uproject_file = create_readonly_test_project 25 | 26 | logger.info(f"Creating job from project {uproject_file}") 27 | success, output_lines = run_unreal_test("DeadlineCloud.Integration.CreateJob", uproject_file) 28 | assert success, "Create job test failed" 29 | 30 | # Extract job ID and farm ID from the output 31 | job_id, farm_id, queue_id = extract_job_info_from_test_output(output_lines) 32 | 33 | if job_id and farm_id and queue_id: 34 | 35 | # Wait for job completion 36 | success, status, message = wait_for_job_state( 37 | deadline_client=deadline_client, 38 | farm_id=farm_id, 39 | job_id=job_id, 40 | queue_id=queue_id, 41 | expected_states=["SUCCEEDED"], 42 | max_wait_time=600, 43 | wait_interval=10, 44 | ) 45 | 46 | assert success 47 | 48 | logger.info(f"Job {job_id} SUCCEEDED") 49 | else: 50 | logger.warning("Could not extract job ID or farm ID from test output") 51 | assert False, "Could not extract job information from test output" 52 | -------------------------------------------------------------------------------- /test/test_copyright_headers.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | import re 4 | from pathlib import Path 5 | 6 | # For distributed open source and proprietary code, we must include a copyright header in source every file: 7 | _copyright_header_re = re.compile( 8 | r"Copyright Amazon\.com, Inc\. or its affiliates\. All Rights Reserved\.", re.IGNORECASE 9 | ) 10 | _generated_by_scm = re.compile(r"# file generated by setuptools[_-]scm", re.IGNORECASE) 11 | 12 | 13 | def _check_file(filename: Path) -> None: 14 | with open(filename, encoding="utf-8") as infile: 15 | lines_read = 0 16 | for line in infile: 17 | if _copyright_header_re.search(line): 18 | return # success 19 | lines_read += 1 20 | if lines_read > 10: 21 | raise Exception( 22 | f"Could not find a valid Amazon.com copyright header in the top of {filename}." 23 | " Please add one." 24 | ) 25 | # __init__.py files are usually empty, this is to catch that. 26 | raise Exception( 27 | f"Could not find a valid Amazon.com copyright header in the top of {filename}." 28 | " Please add one." 29 | ) 30 | 31 | 32 | def _is_version_file(filename: Path) -> bool: 33 | if filename.name != "_version.py": 34 | return False 35 | with open(filename, encoding="utf-8") as infile: 36 | lines_read = 0 37 | for line in infile: 38 | if _generated_by_scm.search(line): 39 | return True 40 | lines_read += 1 41 | if lines_read > 10: 42 | break 43 | return False 44 | 45 | 46 | def test_copyright_headers(): 47 | """Verifies every .py file has an Amazon copyright header.""" 48 | root_project_dir = Path(__file__) 49 | # The root of the project is the directory that contains the test directory. 50 | while not (root_project_dir / "test").exists(): 51 | root_project_dir = root_project_dir.parent 52 | # Choose only a few top level directories to test. 53 | # That way we don't snag any virtual envs a developer might create, at the risk of missing 54 | # some top level .py files. 55 | # Additionally, ignore any files in the `node_modules` directory that we use in the VS Code 56 | # extension. 57 | top_level_dirs = [ 58 | "src", 59 | "test", 60 | "scripts", 61 | ] 62 | file_count = 0 63 | for top_level_dir in top_level_dirs: 64 | for glob_pattern in ("**/*.py", "**/*.sh", "**/Dockerfile", "**/*.ts"): 65 | for path in Path(root_project_dir / top_level_dir).glob(glob_pattern): 66 | print(path) 67 | if not _is_version_file(path): 68 | _check_file(path) 69 | file_count += 1 70 | 71 | print(f"test_copyright_headers checked {file_count} files successfully.") 72 | assert file_count > 0, "Test misconfiguration" 73 | 74 | 75 | if __name__ == "__main__": 76 | test_copyright_headers() 77 | --------------------------------------------------------------------------------