├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── community_extension.md │ ├── community_template.md │ ├── feature_request.md │ └── question.md └── dependabot.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── docs ├── .dockerignore ├── .gitignore ├── docker-compose.yml ├── main │ ├── .vuepress │ │ ├── config.ts │ │ └── styles │ │ │ └── index.scss │ ├── contributing │ │ ├── development.md │ │ ├── documentation.md │ │ ├── images │ │ │ ├── development │ │ │ │ ├── 1.jpg │ │ │ │ ├── 2.jpg │ │ │ │ ├── 3.png │ │ │ │ └── 4.png │ │ │ └── documentation │ │ │ │ ├── 1.png │ │ │ │ ├── 2.jpg │ │ │ │ ├── 3.jpg │ │ │ │ └── 4.jpg │ │ └── testing.md │ ├── images │ │ ├── 1.png │ │ ├── send2ue │ │ │ ├── 1.gif │ │ │ ├── 2.png │ │ │ └── 4.gif │ │ └── ue2rigify │ │ │ ├── 1.gif │ │ │ └── 2.png │ └── index.md ├── package-lock.json ├── package.json ├── path.js ├── send2ue │ ├── .vuepress │ │ ├── config.ts │ │ ├── public │ │ │ └── images │ │ │ │ ├── overview.svg │ │ │ │ └── unreal.png │ │ └── styles │ │ │ └── index.scss │ ├── asset-types │ │ ├── animation-sequence.md │ │ ├── groom.md │ │ ├── images │ │ │ ├── animation │ │ │ │ ├── 1.png │ │ │ │ ├── 2.gif │ │ │ │ ├── 3.gif │ │ │ │ ├── 4.gif │ │ │ │ ├── 5.gif │ │ │ │ ├── 6.gif │ │ │ │ ├── 7.png │ │ │ │ └── 8.gif │ │ │ ├── groom │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ └── 4.png │ │ │ ├── skeletal-mesh │ │ │ │ ├── 1.gif │ │ │ │ ├── 2.gif │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ ├── 5.png │ │ │ │ ├── 6.png │ │ │ │ └── overview.svg │ │ │ └── static-mesh │ │ │ │ ├── 1.gif │ │ │ │ ├── 2.gif │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ ├── 5.png │ │ │ │ ├── 6.png │ │ │ │ ├── 7.png │ │ │ │ └── 8.png │ │ ├── skeletal-mesh.md │ │ └── static-mesh.md │ ├── customize │ │ ├── extensions.md │ │ ├── images │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── extensions │ │ │ │ ├── 1.svg │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ └── 4.png │ │ │ ├── python │ │ │ │ └── 1.png │ │ │ └── templates │ │ │ │ ├── 1.gif │ │ │ │ └── 2.gif │ │ ├── python-api.md │ │ └── templates.md │ ├── extensions │ │ ├── affixes.md │ │ ├── combine-assets.md │ │ ├── create-post-import-groom-assets.md │ │ ├── images │ │ │ ├── combine-assets │ │ │ │ ├── 0.png │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ ├── 5.png │ │ │ │ ├── child_meshes.png │ │ │ │ ├── groom_per_combined_mesh.png │ │ │ │ ├── groom_per_mesh.png │ │ │ │ └── off.png │ │ │ ├── combine-meshes │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ └── 3.png │ │ │ ├── create-post-import-groom-assets │ │ │ │ ├── 0.png │ │ │ │ └── 2.png │ │ │ └── use-immediate-parent-name │ │ │ │ ├── 0.png │ │ │ │ └── 1.png │ │ ├── instance-assets.md │ │ ├── ue2rigify.md │ │ ├── use-collections-as-folders.md │ │ └── use-immediate-parent-name.md │ ├── extras │ │ ├── addon-preferences.md │ │ ├── community-extensions.md │ │ ├── images │ │ │ ├── extensions │ │ │ │ └── combine-meshes │ │ │ │ │ ├── 1.png │ │ │ │ │ ├── 2.png │ │ │ │ │ └── 3.png │ │ │ └── pipeline-menu │ │ │ │ ├── 1.png │ │ │ │ └── 2.png │ │ └── pipeline-menu.md │ ├── index.md │ ├── introduction │ │ ├── images │ │ │ ├── 1.png │ │ │ ├── 10.png │ │ │ ├── 11.png │ │ │ ├── 12.png │ │ │ ├── 13.png │ │ │ ├── 14.png │ │ │ ├── 15.png │ │ │ ├── 16.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 6_1.png │ │ │ ├── 7.png │ │ │ ├── 8.png │ │ │ └── 9.png │ │ └── quickstart.md │ ├── settings │ │ ├── export.md │ │ ├── images │ │ │ ├── export │ │ │ │ └── 1.jpg │ │ │ ├── import │ │ │ │ ├── 1.png │ │ │ │ └── 2.png │ │ │ └── paths │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ └── 4.png │ │ ├── import.md │ │ ├── paths.md │ │ └── validations.md │ └── trouble-shooting │ │ ├── errors.md │ │ └── faq.md └── ue2rigify │ ├── .vuepress │ ├── config.ts │ └── styles │ │ └── index.scss │ ├── advanced │ ├── images │ │ └── relink-constraints │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ └── 7.jpg │ └── relink-constraints.md │ ├── concepts │ ├── images │ │ ├── modes │ │ │ ├── 1.jpg │ │ │ └── 2.jpg │ │ └── templates │ │ │ ├── 1.jpg │ │ │ ├── 10.jpg │ │ │ ├── 11.jpg │ │ │ ├── 12.jpg │ │ │ ├── 13.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ └── 9.jpg │ ├── modes.md │ └── templates.md │ ├── extras │ └── community-templates.md │ ├── index.md │ ├── introduction │ ├── images │ │ └── quickstart │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ └── 9.jpg │ └── quickstart.md │ ├── trouble-shooting │ ├── errors.md │ └── faq.md │ ├── usage │ ├── animation.md │ ├── images │ │ ├── animation │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ └── 3.jpg │ │ └── new-template-example │ │ │ ├── 1.jpg │ │ │ ├── 10.jpg │ │ │ ├── 11.jpg │ │ │ ├── 12.jpg │ │ │ ├── 13.jpg │ │ │ ├── 14.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ └── 9.jpg │ └── new-template-example.md │ └── user-interface │ ├── 3d-view-panel.md │ ├── hot-keys.md │ ├── images │ ├── 3d-view-panel │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.png │ └── node-editor-panel │ │ └── 1.jpg │ └── node-editor-panel.md ├── requirements.txt ├── scripts ├── addon-watcher.xml ├── addon_watcher.py ├── create_release.py └── dev_helpers.py ├── send2ue ├── __init__.py ├── constants.py ├── core │ ├── __init__.py │ ├── export.py │ ├── extension.py │ ├── formatting.py │ ├── ingest.py │ ├── io │ │ ├── __init__.py │ │ └── fbx.py │ ├── settings.py │ ├── utilities.py │ └── validations.py ├── dependencies │ ├── __init__.py │ ├── remote_execution.py │ ├── rpc │ │ ├── __init__.py │ │ ├── base_server.py │ │ ├── blender_server.py │ │ ├── client.py │ │ ├── exceptions.py │ │ ├── factory.py │ │ ├── server.py │ │ ├── unreal_server.py │ │ └── validations.py │ └── unreal.py ├── operators.py ├── properties.py ├── release_notes.md ├── resources │ ├── extensions │ │ ├── affixes.py │ │ ├── combine_assets.py │ │ ├── create_post_import_assets_for_groom.py │ │ ├── instance_assets.py │ │ ├── ue2rigify.py │ │ ├── use_collections_as_folders.py │ │ └── use_immediate_parent_name.py │ ├── setting_templates │ │ └── default.json │ └── settings.json └── ui │ ├── __init__.py │ ├── addon_preferences.py │ ├── dialog.py │ ├── file_browser.py │ └── header_menu.py ├── tests ├── .gitignore ├── run_tests.py ├── test_files │ ├── blender_files │ │ ├── cubes.blend │ │ └── mannequins.blend │ ├── fbx_files │ │ └── ThirdPersonRun.FBX │ ├── send2ue_extensions │ │ └── example_extension.py │ ├── send2ue_templates │ │ ├── default.json │ │ └── template_1.json │ └── unreal_projects │ │ └── test01 │ │ ├── Config │ │ ├── DefaultEditor.ini │ │ ├── DefaultEngine.ini │ │ └── DefaultGame.ini │ │ └── test01.uproject ├── test_send2ue_core.py ├── test_send2ue_cubes.py ├── test_send2ue_extension_affixes.py ├── test_send2ue_extension_combine_assets.py ├── test_send2ue_extension_create_post_import_assets_for_groom.py ├── test_send2ue_extension_example.py ├── test_send2ue_extension_instance_assets.py ├── test_send2ue_extension_use_collections_as_folders.py ├── test_send2ue_extension_use_immediate_parent_name.py ├── test_send2ue_mannequins.py ├── test_ue2rigify_core.py ├── test_ue2rigify_mannequins.py └── utils │ ├── __init__.py │ ├── addon_packager.py │ ├── base_test_case.py │ ├── blender.py │ └── container_test_manager.py ├── tox.ini └── ue2rigify ├── __init__.py ├── constants.py ├── core ├── __init__.py ├── nodes.py ├── scene.py ├── templates.py ├── utilities.py └── validations.py ├── operators.py ├── properties.py ├── release_notes.md ├── resources └── rig_templates │ ├── female_mannequin │ ├── control_metadata.json │ ├── fk_to_source_links.json │ ├── fk_to_source_nodes.json │ ├── metarig.py │ ├── source_to_deform_links.json │ └── source_to_deform_nodes.json │ └── male_mannequin │ ├── fk_to_source_links.json │ ├── fk_to_source_nodes.json │ ├── metarig.py │ ├── source_to_deform_links.json │ └── source_to_deform_nodes.json ├── settings ├── __init__.py ├── tool_tips.py └── viewport_settings.py └── ui ├── __init__.py ├── addon_preferences.py ├── exporter.py ├── node_editor.py └── view_3d.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig https://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{py,md,scss}] 12 | indent_size = 4 13 | indent_style = space 14 | 15 | [*.{yaml,yml,html}] 16 | indent_size = 2 17 | indent_style = space 18 | 19 | [Dockerfile] 20 | indent_size = 4 21 | indent_style = space 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Before creating an issue DO THIS FIRST! 11 | Search the existing [issues](https://github.com/EpicGamesExt/BlenderTools/issues?q=) 12 | 13 | ## Bug 14 | ### IMPORTANT: Do this before you create a bug ticket! 15 | 1. Remove the addon. 16 | 1. Shutdown Blender. 17 | 1. Download and install the latest addon version. 18 | 1. Start Blender. 19 | 1. Install the latest addon. 20 | 1. If the bug still exists, report it by copying the info below into a new issue. 21 | 22 | Create a **Title** with the addon name first i.e. Send to Unreal - `````` 23 | 24 | ### In the description paste in and edit the following: 25 | * **Addon:** i.e Send to Unreal 26 | * **Steps to Reproduce the Problem:** i.e. I clicked Pipeline > Export > Send to Unreal 27 | * **Error Log:** Paste the full error log 28 | * **OS:** i.e.Windows, Mac, Linux 29 | * **Addon Version:** i.e. Send to Unreal 1.4.0 30 | * **Blender Version:** i.e. Blender 2.83 31 | * **Unreal Version:** i.e. Unreal 4.25 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/community_extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Send to Unreal Community Extension 3 | about: Create a request to have your extension listed on the Send to Unreal docs as a community extension. 4 | title: '' 5 | labels: send2ue-community-extension 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Checklist: 11 | 1. Is the extension code in a public GitHub repo? 12 | 1. Does the extension have a link to publicly available documentation or a README? 13 | 1. Does the extension have passing test cases when run in the Send to Unreal testing environment? 14 | 15 | Give a brief description of your extension and why you think it would be valuable for others. 16 | 17 | ### Notice: 18 | We reserve the right to remove your extension from the community page for these or any other reasons: 19 | * Out of date code that no longer runs with the latest supported version of Send to Unreal. 20 | * Malicious or suspicious activity 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/community_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: UE to Rigify Community Template 3 | about: Create a request to have your template listed on the UE to Rigify docs as a community template. 4 | title: '' 5 | labels: ue2rigify-community-template 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Checklist: 11 | 1. Is the template in a public GitHub repo? 12 | 1. Does the template have a link to public README describing the template and what rig it is designed for? 13 | 14 | Give a brief description of your template and why you think it would be valuable for others. 15 | 16 | ### Notice: 17 | We reserve the right to remove your template from the community page for these or any other reasons: 18 | * Out of date template that is no longer compatible with the latest supported version of UE to Rigify. 19 | * Malicious or suspicious activity 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project. 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Before creating an issue DO THIS FIRST! 11 | Search the existing [issues](https://github.com/EpicGamesExt/BlenderTools/issues?q=) 12 | 13 | ## Feature 14 | ### IMPORTANT: Do this before you create a feature ticket! 15 | 1. Search the Documentation. 16 | 1. Watch all the videos in the documentation. 17 | 1. If the action you are trying to do is currently not possible, or you think a pretty good case can be made for having a specific set of actions automated, create an issue with a **'discussion'** label so other users can chime in and discuss the new workflow the new feature. 18 | 1. Once the workflow is agreed on create a new feature issue close by copying the info below. Leave links to the new feature issues, and then close the discussion issue. 19 | 20 | Create a **Title** with the addon name first i.e. UE to Rigify - `````` 21 | 22 | ### In the description paste in and edit the following: 23 | * **Addon:** i.e UE to Rigify 24 | * **Workflow:** i.e. Select a bone, then hit a hot key and get a pie menu with 2 options. 25 | * **Description:** i.e. For this two work you would need to create 2 new operator that are specific to only the 3D view... etc. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question. 4 | title: '' 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Before creating an issue DO THIS FIRST! 11 | Search the existing [issues](https://github.com/EpicGamesExt/BlenderTools/issues?q=) 12 | 13 | ## Questions 14 | ### IMPORTANT: Do this before you create a question ticket! 15 | 1. Search the Documentation. 16 | 1. Search the FAQ to see if your question was already asked. 17 | 1. If question you have is not covered in the documentation or the FAQ, feel free to create a issue. 18 | 19 | Create a **Title** with the addon name first i.e. UE to Rigify - `````` 20 | 21 | ### In the description paste in and edit the following: 22 | * **Addon:** i.e UE to Rigify 23 | * **Question:** i.e. How do you export a template? 24 | -------------------------------------------------------------------------------- /.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: "npm" # See documentation for possible values 9 | directory: "/docs" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | .temp 4 | .cache 5 | *.pyc 6 | *.log 7 | *~ 8 | *.swp 9 | /venv/* 10 | release/* 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Directions on how to contribute can be found [here](https://epicgamesext.github.io/BlenderTools/contributing/development.html). -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 - 2024 Epic Games, Inc. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | icon 3 |

4 |

Blender Tools

5 |

6 | 7 | A repository of blender addons that improve the game development workflow between Blender and Unreal Engine. 8 | 9 | ## Send to Unreal 10 | 11 | ![4](docs/main/images/send2ue/4.gif) 12 | 13 | A one-click solution for sending assets from Blender to Unreal Engine. 14 | 15 | * [Read Docs](https://epicgamesext.github.io/BlenderTools/send2ue/) 16 | * [Download Addon](https://github.com/EpicGamesExt/BlenderTools/releases?q=Send+to+Unreal&expanded=true) 17 | 18 | 19 | ## UE to Rigify 20 | 21 | ![2](./docs/main/images/ue2rigify/2.png) 22 | 23 | A node based retargeting system for Blender's 24 | [Rigify](https://docs.blender.org/manual/en/latest/addons/rigging/rigify/index.html) addon. Quickly retarget and author 25 | new animation on unreal marketplace assets and more! 26 | 27 | * [Read Docs](https://epicgamesext.github.io/BlenderTools/ue2rigify/) 28 | * [Download Addon](https://github.com/EpicGamesExt/BlenderTools/releases?q=UE+to+Rigify&expanded=true) 29 | 30 | 31 | ## Help Contribute 32 | Contributions are encouraged! Find out how you can contribute to this repo in one of the following ways: 33 | 34 | * [Help Develop](https://epicgamesext.github.io/BlenderTools/contributing/development.html) 35 | * [Help Document](https://epicgamesext.github.io/BlenderTools/contributing/documentation.html) 36 | * [Help Test](https://epicgamesext.github.io/BlenderTools/contributing/testing.html) 37 | 38 | 39 | ## Get Notified on a New Release 40 | Never miss a new addon release! Do this: 41 | 1. At the top right of this page select `Watch` 42 | 1. Select `Custom` from the dropdown. 43 | 1. Check `Releases` 44 | 1. Click `Apply`. 45 | 46 | You will now get an email notification everytime there is a new version of an addon released. 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | dist 4 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | pids 2 | logs 3 | node_modules 4 | npm-debug.log 5 | coverage/ 6 | run 7 | dist 8 | .DS_Store 9 | .nyc_output 10 | .basement 11 | config.local.js 12 | basement_dist 13 | -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | builds-docs: 5 | image: node:18-alpine 6 | volumes: 7 | - ./:/tmp/docs 8 | environment: 9 | PROD: 1 10 | GA_ID: $GA_ID 11 | working_dir: /tmp/docs 12 | entrypoint: npm 13 | command: run build 14 | -------------------------------------------------------------------------------- /docs/main/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | const {description, repository} = require('../../package') 2 | const { getRootPath } = require('../../path') 3 | import { defaultTheme } from '@vuepress/theme-default' 4 | import { defineUserConfig } from '@vuepress/cli' 5 | import { palettePlugin } from '@vuepress/plugin-palette' 6 | // @ts-ignore 7 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' 8 | 9 | 10 | export default defineUserConfig({ 11 | title: 'Documentation', 12 | description: description, 13 | base: getRootPath(), 14 | theme: defaultTheme({ 15 | repo: repository, 16 | docsDir: 'docs/main', 17 | editLinkText: 'Help us improve this page!', 18 | lastUpdated: false, 19 | 20 | navbar: [ 21 | { 22 | text: 'Home', 23 | link: '/', 24 | } 25 | ], 26 | sidebar: { 27 | '/': [ 28 | { 29 | text: 'Blender', 30 | children: [ 31 | '/' 32 | ] 33 | }, 34 | { 35 | text: 'Contributing', 36 | children: [ 37 | '/contributing/development', 38 | '/contributing/documentation', 39 | '/contributing/testing', 40 | ] 41 | } 42 | ], 43 | } 44 | }), 45 | 46 | plugins: [ 47 | palettePlugin({preset: 'sass'}), 48 | googleAnalyticsPlugin({id: process.env.GA_ID}) 49 | ] 50 | }) 51 | -------------------------------------------------------------------------------- /docs/main/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | // brand colors 3 | --c-brand: #4289b9 !important; 4 | --c-brand-light: #469fcd !important; 5 | 6 | // custom container colors 7 | --c-tip: #469fcd !important; 8 | --c-text-accent: #4289b9 !important; 9 | } 10 | -------------------------------------------------------------------------------- /docs/main/contributing/documentation.md: -------------------------------------------------------------------------------- 1 | # Help Document 2 | Having accurate and up to date documentation is important, so that is why we have made it easy to submit changes to our documentation. All the documentation pages are written in markdown, but html tags are supported. 3 | 4 | ## Editing a Page 5 | To edit an existing page, click the link "Help us improve this page!" in the footer of the page you want to edit. 6 | 7 | ![1](./images/documentation/1.png) 8 | 9 | You will then be prompted to make your own fork of the repository. Click 'Fork this repository'. 10 | 11 | ![2](./images/documentation/2.jpg) 12 | 13 | Edit the markdown file and click 'Propose changes'. 14 | 15 | ![3](./images/documentation/3.jpg) 16 | 17 | Then create a pull request. 18 | 19 | ![4](./images/documentation/4.jpg) 20 | 21 | After your pull request is merged in a new deployment of the site will be made. 22 | 23 | ## Testing Locally 24 | The documentation sites are static html sites that are generated using vuepress. To get up and running with vuepress. 25 | packages are managed by `npm`. So first install the latest version of [node](https://nodejs.org/en/) 26 | Once you have node and npm installed switch to the `/docs` folder and start the server for the site you want to preview by 27 | running these commands: 28 | 29 | ``` shell 30 | cd ./docs 31 | npm install 32 | npm run dev-main 33 | ``` 34 | 35 | The site should now be available to preview at: 36 | 37 | [http://localhost:8080/](http://localhost:8080/) 38 | 39 | There are multiple sites in the `docs` folder each site can be run like so: 40 | * `npm run dev-main` 41 | * `npm run dev-send2ue` 42 | * `npm run dev-ue2rigify` 43 | 44 | For further information on how to customize this site check out 45 | the [vuepress documentation](https://v2.vuepress.vuejs.org/) 46 | 47 | ::: tip Note 48 | If you notice a local site taking longer than expected to load, the issue may be caused by browser plugins 49 | (ex: adblock). Disable browser plugins that may block .gif content to resolve the issue. 50 | ::: 51 | 52 | # Building 53 | All the sites get built into a single static html site when running: 54 | ```shell 55 | cd ./docs 56 | docker-compose up 57 | ``` 58 | 59 | If successful, a `dist` folder should get generated in the `docs` folder. These files are what is deployed to the server. 60 | You can serve them locally with: 61 | ```shell 62 | python -m http.server --directory ./dist 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/main/contributing/images/development/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/development/1.jpg -------------------------------------------------------------------------------- /docs/main/contributing/images/development/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/development/2.jpg -------------------------------------------------------------------------------- /docs/main/contributing/images/development/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/development/3.png -------------------------------------------------------------------------------- /docs/main/contributing/images/development/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/development/4.png -------------------------------------------------------------------------------- /docs/main/contributing/images/documentation/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/documentation/1.png -------------------------------------------------------------------------------- /docs/main/contributing/images/documentation/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/documentation/2.jpg -------------------------------------------------------------------------------- /docs/main/contributing/images/documentation/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/documentation/3.jpg -------------------------------------------------------------------------------- /docs/main/contributing/images/documentation/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/contributing/images/documentation/4.jpg -------------------------------------------------------------------------------- /docs/main/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/1.png -------------------------------------------------------------------------------- /docs/main/images/send2ue/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/send2ue/1.gif -------------------------------------------------------------------------------- /docs/main/images/send2ue/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/send2ue/2.png -------------------------------------------------------------------------------- /docs/main/images/send2ue/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/send2ue/4.gif -------------------------------------------------------------------------------- /docs/main/images/ue2rigify/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/ue2rigify/1.gif -------------------------------------------------------------------------------- /docs/main/images/ue2rigify/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/main/images/ue2rigify/2.png -------------------------------------------------------------------------------- /docs/main/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: false 3 | --- 4 | # Addons 5 | 6 | ## Send to Unreal 7 | 8 | ![1](./images/send2ue/1.gif) 9 | 10 | A one-click solution for sending assets from Blender to Unreal Engine. 11 | 12 | * [Read Docs](./send2ue) 13 | * [Download Addon](https://github.com/EpicGamesExt/BlenderTools/releases?q=Send+to+Unreal&expanded=true) 14 | 15 | ::: tip Note 16 | If you get a 404 error when you click the `Download Addon` link above, then you will need to sign in to your github account and link it with your Epic Games account. 17 | Here is a [link with instructions](https://www.unrealengine.com/en-US/ue4-on-github) on how to link your accounts. 18 | ::: 19 | 20 | 21 | ## UE to Rigify 22 | 23 | ![1](./images/ue2rigify/1.gif) 24 | 25 | A node based retargeting system for Blender's 26 | [Rigify](https://docs.blender.org/manual/en/latest/addons/rigging/rigify/index.html) addon. Quickly retarget and author 27 | new animation on unreal marketplace assets and more! 28 | 29 | * [Read Docs](./ue2rigify) 30 | * [Download Addon](https://github.com/EpicGamesExt/BlenderTools/releases?q=UE+to+Rigify&expanded=true) 31 | 32 | 33 | ::: tip Note 34 | If you get a 404 error when you click the `Download Addon` link above, then you will need to sign in to your github account and link it with your Epic Games account. 35 | Here is a [link with instructions](https://www.unrealengine.com/en-US/ue4-on-github) on how to link your accounts. 36 | ::: 37 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BlenderTools", 3 | "version": "0.0.1", 4 | "description": "Blender addons that improve the game development workflow between Blender and Unreal.", 5 | "main": "index.js", 6 | "authors": { 7 | "name": "Epic Games Inc.", 8 | "email": "" 9 | }, 10 | "repository": "https://github.com/EpicGamesExt/BlenderTools", 11 | "scripts": { 12 | "dev-main": "vuepress dev main", 13 | "dev-send2ue": "vuepress dev send2ue", 14 | "dev-ue2rigify": "vuepress dev ue2rigify", 15 | "build": "npm install && rm -f -r dist && vuepress build main && vuepress build send2ue && vuepress build ue2rigify && cp -r ./main/.vuepress/dist ./dist && cp -r ./ue2rigify/.vuepress/dist ./dist/ue2rigify && cp -r ./send2ue/.vuepress/dist ./dist/send2ue" 16 | }, 17 | "license": "MIT", 18 | "dependencies": { 19 | "vuepress": "^2.0.0-rc.0" 20 | }, 21 | "devDependencies": { 22 | "@vuepress/cli": "^2.0.0-beta.66", 23 | "@vuepress/plugin-google-analytics": "^2.0.0-rc.0", 24 | "@vuepress/plugin-palette": "^2.0.0-beta.66" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/path.js: -------------------------------------------------------------------------------- 1 | const {name} = require('./package') 2 | 3 | export const getRootPath = (addon_name='') => { 4 | if (process.env.PROD === '1') { 5 | if (addon_name !== '') 6 | { 7 | return `/${name}/${addon_name}/` 8 | } else { 9 | return `/${name}/` 10 | } 11 | } 12 | if (process.env.TEST === '1') { 13 | if (addon_name !== '') 14 | { 15 | return `/${addon_name}/` 16 | } else { 17 | return '/' 18 | } 19 | } 20 | return '/' 21 | } 22 | -------------------------------------------------------------------------------- /docs/send2ue/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | const {description, repository} = require('../../package') 2 | const { getRootPath } = require('../../path') 3 | import { defaultTheme } from '@vuepress/theme-default' 4 | import { defineUserConfig } from '@vuepress/cli' 5 | import { palettePlugin } from '@vuepress/plugin-palette' 6 | // @ts-ignore 7 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' 8 | 9 | 10 | export default defineUserConfig({ 11 | title: 'Send to Unreal', 12 | description: description, 13 | base: getRootPath('send2ue'), 14 | theme: defaultTheme({ 15 | repo: repository, 16 | docsDir: 'docs/send2ue', 17 | editLinkText: 'Help us improve this page!', 18 | lastUpdated: false, 19 | 20 | navbar: [ 21 | { 22 | text: 'Home', 23 | link: process.env.PROD === '1' ? 'https://epicgamesext.github.io/BlenderTools/' : '/', 24 | target:'_self' 25 | } 26 | ], 27 | sidebar: { 28 | '/': [ 29 | { 30 | text: 'Introduction', 31 | children: [ 32 | '/introduction/quickstart' 33 | ] 34 | }, 35 | { 36 | text: 'Asset Types', 37 | children: [ 38 | '/asset-types/skeletal-mesh', 39 | '/asset-types/static-mesh', 40 | '/asset-types/animation-sequence', 41 | '/asset-types/groom' 42 | ] 43 | }, 44 | { 45 | text: 'Settings', 46 | children: [ 47 | '/settings/paths', 48 | '/settings/export', 49 | '/settings/import', 50 | '/settings/validations', 51 | ] 52 | }, 53 | { 54 | text: 'Customize', 55 | children: [ 56 | '/customize/templates', 57 | '/customize/python-api', 58 | '/customize/extensions' 59 | ] 60 | }, 61 | { 62 | text: 'Supported Extensions', 63 | children: [ 64 | '/extensions/affixes', 65 | '/extensions/combine-assets', 66 | '/extensions/create-post-import-groom-assets', 67 | '/extensions/ue2rigify', 68 | '/extensions/use-immediate-parent-name', 69 | '/extensions/use-collections-as-folders', 70 | '/extensions/instance-assets' 71 | ] 72 | }, 73 | { 74 | text: 'Extras', 75 | children: [ 76 | '/extras/pipeline-menu', 77 | '/extras/addon-preferences', 78 | '/extras/community-extensions', 79 | ] 80 | }, 81 | { 82 | text: 'Trouble Shooting', 83 | children: [ 84 | '/trouble-shooting/faq', 85 | '/trouble-shooting/errors', 86 | ] 87 | } 88 | ], 89 | } 90 | }), 91 | plugins: [ 92 | palettePlugin({preset: 'sass'}), 93 | googleAnalyticsPlugin({id: process.env.GA_ID}) 94 | ] 95 | }) 96 | 97 | -------------------------------------------------------------------------------- /docs/send2ue/.vuepress/public/images/unreal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/.vuepress/public/images/unreal.png -------------------------------------------------------------------------------- /docs/send2ue/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | // brand colors 3 | --c-brand: #4289b9 !important; 4 | --c-brand-light: #469fcd !important; 5 | 6 | // custom container colors 7 | --c-tip: #469fcd !important; 8 | --c-text-accent: #4289b9 !important; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /docs/send2ue/asset-types/groom.md: -------------------------------------------------------------------------------- 1 | # Groom 2 | 3 | ::: warning Required UE Plugins 4 | Make sure to have the unreal plugins "Alembic Groom Importer" and "Groom" enabled for the addon to work properly. 5 | ![3](./images/groom/3.png) 6 | ::: 7 | 8 | ::: warning Required UE Project Setting 9 | Make sure to have the setting "Support Compute Skin Cache" turned on in Project Settings > Engine > Rendering > Optimizations for grooms to render properly when bound to a skeletal mesh. 10 | ![3](./images/groom/4.png) 11 | ::: 12 | 13 | The tool infers an Unreal groom asset based strictly on the content of your `Export` collection. By default, each 14 | particle system of type 'Hair' on each mesh in the collection is exported as an individual alembic file, which is 15 | imported to unreal as a groom asset. 16 | 17 | ![1](./images/groom/1.png) 18 | 19 | ::: tip Combining Groom Assets 20 | To gain more control over how particle systems are exported, use the [_combine assets_](https://epicgamesext.github.io/BlenderTools/send2ue/extensions/combine-assets.html) 21 | extension that has options such as _combine groom for each mesh_ and more. 22 | ::: 23 | 24 | ::: warning 25 | Please give each particle system and curves object a unique name across all meshes. While Blender lets particles on 26 | different meshes share the same name, the addon requires each name to be unique to prevent assets getting overwritten 27 | in Unreal. This is because multiple groom assets can be imported into the same directory in unreal, and any 28 | asset with duplicate names will get overwritten. 29 | 30 | drawing 31 | ::: 32 | 33 | ## Curves Objects 34 | 35 | The Curves object type was introduced in [Blender 3.3](https://www.blender.org/download/releases/3-3/), enabling a revamped hair sculpting workflow. The send2ue addon 36 | supports the export of a curves object into a groom asset in unreal. Under the hood, the addon temporarily converts 37 | the curves object into a hair particle system on the mesh that it’s surfaced to, which would then be exported as an alembic file. 38 | 39 | ## Only Groom 40 | 41 | By default, the groom asset will import along with the mesh asset that it is surfaced to. To run a strictly groom asset 42 | import (meaning no other asset types will be exported from blender and imported to unreal), all import options (mesh, 43 | animation, textures) must be turned off in your [import settings](https://epicgamesext.github.io/BlenderTools/send2ue/settings/import.html) except for `Groom`. Alternatively, 44 | the blender `Curves` objects can be placed in the `Export` collection (without their surface mesh objects) which 45 | denotes an exclusive groom workflow as well. 46 | 47 | ## Binding Assets and More 48 | 49 | The addon provides an extension called [create post import assets for groom](https://epicgamesext.github.io/BlenderTools/send2ue/extensions/create-post-import-groom-assets.html) 50 | to automatically create unreal assets (such as a binding asset) for the imported groom asset. See the extensions section 51 | for more information on its usage. 52 | -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/1.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/2.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/3.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/4.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/5.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/6.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/7.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/animation/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/animation/8.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/groom/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/groom/1.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/groom/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/groom/2.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/groom/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/groom/3.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/groom/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/groom/4.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/1.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/2.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/3.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/4.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/5.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/skeletal-mesh/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/skeletal-mesh/6.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/1.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/2.gif -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/3.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/4.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/5.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/6.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/7.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/images/static-mesh/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/asset-types/images/static-mesh/8.png -------------------------------------------------------------------------------- /docs/send2ue/asset-types/skeletal-mesh.md: -------------------------------------------------------------------------------- 1 | # Skeletal Mesh 2 | 3 | The tool infers an Unreal Skeletal Mesh asset based strictly on the content of your `Export` collection. Here is what 4 | it is doing: 5 | 6 | 7 | ![overview](./images/skeletal-mesh/overview.svg) 8 | 9 | ::: tip Note 10 | The armature placed in the `Export` collection must be responsible for deformation, meaning only bones that are 11 | skinned to a mesh. No bones used for control schemes should be put in the `Export` collection. 12 | ::: 13 | 14 | ![1](./images/skeletal-mesh/1.gif) 15 | 16 | The important thing to remember is that only armatures and meshes inside that collection can be used to build the data for the 17 | skeletal mesh export and import. 18 | 19 | ![2](./images/skeletal-mesh/2.gif) 20 | 21 | As you can see, a related mesh and armature combination results in an Unreal Skeletal Mesh asset being generated along with 22 | Materials, a Skeleton, and a Physics Asset. Also notice that the Skeletal Mesh name matches the mesh name in blender, as well 23 | as the skeleton and physics asset with `_Skeleton` and `_PhysicsAsset` post fixed respectively. 24 | 25 | 26 | To run a strictly skeletal mesh import(meaning no animation will be exported), the animations import option must be 27 | turned off in your [Import](/settings/import.html#animation) settings. 28 | 29 | ![3](./images/skeletal-mesh/3.png) 30 | 31 | ## LODs 32 | 33 | LOD workflows for skeletal meshes are supported. Simply activate the LODs option in the LOD Settings group and Send to 34 | Unreal will handle exporting and importing each LOD. 35 | 36 | ![4](./images/skeletal-mesh/4.png) 37 | 38 | 39 | There is a sub category for skeletal meshes that allows you to specify a path to a LOD Settings data asset in your 40 | Unreal project. This can be referenced directly to automatically set your skeletal 41 | mesh lod settings. 42 | 43 | ![5](./images/skeletal-mesh/5.png) 44 | 45 | ::: tip Note 46 | If your mesh has a LOD naming scheme and Import LODs is true, the LOD postfix will get stripped out of the final asset name based on the lod regex. For 47 | example 48 | `SK_Mannequin_LOD0 = SK_Mannequin` 49 | ::: 50 | 51 | Also notice that the LOD build settings can be set under the 52 | `Import > Editor Settings > Skeletal Mesh LOD Build Settings` group. 53 | 54 | ![6](./images/skeletal-mesh/6.png) 55 | 56 | ::: tip Note 57 | The Editor Settings corresponds to what is available in the [EditorSkeletalMeshLibrary](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/EditorSkeletalMeshLibrary.html) in the Unreal Python API: 58 | ::: 59 | 60 | ## Only Mesh 61 | 62 | To run a strictly mesh asset import (ex: excluding import of particle systems as groom assets), all import options 63 | must be turned off in your [import settings](/settings/import.html) except for `Mesh`. 64 | -------------------------------------------------------------------------------- /docs/send2ue/asset-types/static-mesh.md: -------------------------------------------------------------------------------- 1 | # Static Mesh 2 | 3 | Static meshes are simple. The tool looks in the `Export` set for objects of type `MESH` and sends them to unreal as 4 | individual Static Mesh assets to unreal. 5 | 6 | 7 | ![1](./images/static-mesh/1.gif) 8 | 9 | In this example, you can see the result is two Unreal Static Mesh assets along with their material. 10 | 11 | ![2](./images/static-mesh/2.gif) 12 | 13 | 14 | ## LODs 15 | 16 | LOD workflows for static meshes are supported. Simply activate the LODs option in the LOD Settings group and Send to 17 | Unreal will handle exporting and importing each LOD. 18 | 19 | ![3](./images/static-mesh/3.png) 20 | 21 | 22 | ::: tip Note 23 | If your mesh has a LOD naming scheme and Import LODs is true, the LOD postfix will get stripped out of the final asset name based on the lod regex. For 24 | example: 25 | 26 | `pCube1_LOD0 = pCube1` 27 | 28 | `pCube2_lod0_mesh = pCube2` 29 | ::: 30 | 31 | Also notice that the LOD build settings can be set under the 32 | `Import > Editor Settings > Static Mesh LOD Build Settings` group. 33 | 34 | ![4](./images/static-mesh/4.png) 35 | 36 | ::: tip Note 37 | The Editor Settings corresponds to what is available in the [EditorStaticMeshLibrary](https://docs.unrealengine.com/5.0/en-US/PythonAPI/class/EditorStaticMeshLibrary.html) in the Unreal Python API: 38 | ::: 39 | 40 | ## Collisions 41 | 42 | Simple collision workflows for static meshes are supported by prefixing your collision names with their respective identifiers and making them a child of the mesh. 43 | | Mesh Prefix and Name | Description | 44 | | -------------- | ----------------------- | 45 | | `UBX_[RenderMeshName]_##` | A Box must be created using a regular rectangular 3D object. You cannot move the vertices around or deform it in any way to make it something other than a rectangular prism, or else it will not work. | 46 | | `UCP_[RenderMeshName]_##` | A Capsule must be a cylindrical object capped with hemispheres. It does not need to have many segments (8 is a good number) at all because it is converted into a true capsule for collision. Like boxes, you should not move the individual vertices around.| 47 | | `USP_[RenderMeshName]_##` | A Sphere does not need to have many segments (8 is a good number) at all because it is converted into a true sphere for collision. Like boxes, you should not move the individual vertices around. | 48 | | `UCX_[RenderMeshName]_##` | A Convex object can be any completely closed convex 3D shape. For example, a box can also be a convex object. | 49 | 50 | The underlying mechanism for this is the Unreal FBX importer, so for further information, please refer to the [FBX Guide for static meshes](https://docs.unrealengine.com/5.0/en-US/WorkingWithContent/Importing/FBX/StaticMeshes/). 51 | 52 | 53 | ![5](./images/static-mesh/5.png) 54 | 55 | Collisions are imported with the asset that matches the `[RenderMeshName]` after the collision prefix. 56 | 57 | ![6](./images/static-mesh/6.png) 58 | 59 | ::: tip Note 60 | Collisions must be in the `Export` collection to be exported. 61 | ::: 62 | 63 | ## Sockets 64 | 65 | There is a supported workflow for adding sockets to static meshes. 66 | 67 | ![8](./images/static-mesh/7.png) 68 | 69 | Any child mesh that has the pre fix `SOCKET_` in its name will be separately imported as a socket of its parent. 70 | 71 | ![9](./images/static-mesh/8.png) 72 | 73 | ::: tip Note 74 | Socket names have the `SOCKET_` prefix stripped out. `SOCKET_socket_01` in blender becomes `socket_01` in unreal. 75 | ::: 76 | 77 | ## Only Mesh 78 | 79 | To run a strictly mesh asset import (ex: excluding import of particle systems as groom assets), all import options 80 | must be turned off in your [import settings](/settings/import.html) except for `Mesh`. 81 | -------------------------------------------------------------------------------- /docs/send2ue/customize/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/1.jpg -------------------------------------------------------------------------------- /docs/send2ue/customize/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/2.jpg -------------------------------------------------------------------------------- /docs/send2ue/customize/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/3.jpg -------------------------------------------------------------------------------- /docs/send2ue/customize/images/extensions/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/extensions/2.png -------------------------------------------------------------------------------- /docs/send2ue/customize/images/extensions/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/extensions/3.png -------------------------------------------------------------------------------- /docs/send2ue/customize/images/extensions/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/extensions/4.png -------------------------------------------------------------------------------- /docs/send2ue/customize/images/python/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/python/1.png -------------------------------------------------------------------------------- /docs/send2ue/customize/images/templates/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/templates/1.gif -------------------------------------------------------------------------------- /docs/send2ue/customize/images/templates/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/customize/images/templates/2.gif -------------------------------------------------------------------------------- /docs/send2ue/customize/python-api.md: -------------------------------------------------------------------------------- 1 | # Python API 2 | Send to Unreal was designed to handle the generation of Unreal asset types. However, it does not handle every possible 3 | scenario that your production might need. That is why the tool has a programmable python interface that allows the 4 | user to set properties and to automate processes before and after the Send to Unreal operation. 5 | 6 | ## Properties 7 | All of the properties can be accessed directly on the following scene data object in the blender API. 8 | ```python 9 | bpy.context.scene.send2ue 10 | ``` 11 | 12 | ::: tip Note 13 | This scene property data is persistent and stored within your blend file. If your blend file is saved, 14 | then the state of your scene properties gets saved into the file as well. 15 | ::: 16 | 17 | To find the name of the property you want to read or edit, you can use the blender python console and the tab key to list 18 | the properties, or open the Send to Unreal Settings Dialog and hover on a property. Under the tool tip you will see the API reference for 19 | the desired property. 20 | 21 | 22 | ![1](./images/python/1.png) 23 | 24 | ## Operators 25 | Operators are just callable methods that have been registered in a submodule of the Blender API. The listed 26 | operators should allow you to do anything that is possible to do from the Send to Unreal menu as well as the 27 | Settings Dialog. 28 | 29 | ### Send to Unreal 30 | Quickly send your assets to an open Unreal editor instance without a dialog, 31 | ```python 32 | bpy.ops.wm.send2ue() 33 | ``` 34 | 35 | ### Settings Dialog 36 | Open the settings dialog to modify the tool properties, 37 | ```python 38 | bpy.ops.wm.settings_dialog() 39 | ``` 40 | 41 | ### Import Asset 42 | Import a file that came from Unreal, 43 | ```python 44 | bpy.ops.wm.import_asset() 45 | ``` 46 | 47 | ### Create Pre-defined Collections 48 | Create the predefined collections that are needed for data collection (Export). 49 | ```python 50 | bpy.ops.send2ue.create_predefined_collections() 51 | ``` 52 | 53 | ### Save Template 54 | Saves the current state of the properties to the specified template file. 55 | - param `str` `filepath` The full path of the template file. 56 | ```python 57 | bpy.ops.send2ue.save_template(filepath: str) 58 | ``` 59 | 60 | ### Load Template 61 | Loads the specified template file into the template folder location. 62 | - param `str` `filepath` The full path of the template file. 63 | ```python 64 | bpy.ops.send2ue.load_template(filepath: str) 65 | ``` 66 | 67 | ### Remove Template 68 | Remove the settings template that is currently selected as active. 69 | ```python 70 | bpy.ops.send2ue.remove_template() 71 | ``` 72 | 73 | ### Reload Extensions 74 | Reload the extensions files. If changes are made to the extension code, this should be called to reload the code. 75 | ```python 76 | bpy.ops.send2ue.reload_extensions() 77 | ``` 78 | 79 | ### Start RPC Servers 80 | Bootstraps Unreal and Blender with RPC server threads so that they are ready for remote calls. 81 | ```python 82 | bpy.ops.send2ue.start_rpc_servers() 83 | ``` 84 | 85 | ## Examples 86 | 87 | ::: tip Change Template Example 88 | Here is how you could automate loading a settings template from a file and making it the active template. 89 | ```python 90 | import bpy 91 | 92 | # load the file into the template folder location 93 | bpy.ops.send2ue.load_template(filepath=r'C:/some/file/path/my_template.json') 94 | 95 | # set the active template which modifies the state of the properties 96 | bpy.context.scene.send2ue.active_settings_template = 'my_template.json' 97 | ``` 98 | ::: 99 | 100 | ::: tip Change Properties Example 101 | Here is how you could use Python to dynamically change the mesh import folder of your asset. 102 | ```python 103 | import bpy 104 | 105 | # set the mesh import folder 106 | folder_name = some_custom_function_that_gets_a_folder_name() 107 | bpy.context.scene.send2ue.unreal_mesh_folder_path = f'/Game/{folder_name}/' 108 | 109 | # run send to unreal 110 | bpy.ops.wm.send2ue() 111 | ``` 112 | ::: 113 | 114 | 115 | The same process can be used to dynamically set any property on the Send to Unreal tool. 116 | 117 | -------------------------------------------------------------------------------- /docs/send2ue/customize/templates.md: -------------------------------------------------------------------------------- 1 | # Templates 2 | A powerful feature of Send to Unreal is that you can configure `Setting Templates` which are just json files that can 3 | be shared among your team members. These templates contain the values of every Send to Unreal property in the tool. This 4 | could be useful to help "standardize" your pipeline by ensuring everyone is using the correct export 5 | and import settings, or just help speed up a workflow by minimizing clicks. 6 | 7 | ## Saving a Template 8 | A template can be saved within the Settings Dialog. Take the following example of saving your settings 9 | that have been configured to support LODs. 10 | 11 | ![1](./images/templates/1.gif) 12 | 13 | 14 | Once your properties are set to your liking you can click `Save` then choose a location 15 | and a file name for your template on disk. This file can be shared with your team or you can load it in to use 16 | later. 17 | 18 | ## Loading a Template 19 | A template can be loaded within the Settings Dialog. Continuing with the example above, we can load in the settings 20 | template that has been configured to for LODs. Click `Load` then choose the location of the template file on disk. 21 | 22 | ![2](./images/templates/2.gif) 23 | 24 | ::: tip Note 25 | The properties won't change until the active template is selected from the dropdown. Loading the template 26 | makes the template available in the dropdown, but does not modify the properties. 27 | ::: 28 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/affixes.md: -------------------------------------------------------------------------------- 1 | # Affixes 2 | 3 | The Affixes extension provides a convenient way to enforce prefix or postfix naming conventions on 4 | assets of a particular type. Currently, supported asset types are: 5 | * `Static Mesh` 6 | * `Skeletal Mesh` 7 | * `Animation Sequence` 8 | * `Material` 9 | * `Texture` 10 | 11 | ## Properties 12 | ### Automatically add affixes on export 13 | If true, this will automatically add the affixes (prefix/suffix) by renaming all assets that are currently in the 14 | `Export` collection when the Send to Unreal operation runs. 15 | 16 | ### Automatically remove affixes after export 17 | If true, this will automatically remove the affixes (prefix/suffix) by renaming all assets that are currently in the 18 | `Export` collection after the Send to Unreal operation runs. 19 | 20 | 21 | ::: tip Note 22 | This will rename the objects in Blender, like Meshes, Textures, Materials and Actions. Be aware that this will also rename the texture image files on your hard-disk. 23 | ::: 24 | 25 | ## UI 26 | The settings can be found under the `Export` tab 27 | 28 | 29 | ## Utility Operators 30 | ### Add Asset Affixes 31 | Adds the affixes (prefix/suffix) by renaming all assets that are currently in the `Export` collection. 32 | 33 | ### Removes Asset Affixes 34 | Removes the affixes (prefix/suffix) by renaming all assets that are currently in the `Export` collection. 35 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/combine-assets.md: -------------------------------------------------------------------------------- 1 | # Combine Assets 2 | 3 | The _Combine Assets_ extension provides a convenient way to combine blender objects into one unreal asset. There are 4 4 | options, each provides a different way to customize your export. 5 | 6 | ## Overview 7 | ![1](./images/combine-assets/1.png) 8 | 9 | ## Properties 10 | ## Combine 11 | #### _off_ 12 | This exports each object and particle system in the `Export` collection as individual assets. 13 | 14 | off 15 | 16 | #### _child meshes_ 17 | For each empty object or armature parent, this combines its child meshes into a single mesh when exported. 18 | 19 | child_meshes 20 | 21 | #### _groom per mesh_ 22 | For each mesh in the Export collection, this combines every hair objects/systems surfaced on the mesh as a single groom asset. 23 | 24 | groom_per_mesh 25 | 26 | #### _groom per combined mesh_ 27 | For each empty object or armature parent, this combines its child meshes into a single mesh when exported. 28 | For each combined mesh, all hair objects/systems surfaced on it export as a single groom asset. 29 | 30 | groom_per_combined_mesh 31 | 32 | ## UI 33 | The settings can be found under the `Export` tab 34 | 35 | ## Static Meshes 36 | For options _**child meshes**_, and _**groom per combined mesh**_, all child meshes under an empty 37 | will be combined into one static mesh using the name of the empty. 38 | 39 | ![0](./images/combine-assets/0.png) 40 | 41 | In this example the name of the combine static mesh in unreal would be `CombinedCubes` 42 | 43 | ::: tip Note 44 | When using this with custom collisions, each collision name must correspond to each mesh name, not the final 45 | combined Static Mesh asset name. 46 | 47 | In this example the final name of the combined asset is `S_Boards_Platform_1x1` and all the collisions below match 48 | to each mesh within the combined asset. 49 | 50 | ![3](./images/combine-assets/3.png) 51 | 52 | ::: 53 | 54 | ## Skeletal Meshes 55 | For options _**child meshes**_, and **_groom per combined mesh_**, all child meshes under an armature 56 | will be combined into one skeletal mesh using the name of the first child mesh in alphanumerical order by object name 57 | (the default order of objects in the blender outliner). 58 | 59 | ::: tip Note 60 | This might not give you enough control over the skeletal mesh name, so using the 61 | [immediate parent name](https://epicgamesext.github.io/BlenderTools/send2ue/extensions/use-immediate-parent-name.html) 62 | extension can be useful. 63 | ::: 64 | 65 | ![2](./images/combine-assets/2.png) 66 | 67 | In this example the name of the combine skeletal mesh in unreal would be `SK_Mannequin_Female` 68 | 69 | ## Groom 70 | * For the options _**off**_ and _**child meshes**_, each particle system and curves object exports as an individual alembic file. 71 | The imported groom asset takes on the name of the particle system or curves object. 72 | 73 | * For the option _**groom per mesh**_ and _**groom per combined mesh**_, all particle systems and curves objects surfaced to one mesh 74 | will be combined into one groom asset using the name of their surface mesh post fixed with `_Groom`. 75 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/create-post-import-groom-assets.md: -------------------------------------------------------------------------------- 1 | # Create Post Import Assets For Groom 2 | The _Create Post Import Assets For Groom_ extension provides a convenient way to create additional unreal assets related to the 3 | imported groom asset. 4 | 5 | ![0](./images/create-post-import-groom-assets/0.png) 6 | 7 | ## Properties 8 | ### Groom Binding Asset 9 | This creates a binding asset for the imported groom asset. The target skeletal mesh is the hair's surface mesh in blender 10 | that is part of the same import. For this option to work correctly, the _import mesh_ and _import groom_ options in the 11 | [import settings](https://epicgamesext.github.io/BlenderTools/send2ue/settings/import.html) must be turned on. 12 | 13 | The binding asset will use the name of the groom asset and the name of the target skeletal mesh post fixed with `_Binding`. 14 | Note this is the unreal convention of naming binding assets. 15 | 16 | For example, a groom asset sourced from a particle system named `hair` with a surface mesh named `SK_Mannequin_Female` 17 | will yield a binding asset named `hair_SK_Mannequin_Female_Binding`. 18 | 19 | ::: tip Note 20 | A binding asset can only be created when the groom's surface mesh is a [skeletal mesh](https://epicgamesext.github.io/BlenderTools/send2ue/asset-types/skeletal-mesh.html). 21 | ::: 22 | 23 | ### Blueprint Asset with Groom 24 | This creates a blueprint asset for each imported skeletal mesh and its surface hairs. The blueprint asset will have 25 | one skeletal mesh component and one or more groom components created from the imported mesh and groom assets. The 26 | blueprint asset uses the name of the skeletal mesh asset with a postfix `_BP`. 27 | 28 | - In the example below, a blueprint asset created with the skeletal mesh `SK_Mannequin` is named `SK_Mannequin_BP`. 29 | There are multiple hair systems surfaced on the mesh object `SK_Mannequin`, which results in a groom 30 | component created for each groom asset imported. 31 | 32 | 2 33 | 34 | ::: tip Note 35 | Each groom component is automatically populated with a groom asset and a binding asset that connects the groom to the 36 | skeletal mesh in the skeletal mesh component. For this reason, the _**binding asset**_ option must be turned 37 | on for the _**blueprint asset with groom binding**_ option to work correctly. 38 | ::: 39 | 40 | ## UI 41 | The settings can be found under the `Import` tab 42 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/0.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/1.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/2.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/3.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/4.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/5.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/child_meshes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/child_meshes.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/groom_per_combined_mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/groom_per_combined_mesh.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/groom_per_mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/groom_per_mesh.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-assets/off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-assets/off.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-meshes/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-meshes/1.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-meshes/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-meshes/2.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/combine-meshes/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/combine-meshes/3.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/create-post-import-groom-assets/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/create-post-import-groom-assets/0.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/create-post-import-groom-assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/create-post-import-groom-assets/2.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/use-immediate-parent-name/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/use-immediate-parent-name/0.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/images/use-immediate-parent-name/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extensions/images/use-immediate-parent-name/1.png -------------------------------------------------------------------------------- /docs/send2ue/extensions/instance-assets.md: -------------------------------------------------------------------------------- 1 | # Instance Assets 2 | Spawns the imported assets as actors in the active unreal level with a location that matches the world location of 3 | the object in the blender scene. 4 | 5 | ## Properties 6 | ### Place in active level 7 | Spawns assets in the active level at the same location they are positioned in the blender scene. 8 | 9 | This is only supported for the following asset types: 10 | * `StaticMesh` 11 | * `SkeletalMesh` 12 | * `AnimSequence` 13 | 14 | ### Use mesh instances 15 | Instances static and skeletal meshes in the active level. If the data on an object is linked it will not be 16 | re-imported, just instanced. Note that this will force the asset to take on the name of its mesh data, 17 | rather than its object name, and the actors in the unreal level will match the blender object name. 18 | 19 | ### UI 20 | The settings can be found under the `Import` tab 21 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/ue2rigify.md: -------------------------------------------------------------------------------- 1 | # UE to Rigify 2 | 3 | A small extension that can sync up your NLA tracks before export. 4 | 5 | ## Properties 6 | ### Sync control rig tracks to source rig 7 | If enabled and using the UE to Rigify addon in control mode, the NLA tracks of the control rig will be 8 | synced to the source rig before they are exported. 9 | 10 | ## UI 11 | The settings can be found under the `Export` tab 12 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/use-collections-as-folders.md: -------------------------------------------------------------------------------- 1 | # Use Collections as Folders 2 | Let collections in blender persist through the send2ue operation as folders in unreal. 3 | 4 | ## Properties 5 | ### use collections as folders 6 | When active, this uses the collection hierarchy in your scene as sub folders from the specified mesh folder in your unreal project. This setting can be used concurrently with import LODs or combine meshes. 7 | 8 | ## UI 9 | The settings can be found under the `Paths` tab 10 | 11 | ::: warning Exclusive Usage Extension 12 | _Use Collections as Folders_ is an **exclusive usage extension**, which means that an error will be raised if it is used in combination with another exclusive usage extension. 13 | ::: 14 | -------------------------------------------------------------------------------- /docs/send2ue/extensions/use-immediate-parent-name.md: -------------------------------------------------------------------------------- 1 | # Use Immediate Parent Name 2 | Gives the user more control over the naming of the assets sent to unreal with the asset taking on the name of its immediate parent that is either a collection or an empty type object. 3 | 4 | ## Properties 5 | ### use immediate parent name 6 | When active, this makes the immediate parent the name of the asset if the immediate parent is a collection or an empty type object. This setting can be used concurrently with import LODs or combine meshes. 7 | 8 | 0 9 | 10 | In the outliner pictured above, the imported static mesh would be named `Empty_Parent` 11 | 12 | ::: tip Note 13 | A mesh under an armature will take the name of the armature's immediate parent if the immediate parent is an empty type object or a collection. 14 | 15 | 1 16 | 17 | In the outliner pictured above, the imported skeletal mesh would be named `SK_Collection` 18 | ::: 19 | 20 | ### UI 21 | The settings can be found under the `Paths` tab 22 | 23 | ::: warning Exclusive Usage Extension 24 | _Use Immediate Parent Name_ is an **exclusive usage extension**, which means that an error will be raised if it is used in combination with another exclusive usage extension. 25 | ::: 26 | -------------------------------------------------------------------------------- /docs/send2ue/extras/addon-preferences.md: -------------------------------------------------------------------------------- 1 | # Addon Preferences 2 | These preferences can be found by going to `Edit > Preferences > Addons > Send to Unreal` 3 | 4 | ### Automatically create pre-defined collections 5 | This automatically creates the pre-defined collection (Export). 6 | 7 | 8 | ### RPC response timeout 9 | The amount of seconds that blender stops waiting for an unreal response after it has issued a command. This might 10 | need to be increased if you plan on importing really large assets, where the import could be longer then the 11 | timeout value. 12 | 13 | ::: warning 14 | It is not recommended to set the timeout too high. The timeout is a safeguard against freezing blender and unreal 15 | indefinitely. 16 | ::: 17 | 18 | ### Extensions Repo Path 19 | Set this path to the folder that contains your Send to Unreal python extensions. All extensions in this folder 20 | will be automatically loaded. 21 | -------------------------------------------------------------------------------- /docs/send2ue/extras/community-extensions.md: -------------------------------------------------------------------------------- 1 | # Community Extensions 2 | 3 | Send to Unreal extensions are a powerful way for the community to extend the Send to Unreal tool to 4 | support their needs for projects. However, instead of isolating this from the tool, we want to create a free ecosystem 5 | of extensions. As this grows overtime, we want this page to be filled with links to extensions that the community 6 | has authored, and can hopefully help others customize their blender unreal pipelines. 7 | 8 | ## Guidelines 9 | 10 | In order to have your extension linked to this page, several requirements must be met. 11 | 12 | ### Requirements 13 | * Code must be in a public GitHub repo 14 | * Must have a link to publicly available documentation or a README 15 | * Must have passing test cases when run in the Send to Unreal testing environment 16 | 17 | ### Notice 18 | We reserve the right to remove your extension link from this page for these or any other reasons: 19 | * Out of date code that no longer runs with the latest supported version of Send to Unreal. 20 | * Malicious or suspicious activity 21 | 22 | ### Liability 23 | This page is a list of community extensions that you are free to explore, but we do not support them in any way. We are in no way responsible for 24 | the extensions you decide to download. When you decide to download any of these extensions you accept that 25 | you are exposing yourself to security vulnerabilities and potential system failure. Always use caution. Read through 26 | the code or consult a security professional before proceeding to download code from the internet. Any issues that you have with the extension 27 | must be reported to the extension author not to us. 28 | 29 | -------------------------------------------------------------------------------- /docs/send2ue/extras/images/extensions/combine-meshes/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extras/images/extensions/combine-meshes/1.png -------------------------------------------------------------------------------- /docs/send2ue/extras/images/extensions/combine-meshes/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extras/images/extensions/combine-meshes/2.png -------------------------------------------------------------------------------- /docs/send2ue/extras/images/extensions/combine-meshes/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extras/images/extensions/combine-meshes/3.png -------------------------------------------------------------------------------- /docs/send2ue/extras/images/pipeline-menu/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extras/images/pipeline-menu/1.png -------------------------------------------------------------------------------- /docs/send2ue/extras/images/pipeline-menu/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/extras/images/pipeline-menu/2.png -------------------------------------------------------------------------------- /docs/send2ue/extras/pipeline-menu.md: -------------------------------------------------------------------------------- 1 | # Pipeline Menu 2 | 3 | ## Import 4 | 5 | ### Import Asset 6 | `Pipeline > Import > Import Asset` 7 | 8 | The Asset importer allows you to import assets then run a series of operations on them to fix them. The series 9 | of operations run on the imported asset depends on what source application you select from the drop down. A source 10 | application is the application the original file was generated in. Currently, the supported source applications are 11 | Unreal Engine 4 and Unreal Engine 5. 12 | 13 | ![1](./images/pipeline-menu/1.png) 14 | 15 | After the selected FBX file is imported the imported action location f-curves are scaled up to a match the scene scale 16 | factor with a scale of 1, the objects are applied with a scale factor of 1. The scaled keyframes on the root object 17 | are removed, and the keyframes are rounded to the nearest integer based on the current frame rate. 18 | 19 | 20 | ## Export 21 | 22 | ### Send to Unreal 23 | `Pipeline > Export > Send to Unreal` 24 | 25 | This operator quickly sends your assets to an open unreal editor instance without invoking a dialog. The settings 26 | used for the operation can be defined in the `Settings Dialog`. 27 | 28 | ### Settings Dialog 29 | `Pipeline > Export > Settings Dialog` 30 | 31 | This operator invokes a dialog that gives you access to the underlying scene data that the Send to Unreal operator uses. 32 | The sending to unreal, saving templates, and loading templates can all be done in this interface. 33 | 34 | ![2](./images/pipeline-menu/2.png) 35 | 36 | 37 | ## Utilities 38 | 39 | ### Create Pre-Defined Collections 40 | `Pipeline > Utilities > Create Pre-Defined Collections` 41 | 42 | Creates the pre-defined collection `Export` that is needed to collect asset data. 43 | 44 | 45 | ### Start RPC Servers 46 | `Pipeline > Utilities > Start RPC Servers` 47 | 48 | Bootstraps unreal and blender with rpc server threads, so that they are ready for remote calls. Unreal 49 | must be open and `remote execution` enabled or this will fail. 50 | -------------------------------------------------------------------------------- /docs/send2ue/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroText: Send to Unreal 4 | tagline: A one-click solution for sending data from Blender to Unreal Engine. 5 | actions: 6 | - text: Quick Start 7 | link: /introduction/quickstart 8 | features: 9 | - title: Static Meshes 10 | details: Supports static mesh workflows with lods, mesh origins, and batched exports. 11 | - title: Skeletal Meshes 12 | details: Bring a skeletal mesh into unreal with its lods and customized lod build settings. 13 | - title: Animation Sequences 14 | details: Batch export or send individual animations directly to the editor. 15 | - title: Grooms 16 | details: Batch export or send individual hair systems as alembic files to the editor as groom assets. 17 | footer: Copyright © Epic Games Inc. 18 | --- 19 | ## Overview 20 | 21 | overview 22 | 23 | 24 | The reason our tool can provide a "one-click" solution for these assets is because it can automatically infer the correct unreal asset type based on just the contents of a single `Export` 25 | collection. That, along with giving the user the ability to customize and share settings templates, allows assets and scenes to be completely configured ahead of time. 26 | A saved file can be opened by an artist and in one-click they can have their assets in unreal engine. The main purpose of this tool 27 | is for rapid iteration and standardization of asset workflows. If you are interested in learning more, please read through the rest of our documentation 28 | starting with our [quickstart guide](./introduction/quickstart) 29 | 30 | ## Help us document 31 | Our goal is for this documentation to be completely comprehensive so that it can be fully self-serving. If you notice any part of it to be incorrect, unclear, outdated, or missing 32 | information please consider contributing to our documentation. 33 | -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/1.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/10.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/11.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/12.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/13.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/14.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/15.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/16.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/2.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/3.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/4.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/5.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/6.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/6_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/6_1.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/7.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/8.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/images/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/introduction/images/9.png -------------------------------------------------------------------------------- /docs/send2ue/introduction/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | This quick start guide will help you get up and running with Send to Unreal. 3 | 4 | First thing you need to do is download the latest versioned zip file from the [releases page](https://github.com/EpicGamesExt/BlenderTools/releases?q=Send+to+unreal&expanded=true) 5 | under the `Assets` dropdown. The zip file name will start with `send2ue`. 6 | 7 | ::: tip Note 8 | If you get a 404 error when you click the link above, then you will need to sign in to your github account and link 9 | it with your Epic Games account. Here is a [link with instructions](https://www.unrealengine.com/en-US/ue4-on-github) 10 | on how to link your accounts. 11 | ::: 12 | 13 | Next install the addon in Blender. Go to `Edit > Preferences` then to the addons tab. Click `install`. 14 | 15 | ![1](./images/1.png) 16 | 17 | Go to the location where you downloaded your addon on disk and install the zip file. 18 | 19 | ![2](./images/2.png) 20 | 21 | Now search for the addon and activate it. 22 | 23 | ![3](./images/3.png) 24 | 25 | You'll notice when you activate it. This pipeline menu gets built. 26 | 27 | ![4](./images/4.png) 28 | 29 | Next, you'll need to configure your unreal project (or verify that your project settings are already correct). 30 | So let's walk through an example with a new project. First, open Unreal and create a new project. 31 | Once your project is open, go to `Edit > Plugins`. 32 | 33 | ![5](./images/5.png) 34 | 35 | Search for the "Python Editor Script Plugin" and enable it. Also ensure that the "Editor Scripting Utilities Plugin" is 36 | already enabled. 37 | 38 | ![6](./images/6.png) 39 | 40 | If you are also working with groom assets and would like to export alembic files from blender as unreal groom assets, 41 | make sure to also have the plugins "Alembic Groom Importer" and "Groom" enabled. 42 | 43 | ![6_1](./images/6_1.png) 44 | 45 | Additionally, make sure the "Support Compute Skin Cache" setting is turned on in Project Settings > Engine > Rendering > Optimizations. 46 | This ensures grooms to render properly when bound to a skeletal mesh. 47 | 48 | ![16](./images/16.png) 49 | 50 | Once you have enabled the plugins and project settings, you'll be prompted to restart the editor. Go ahead and restart. Once you've restarted, go to `Edit > Project Settings`. 51 | 52 | ![7](./images/7.png) 53 | 54 | Search for "python" and then enable remote execution. Now Send to Unreal will work with your new Unreal project. 55 | 56 | ![8](./images/8.png) 57 | 58 | Another thing that is useful to enable under `Edit > Editor Preferences` 59 | 60 | ![9](./images/9.png) 61 | 62 | Search for "CPU", then under Editor Performance disable "Use Less CPU when in Background". 63 | That way unreal continues to update even when it is not the active application, which means the Unreal user interface 64 | will update constantly, and you will see your changes update without having to click on the Unreal Editor. 65 | 66 | ![10](./images/10.png) 67 | 68 | Now lets run through a basic example with the default cube in your Blender scene. 69 | 70 | ![11](./images/11.png) 71 | 72 | A simple test we can try in Blender to make sure this is working is move our cube to our `Export` collection. 73 | 74 | ![12](./images/12.png) 75 | 76 | Click `Pipeline > Export > Send to Unreal`. 77 | 78 | ![13](./images/13.png) 79 | 80 | 81 | ::: tip Note 82 | On Windows, if you see a security alert, go ahead and allow Blender on your private network. 83 | ::: 84 | 85 | You should now see the cube in unreal under `/untitled category/untitled asset/Cube`. 86 | 87 | ![14](./images/14.png) 88 | 89 | 90 | Congrats, Send to Unreal is now working! To customize Send to Unreal to your needs, go to 91 | `Pipeline > Export > Settings Dialog`. Here you can customize the paths for exports and imports 92 | as well as the export and import settings, and validations. 93 | 94 | 15 95 | -------------------------------------------------------------------------------- /docs/send2ue/settings/export.md: -------------------------------------------------------------------------------- 1 | # Export 2 | When Send to Unreal writes files, the following properties dictate what and how assets are exported. 3 | 4 | ### Export object name as root bone 5 | If true, this uses the armature object's name in blender as the root bone name in Unreal, otherwise the first bone in 6 | the armature hierarchy is used as the root bone in unreal. 7 | 8 | ### Use object origin 9 | This forces the unreal asset to use the blender object origin instead of the blender scene's world origin. 10 | 11 | ## Animation Settings 12 | 13 | ### Auto stash active action 14 | This is supposed to simplify the process of creating animation and stashing it into the object’s NLA strips. 15 | With this option turned on you can start animating on an object and export it and not have to manually edit NLA strips. 16 | 17 | ### Export all Actions 18 | This setting ensures that regardless of the mute values or the solo value in the time editor tracks, your clips 19 | will get exported. 20 | 21 | ### Export custom property fcurves 22 | When enabled, this will export any object's custom properties that are in the action fcurves 23 | 24 | ## FBX Settings 25 | All the standard FBX export settings that are in the blender FBX addon are available in this section to be 26 | customized. 27 | -------------------------------------------------------------------------------- /docs/send2ue/settings/images/export/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/export/1.jpg -------------------------------------------------------------------------------- /docs/send2ue/settings/images/import/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/import/1.png -------------------------------------------------------------------------------- /docs/send2ue/settings/images/import/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/import/2.png -------------------------------------------------------------------------------- /docs/send2ue/settings/images/paths/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/paths/1.png -------------------------------------------------------------------------------- /docs/send2ue/settings/images/paths/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/paths/2.png -------------------------------------------------------------------------------- /docs/send2ue/settings/images/paths/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/paths/3.png -------------------------------------------------------------------------------- /docs/send2ue/settings/images/paths/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/send2ue/settings/images/paths/4.png -------------------------------------------------------------------------------- /docs/send2ue/settings/import.md: -------------------------------------------------------------------------------- 1 | # Import 2 | The following properties dictate what and how assets are imported into unreal. 3 | 4 | ![2](./images/import/2.png) 5 | #### Meshes 6 | Whether or not to import meshes from the FBX file. 7 | 8 | #### Materials and Textures 9 | Whether or not to import the materials and textures from the FBX file. 10 | 11 | #### Animation 12 | Whether or not to import the animation from the FBX file. 13 | 14 | #### Groom 15 | Whether or not to export groom as an alembic file and import to unreal. 16 | 17 | #### Launch Import UI 18 | When enabled this option launches the import UI in Unreal. 19 | 20 | ::: tip Note 21 | This will launch the Import UI on the first import of the asset, however it will not launch the UI again on a 22 | reimport. If you want to reimport an asset with new custom settings, the recommendation is to delete the asset in your 23 | unreal project and then just run Send to Unreal again. 24 | ::: 25 | 26 | ## LOD Settings 27 | The section contains the settings related to LOD workflows. You can read more about these under the 28 | [Skeletal Mesh](/asset-types/skeletal-mesh.html#lods) and [Static Mesh](/asset-types/static-mesh.html#lods) pages. 29 | 30 | #### LODs 31 | Whether or not to export the custom LODs 32 | 33 | #### LOD Regex 34 | Set a regular expression to determine an asset's lod identifier. The remaining unmatched string will be used as the 35 | asset name. The first matched group's last character should be the LOD index. 36 | 37 | ![1](./images/import/1.png) 38 | 39 | ### Skeletal Mesh 40 | #### LOD Settings (Unreal) 41 | This is the direct path to the LOD settings data asset in your unreal project. You can get this path 42 | by right-clicking on the LOD settings data asset in Unreal and selecting "Copy Reference" 43 | 44 | 45 | 46 | ## FBX Import Settings 47 | This section exposes the following editor properties with the Unreal Python API. 48 | - [FbxSkeletalMeshImportData](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/FbxSkeletalMeshImportData.html) 49 | - [FbxStaticMeshImportData](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/FbxStaticMeshImportData.html) 50 | - [FbxAnimSequenceImportData](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/FbxAnimSequenceImportData.html) 51 | - [FbxTextureImportData](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/FbxTextureImportData.html) 52 | 53 | ## Editor Settings 54 | This section exposes the following editor properties with the Unreal Python API. 55 | - ### Static Mesh 56 | - [MeshBuildSettings](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/MeshBuildSettings.html) 57 | 58 | - ### Skeletal Mesh 59 | - [SkeletalMeshBuildSettings](https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/SkeletalMeshBuildSettings.html) 60 | -------------------------------------------------------------------------------- /docs/send2ue/settings/paths.md: -------------------------------------------------------------------------------- 1 | # Paths 2 | The `Paths` section of the settings dialog is where all export and import paths can be configured. There are several 3 | different paths available depending on which `Path Mode` is selected: 4 | 5 | ## Path Modes 6 | Select which path mode Send to Unreal should use. 7 | 8 | ### Send to Project 9 | Sends the intermediate files to a temporary location on disk and then imports them into 10 | the Unreal Project. This doesn't require any extra configuration, but might not be ideal if your intermediate files 11 | need to be under source control. 12 | 13 | 1 14 | 15 | ### Send to Disk 16 | Sends the intermediate files to a specified location on disk and does not import them. 17 | 18 | 2 19 | 20 | ### Send to Disk then Project 21 | Sends the intermediate files to a specified location on disk and then imports them into 22 | the Unreal Project. This requires extra paths to be configured, but is ideal if your intermediate files 23 | need to be under source control. 24 | 25 | 3 26 | 27 | 28 | ## Relative Paths 29 | When specifying a location on disk with either the `Send to Disk` or `Send to Disk then Project`, relative paths 30 | can be used if the blender file is saved. The paths are relative to the currently open blender file. 31 | 32 | 4 33 | 34 | ::: tip Note 35 | A relative disk path is relative to where the blend file is saved on disk. 36 | ::: 37 | 38 | ## Path Properties 39 | #### Mesh Folder (Unreal): 40 | This is the mesh import path. All your static and skeletal meshes will be imported to this location in your open 41 | unreal project. 42 | 43 | #### Animation Folder (Unreal): 44 | This is the animation import path. All your actions that are in an Armature object’s NLA strips will be imported to 45 | this location in your open Unreal Project. 46 | 47 | #### Groom Folder (Unreal): 48 | This is the groom import path. All your particle hair systems and Curves objects will be imported to this location in 49 | your open unreal project. 50 | 51 | #### Skeleton Asset (Unreal): 52 | This is the direct path to the Skeleton you want to import animation on. You can get this path by 53 | right-clicking on the skeleton asset in Unreal and selecting "Copy Reference". 54 | 55 | #### Physics Asset (Unreal): 56 | This is the direct path to the physics asset you want to use. You can get this path by 57 | right-clicking on the physics asset in Unreal and selecting "Copy Reference" 58 | 59 | #### Mesh Folder (Disk): 60 | This is the path to the folder where meshes are exported on disk. All your static and skeletal 61 | meshes will be exported to this location. The file names will match the name of the mesh in maya 62 | 63 | #### Animation Folder (Disk): 64 | This is the path to the folder where your animations will be exported to on disk. All your action strips 65 | that are in the NLA Editor will be exported to this location. The file names will match 66 | the action name in blender. 67 | 68 | #### Groom Folder (Disk): 69 | This is the path to the folder where your particle hair systems and curves objects will be exported t on disk. 70 | The file names will match the particle system or curves object name in blender. 71 | -------------------------------------------------------------------------------- /docs/send2ue/settings/validations.md: -------------------------------------------------------------------------------- 1 | # Validations 2 | Validations are optional checks that can be turned off or configured to check a particular setting before starting the 3 | Send to Unreal operation. This way an error message can be thrown to a user that tells them to correct a detail that 4 | has been detected as "incorrect". 5 | 6 | ### Check scene scale 7 | This checks that the scene scale is set to 1. 8 | 9 | ### Check scene frame rate 10 | This checks the scene time units and ensures they are set to the specified value. 11 | 12 | ### Check armatures for un-applied transforms 13 | If an armature object has un-applied transforms (meaning location and rotation are not [0,0,0] and scale is not [1,1,1]) a message is thrown to the user. 14 | 15 | ### Check if asset has unused materials 16 | If this option is on it looks at each material index on the object and it checks if that material is 17 | assigned to a vertex on the mesh object. If there is a unused material, then an error message is thrown to the user. 18 | 19 | ### Check texture references 20 | This checks the texture references and sees if they actually exist on disk. 21 | 22 | ### Check paths 23 | This checks the export and import paths and makes sure they are valid before preforming 24 | the operation. 25 | 26 | ### Check project settings 27 | This checks whether the required unreal project settings are in place before performing 28 | the operation. 29 | 30 | ### Check blender object names 31 | This checks whether the blender object names in the Export collection contain any 32 | invalid special characters or white space. While the following special characters ```'".,/.:|&!~\n\r\t@#(){}[]=;^%$\`*?<>``` have 33 | valid usage in Blender, they are not valid to use in asset names in Unreal. 34 | 35 | Send2UE automatically converts any invalid characters to `_` during the export process 36 | if this validation is turned off. 37 | 38 | ### Check meshes for vertex groups 39 | This checks that a mesh with an armature modifier has vertex groups. 40 | -------------------------------------------------------------------------------- /docs/send2ue/trouble-shooting/errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | ### Could not find an open Unreal Editor instance! 4 | This happens when remote execution is not working with your project. To fix this go through all the steps 5 | in the quickstart again. If that doesn't work the issue is most likely due to a 6 | networking issue. Check your systems firewall for maya and python. Also check the port `6766` on your computer to see 7 | if it is blocked by another application. 8 | 9 | ### You do not have a collection "Export" in your outliner. Please create it. 10 | You will receive this error if you do not have an "Export" set in your outliner. To fix this go to 11 | `Pipeline > Utilites > Create Pre-Defined Collections`. 12 | 13 | ### NoOptionError: No option 'r.skincache.compileshaders' 14 | The option "Support Compute Skin Cache" is required for groom imports. If you have this project setting 15 | on but consistently receive this error, consider turning off the "Check project settings" validation in 16 | send to unreal validations settings. This issue has been reported by users in [#533](https://github.com/EpicGamesExt/BlenderTools/issues/533). 17 | -------------------------------------------------------------------------------- /docs/send2ue/trouble-shooting/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ### Could not find an open Unreal Editor instance! 4 | Toggle `remote execution` off and back on in your project settings. 5 | 6 | Make sure the Multicast Bind Address in the unreal project is set to `127.0.0.1`. 7 | 8 | Go through the quickstart again. If that doesn't work the issue is most likely due to a 9 | networking issue. Check your systems firewall for blender and python. Also check the ports `6766` and `9998` on your 10 | computer to see if they are blocked by another application. 11 | 12 | Before you start the Unreal Editor, run these commands from a PowerShell prompt: 13 | 14 | ```commandline 15 | netstat -an|sls 6766 16 | ``` 17 | 18 | Then start your project (that has Remote Execution enabled with the multicast group endpoint presumably set to 19 | 239.0.0.1:6766) and run these commands again. 20 | 21 | The first time, you run `netstat`, nothing should show up. The second time you run it, you should see this: 22 | 23 | ```commandline 24 | UDP 0.0.0.0:6766 *:* 25 | ``` 26 | 27 | 28 | 29 | ### Can I have multiple Unreal editors open at once and use Send to Unreal? 30 | Currently, no. Send to Unreal connects to the first Unreal editor process on your OS. So there isn't a good way of 31 | specifying which Unreal editor instance to connect to at the moment. There are plans to support this is the future 32 | though. 33 | 34 | 35 | ### Are my settings saved? 36 | Yes, the state of the tool's properties get tracked in each blend file and saved along with the rest of the 37 | blend file scene data. 38 | 39 | ### Why are my settings back to their defaults? 40 | If you open a new blend file that does not already contain Send to Unreal properties, then the settings are just 41 | the defaults. If you load a saved file, the settings will be the values they were saved at. 42 | 43 | ### Why isn't it finding my X (skeleton, physics asset, ...)? 44 | For setting the skeleton and physics asset in the Path setting, make sure the game isn't running in PIE. For doing anything with the addon make sure not to have PIE running. 45 | -------------------------------------------------------------------------------- /docs/ue2rigify/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | const {description, repository} = require('../../package') 2 | const { getRootPath } = require('../../path') 3 | import { defaultTheme } from '@vuepress/theme-default' 4 | import { defineUserConfig } from '@vuepress/cli' 5 | import { palettePlugin } from '@vuepress/plugin-palette' 6 | // @ts-ignore 7 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' 8 | 9 | 10 | export default defineUserConfig({ 11 | title: 'UE to Rigify', 12 | description: description, 13 | base: getRootPath('ue2rigify'), 14 | theme: defaultTheme({ 15 | repo: repository, 16 | docsDir: 'docs/ue2rigify', 17 | editLinkText: 'Help us improve this page!', 18 | lastUpdated: false, 19 | 20 | navbar: [ 21 | { 22 | text: 'Home', 23 | link: process.env.PROD === '1' ? 'https://epicgamesext.github.io/BlenderTools/' : '/', 24 | target:'_self' 25 | } 26 | ], 27 | sidebar: { 28 | '/': [ 29 | { 30 | text: 'Introduction', 31 | children: [ 32 | '/introduction/quickstart' 33 | ] 34 | }, 35 | { 36 | text: 'Concepts', 37 | children: [ 38 | '/concepts/modes', 39 | '/concepts/templates' 40 | ] 41 | }, 42 | { 43 | text: 'Usage', 44 | children: [ 45 | '/usage/animation', 46 | '/usage/new-template-example' 47 | ] 48 | }, 49 | { 50 | text: 'Advanced', 51 | children: [ 52 | '/advanced/relink-constraints' 53 | ] 54 | }, 55 | { 56 | text: 'Extras', 57 | children: [ 58 | '/extras/community-templates' 59 | ] 60 | }, 61 | { 62 | text: 'Trouble Shooting', 63 | children: [ 64 | '/trouble-shooting/faq', 65 | '/trouble-shooting/errors', 66 | ] 67 | } 68 | ], 69 | } 70 | }), 71 | plugins: [ 72 | palettePlugin({preset: 'sass'}), 73 | googleAnalyticsPlugin({id: process.env.GA_ID}) 74 | ] 75 | }) 76 | 77 | -------------------------------------------------------------------------------- /docs/ue2rigify/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | // brand colors 3 | --c-brand: #4289b9 !important; 4 | --c-brand-light: #469fcd !important; 5 | 6 | // custom container colors 7 | --c-tip: #469fcd !important; 8 | --c-text-accent: #4289b9 !important; 9 | } 10 | -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/4.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/5.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/6.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/images/relink-constraints/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/advanced/images/relink-constraints/7.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/advanced/relink-constraints.md: -------------------------------------------------------------------------------- 1 | # Relink Constraints 2 | 3 | [UE to Rigify Customization](https://docs.blender.org/manual/en/latest/addons/rigging/rigify/rig_types/basic.html) 4 | allows retargeting constraints belonging to the bone to point at bones created in the process of generating the rig, 5 | thus allowing custom rigging to integrate with generated bones. 6 | 7 | To use this feature, add `@` and the intended target bone name to the constraint name, resulting in the `...@bone_name` 8 | syntax. After all bones of the rig are generated, the constraint target bone will be replaced. If the new bone name is 9 | just `CTRL`, `MCH` or `DEF`, this will just replace the `ORG` prefix in the existing target bone name. For the Armature 10 | constraint you can add a `@` suffix for each target, or just one `@CTRL`, `@MCH` or `@DEF` suffix to update all. 11 | 12 | ![1](./images/relink-constraints/1.jpg) 13 | 14 | ### Parent 15 | If the field is not empty, applies the same name substitution logic to the parent of the bone. 16 | 17 | ![2](./images/relink-constraints/2.jpg) 18 | 19 | When this feature is enabled, the bone will not be automatically parented to the root bone even if it has no parent; 20 | enter root in the Parent field if that is necessary. 21 | 22 | 23 | ### Relinking Constraints 24 | Set the UE to Rigify mode to "Edit Metarig" 25 | 26 | ![3](./images/relink-constraints/3.jpg) 27 | 28 | While edit mode is enabled, create the new bone you want to rig "rigBone". In this case it is a bone that will help the 29 | pants deform. We need to have it constrained between the legs once the Rigify rig is built. 30 | 31 | ![4](./images/relink-constraints/4.jpg) 32 | 33 | Setup the Rigify type on the new bone. Switch to Pose mode and with the "rigBone" selected go to the Bone Properites 34 | tab. In the Rigify Type-Rig Type, selct raw copy or super_copy as these settings will allow us to use the relink 35 | constraint feature. 36 | 37 | ![5](./images/relink-constraints/5.jpg) 38 | 39 | Now add an armature constraint to the "rigBone" and pick your constraint targets from the metarig. To have the relink 40 | setting work, the constraint name must match the bone name it is on, "rigBone" and for the targets you must add a 41 | prefix. In this example @DEF is the prefix for the bones created in the Rigify Rig. Right now the target will be the 42 | Metarig armature and bones. 43 | 44 | ![6](./images/relink-constraints/6.jpg) 45 | 46 | Save the Metarig and switch to Control mode. Select the "rigBone" and notice that the target armatre and bones have 47 | changed to be the newly created control Rigify rig and bones, DEF-Leg_00.L as an example. This means that the target 48 | for the constraint has switched to the DEF bone created when the rig was built. The custom rig is complete and remains 49 | part of the Metarig template so that you don't lose the custom rigging created using constraints. 50 | 51 | ![7](./images/relink-constraints/7.jpg) 52 | -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/modes/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/modes/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/modes/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/modes/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/10.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/11.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/12.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/13.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/4.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/5.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/6.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/7.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/8.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/images/templates/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/concepts/images/templates/9.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/modes.md: -------------------------------------------------------------------------------- 1 | # Modes 2 | 3 |
4 | 5 |
6 | 7 | Now that we understand what templates are, let's talk about how they're created. Templates are created in UE to Rigify 8 | using five different modes: 9 | 10 | ![1](./images/modes/1.jpg) 11 | 12 | These modes become available as soon as you select a "Source" rig. 13 | 14 | ![2](./images/modes/2.jpg) 15 | 16 | 17 | ::: tip Note 18 | Your "Source" rig is the rig that you create in blender or the rig that you import into blender that has the skinned 19 | to mesh attached to it. The idea of UE to Rigify is that you want to drive the "Source" rig with your "Control" rig. 20 | ::: 21 | 22 | ## Source 23 | 24 | This mode is where you can see your original source rig. 25 | 26 | 27 | ## Edit Metarig 28 | 29 | This mode is where you add or remove bones, edit bone positions, and edit the rigify bones types. 30 | 31 | 32 | ## FK to Source 33 | 34 | This mode is where you edit the nodes that constrain your FK bones to the original source bones. These node links are needed if you want to transfer the existing animation from the ‘Source’ rig to the control rig. 35 | 36 | 37 | ## Source to Deform 38 | 39 | This mode is where you edit the nodes that constrain your original source bones to the deformation bones on your ‘Control’ rig. 40 | 41 | 42 | ## Control 43 | 44 | This mode is where you can control your new rig and animate. 45 | -------------------------------------------------------------------------------- /docs/ue2rigify/concepts/templates.md: -------------------------------------------------------------------------------- 1 | # Templates 2 | 3 |
4 | 5 |
6 | 7 | Let's talk about templates in UE to Rigify. 8 | 9 | Using the mannequin as an example again, you can see If you hit `Convert`, that a Rigify "Control" rig is created 10 | that drives the original "Source" rig. 11 | 12 | ![1](./images/templates/1.jpg) 13 | 14 | This is possible because of a predefined template for the unreal mannequin character that is selected from the 15 | template dropdown. This template contains all of the relationships and the bones necessary to create this rig. 16 | 17 | ![2](./images/templates/2.jpg) 18 | 19 | If I wanted to create a new template, I could go over here to this template panel and I could click `create new`. 20 | 21 | ![3](./images/templates/3.jpg) 22 | 23 | You can see that it adds in one of the default Rigify meta rigs. 24 | 25 | ![4](./images/templates/4.jpg) 26 | 27 | So basically, how this process works is you pick one of these default Rigify meta rigs and use one as a starting point. 28 | 29 | ![5](./images/templates/5.jpg) 30 | 31 | You name it, and then click `Save Metarig`. 32 | 33 | ![6](./images/templates/6.jpg) 34 | 35 | Now I am back in "Source" mode. If I click this delete button, I can remove this template. 36 | 37 | ![7](./images/templates/7.jpg) 38 | 39 | Also, you can import templates from an external file. To demonstrate this, I'm going to switch over to another file 40 | where I have another character. 41 | 42 | ![8](./images/templates/8.jpg) 43 | 44 | The unreal mannequin template is not going work with this. So I need to import the template that was made for this 45 | character. I'm going go over to the header menu and select `Edit > Preferences > Addons > UE to Rigify`. Here you can 46 | see there is an import template and export template import template. 47 | 48 | ![9](./images/templates/9.jpg) 49 | 50 | I'm just going import this template file from disk. 51 | 52 | ![10](./images/templates/10.jpg) 53 | 54 | Now if I click `Convert`. You can see that the rig is generated from this template, and it all matches up because 55 | this template has been created specifically for this character. 56 | 57 | ![11](./images/templates/11.jpg) 58 | 59 | Now let's say we made modifications to this character’s template and we want someone else to be able to use it. All 60 | we have to do is go to `Edit > Preferences > UE to Rigify` and `Export Template`. 61 | 62 | ![12](./images/templates/12.jpg) 63 | 64 | You can select which template you want to export in the side panel of the export window. 65 | 66 | ![13](./images/templates/13.jpg) 67 | 68 | That is how you can use templates in "UE to Rigify"! 69 | -------------------------------------------------------------------------------- /docs/ue2rigify/extras/community-templates.md: -------------------------------------------------------------------------------- 1 | # Community Templates 2 | 3 | UE to Rigify templates are a powerful way to share rigs and retarget animation regardless of 4 | what app the skeleton and skin weights were originally created with. As the number of templates created grows, 5 | we want this page to be filled with links to templates that the community has authored, and can hopefully help others 6 | with their blender and unreal pipelines. 7 | 8 | ## Manny 9 | * **Description**: Manny character from the Unreal Engine 5 third person project example. 10 | * **Download**: [https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Manny.zip](https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Manny.zip) 11 | 12 | ## Quinn 13 | * **Description**: Quinn character from the Unreal Engine 5 third person project example. 14 | * **Download**: [https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Quinn.zip](https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Quinn.zip) 15 | 16 | ## Echo 17 | * **Description**: Echo character from the Valley of the Ancients Unreal Engine demo. 18 | * **Download**: [https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Echo.zip](https://github.com/gzmuszynski/UE-to-Rigify/blob/main/Echo.zip) 19 | 20 | ## Metahuman 21 | * **Description**: Template for character bodies made with Metahuman Creator. 22 | * **Download**: [https://github.com/gzmuszynski/UE-to-Rigify/blob/main/MetaHuman.zip](https://github.com/gzmuszynski/UE-to-Rigify/blob/main/MetaHuman.zip) 23 | 24 | 25 | 26 | ## How to Contribute? 27 | ### Guidelines 28 | 29 | In order to have your template linked to this page, several requirements must be met. 30 | 31 | ### Requirements 32 | * Code must be in a public GitHub repo 33 | * Must have a link to a publicly available README with a brief description of the template and what rig it is designed for. 34 | 35 | ### Notice 36 | We reserve the right to remove your template link from this page for these or any other reasons: 37 | * Out of date template that is no longer compatible with the latest supported version of UE to Rigify. 38 | * Malicious or suspicious activity 39 | 40 | ### Liability 41 | This page is a list of community templates that you are free to explore, but we do not support them in any way. We are in no way responsible for 42 | the templates you decide to download. When you decide to download any of these templates you accept that 43 | you are exposing yourself to security vulnerabilities and potential system failure. Always use caution. Read through 44 | the code or consult a security professional before proceeding to download code from the internet. Any issues that you have with the template 45 | must be reported to the template author not to us. 46 | -------------------------------------------------------------------------------- /docs/ue2rigify/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroText: UE to Rigify 4 | tagline: A node based retargeting system for Blender's Rigify addon. 5 | actions: 6 | - text: Quick Start 7 | link: /introduction/quickstart 8 | features: 9 | - title: Retarget Animation 10 | details: Use nodes and operators to create relationships between your rig and the rigify controls. 11 | - title: Use Marketplace Assets 12 | details: Contains templates for the Unreal Mannequins, but any custom template can be built for any rig from any app. 13 | - title: Share Templates 14 | details: Build a template to retarget any rig, then share with your team and never retarget the same rig again. 15 | footer: Copyright © Epic Games Inc. 16 | --- 17 | 18 | ## Help us document 19 | Our goal is for this documentation to be completely comprehensive so that it can be fully self-serving. If you notice 20 | any part of it to be incorrect, unclear, outdated, or missing 21 | information please consider contributing to our documentation. 22 | -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/4.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/5.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/6.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/7.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/8.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/images/quickstart/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/introduction/images/quickstart/9.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/introduction/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | This quick start guide will help you get up and running with the UE to Rigify addon. 4 | 5 | First thing you need to do is download the latest versioned zip file from the [releases page](https://github.com/EpicGamesExt/BlenderTools/releases?q=UE+to+Rigify&expanded=true) 6 | under the `Assets` dropdown. The zip file name will start with `ue2rigify`. 7 | 8 | ::: tip Note 9 | If you get a 404 error when you click the link above, then you will need to sign in to your github account and link 10 | it with your Epic Games account. Here is a [link with instructions](https://www.unrealengine.com/en-US/ue4-on-github) 11 | on how to link your accounts. 12 | ::: 13 | 14 | Open Blender and install the add on. Go to `Edit > Preferences` then to addons. Click `install`. 15 | 16 | ![1](./images/quickstart/1.jpg) 17 | 18 | Go to the location where you have your addon on disk and install the zip file. Once installed. Go ahead and activate it. 19 | 20 | ![2](./images/quickstart/2.jpg) 21 | 22 | In the 3D View , if you hit `N` you can see the `UE to Rigify Toolkit` in the side panel. If Rigify is not active you will get this message: "Activate the Rigify addon!" 23 | 24 | ![3](./images/quickstart/3.jpg) 25 | 26 | Make sure that the Rigify addon is active. Rigify is a dependency for this addon to work correctly. 27 | 28 | ![4](./images/quickstart/4.jpg) 29 | 30 | Now I'm just going to import an FBX file. This is just the standard third person mannequin with the run animation. 31 | 32 | ![6](./images/quickstart/6.jpg) 33 | 34 | Now that it's imported. All I have to do now is go over to the UE to Rigify Panel, and get the picker and select the source rig. 35 | 36 | ![7](./images/quickstart/7.jpg) 37 | 38 | Then just hit Convert. 39 | 40 | ![8](./images/quickstart/8.jpg) 41 | 42 | You can now see that ‘UE to Rigify’ has converted our mannequin character and the third person run animation into a Rigify rig, and the run cycle has been transferred over as well. 43 | 44 | ![9](./images/quickstart/9.jpg) 45 | 46 | You can now control your original "Source" rig with the new Rigify "Control" rig! 47 | -------------------------------------------------------------------------------- /docs/ue2rigify/trouble-shooting/errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | ### Error: RIGIFY ERROR: Bone ``: `` 4 | This error message specifies a bone that is causing an error when generating the Rigify rig, and displays the rigify 5 | error message. Consult the Rigify documentation to find the rigify error message, but more than likely this error is 6 | being caused because of the Rigify properties you set on the bone. Click ‘Ok’ to see the bone that is causing the 7 | issue, then manually fix the Rigify properties. 8 | -------------------------------------------------------------------------------- /docs/ue2rigify/trouble-shooting/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ### How can I share a template I created with another artist? 4 | Go to Edit > Preferences > Addons > UE to Rigify and select ‘Export Template’. From the sidebar in the file window 5 | select the template you want to export. Then select the location on your hard drive and click `Export Template`. 6 | They can now click ‘Import Template’ and select this file, then click ‘Import Template’. 7 | 8 | ### How can I use a Rigify metarig as the source rig? 9 | If you want to use the tool to drive a rig you made in blender that is a Rigify metarig template, you need to rename 10 | it. You should stay away from the names "metarig" and "rig" because those are Rigify reserved names and when UE to 11 | Rigify generates a new rigify rig, those could get stomped on. Thus, renaming the metarig you added as your source 12 | rig is necessary for this to work. 13 | 14 | ## Where are Rig templates stored? 15 | Rig templates are stored within: 16 | - windows: `%TEMP%\ue2rigify\resources\rig_templates` 17 | - unix: `/tmp/ue2rigify/resources/rig_templates` -------------------------------------------------------------------------------- /docs/ue2rigify/usage/animation.md: -------------------------------------------------------------------------------- 1 | # Animation 2 | 3 |
4 | 5 |
6 | 7 | Let's talk about the animation workflow with UE to Rigify. When you have an animation on your "Source" rig and you 8 | click `Convert` and switch to `Control` mode, a new Rigify rig is being created and the key frames from your original 9 | source rig are being copied over into a new action on that rig. 10 | 11 | 12 | So let's take a look at this current action on this "Source" rig called `run`. 13 | 14 | ![1](./images/animation/1.jpg) 15 | 16 | When I hit `Convert`. It converts that action over to the Rigify rig. 17 | 18 | ![2](./images/animation/2.jpg) 19 | 20 | ::: tip Note 21 | UE to Rigify renames the original action to have `SOURCE_` in front of it. It prefixes every action from 22 | the "Source" rig so it does not overwrite any bone animations just in case the Rigify "Control" rig and the "Source" 23 | rig happen to have matching bone names. 24 | ::: 25 | 26 | Then I would click `Bake`, and confirm. 27 | 28 | ![3](./images/animation/3.jpg) 29 | 30 | Now we're back to our "Source" rig. Now our "Source" rig has the new animation on our original bones. Now the 31 | modified rig can be exported to a file! 32 | -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/animation/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/animation/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/animation/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/animation/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/animation/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/animation/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/10.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/11.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/12.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/13.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/14.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/4.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/5.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/6.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/7.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/8.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/images/new-template-example/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/usage/images/new-template-example/9.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/usage/new-template-example.md: -------------------------------------------------------------------------------- 1 | # New Template Example 2 | 3 |
4 | 5 |
6 | 7 | Now that we understand a bit about templates and modes, let's walk through creating our own template. 8 | 9 | So the first thing you need to do when you want to create a new template is go over here to the templates drop down, 10 | then select `create new`. 11 | 12 | ![1](./images/new-template-example/1.jpg) 13 | 14 | I'm just going to select the basic human as my starter template, and call this new template `Demo`. 15 | 16 | ![2](./images/new-template-example/2.jpg) 17 | 18 | I'm going to click `Save Metarig` and then I'll click `Convert` to switch to control mode. Here you can see our Rigify 19 | rig, but nothing is attached and the bones aren't in the right positions. 20 | 21 | ![3](./images/new-template-example/3.jpg) 22 | 23 | To fix this lets switch to ‘Edit Metarig’ mode. What we need to do is remove the bones that we don't need and set the 24 | others in the correct position. X-axis mirroring and vertex snapping is automatically turned on to make this easier. 25 | 26 | ![4](./images/new-template-example/4.jpg) 27 | 28 | Now I will set my bones to the correct positions(I am just doing the arms for the sake of this demo). 29 | 30 | ![5](./images/new-template-example/5.jpg) 31 | 32 | I'm gonna go ahead and switch over to ‘FK to Source’ mode. When I'm in this mode, I can start constraining the Rigify 33 | FK bones to the "Source" bones. I can do this by selecting the two bones that need to be linked and hit Alt+1 in the 34 | 3D viewport and select "Link Selected Bones". 35 | 36 | ![6](./images/new-template-example/6.jpg) 37 | 38 | This creates these two nodes in the node tree of the `Bone Remapping Nodes` view. 39 | 40 | ![7](./images/new-template-example/7.jpg) 41 | 42 | By using the X-axis mirroring feature and the correct custom bone name tokens for the left and right values, we can 43 | constrain both arms simultaneously. 44 | 45 | ![8](./images/new-template-example/8.jpg) 46 | 47 | We will do the same thing in `Source to Deform` mode. 48 | 49 | ![9](./images/new-template-example/9.jpg) 50 | 51 | Now if I switch to ‘Control’ mode, you can see that we have our arms and their animation copied over. You can see 52 | that are rig doesn't match up entirely because we only did the arms. But it's the exact same process to map the rest 53 | of the skeleton. 54 | 55 | ![10](./images/new-template-example/10.jpg) 56 | 57 | We can even go back to metarig mode and change the Rigify bone types from `limbs.super_limb` to `limbs.simple_tenticle` 58 | and adjust the mappings to switch the arm chain to a tentacle chain. 59 | 60 | ![11](./images/new-template-example/11.jpg) 61 | 62 | Now you can see the tentacle controls in `Control` mode. 63 | 64 | ![12](./images/new-template-example/12.jpg) 65 | 66 | Transferring root motion is also possible by using the source rig object node. A link can be made between it and the 67 | desired bone in `FK to Source` mode and `Source to Deform` mode. The source rig object node can be added to the node 68 | tree by hitting: 69 | 70 | `SHIFT+A > Object > Source Rig Object` 71 | 72 | ![13](./images/new-template-example/13.jpg) 73 | ![14](./images/new-template-example/14.jpg) 74 | 75 | This is essentially the process that you have to go through to create your own templates for your own unique rigs. 76 | -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/3d-view-panel.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | # UE to Rigify Panel 6 | This section defines all the properties and operators depicted below in the ‘UE to Rigify’ panel in the 3D viewport. 7 | 8 | ![1](./images/3d-view-panel/1.jpg) 9 | ![2](./images/3d-view-panel/2.jpg) 10 | ![3](./images/3d-view-panel/3.jpg) 11 | ![4](./images/3d-view-panel/4.png) 12 | 13 | ### Source 14 | 15 | This object picker specifies which object is the ‘Source’ rig. 16 | 17 | 18 | ### Template 19 | 20 | This dropdown allows you to select a template or create a new one. New templates are stored within: 21 | - windows: `%TEMP%\ue2rigify\resources\rig_templates` 22 | - unix: `/tmp/ue2rigify/resources/rig_templates` 23 | 24 | 25 | ### Mode 26 | 27 | This dropdown allows you to select which mode you want to edit your rig template in. The ‘UE to Rigify’ modes are: ‘Source’, ‘Edit Metarig’, ‘FK to Source’, ‘Source to Deform’, and ‘Control’. 28 | 29 | 30 | ### Overwrite Animation 31 | 32 | If enabled, your control rig animation data will be overwritten by the animation data from your source rig. 33 | 34 | 35 | ### Metarig 36 | 37 | This dropdown gives you some metarig presets that you can use as starting points when creating your new metarig template. 38 | 39 | 40 | ### Name 41 | 42 | This property defines the name of your new rig template. 43 | 44 | 45 | ### Save Metarig 46 | 47 | This operator saves the state of your current metarig into the rig template file, and switches the mode back to ‘Source’ mode. 48 | 49 | 50 | ### Save Nodes 51 | 52 | This operator saves the state of your current node tree into the rig template file, and switches the mode back to ‘Source’ mode. 53 | 54 | 55 | ### Convert 56 | 57 | This operator switches the current mode to ‘Control’ mode, builds the Rigify rig, and constrains the ‘Source’ rig bones to it. 58 | 59 | 60 | ### Revert 61 | 62 | This operator switches the current mode to ‘Source’ mode, and restores the view to just the ‘Source’ rig. 63 | 64 | 65 | ### Bake 66 | 67 | This operator bakes the ‘Control’ rig actions to the ‘Source’ rig actions. 68 | 69 | ### Bake every bone 70 | 71 | If enabled, this will bake every bone on the source rig. If not enabled, it will only bake the source rig bones 72 | that are linked to the control rig's FK bones in the FK to Source template. 73 | -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/hot-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | # Hot Keys 6 | 7 | ### ALT+1 8 | In the 3D view while in ‘FK to Source’ and ‘Source to Deform’ mode, this activates a pie menu with these options: 9 | 10 | * **Link Selected Bones** 11 | 12 | Create nodes that will have sockets with names of the selected bones 13 | 14 | 15 | * **Nodes from Selected Bones** 16 | 17 | Create a pair of linked nodes from the selected bones 18 | 19 | 20 | ### SHIFT+A 21 | When in ‘FK to Source’ and ‘Source to Deform’ mode in the ‘Bone Remapping Nodes’ view, this lets you add bones categorized by their rigs or search by their bone names. -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/images/3d-view-panel/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/user-interface/images/3d-view-panel/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/images/3d-view-panel/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/user-interface/images/3d-view-panel/2.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/images/3d-view-panel/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/user-interface/images/3d-view-panel/3.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/images/3d-view-panel/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/user-interface/images/3d-view-panel/4.png -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/images/node-editor-panel/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/docs/ue2rigify/user-interface/images/node-editor-panel/1.jpg -------------------------------------------------------------------------------- /docs/ue2rigify/user-interface/node-editor-panel.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | ### Node Editor Panel 6 | This section defines all the properties and operators depicted below in the ‘Node Editor’ panel that is available in ‘FK to Source’ and ‘Source to Deform’ mode under the ‘Bone Remapping Nodes’ view. 7 | 8 | ![1](./images/node-editor-panel/1.jpg) 9 | 10 | ### X-axis Mirror 11 | 12 | When this property is enabled, this will mirror your constraints across the x-axis. 13 | 14 | 15 | ### Left 16 | 17 | This property is the left token name found in all left bones on the source rig. 18 | 19 | 20 | ### Right 21 | 22 | This property is the right token name found in all left bones on the source rig 23 | 24 | 25 | ### Align Active Node Sockets 26 | 27 | This operator aligns the active node sockets with the sockets of the node it is linked to. 28 | 29 | 30 | ### Combine Selected Nodes 31 | 32 | This operator Combines the selected nodes into a new node that will have the name of the active node. 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | docker==6.1.3 2 | unittest-xml-reporting==3.2.0 3 | fake-bpy-module-latest==20231010 4 | PyGithub==2.1.1 5 | pydevd-pycharm~=223.7571.203 6 | -------------------------------------------------------------------------------- /scripts/addon-watcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /scripts/addon_watcher.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, 'send2ue', 'dependencies')) 4 | import rpc 5 | 6 | 7 | @rpc.factory.remote_call(port=9997) 8 | def reload_addon(addon, scripts_path): 9 | sys.path.append(scripts_path) 10 | import dev_helpers 11 | dev_helpers.reload_addon_source_code([addon]) 12 | 13 | 14 | if __name__ == '__main__': 15 | changed_file_path = os.path.normpath(sys.argv[-1]) 16 | print(f'Checking path "{changed_file_path}"...') 17 | split_path = changed_file_path.split(os.sep) 18 | print('test') 19 | if split_path: 20 | root_folder = split_path[0] 21 | if root_folder in ['send2ue', 'ue2rigify']: 22 | addon_name = root_folder 23 | print(f'reloading "{addon_name}"...') 24 | reload_addon(addon_name, os.path.basename(__file__)) 25 | else: 26 | print(f'No addon to reload') 27 | -------------------------------------------------------------------------------- /scripts/dev_helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import bpy 4 | import importlib 5 | import threading 6 | 7 | repo_folder = os.path.join(os.path.dirname(__file__), os.pardir) 8 | tests_folder = os.path.join(repo_folder, 'tests') 9 | 10 | sys.path.append(repo_folder) 11 | sys.path.append(os.path.join(tests_folder, 'utils')) 12 | from addon_packager import AddonPackager 13 | 14 | 15 | def reload_addon_source_code(addons, only_unregister=False): 16 | """" 17 | Does a full reload of the addons directly from their source code in the repo. This 18 | tends to be the preferred method of working since stack traces will link back to the 19 | source code. 20 | 21 | :param list addons: A list of addon names. 22 | :param bool only_unregister: Whether or not to only unregister the addon code. 23 | """ 24 | # forces reloading of modules, regeneration of properties, and sends all errors 25 | # to stderr instead of a dialog 26 | for addon in addons: 27 | os.environ[f'{addon.upper()}_DEV'] = '1' 28 | addon = importlib.import_module(addon) 29 | importlib.reload(addon) 30 | 31 | addon.unregister() 32 | if not only_unregister: 33 | addon.register() 34 | 35 | 36 | def reload_addon_zips(addons): 37 | """ 38 | Does a full install and reload of the addons from their zip files. This is useful when 39 | testing the full addon installation, and when you need to see the addon preferences UI which 40 | is only available when a addon is physically installed. 41 | 42 | :param list addons: A list of addon names. 43 | """ 44 | # unregister any registered addons 45 | reload_addon_source_code(addons, only_unregister=True) 46 | 47 | # zip up each addon 48 | for addon in addons: 49 | os.environ[f'{addon.upper()}_DEV'] = '1' 50 | addon_folder_path = os.path.join(repo_folder, addon) 51 | release_folder_path = os.path.join(repo_folder, 'release') 52 | addon_packager = AddonPackager(addon, addon_folder_path, release_folder_path) 53 | addon_packager.zip_addon() 54 | addon_packager.install_addon() 55 | 56 | bpy.ops.script.reload() 57 | -------------------------------------------------------------------------------- /send2ue/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | import os 5 | import importlib 6 | from .constants import ToolInfo 7 | from . import operators, properties, constants 8 | from .dependencies import remote_execution, unreal 9 | from .dependencies.unreal import UnrealRemoteCalls 10 | from .ui import header_menu, addon_preferences, file_browser, dialog 11 | from .core import formatting, validations, settings, utilities, export, ingest, extension, io 12 | 13 | bl_info = { 14 | "name": "Send to Unreal", 15 | "author": "Epic Games Inc.", 16 | "version": (2, 4, 3), 17 | "blender": (3, 3, 0), 18 | "location": "Header > Pipeline > Send to Unreal", 19 | "description": "Sends an asset to the first open Unreal Editor instance on your machine.", 20 | "warning": "", 21 | "wiki_url": "https://epicgamesext.github.io/BlenderTools/send2ue", 22 | "category": "Pipeline", 23 | } 24 | 25 | modules = [ 26 | export, 27 | ingest, 28 | unreal, 29 | utilities, 30 | formatting, 31 | validations, 32 | dialog, 33 | file_browser, 34 | settings, 35 | operators, 36 | properties, 37 | constants, 38 | remote_execution, 39 | addon_preferences, 40 | extension, 41 | io.fbx 42 | ] 43 | 44 | 45 | def register(): 46 | """ 47 | Registers the addon classes when the addon is enabled. 48 | """ 49 | # reload the submodules 50 | if os.environ.get('SEND2UE_DEV'): 51 | for module in modules: 52 | importlib.reload(module) 53 | 54 | try: 55 | # register the properties 56 | properties.register() 57 | 58 | # register the operators 59 | operators.register() 60 | 61 | # register the header menu 62 | header_menu.register() 63 | 64 | # register the addon preferences 65 | addon_preferences.register() 66 | 67 | except RuntimeError as error: 68 | print(error) 69 | 70 | # add an event handler that will run on new file loads 71 | bpy.app.handlers.load_post.append(bpy.app.handlers.persistent(utilities.setup_project)) 72 | 73 | # add a function to the event timer that will fire after the addon is enabled 74 | bpy.app.timers.register(utilities.addon_enabled, first_interval=0.1) 75 | 76 | 77 | def unregister(): 78 | """ 79 | Unregisters the addon classes when the addon is disabled. 80 | """ 81 | # remove event handlers 82 | if utilities.setup_project in bpy.app.handlers.load_post: 83 | bpy.app.handlers.load_post.remove(utilities.setup_project) 84 | 85 | try: 86 | # remove the pipeline menu 87 | header_menu.remove_parent_menu() 88 | 89 | # unregister the header menu 90 | header_menu.unregister() 91 | 92 | # register the addon preferences 93 | addon_preferences.unregister() 94 | 95 | # unregister the operators 96 | operators.unregister() 97 | 98 | # unregister the properties 99 | properties.unregister() 100 | 101 | except RuntimeError as error: 102 | print(error) 103 | 104 | # remove the temp data 105 | utilities.remove_temp_data() 106 | -------------------------------------------------------------------------------- /send2ue/constants.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | import os 3 | from enum import Enum 4 | 5 | 6 | class PreFixToken(Enum): 7 | SOCKET = 'SOCKET' 8 | BOX_COLLISION = 'UBX' 9 | CAPSULE_COLLISION = 'UCP' 10 | SPHERE_COLLISION = 'USP' 11 | CONVEX_COLLISION = 'UCX' 12 | 13 | 14 | class BlenderTypes: 15 | SKELETON = 'ARMATURE' 16 | MESH = 'MESH' 17 | ANIMATION = 'ANIMATION' 18 | PARTICLE_HAIR = 'HAIR' 19 | CURVES = 'CURVES' 20 | 21 | 22 | class UnrealTypes: 23 | SKELETAL_MESH = 'SkeletalMesh' 24 | STATIC_MESH = 'StaticMesh' 25 | ANIM_SEQUENCE = 'AnimSequence' 26 | GROOM = 'Groom' 27 | 28 | 29 | class FileTypes: 30 | ABC = 'abc' 31 | FBX = 'fbx' 32 | 33 | 34 | class ToolInfo(Enum): 35 | NAME = 'send2ue' 36 | APP = 'blender' 37 | LABEL = 'Send to Unreal' 38 | EXPORT_COLLECTION = 'Export' 39 | COLLECTION_NAMES = [EXPORT_COLLECTION] 40 | TEMPLATE_VERSION = 1 41 | FCURVE_FILE = '{file_path}_custom_property_fcurves.json' 42 | EXECUTION_QUEUE = 'send2ue_execution_queue' 43 | RESOURCE_FOLDER = os.path.join(os.path.dirname(__file__), 'resources') 44 | 45 | 46 | class Template: 47 | NAME = 'templates' 48 | IGNORED_PROPERTIES = ['active_settings_template'] 49 | DEFAULT = 'default.json' 50 | VERSION = 1 51 | 52 | 53 | class Extensions: 54 | NAME = 'extensions' 55 | DRAW_NAMESPACE = f'{ToolInfo.NAME.value}_{NAME}_' 56 | DRAW_TABS = ['draw_export', 'draw_import', 'draw_validations'] 57 | FOLDER = os.path.join(ToolInfo.RESOURCE_FOLDER.value, NAME) 58 | 59 | 60 | class ExtensionTasks(Enum): 61 | PRE_OPERATION = 'pre_operation' 62 | PRE_VALIDATIONS = 'pre_validations' 63 | POST_VALIDATIONS = 'post_validations' 64 | PRE_ANIMATION_EXPORT = 'pre_animation_export' 65 | POST_ANIMATION_EXPORT = 'post_animation_export' 66 | PRE_MESH_EXPORT = 'pre_mesh_export' 67 | POST_MESH_EXPORT = 'post_mesh_export' 68 | PRE_GROOM_EXPORT = 'pre_groom_export' 69 | POST_GROOM_EXPORT = 'post_groom_export' 70 | PRE_IMPORT = 'pre_import' 71 | POST_IMPORT = 'post_import' 72 | POST_OPERATION = 'post_operation' 73 | FILTER_OBJECTS = 'filter_objects' 74 | 75 | 76 | class PathModes(Enum): 77 | SEND_TO_PROJECT = 'send_to_project' 78 | SEND_TO_DISK = 'send_to_disk' 79 | SEND_TO_DISK_THEN_PROJECT = 'send_to_disk_then_project' 80 | 81 | 82 | class RegexPresets: 83 | INVALID_NAME_CHARACTERS = r"[^-+\w]+" 84 | 85 | -------------------------------------------------------------------------------- /send2ue/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /send2ue/core/io/__init__.py: -------------------------------------------------------------------------------- 1 | from . import fbx 2 | 3 | __all__ = [ 4 | fbx 5 | ] 6 | -------------------------------------------------------------------------------- /send2ue/dependencies/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/__init__.py: -------------------------------------------------------------------------------- 1 | from . import client, factory 2 | 3 | __all__ = [ 4 | client, 5 | factory 6 | ] 7 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/blender_server.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import os 4 | import sys 5 | from . import base_server 6 | from .base_server import BaseRPCServerThread, BaseRPCServerManager 7 | 8 | 9 | def execute_queued_calls(): 10 | """ 11 | Adds calls in the execution que that get picked up by blender app timer. 12 | :return float: The amount of time between timer calls. 13 | """ 14 | try: 15 | base_server.execute_queued_calls() 16 | except Exception as error: 17 | sys.stderr.write(str(error)) 18 | return 0.1 19 | 20 | 21 | class BlenderRPCServerThread(BaseRPCServerThread): 22 | def thread_safe_call(self, callable_instance, *args): 23 | """ 24 | Implementation of a thread safe call in Blender. 25 | """ 26 | return lambda *args: base_server.run_in_main_thread(callable_instance, *args) 27 | 28 | 29 | class RPCServer(BaseRPCServerManager): 30 | def __init__(self): 31 | """ 32 | Initialize the blender rpc server, with its name and specific port. 33 | """ 34 | super(RPCServer, self).__init__() 35 | self.name = 'BlenderRPCServer' 36 | self.port = int(os.environ.get('RPC_PORT', 9997)) 37 | self.threaded_server_class = BlenderRPCServerThread 38 | 39 | def start_server_thread(self): 40 | """ 41 | Starts the server thread. 42 | """ 43 | import bpy 44 | bpy.app.timers.register( 45 | bpy.app.handlers.persistent(execute_queued_calls), 46 | persistent=True 47 | ) 48 | super(RPCServer, self).start_server_thread() 49 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/client.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import logging 4 | import inspect 5 | from xmlrpc.client import ( 6 | ServerProxy, 7 | Unmarshaller, 8 | Transport, 9 | ExpatParser, 10 | Fault, 11 | ResponseError 12 | ) 13 | logger = logging.getLogger(__package__) 14 | 15 | 16 | class RPCUnmarshaller(Unmarshaller): 17 | def __init__(self, *args, **kwargs): 18 | Unmarshaller.__init__(self, *args, **kwargs) 19 | self.error_pattern = re.compile(r'(?P[^:]*):(?P.*$)') 20 | self.builtin_exceptions = self._get_built_in_exceptions() 21 | 22 | @staticmethod 23 | def _get_built_in_exceptions(): 24 | """ 25 | Gets a list of the built-in exception classes in python. 26 | 27 | :return list[BaseException] A list of the built in exception classes in python: 28 | """ 29 | builtin_exceptions = [] 30 | for builtin_name, builtin_class in globals().get('__builtins__').items(): 31 | if builtin_class and inspect.isclass(builtin_class) and issubclass(builtin_class, BaseException): 32 | builtin_exceptions.append(builtin_class) 33 | 34 | return builtin_exceptions 35 | 36 | def close(self): 37 | """ 38 | Override so we redefine the unmarshaller. 39 | 40 | :return tuple: A tuple of marshallables. 41 | """ 42 | if self._type is None or self._marks: 43 | raise ResponseError() 44 | 45 | if self._type == 'fault': 46 | marshallables = self._stack[0] 47 | match = self.error_pattern.match(marshallables.get('faultString', '')) 48 | if match: 49 | exception_name = match.group('exception').strip("") 50 | exception_message = match.group('exception_message') 51 | 52 | if exception_name: 53 | for exception in self.builtin_exceptions: 54 | if exception.__name__ == exception_name: 55 | raise exception(exception_message) 56 | 57 | # if all else fails just raise the fault 58 | raise Fault(**marshallables) 59 | return tuple(self._stack) 60 | 61 | 62 | class RPCTransport(Transport): 63 | def getparser(self): 64 | """ 65 | Override so we can redefine our transport to use its own custom unmarshaller. 66 | 67 | :return tuple(ExpatParser, RPCUnmarshaller): The parser and unmarshaller instances. 68 | """ 69 | unmarshaller = RPCUnmarshaller() 70 | parser = ExpatParser(unmarshaller) 71 | return parser, unmarshaller 72 | 73 | 74 | class RPCServerProxy(ServerProxy): 75 | auth_key = None 76 | 77 | def __init__(self, *args, **kwargs): 78 | """ 79 | Override so we can redefine the ServerProxy to use our custom transport. 80 | """ 81 | kwargs['transport'] = RPCTransport() 82 | ServerProxy.__init__(self, *args, **kwargs) 83 | 84 | 85 | class RPCClient: 86 | def __init__(self, port, marshall_exceptions=True): 87 | """ 88 | Initializes the rpc client. 89 | 90 | :param int port: A port number the client should connect to. 91 | :param bool marshall_exceptions: Whether the exceptions should be marshalled. 92 | """ 93 | server_ip = os.environ.get('RPC_SERVER_IP', '127.0.0.1') 94 | 95 | self.proxy = RPCServerProxy( 96 | f"http://{server_ip}:{port}", 97 | allow_none=True, 98 | ) 99 | self.marshall_exceptions = marshall_exceptions 100 | self.port = port 101 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | class BaseRPCException(Exception): 3 | """ 4 | Raised when a rpc class method is not authored as a static method. 5 | """ 6 | def __init__(self, message=None, line_link=''): 7 | self.message = message + line_link 8 | super().__init__(self.message) 9 | 10 | 11 | class InvalidClassMethod(BaseRPCException): 12 | """ 13 | Raised when a rpc class method is not authored as a static method. 14 | """ 15 | def __init__(self, cls, method, message=None, line_link=''): 16 | self.message = message 17 | 18 | if message is None: 19 | self.message = ( 20 | f'\n {cls.__name__}.{method.__name__} is not a static method. Please decorate with @staticmethod.' 21 | ) 22 | BaseRPCException.__init__(self, self.message, line_link) 23 | 24 | 25 | class InvalidTestCasePort(BaseRPCException): 26 | """ 27 | Raised when a rpc test case class does not have a port defined. 28 | """ 29 | def __init__(self, cls, message=None, line_link=''): 30 | self.message = message 31 | 32 | if message is None: 33 | self.message = f'\n You must set {cls.__name__}.port to a supported RPC port.' 34 | BaseRPCException.__init__(self, self.message, line_link) 35 | 36 | 37 | class InvalidKeyWordParameters(BaseRPCException): 38 | """ 39 | Raised when a rpc function has key word arguments in its parameters. 40 | """ 41 | def __init__(self, function, kwargs, message=None, line_link=''): 42 | self.message = message 43 | 44 | if message is None: 45 | self.message = ( 46 | f'\n Keyword arguments "{kwargs}" were found on "{function.__name__}". The RPC client does not ' 47 | f'support key word arguments . Please change your code to use only arguments.' 48 | ) 49 | BaseRPCException.__init__(self, self.message, line_link) 50 | 51 | 52 | class UnsupportedArgumentType(BaseRPCException): 53 | """ 54 | Raised when a rpc function's argument type is not supported. 55 | """ 56 | def __init__(self, function, arg, supported_types, message=None, line_link=''): 57 | self.message = message 58 | 59 | if message is None: 60 | self.message = ( 61 | f'\n "{function.__name__}" has an argument of type "{arg.__class__.__name__}". The only types that are' 62 | f' supported by the RPC client are {[supported_type.__name__ for supported_type in supported_types]}.' 63 | ) 64 | BaseRPCException.__init__(self, self.message, line_link) 65 | 66 | 67 | class FileNotSavedOnDisk(BaseRPCException): 68 | """ 69 | Raised when a rpc function is called in a context where it is not a saved file on disk. 70 | """ 71 | def __init__(self, function, message=None): 72 | self.message = message 73 | 74 | if message is None: 75 | self.message = ( 76 | f'\n "{function.__name__}" is not being called from a saved file. The RPC client does not ' 77 | f'support code that is not saved. Please save your code to a file on disk and re-run it.' 78 | ) 79 | BaseRPCException.__init__(self, self.message) 80 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/server.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.dirname(__file__)) 4 | 5 | from base_server import BaseRPCServerManager 6 | 7 | 8 | class RPCServer(BaseRPCServerManager): 9 | def __init__(self): 10 | """ 11 | Initialize the blender rpc server, with its name and specific port. 12 | """ 13 | super(RPCServer, self).__init__() 14 | self.name = 'RPCServer' 15 | self.port = int(os.environ.get('RPC_PORT', 9998)) 16 | 17 | 18 | if __name__ == '__main__': 19 | rpc_server = RPCServer() 20 | rpc_server.start(threaded=False) 21 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/unreal_server.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import os 4 | 5 | from . import base_server 6 | from .base_server import BaseRPCServerThread, BaseRPCServerManager 7 | 8 | 9 | class UnrealRPCServerThread(BaseRPCServerThread): 10 | def thread_safe_call(self, callable_instance, *args): 11 | """ 12 | Implementation of a thread safe call in Unreal. 13 | """ 14 | return lambda *args: base_server.run_in_main_thread(callable_instance, *args) 15 | 16 | 17 | class RPCServer(BaseRPCServerManager): 18 | def __init__(self): 19 | """ 20 | Initialize the unreal rpc server, with its name and specific port. 21 | """ 22 | super(RPCServer, self).__init__() 23 | self.name = 'UnrealRPCServer' 24 | self.port = int(os.environ.get('RPC_PORT', 9998)) 25 | self.threaded_server_class = UnrealRPCServerThread 26 | 27 | def start_server_thread(self): 28 | """ 29 | Starts the server thread. 30 | """ 31 | # TODO use a timer exposed from FTSTicker instead of slate tick, less aggressive and safer 32 | # https://docs.unrealengine.com/4.27/en-US/PythonAPI/class/AutomationScheduler.html?highlight=automationscheduler#unreal.AutomationScheduler 33 | import unreal 34 | unreal.register_slate_post_tick_callback(base_server.execute_queued_calls) 35 | super(RPCServer, self).start_server_thread() 36 | -------------------------------------------------------------------------------- /send2ue/dependencies/rpc/validations.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | from .exceptions import ( 4 | InvalidClassMethod, 5 | InvalidTestCasePort, 6 | InvalidKeyWordParameters, 7 | UnsupportedArgumentType, 8 | FileNotSavedOnDisk, 9 | ) 10 | 11 | 12 | def get_source_file_path(function): 13 | """ 14 | Gets the full path to the source code. 15 | 16 | :param callable function: A callable. 17 | :return str: A file path. 18 | """ 19 | client_module = inspect.getmodule(function) 20 | return client_module.__file__ 21 | 22 | 23 | def get_line_link(function): 24 | """ 25 | Gets the line number of a function. 26 | 27 | :param callable function: A callable. 28 | :return int: The line number 29 | """ 30 | lines, line_number = inspect.getsourcelines(function) 31 | file_path = get_source_file_path(function) 32 | return f' File "{file_path}", line {line_number}' 33 | 34 | 35 | def validate_arguments(function, args): 36 | """ 37 | Validates arguments to ensure they are a supported type. 38 | 39 | :param callable function: A function reference. 40 | :param tuple(Any) args: A list of arguments. 41 | """ 42 | supported_types = [str, int, float, tuple, list, dict, bool] 43 | line_link = get_line_link(function) 44 | for arg in args: 45 | if arg is None: 46 | continue 47 | 48 | if type(arg) not in supported_types: 49 | raise UnsupportedArgumentType(function, arg, supported_types, line_link=line_link) 50 | 51 | 52 | def validate_test_case_class(cls): 53 | """ 54 | This is use to validate a subclass of RPCTestCase. While building your test 55 | suite you can call this method on each class preemptively to validate that it 56 | was defined correctly. 57 | 58 | :param RPCTestCase cls: A class. 59 | :param str file_path: Optionally, a file path to the test case can be passed to give 60 | further context into where the error is occurring. 61 | """ 62 | line_link = get_line_link(cls) 63 | if not cls.__dict__.get('port'): 64 | raise InvalidTestCasePort(cls, line_link=line_link) 65 | 66 | for attribute, method in cls.__dict__.items(): 67 | if callable(method) and not isinstance(method, staticmethod): 68 | if method.__name__.startswith('test'): 69 | raise InvalidClassMethod(cls, method, line_link=line_link) 70 | 71 | 72 | def validate_class_method(cls, method): 73 | """ 74 | Validates a method on a class. 75 | 76 | :param Any cls: A class. 77 | :param callable method: A callable. 78 | """ 79 | if callable(method) and not isinstance(method, staticmethod): 80 | line_link = get_line_link(method) 81 | raise InvalidClassMethod(cls, method, line_link=line_link) 82 | 83 | 84 | def validate_key_word_parameters(function, kwargs): 85 | """ 86 | Validates a method on a class. 87 | 88 | :param callable function: A callable. 89 | :param dict kwargs: A dictionary of key word arguments. 90 | """ 91 | if kwargs: 92 | line_link = get_line_link(function) 93 | raise InvalidKeyWordParameters(function, kwargs, line_link=line_link) 94 | 95 | 96 | def validate_file_is_saved(function): 97 | """ 98 | Validates that the file that the function is from is saved on disk. 99 | 100 | :param callable function: A callable. 101 | """ 102 | try: 103 | inspect.getsourcelines(function) 104 | except OSError: 105 | raise FileNotSavedOnDisk(function) 106 | -------------------------------------------------------------------------------- /send2ue/release_notes.md: -------------------------------------------------------------------------------- 1 | ## Minor Changes 2 | * Added collections as folder support for 'send to disk' 3 | * [658](https://github.com/EpicGamesExt/BlenderTools/pull/658) 4 | * Fixed Validation that detects invalid material assigned to polygon. 5 | * [656](https://github.com/EpicGamesExt/BlenderTools/pull/656) 6 | * Fixed export with object origin causes some collisions to be offset bug 7 | * [587](https://github.com/EpicGamesExt/BlenderTools/issues/587) 8 | * Fixed use object origin with combine meshes bug 9 | * [627](https://github.com/EpicGamesExt/BlenderTools/issues/627) 10 | * [628](https://github.com/EpicGamesExt/BlenderTools/issues/628) 11 | 12 | ## Special Thanks 13 | @SalamiArmi, @namrog84 14 | 15 | ## Tests Passing On 16 | * Blender `3.3`, `3.6` (installed from blender.org) 17 | * Unreal `5.3` 18 | -------------------------------------------------------------------------------- /send2ue/resources/extensions/create_post_import_assets_for_groom.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from send2ue.core.extension import ExtensionBase 5 | from send2ue.core import utilities 6 | from send2ue.constants import UnrealTypes 7 | from send2ue.dependencies.unreal import UnrealRemoteCalls 8 | 9 | 10 | class CreatePostImportAssetsForGroom(ExtensionBase): 11 | name = 'create_post_import_assets_for_groom' 12 | 13 | binding_asset: bpy.props.BoolProperty( 14 | name="Groom binding asset", 15 | default=True, 16 | description=( 17 | "This creates a binding asset for the imported groom asset and associated mesh asset." 18 | ) 19 | ) 20 | 21 | blueprint_with_groom: bpy.props.BoolProperty( 22 | name="Blueprint asset with groom component", 23 | default=False, 24 | description=( 25 | 'This creates a blueprint asset with groom components from the imported groom assets parented under' 26 | 'their associated skeletal mesh from the same import.' 27 | ) 28 | ) 29 | 30 | def pre_validations(self, properties): 31 | """ 32 | Defines the pre validations logic that checks whether create binding asset is on if create blueprint with groom 33 | is checked. 34 | 35 | :param Send2UeSceneProperties properties: The scene property group that contains all the addon properties. 36 | """ 37 | if self.blueprint_with_groom: 38 | if not self.binding_asset: 39 | utilities.report_error( 40 | f'Cannot create blueprint asset with groom if not creating binding asset!' 41 | ) 42 | return False 43 | return True 44 | 45 | def post_import(self, asset_data, properties): 46 | """ 47 | Defines the post import logic for creating post import assets for the current groom asset. 48 | 49 | :param dict asset_data: A mutable dictionary of asset data for the current asset. 50 | :param Send2UeSceneProperties properties: The scene property group that contains all the addon properties. 51 | """ 52 | if asset_data.get('_asset_type') == UnrealTypes.GROOM: 53 | if self.binding_asset and properties.import_meshes: 54 | binding_asset_path = None 55 | # get the mesh asset data related to this groom asset data 56 | mesh_asset_data = utilities.get_related_mesh_asset_data_from_groom_asset_data(asset_data) 57 | groom_asset_path = asset_data.get('asset_path', '') 58 | mesh_asset_path = mesh_asset_data.get('asset_path', '') 59 | 60 | if not UnrealRemoteCalls.asset_exists(groom_asset_path): 61 | return 62 | 63 | # don't create a binding asset if the mesh doesn't exist. This happens in a groom only export 64 | if not UnrealRemoteCalls.asset_exists(mesh_asset_path): 65 | return 66 | 67 | if groom_asset_path and mesh_asset_path: 68 | binding_asset_path = UnrealRemoteCalls.create_binding_asset(groom_asset_path, mesh_asset_path) 69 | 70 | if self.blueprint_with_groom and binding_asset_path: 71 | UnrealRemoteCalls.create_blueprint_with_groom(groom_asset_path, mesh_asset_path, binding_asset_path) 72 | 73 | def draw_import(self, dialog, layout, properties): 74 | """ 75 | Draws an interface for the create_post_import_assets_for_groom extension in the import tab. 76 | 77 | :param Send2UnrealDialog dialog: The dialog class. 78 | :param bpy.types.UILayout layout: The extension layout area. 79 | :param Send2UeSceneProperties properties: The scene property group that contains all the addon properties. 80 | """ 81 | box = layout.box() 82 | box.label(text='Create post-import assets for groom:') 83 | dialog.draw_property(self, box, 'binding_asset') 84 | dialog.draw_property(self, box, 'blueprint_with_groom') 85 | -------------------------------------------------------------------------------- /send2ue/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/send2ue/ui/__init__.py -------------------------------------------------------------------------------- /send2ue/ui/addon_preferences.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from ..properties import Send2UeAddonProperties 5 | from ..constants import ToolInfo 6 | 7 | 8 | class SendToUnrealPreferences(Send2UeAddonProperties, bpy.types.AddonPreferences): 9 | """ 10 | This class creates the settings interface in the send to unreal addon. 11 | """ 12 | bl_idname = ToolInfo.NAME.value 13 | 14 | def draw(self, context): 15 | """ 16 | This defines the draw method, which is in all Blender UI types that create interfaces. 17 | 18 | :param context: The context of this interface. 19 | """ 20 | row = self.layout.row() 21 | row.prop(self, 'automatically_create_collections') 22 | row = self.layout.row() 23 | row.label(text='RPC Response Timeout') 24 | row.prop(self, 'rpc_response_timeout', text='') 25 | row = self.layout.row() 26 | row.label(text='Extensions Repo Path:') 27 | row = self.layout.row() 28 | row = row.split(factor=0.95, align=True) 29 | row.prop(self, 'extensions_repo_path', text='') 30 | row.operator('send2ue.reload_extensions', text='', icon='UV_SYNC_SELECT') 31 | 32 | def register(): 33 | """ 34 | Registers the addon preferences when the addon is enabled. 35 | """ 36 | bpy.utils.register_class(SendToUnrealPreferences) 37 | 38 | 39 | def unregister(): 40 | """ 41 | Unregisters the addon preferences when the addon is disabled. 42 | """ 43 | bpy.utils.unregister_class(SendToUnrealPreferences) 44 | -------------------------------------------------------------------------------- /send2ue/ui/file_browser.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from bpy_extras.io_utils import ImportHelper, ExportHelper 5 | 6 | 7 | class ImportAsset(ImportHelper): 8 | """ 9 | This class subclasses the import helper to define a custom file browser for importing assets. 10 | """ 11 | filter_glob: bpy.props.StringProperty( 12 | default="*.fbx", 13 | options={"HIDDEN"}, 14 | subtype="FILE_PATH", 15 | ) 16 | 17 | def draw(self, context): 18 | """ 19 | This function overrides the draw method in the ImportHelper class. The draw method is the function that 20 | defines the user interface layout and gets updated routinely. 21 | 22 | :param object context: The window context. 23 | """ 24 | window_properties = bpy.context.window_manager.send2ue 25 | 26 | layout = self.layout 27 | row = layout.row() 28 | row.label(text='Source Application:') 29 | row = layout.row() 30 | row.prop(window_properties, 'source_application', text='') 31 | 32 | 33 | class ImportTemplate(ImportHelper): 34 | """ 35 | Subclasses the import helper to define a custom file browser for importing setting templates. 36 | """ 37 | filter_glob: bpy.props.StringProperty( 38 | default="*.json", 39 | options={"HIDDEN"}, 40 | subtype="FILE_PATH", 41 | ) 42 | 43 | 44 | class ExportTemplate(ExportHelper): 45 | """ 46 | Subclasses the export helper to define a custom file browser for exporting setting templates. 47 | """ 48 | filter_glob: bpy.props.StringProperty( 49 | default="*.json", 50 | options={"HIDDEN"}, 51 | subtype="FILE_PATH", 52 | ) 53 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.blend1 2 | results/* 3 | data/* 4 | test_files/unreal_projects/test01/Content/* 5 | test_files/unreal_projects/test01/DerivedDataCache/* 6 | test_files/unreal_projects/test01/Intermediate/* 7 | test_files/unreal_projects/test01/Saved/* 8 | -------------------------------------------------------------------------------- /tests/test_files/blender_files/cubes.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/tests/test_files/blender_files/cubes.blend -------------------------------------------------------------------------------- /tests/test_files/blender_files/mannequins.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/tests/test_files/blender_files/mannequins.blend -------------------------------------------------------------------------------- /tests/test_files/fbx_files/ThirdPersonRun.FBX: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/tests/test_files/fbx_files/ThirdPersonRun.FBX -------------------------------------------------------------------------------- /tests/test_files/unreal_projects/test01/Config/DefaultEditor.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/tests/test_files/unreal_projects/test01/Config/DefaultEditor.ini -------------------------------------------------------------------------------- /tests/test_files/unreal_projects/test01/Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/EngineSettings.GameMapsSettings] 4 | GameDefaultMap=/Engine/Maps/Templates/Template_Default.Template_Default 5 | 6 | 7 | [/Script/HardwareTargeting.HardwareTargetingSettings] 8 | TargetedHardwareClass=Desktop 9 | AppliedTargetedHardwareClass=Desktop 10 | DefaultGraphicsPerformance=Maximum 11 | AppliedDefaultGraphicsPerformance=Maximum 12 | 13 | [/Script/Engine.RendererSettings] 14 | r.GenerateMeshDistanceFields=True 15 | r.DynamicGlobalIlluminationMethod=1 16 | r.ReflectionMethod=1 17 | r.Shadow.Virtual.Enable=1 18 | r.SkinCache.CompileShaders=True 19 | 20 | [/Script/WorldPartitionEditor.WorldPartitionEditorSettings] 21 | bEnableWorldPartition=False 22 | bEnableConversionPrompt=True 23 | CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet 24 | 25 | [/Script/Engine.Engine] 26 | +ActiveGameNameRedirects=(OldGameName="TP_BlankBP",NewGameName="/Script/test01") 27 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_BlankBP",NewGameName="/Script/test01") 28 | 29 | [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] 30 | bEnablePlugin=True 31 | bAllowNetworkConnection=True 32 | SecurityToken=CD7E6E84891D4EE19EDC7916615BB995 33 | bIncludeInShipping=False 34 | bAllowExternalStartInShipping=False 35 | bCompileAFSProject=False 36 | bUseCompression=False 37 | bLogFiles=False 38 | bReportStats=False 39 | ConnectionType=USBOnly 40 | bUseManualIPAddress=False 41 | ManualIPAddress= 42 | 43 | 44 | 45 | [/Script/PythonScriptPlugin.PythonScriptPluginSettings] 46 | bRemoteExecution=True 47 | RemoteExecutionMulticastBindAddress=127.0.0.1 48 | 49 | [/Script/WindowsTargetPlatform.WindowsTargetSettings] 50 | DefaultGraphicsRHI=DefaultGraphicsRHI_Default 51 | -D3D12TargetedShaderFormats=PCD3D_SM5 52 | +D3D12TargetedShaderFormats=PCD3D_SM5 53 | +D3D12TargetedShaderFormats=PCD3D_SM6 54 | -D3D11TargetedShaderFormats=PCD3D_SM5 55 | +D3D11TargetedShaderFormats=PCD3D_SM5 56 | Compiler=Default 57 | AudioSampleRate=48000 58 | AudioCallbackBufferFrameSize=1024 59 | AudioNumBuffersToEnqueue=1 60 | AudioMaxChannels=0 61 | AudioNumSourceWorkers=4 62 | SpatializationPlugin= 63 | SourceDataOverridePlugin= 64 | ReverbPlugin= 65 | OcclusionPlugin= 66 | CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) 67 | CacheSizeKB=65536 68 | MaxChunkSizeOverrideKB=0 69 | bResampleForDevice=False 70 | MaxSampleRate=48000.000000 71 | HighSampleRate=32000.000000 72 | MedSampleRate=24000.000000 73 | LowSampleRate=12000.000000 74 | MinSampleRate=8000.000000 75 | CompressionQualityModifier=1.000000 76 | AutoStreamingThreshold=0.000000 77 | SoundCueCookQualityIndex=-1 78 | 79 | -------------------------------------------------------------------------------- /tests/test_files/unreal_projects/test01/Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/EngineSettings.GeneralProjectSettings] 4 | ProjectID=315901C344372046154A74A2646A9100 5 | -------------------------------------------------------------------------------- /tests/test_files/unreal_projects/test01/test01.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "5.3", 4 | "Category": "", 5 | "Description": "", 6 | "Plugins": [ 7 | { 8 | "Name": "PythonScriptPlugin", 9 | "Enabled": true 10 | }, 11 | { 12 | "Name": "AlembicHairImporter", 13 | "Enabled": true 14 | }, 15 | { 16 | "Name": "HairStrands", 17 | "Enabled": true 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tests/test_send2ue_extension_create_post_import_assets_for_groom.py: -------------------------------------------------------------------------------- 1 | from utils.base_test_case import BaseSend2ueTestCaseCore, BaseSend2ueTestCase, SkipSend2UeTests 2 | from test_send2ue_mannequins import TestSend2UeMannequins 3 | 4 | 5 | class TestSend2UeExtensionCreatePostImportAssetsForGroomBase(BaseSend2ueTestCaseCore, BaseSend2ueTestCase): 6 | def run_create_post_import_assets_for_groom_option_tests(self, meshes_and_hairs): 7 | self.log(f'Creating binding asset...') 8 | 9 | # NOTE: passing in particle system names here only works because all particle modifiers share the same name 10 | # as their associated particle systems in the .blend mannequin test file 11 | for mesh_name, particle_names in meshes_and_hairs.items(): 12 | self.blender.set_particles_visible(mesh_name, particle_names) 13 | 14 | self.blender.set_addon_property( 15 | 'scene', 16 | 'send2ue', 17 | 'extensions.create_post_import_assets_for_groom.binding_asset', 18 | True 19 | ) 20 | 21 | self.send2ue_operation() 22 | 23 | for mesh_name, hairs in meshes_and_hairs.items(): 24 | for hair_name in hairs: 25 | self.assert_binding_asset(hair_name, mesh_name) 26 | 27 | self.tearDown() 28 | 29 | for mesh_name, particle_names in meshes_and_hairs.items(): 30 | self.blender.set_particles_visible(mesh_name, particle_names) 31 | 32 | self.blender.set_addon_property( 33 | 'scene', 34 | 'send2ue', 35 | 'extensions.create_post_import_assets_for_groom.binding_asset', 36 | True 37 | ) 38 | self.blender.set_addon_property( 39 | 'scene', 40 | 'send2ue', 41 | 'extensions.create_post_import_assets_for_groom.blueprint_with_groom', 42 | True 43 | ) 44 | 45 | self.log(f'Creating blueprint asset with skeletal mesh and groom components...') 46 | 47 | self.send2ue_operation() 48 | 49 | for mesh_name, hairs in meshes_and_hairs.items(): 50 | blueprint_asset_name = f'{mesh_name}_BP' 51 | # Todo there is currently a failure on linux 52 | self.assert_blueprint_asset(blueprint_asset_name) 53 | 54 | for hair_name in hairs: 55 | binding_asset_name = f'{hair_name}_{mesh_name}_Binding' 56 | self.assert_blueprint_with_groom(blueprint_asset_name, hair_name, binding_asset_name, mesh_name) 57 | 58 | 59 | class TestSend2UeExtensionCreatePostImportAssetsForGroomMannequins( 60 | SkipSend2UeTests, 61 | TestSend2UeMannequins, 62 | TestSend2UeExtensionCreatePostImportAssetsForGroomBase 63 | ): 64 | def test_extension(self): 65 | """ 66 | Checks that the create post import assets for groom extension loaded properly. 67 | """ 68 | self.run_extension_tests({ 69 | 'default': { 70 | 'create_post_import_assets_for_groom': { 71 | 'properties': { 72 | 'binding_asset': True, 73 | 'blueprint_with_groom': False 74 | }, 75 | 'tasks': [ 76 | 'pre_validations', 77 | 'post_import' 78 | ], 79 | 'draws': [ 80 | 'draw_import' 81 | ] 82 | } 83 | } 84 | }) 85 | 86 | def test_create_post_import_assets_for_groom_option(self): 87 | """ 88 | Runs several test cases with the create post import assets extension for groom on the mannequin meshes. 89 | """ 90 | self.move_to_collection([ 91 | 'male_root', 92 | 'SK_Mannequin_LOD1' 93 | ], 'Export') 94 | 95 | self.move_to_collection([ 96 | 'back_curves', 97 | 'shoulder_curves', 98 | 'back_sparse_curves' 99 | ], 'Export') 100 | 101 | self.run_create_post_import_assets_for_groom_option_tests(meshes_and_hairs={ 102 | 'SK_Mannequin_LOD1': [ 103 | 'back_curves', 104 | 'shoulder_curves', 105 | 'back_sparse_curves', 106 | 'particle_hair_waist', 107 | 'particle_hair_hand_r' 108 | ] 109 | }) 110 | -------------------------------------------------------------------------------- /tests/test_send2ue_extension_example.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | from utils.base_test_case import BaseSend2ueTestCaseCore, SkipSend2UeTests 4 | from test_send2ue_cubes import TestSend2UeCubes 5 | 6 | 7 | class TestSend2UeExtensionExampleCubes(SkipSend2UeTests, TestSend2UeCubes, BaseSend2ueTestCaseCore): 8 | """ 9 | Runs several test cases with the affix extension on the cube meshes. 10 | """ 11 | def setUp(self): 12 | super().setUp() 13 | self.set_extension_repo(os.path.join(self.test_folder, 'test_files', 'send2ue_extensions')) 14 | self.blender.set_addon_property('scene', 'send2ue', 'extensions.example.use_example_extension', True) 15 | 16 | def test_extension(self): 17 | """ 18 | Checks that the example extension load and function properly. 19 | """ 20 | self.run_extension_tests({ 21 | 'external': { 22 | 'example': { 23 | 'properties': {'hello_property': 'Hello world'}, 24 | 'tasks': [ 25 | 'post_operation', 26 | 'pre_operation', 27 | 'pre_validations' 28 | ], 29 | 'draws': [ 30 | 'draw_validations' 31 | ] 32 | }, 33 | } 34 | }) 35 | 36 | def test_default_send_to_unreal(self): 37 | """ 38 | Sends a cube mesh with default settings. 39 | """ 40 | self.move_to_collection(['Cube1_LOD0'], 'Export') 41 | self.send2ue_operation() 42 | self.assert_mesh_import('Cube1_LOD0_added_this_renamed_again') 43 | 44 | # A one off test against the ./test_files/send2ue_extensions/example.py extension 45 | value = self.blender.get_addon_property('scene', self.addon_name, 'unreal_mesh_folder_path') 46 | self.assertEqual( 47 | value, 48 | '/Game/example_extension/test/', 49 | f'The unreal mesh folder "{value}" does not match the value it is set to in the example extension file' 50 | ) 51 | -------------------------------------------------------------------------------- /tests/test_ue2rigify_core.py: -------------------------------------------------------------------------------- 1 | from utils.base_test_case import BaseTestCase 2 | 3 | 4 | class TestUe2RigifyCore(BaseTestCase): 5 | """ 6 | Checks core features of UE to Rigify 7 | """ 8 | def __init__(self, *args, **kwargs): 9 | super(TestUe2RigifyCore, self).__init__(*args, **kwargs) 10 | self.excluded_properties = [ 11 | 'context', 12 | 'saved_metarig_data', 13 | 'saved_links_data', 14 | 'saved_node_data', 15 | 'previous_mode', 16 | 'categorized_nodes', 17 | 'check_node_tree_for_updates', 18 | 'current_nodes_and_links', 19 | 'previous_viewport_settings' 20 | ] 21 | self.addon_name = 'ue2rigify' 22 | 23 | def test_property_names(self): 24 | """ 25 | Checks if all the property names are unique and not empty. 26 | """ 27 | self.blender.check_property_attribute(self.addon_name, 'name') 28 | 29 | def test_property_descriptions(self): 30 | """ 31 | Checks if all the property descriptions are unique and not empty. 32 | """ 33 | self.blender.check_property_attribute(self.addon_name, 'description', self.excluded_properties) 34 | -------------------------------------------------------------------------------- /tests/test_ue2rigify_mannequins.py: -------------------------------------------------------------------------------- 1 | from utils.base_test_case import BaseUe2RigifyTestCase 2 | 3 | 4 | class TestUe2RigifyMannequins(BaseUe2RigifyTestCase): 5 | """ 6 | Runs several test cases with the mannequins. 7 | """ 8 | 9 | def __init__(self, *args, **kwargs): 10 | super(TestUe2RigifyMannequins, self).__init__(*args, **kwargs) 11 | self.file_name = 'mannequins.blend' 12 | 13 | def test_modes(self): 14 | """ 15 | Switches through each mode. 16 | """ 17 | self.run_modes_tests({ 18 | 'male_root': { 19 | 'template': 'male_mannequin', 20 | 'modes': [ 21 | 'SOURCE', 22 | 'FK_TO_SOURCE', 23 | 'SOURCE_TO_DEFORM', 24 | 'CONTROL', 25 | 'METARIG' 26 | ] 27 | }, 28 | 'female_root': { 29 | 'template': 'female_mannequin', 30 | 'modes': [ 31 | 'FK_TO_SOURCE', 32 | 'SOURCE_TO_DEFORM', 33 | 'SOURCE', 34 | 'METARIG', 35 | 'CONTROL' 36 | ] 37 | } 38 | }) 39 | 40 | def test_new_template(self): 41 | """ 42 | Tests creating a new template. 43 | https://github.com/EpicGamesExt/BlenderTools/issues/233 44 | """ 45 | self.run_new_template_tests({ 46 | 'male_root': { 47 | 'new_template_name': 'test_basic_human', 48 | 'starter_template_name': 'bpy.ops.object.armature_basic_human_metarig_add()', 49 | 'fk_to_source': {'upper_arm_fk.L': 'upperarm_l'}, 50 | 'source_to_deform': {'upperarm_l': 'DEF-upper_arm.L'} 51 | }, 52 | 'female_root': { 53 | 'new_template_name': 'test_mannequin', 54 | 'starter_template_name': 'female_mannequin', 55 | 'fk_to_source': {'upper_arm_fk.L': 'upperarm_l'}, 56 | 'source_to_deform': {'upperarm_l': 'DEF-upper_arm.L'} 57 | } 58 | }) 59 | 60 | def test_baking(self): 61 | """ 62 | Tests that baking functions correctly. 63 | This tests that baking the bone transforms is correct. 64 | https://github.com/EpicGamesExt/BlenderTools/issues/238 65 | """ 66 | self.run_baking_tests({ 67 | # TODO flip animation order and fix failure 68 | 'male_root': { 69 | 'template': 'male_mannequin', 70 | 'control_rig': 'rig', 71 | 'animations': ['third_person_run_01', 'third_person_walk_01'], 72 | # 'bones': ['pelvis', 'calf_r', 'foot_l', 'hand_l'], # TODO make this pass with the hands and feet 73 | 'bones': ['pelvis', 'calf_r'], 74 | 'frames': [2, 7], 75 | 'ik_fk_switch': { 76 | # IK bake is not precise, greater than 2cm world location difference 77 | 'upper_arm_parent.L': 'hand_ik.L', 78 | 'thigh_parent.L': 'foot_ik.L' 79 | } 80 | }, 81 | # TODO investigate female template fix failure 82 | # 'female_root': { 83 | # 'template': 'female_mannequin', 84 | # 'control_rig': 'rig', 85 | # 'animations': ['third_person_run_01', 'third_person_walk_01'], 86 | # 'bones': ['spine_02', 'calf_l', 'lowerarm_r'], 87 | # # 'frames': [1, 9], 88 | # } 89 | }) 90 | 91 | def test_template_sharing(self): 92 | """ 93 | Checks if exporting, importing, removing templates functions correctly. 94 | """ 95 | self.run_template_sharing_tests({ 96 | 'male_root': { 97 | 'template': 'male_mannequin', 98 | } 99 | }) 100 | 101 | -------------------------------------------------------------------------------- /tests/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EpicGamesExt/BlenderTools/4b42ee3f639393ccb377f5c896b88d1bc996b939/tests/utils/__init__.py -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [pycodestyle] 2 | max-line-length = 99 3 | ignore = E121,E123,E126,E226,E24,E704,W503,W504,E501 4 | exclude = metarig.py 5 | -------------------------------------------------------------------------------- /ue2rigify/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | import os 5 | import importlib 6 | from . import properties, operators, constants 7 | from .settings import tool_tips, viewport_settings 8 | from .core import scene, nodes, templates, utilities, validations 9 | from .ui import view_3d, node_editor, addon_preferences, exporter 10 | 11 | 12 | bl_info = { 13 | "name": "UE to Rigify", 14 | "author": "Epic Games Inc.", 15 | "description": "Allows you to drive a given rig and its animations with a Rigify rig.", 16 | "version": (1, 6, 2), 17 | "blender": (3, 3, 0), 18 | "location": "3D View > Tools > UE to Rigify", 19 | "wiki_url": "https://epicgamesext.github.io/BlenderTools/ue2rigify", 20 | "warning": "", 21 | "category": "Pipeline" 22 | } 23 | 24 | 25 | modules = [ 26 | constants, 27 | scene, 28 | nodes, 29 | view_3d, 30 | exporter, 31 | tool_tips, 32 | utilities, 33 | templates, 34 | operators, 35 | properties, 36 | node_editor, 37 | addon_preferences, 38 | viewport_settings, 39 | validations 40 | ] 41 | 42 | 43 | def register(): 44 | """ 45 | Registers the addon classes when the addon is enabled. 46 | """ 47 | # TODO remove this when new undo is stable 48 | bpy.context.preferences.experimental.use_undo_legacy = True 49 | 50 | templates.copy_default_templates() 51 | 52 | # reload the submodules 53 | if os.environ.get('UE2RIGIFY_DEV'): 54 | for module in modules: 55 | importlib.reload(module) 56 | 57 | properties.register() 58 | addon_preferences.register() 59 | view_3d.register() 60 | operators.register() 61 | nodes.register() 62 | 63 | 64 | def unregister(): 65 | """ 66 | Unregisters the addon classes when the addon is disabled. 67 | """ 68 | nodes.remove_pie_menu_hot_keys() 69 | node_editor.unregister() 70 | nodes.unregister() 71 | operators.unregister() 72 | view_3d.unregister() 73 | addon_preferences.unregister() 74 | properties.unregister() 75 | -------------------------------------------------------------------------------- /ue2rigify/constants.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | import os 3 | import tempfile 4 | from enum import Enum 5 | 6 | 7 | class ToolInfo(Enum): 8 | NAME = 'ue2rigify' 9 | LABEL = 'UE to Rigify' 10 | 11 | 12 | class Modes(Enum): 13 | SOURCE = 'Source' 14 | METARIG = 'Edit Metarig' 15 | FK_TO_SOURCE = 'FK to Source' 16 | SOURCE_TO_DEFORM = 'Source to Deform' 17 | CONTROL = 'Control' 18 | 19 | 20 | class Collections: 21 | EXTRAS_COLLECTION_NAME = 'Extras' 22 | CONSTRAINTS_COLLECTION_NAME = 'Constraints' 23 | 24 | 25 | class Nodes: 26 | BONE_TREE_NAME = 'Bone Remapping Nodes' 27 | NODE_SOCKET_NAME = 'Bone Node Socket' 28 | SOURCE_RIG_OBJECT_NAME = 'Source Rig Object' 29 | SOURCE_RIG_CATEGORY = 'Source Rig Bones' 30 | CONTROL_RIG_FK_CATEGORY = 'Control Rig FK Bones' 31 | CONTROL_RIG_DEFORM_CATEGORY = 'Control Rig Deform Bones' 32 | 33 | 34 | class Template: 35 | RIG_TEMPLATES_PATH = os.path.join(tempfile.gettempdir(), ToolInfo.NAME.value, 'resources', 'rig_templates') 36 | DEFAULT_MALE_TEMPLATE = 'male_mannequin' 37 | DEFAULT_FEMALE_TEMPLATE = 'female_mannequin' 38 | 39 | 40 | class Viewport: 41 | DISPLAY_SPHERE = 'display_sphere' 42 | 43 | 44 | class Rigify: 45 | WIDGETS_COLLECTION_NAME = 'WGTS_rig' 46 | META_RIG_NAME = 'metarig' 47 | CONTROL_RIG_NAME = 'rig' 48 | RIG_UI_FILE_NAME = 'rig_ui.py' 49 | LEFT_TOKEN = '.L' 50 | RIGHT_TOKEN = '.R' 51 | -------------------------------------------------------------------------------- /ue2rigify/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /ue2rigify/core/validations.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | from . import utilities 4 | 5 | 6 | class ValidationManager: 7 | """ 8 | Handles the validation of rigs in each mode. 9 | """ 10 | 11 | def __init__(self, properties): 12 | self.properties = properties 13 | self._validators = [] 14 | self._register_validators() 15 | 16 | def _register_validators(self): 17 | """ 18 | Registers all method in this class that start with `validate_{mode}`. Mode being the 19 | current ue2rigify mode. 20 | """ 21 | for attribute in dir(self): 22 | if attribute.startswith('validate_'): 23 | validator = getattr(self, attribute) 24 | self._validators.append(validator) 25 | 26 | def run(self): 27 | """ 28 | Run the registered validations. 29 | """ 30 | # run the core validations 31 | for validator in self._validators: 32 | if not validator(): 33 | return False 34 | return True 35 | 36 | def validate_source_rig_scale(self): 37 | """ 38 | Checks that the source rig has a scale of 1. 39 | """ 40 | if self.properties.source_rig: 41 | scale = [round(i, 2) for i in self.properties.source_rig.scale[:]] 42 | if not all(i == 1.00 for i in scale): 43 | utilities.report_error( 44 | error_header='Invalid Scale', 45 | error_message=( 46 | f'The source rig "{self.properties.source_rig.name}" has a scale of ' 47 | f'{scale}, it must be 1' 48 | ) 49 | ) 50 | return False 51 | return True 52 | -------------------------------------------------------------------------------- /ue2rigify/properties.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from .constants import ToolInfo, Modes 5 | from .core import scene, templates, utilities 6 | from .settings import tool_tips 7 | 8 | 9 | class UE2RigifyProperties(bpy.types.PropertyGroup): 10 | """ 11 | Defines a property group that lives in the scene. 12 | """ 13 | # --------------------- read/write properties ------------------ 14 | context = {} 15 | 16 | # template variables 17 | saved_metarig_data: bpy.props.StringProperty(default='') 18 | saved_links_data: bpy.props.StringProperty(default='') 19 | saved_node_data: bpy.props.StringProperty(default='') 20 | 21 | # mode variables 22 | previous_mode: bpy.props.StringProperty(default=Modes.SOURCE.name) 23 | 24 | # node variables 25 | categorized_nodes = {} 26 | check_node_tree_for_updates: bpy.props.BoolProperty(default=False) 27 | current_nodes_and_links: bpy.props.IntProperty(default=0, update=scene.update_rig_constraints) 28 | 29 | # utility variables 30 | previous_viewport_settings = {} 31 | 32 | # --------------------- user interface properties ------------------ 33 | source_rig: bpy.props.PointerProperty( 34 | poll=utilities.armature_poll, 35 | type=bpy.types.Object, 36 | update=utilities.initialize_template_paths 37 | ) 38 | 39 | # view 3d properties 40 | new_template_name: bpy.props.StringProperty( 41 | default='', 42 | maxlen=35, 43 | description=tool_tips.new_template_name 44 | ) 45 | overwrite_control_animations: bpy.props.BoolProperty( 46 | default=False, 47 | description=tool_tips.overwrite_animation 48 | ) 49 | 50 | bake_every_bone: bpy.props.BoolProperty( 51 | default=True, 52 | name="Bake every bone", 53 | description=tool_tips.bake_every_bone 54 | ) 55 | 56 | selected_starter_metarig_template: bpy.props.EnumProperty( 57 | name="Metarig", 58 | description=tool_tips.starter_metarig_template_tool_tip, 59 | items=templates.safe_get_starter_metarig_templates, 60 | update=scene.set_meta_rig 61 | ) 62 | 63 | selected_rig_template: bpy.props.EnumProperty( 64 | name="Rig Template", 65 | description=tool_tips.rig_template_tool_tip, 66 | items=templates.safe_populate_templates_dropdown, 67 | options={'ANIMATABLE'}, 68 | update=templates.set_template 69 | ) 70 | 71 | selected_mode: bpy.props.EnumProperty( 72 | name="Modes", 73 | description=tool_tips.mode_tool_tip, 74 | items=templates.safe_get_modes, 75 | options={'ANIMATABLE'}, 76 | update=scene.switch_modes 77 | ) 78 | 79 | # exporter properties 80 | selected_export_template: bpy.props.EnumProperty( 81 | name="Export Rig Template", 82 | description=tool_tips.export_template_tool_tip, 83 | items=templates.safe_get_rig_templates, 84 | options={'ANIMATABLE'} 85 | ) 86 | 87 | # node editor properties 88 | mirror_constraints: bpy.props.BoolProperty( 89 | default=True, 90 | description=tool_tips.mirror_constraints 91 | ) 92 | 93 | left_x_mirror_token: bpy.props.StringProperty( 94 | default='_l', 95 | maxlen=35, 96 | description=tool_tips.left_x_mirror_token 97 | ) 98 | right_x_mirror_token: bpy.props.StringProperty( 99 | default='_r', 100 | maxlen=35, 101 | description=tool_tips.right_x_mirror_token 102 | ) 103 | 104 | 105 | def register(): 106 | """ 107 | Registers the property group class and adds it to the window manager context when the 108 | addon is enabled. 109 | """ 110 | properties = getattr(bpy.types.Scene, ToolInfo.NAME.value, None) 111 | if not properties: 112 | bpy.utils.register_class(UE2RigifyProperties) 113 | bpy.types.Scene.ue2rigify = bpy.props.PointerProperty(type=UE2RigifyProperties) 114 | 115 | 116 | def unregister(): 117 | """ 118 | Unregisters the property group class and deletes it from the window manager context when the 119 | addon is disabled. 120 | """ 121 | properties = getattr(bpy.types.Scene, ToolInfo.NAME.value, None) 122 | if properties: 123 | bpy.utils.unregister_class(UE2RigifyProperties) 124 | del bpy.types.Scene.ue2rigify 125 | -------------------------------------------------------------------------------- /ue2rigify/release_notes.md: -------------------------------------------------------------------------------- 1 | ### Minor Changes 2 | * Added validation to ensure source rig has a scale of 1. 3 | * [601](https://github.com/EpicGamesExt/BlenderTools/issues/601) 4 | 5 | 6 | ## Tests Passing On 7 | * Blender `3.5` (installed from blender.org) 8 | -------------------------------------------------------------------------------- /ue2rigify/settings/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | from . import tool_tips, viewport_settings 4 | 5 | __all__ = [ 6 | 'tool_tips', 7 | 'viewport_settings' 8 | ] 9 | -------------------------------------------------------------------------------- /ue2rigify/settings/tool_tips.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | # ---------- tool tips for the modes enumeration ---------- 4 | source_mode_tool_tip = "This mode is where you can see your original source rig" 5 | 6 | metarig_mode_tool_tip = ( 7 | "This mode is where you add or remove bones, edit bone positions, and edit the rigify bones types" 8 | ) 9 | 10 | fk_to_source_mode_tool_tip = ( 11 | "This mode is where you edit the nodes that constrain your FK bones to the original source bones. These node " 12 | "links are needed if you want to transfer the existing animation from the source rig to the control rig" 13 | ) 14 | 15 | source_to_deform_mode_tool_tip = ( 16 | "This mode is where you edit the nodes that constrain your original source bones to the deformation bones on " 17 | "your control rig" 18 | ) 19 | 20 | control_mode_tool_tip = "This mode is where you can control your new rig and animate" 21 | 22 | # ---------- tool tips for the rig templates enumeration ---------- 23 | template_tool_tip = "This template contains the metarig and node trees for the {template_name} rig" 24 | 25 | starter_metarig_tool_tip = 'This is a metarig preset you can use as a starting point to create your new rig template' 26 | 27 | create_template_tool_tip = ( 28 | "When this is selected you can create a new rig template. A new example metarig is created for you. Give it a " 29 | "name to save it" 30 | ) 31 | 32 | # ---------- tool tips for the user interface properties ---------- 33 | starter_metarig_template_tool_tip = "Select a metarig template as a starting point for your metarig" 34 | 35 | rig_template_tool_tip = "Select a rig template or create a new one" 36 | 37 | mode_tool_tip = "Select the tool mode you would like to work in" 38 | 39 | export_template_tool_tip = "Select a rig template to export" 40 | 41 | overwrite_animation = ( 42 | "If enabled, your control rig animation data will be overwritten by the animation data from your source rig" 43 | ) 44 | 45 | bake_every_bone = ( 46 | "If enabled, this will bake all bones on the source rig regardless if they have a link back to the control rig" 47 | ) 48 | 49 | new_template_name = "Define the name of your new rig template" 50 | 51 | mirror_constraints = "When enabled, this will mirror your constraints across the x-axis" 52 | 53 | left_x_mirror_token = "The left token name found in all left bones on the source rig" 54 | 55 | right_x_mirror_token = "The right token name found in all left bones on the source rig" 56 | -------------------------------------------------------------------------------- /ue2rigify/ui/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | from . import view_3d, node_editor, addon_preferences, exporter 4 | 5 | __all__ = [ 6 | 'view_3d', 7 | 'node_editor', 8 | 'addon_preferences', 9 | 'exporter' 10 | ] 11 | -------------------------------------------------------------------------------- /ue2rigify/ui/addon_preferences.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from ..constants import ToolInfo 5 | 6 | 7 | class Ue2RigifyAddonPreferences(bpy.types.AddonPreferences): 8 | """ 9 | This class subclasses the AddonPreferences class to create the addon preferences interface. 10 | """ 11 | bl_idname = ToolInfo.NAME.value 12 | 13 | def draw(self, context): 14 | """ 15 | This function overrides the draw method in the AddonPreferences class. The draw method is the function 16 | that defines the user interface layout and gets updated routinely. 17 | 18 | :param object context: The addon preferences context. 19 | """ 20 | layout = self.layout 21 | 22 | row = layout.row() 23 | row.operator('ue2rigify.import_rig_template', icon='IMPORT') 24 | row.operator('ue2rigify.export_rig_template', icon='EXPORT') 25 | 26 | 27 | def register(): 28 | """ 29 | Registers the addon preferences when the addon is enabled. 30 | """ 31 | if not hasattr(bpy.types, Ue2RigifyAddonPreferences.bl_idname): 32 | bpy.utils.register_class(Ue2RigifyAddonPreferences) 33 | 34 | 35 | def unregister(): 36 | """ 37 | Unregisters the addon preferences when the addon is disabled. 38 | """ 39 | if hasattr(bpy.types, Ue2RigifyAddonPreferences.bl_idname): 40 | bpy.utils.unregister_class(Ue2RigifyAddonPreferences) 41 | -------------------------------------------------------------------------------- /ue2rigify/ui/exporter.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | from bpy_extras.io_utils import ExportHelper 5 | 6 | 7 | class ExportRigTemplate(ExportHelper): 8 | """ 9 | This class subclasses the export helper to define a custom file browser 10 | """ 11 | bl_idname = "ue2rigify.export_rig_template" 12 | bl_label = "Export Template" 13 | filename_ext = ".zip" 14 | 15 | def draw(self, context): 16 | """ 17 | This function overrides the draw method in the ExportHelper class. The draw method is the function that 18 | defines the user interface layout and gets updated routinely. 19 | 20 | :param object context: The window context. 21 | """ 22 | properties = bpy.context.scene.ue2rigify 23 | 24 | layout = self.layout 25 | row = layout.row() 26 | row.label(text='Export Template:') 27 | row = layout.row() 28 | row.prop(properties, 'selected_export_template', text='') 29 | -------------------------------------------------------------------------------- /ue2rigify/ui/node_editor.py: -------------------------------------------------------------------------------- 1 | # Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | import bpy 4 | import sys 5 | import nodeitems_utils 6 | from ..constants import Nodes 7 | 8 | 9 | class UE_RIGIFY_PT_NodeToolsPanel(bpy.types.Panel): 10 | """ 11 | This class defines the user interface for the panel in the tool tab in the node editor 12 | """ 13 | bl_label = "Node Tools" 14 | bl_space_type = "NODE_EDITOR" 15 | bl_region_type = "UI" 16 | bl_category = "Tool" 17 | 18 | def draw(self, context): 19 | """ 20 | This function overrides the draw method in the Panel class. The draw method is the function that 21 | defines the user interface layout and gets updated routinely. 22 | 23 | :param object context: The node editor context. 24 | """ 25 | properties = bpy.context.scene.ue2rigify 26 | 27 | layout = self.layout 28 | 29 | row = layout.row() 30 | row.prop(properties, 'mirror_constraints', text='X-axis Mirror') 31 | 32 | row = layout.row() 33 | if not properties.mirror_constraints: 34 | row.enabled = False 35 | row.label(text="Right:") 36 | row.label(text="Left:") 37 | 38 | row = layout.row() 39 | if not properties.mirror_constraints: 40 | row.enabled = False 41 | row.prop(properties, 'right_x_mirror_token', text='') 42 | row.prop(properties, 'left_x_mirror_token', text='') 43 | 44 | row = layout.row() 45 | row.scale_y = 2.0 46 | row.operator('wm.align_active_node_sockets') 47 | 48 | row = layout.row() 49 | row.scale_y = 2.0 50 | row.operator('wm.combine_selected_nodes') 51 | 52 | 53 | class BoneRemappingTreeNode: 54 | """ 55 | This class defines the node tree 56 | """ 57 | @classmethod 58 | def poll(cls, node_tree): 59 | """ 60 | This method checks to see if the node tree has the correct bl_idname. 61 | 62 | :param object node_tree: A given node tree object 63 | :return bool: True or false depending on whether the bl_idname of the provided node tree matches the 64 | bl_idname in the properties. 65 | """ 66 | return node_tree.bl_idname == Nodes.BONE_TREE_NAME.replace(' ', '') 67 | 68 | 69 | class BoneRemappingTreeCategory(nodeitems_utils.NodeCategory): 70 | @classmethod 71 | def poll(cls, context): 72 | """ 73 | This method checks to see if the node tree category is the correct type. 74 | 75 | :param object context: A given node tree category 76 | :return bool: True or false depending on whether the type of the node tree in the context matches the 77 | type in the properties. 78 | """ 79 | return context.space_data.tree_type == Nodes.BONE_TREE_NAME.replace(' ', '') 80 | 81 | 82 | class BaseRigBonesNode(bpy.types.Node, BoneRemappingTreeNode): 83 | """ 84 | This class defines the base node class the will be subclassed. 85 | """ 86 | def draw_label(self): 87 | """ 88 | This function overrides the draw_label method in the Node class. The draw method is the function that 89 | defines the label of the node in the user interface. 90 | 91 | :return str: The name of the label. 92 | """ 93 | return self.bl_label 94 | 95 | 96 | def register(): 97 | """ 98 | When called, this function registers the node panel class. 99 | """ 100 | try: 101 | bpy.utils.register_class(UE_RIGIFY_PT_NodeToolsPanel) 102 | except (RuntimeError, ValueError) as error: 103 | sys.stderr.write(str(error)) 104 | 105 | 106 | def unregister(): 107 | """ 108 | When called, the function unregisters the node panel class. 109 | """ 110 | try: 111 | bpy.utils.unregister_class(UE_RIGIFY_PT_NodeToolsPanel) 112 | except (RuntimeError, ValueError) as error: 113 | sys.stderr.write(str(error)) 114 | --------------------------------------------------------------------------------