├── .gitignore ├── LICENSE.md ├── README.md ├── __init__.py ├── addon ├── __init__.py ├── menu │ ├── __init__.py │ └── at_ui_panel.py ├── operator │ ├── __init__.py │ ├── at_bake.py │ ├── at_bake_ao.py │ └── at_create_env.py ├── property │ ├── __init__.py │ ├── at_obj_properties.py │ └── at_properties.py ├── register │ └── __init__.py └── utility │ ├── __init__.py │ └── at_utils.py └── images ├── autobake_bevel_demo.gif ├── baking_ao.gif ├── baking_ao_demo.gif ├── baking_bevel.gif ├── baking_bevel_2.gif ├── logo_f.png ├── logo_f_2x1.png ├── screenshot.png ├── show_marmoset.gif ├── show_substance.gif └── substance_demo.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled optimized DLL files 2 | __pycache__ 3 | .py[cod] 4 | $py.class 5 | 6 | 7 | # C extensions 8 | .so 9 | 10 | # Distribution packaging 11 | .Python 12 | build 13 | develop-eggs 14 | dist 15 | downloads 16 | eggs 17 | .eggs 18 | lib 19 | lib64 20 | parts 21 | sdist 22 | var 23 | wheels 24 | pip-wheel-metadata 25 | sharepython-wheels 26 | .egg-info 27 | .installed.cfg 28 | .egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject dateother infos into it. 34 | .manifest 35 | .spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test coverage reports 42 | htmlcov 43 | .tox 44 | .nox 45 | .coverage 46 | .coverage. 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | .cover 51 | .py,cover 52 | .hypothesis 53 | .pytest_cache 54 | 55 | # Translations 56 | .mo 57 | .pot 58 | 59 | # Django stuff 60 | .log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff 66 | instance 67 | .webassets-cache 68 | 69 | # Scrapy stuff 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs_build 74 | 75 | # PyBuilder 76 | target 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypapipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # PEP 582; used by e.g. github.comDavid-OConnorpyflow 96 | __pypackages__ 97 | 98 | # Celery stuff 99 | celerybeat-schedule 100 | celerybeat.pid 101 | 102 | # SageMath parsed files 103 | .sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env 109 | venv 110 | ENV 111 | env.bak 112 | venv.bak 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | site 123 | 124 | # mypy 125 | .mypy_cache 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre 131 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Contributors][contributors-shield]][contributors-url] 4 | [![Stargazers][stars-shield]][stars-url] 5 | [![support][buy-shield]][buy-url] 6 | [![Total Downloads](https://img.shields.io/github/downloads/GarikDog/autobake_tools/total?style=for-the-badge&logo=appveyor)](https://github.com/GarikDog/autobake_tools/releases) 7 | [![Release][release-shield]][release-url] 8 | [![Issues][issues-shield]][issues-url] 9 | [![MIT License][license-shield]][license-url] 10 | 11 | 12 | 13 |
14 |
15 | 16 | Logo 17 | 18 | 19 |

Auto-bake Tools

20 | 21 |

22 | Blender Add-on for Automatic Bevel Shader - Normal Map Baking 23 |
24 | easy to use 25 |
26 | useful for 3D artists 27 |
28 |

29 |
30 | 31 | 32 | 33 | 34 |
35 | Table of Contents 36 |
    37 |
  1. 38 | About The Project 39 | 42 |
  2. 43 |
  3. 44 | Getting Started 45 | 49 |
  4. 50 |
  5. Usage
  6. 51 |
  7. Explanation of what the addon code does
  8. 52 |
  9. Roadmap
  10. 53 |
  11. License
  12. 54 |
  13. Contact
  14. 55 |
  15. Acknowledgments
  16. 56 |
57 |
58 | 59 | 60 | 61 | ## About The Project 62 | 63 | 64 | 65 | An easy to use Blender Add-on that allows you to bake Bevel Shader to the Normal Map, Ambient Occlusion to the AO Map in fully automatic mode. 66 | 67 | 68 | 69 | 70 | * If You are working in Blender, this will save you a lot of time! 71 | * If You're not working in Blender but need to bake your bevels, this will save you even more time! 72 | 73 | ![](https://github.com/GarikDog/autobake_tools/blob/main/images/autobake_bevel_demo.gif) 74 | ![](https://github.com/GarikDog/autobake_tools/blob/main/images/baking_ao_demo.gif) 75 | ![](https://github.com/GarikDog/autobake_tools/blob/main/images/substance_demo.gif) 76 | [![Product Name Screen Shot][product-screenshot]](https://github.com/GarikDog/autobake_tools/blob/main/images/screenshot.png) 77 | 78 | 79 |

(back to top)

80 | 81 | ### Built With 82 | 83 | * [![bpy][project/bpy]][bpy-url] 84 | 85 | 86 | 87 | ## Getting Started 88 | 89 | 90 | 91 | ### Prerequisites 92 | 93 | 94 | First You need to install Blender (You need the ***3,0,1*** or newer) 95 | 96 | * Download the last blender release: 97 | 98 | * [![blender][blender.org]][blender-url] 99 | 100 | ### Installation 101 | 102 | 1. Download latest release of Autobake Tools: 103 | 104 | * [![Release][release-shield]][release-url] 105 | 106 | * You also can ❤: 107 | 108 | * [![support][buy-shield]][buy-url] 109 | 110 | 2. Run Blender 111 | 112 | 3. Go to ***Edit>Preferences Add-ons tab.*** 113 | 114 | 4. At the top right of the Blender Preferences window, push the ***install...*** button. 115 | 116 | 5. Find the ***downloaded zip with Auto-bake Tools*** in file manager that appeared, select and click ***Install Add-on***. 117 | 118 | 6. Next, use the search in the Blender Preferences window (Directly under the ***Install...*** button), find the addon by name. 119 | 120 | 7. Check the box next to the found Add-on. 121 | 122 |

(back to top)

123 | 124 | 125 | ## Usage 126 | 1. Select an object that need to bake in the scene. ***(Must be UV unwrapped)*** 127 | 128 | 2. If an object is selected, the ***Auto-bake Tools*** Panel will become available. 129 | 130 | 3. Go to ***Auto-bake Tools*** Panel 131 | 132 | 4. Push the ***Create Bake Environment*** button 133 | 134 | 5. Correct Values: 135 | * ***Image Width*** - Bake Image width 136 | * ***Image Height*** - Bake Image height 137 | 138 | For Bevel: 139 | * ***Glossy Preview*** - Sets the glossy shader to visually display Bevel effect 140 | * ***Bevel Samples*** - Number of rays to trace per belel shader evaluation. 141 | * ***Bevel Radius*** - radius of traced bevels (in meters by default) 142 | 143 | For AO: 144 | * ***AO Distance*** - distance of AO tracing 145 | * ***AO Samples*** - Number of rays to trace per Ambient Occlusion evaluation 146 | * ***AO Exponentiation*** - Exponentiation value of AO to increase contrast 147 | 148 | 149 | 6. Push the ***Bake Normal and Show*** button for Bevel or ***Bake AO and Show*** for AO 150 | 7. Wait... And That's All! You may save the Bake result Normal Map/AO Map in Image Window that appeared 151 | 152 | You can look at this gif: 153 | 154 | ![](https://github.com/GarikDog/autobake_tools/blob/main/images/baking_bevel.gif) 155 | 156 | 157 | ***Important additional information:*** 158 | 159 | It is advisable to check if GPU Render is available for Cycles. 160 | 161 | If not available, go to Edit>Preferences System tab 162 | In it, select the CUDA subtab and uncheck / check the boxes next to your video card name and near the processor name. 163 | 164 | After these steps, GPU Compute will be available in most cases (If the hardware is not quite ancient) 165 | 166 | ***GPU Compute for Cycles is extremely important and greatly overclocks the render, please keep in mind!*** 167 | 168 | 169 |

(back to top)

170 | 171 | 172 | 173 | ## Explanation of what the addon code does 174 | 175 | ***Create Bake Environment operator:*** 176 | 177 | * ***Shading setup:*** 178 | 1. Sets the Render Engine to ***Cycles*** 179 | 180 | 2. Sets the Render Feature Set to ***Supported*** 181 | 182 | 3. Trying to set the Render Device to ***GPU*** 183 | 184 | 4. Sets the ***Bake Multires*** to False 185 | 186 | 5. Sets the ***Selected to Active*** to False 187 | 188 | * ***Material Setup:*** 189 | 1. ***Creates Material*** (if selected object have not material) 190 | 191 | 2. Sets the ***Use Nodes*** to True 192 | 193 | * ***Shader Editor setup:*** 194 | 195 | 1. Cleares Nodes 196 | 197 | 2. Creates, places and conneсts ***Glossy BSDF, Diffuse BSDF, Material Output, Bevel node, Image Texture node, Ambient Occlusion, Math(Power)*** 198 | 199 | ***Bake Normal and Show operator:*** 200 | 201 | * Creates the ***Image*** with ***custom _n name ending*** 202 | 203 | * Runs default blender ***Bake*** operator with type ***Normal*** 204 | 205 | ***Bake AO and Show operator:*** 206 | 207 | * Creates the ***Image*** with ***custom _ao name ending*** 208 | 209 | * Runs default blender ***Bake*** operator with type ***DIFFUSE*** 210 | 211 | * Opens the window with the Result 212 | 213 | ***Glossy preview, 214 | Image Width, 215 | Image Height, 216 | Bevel Samples, 217 | Bevel Radius, 218 | AO Distance, 219 | AO Samples, 220 | AO Exponentiation*** - custom properties. It's implementation allows you to change the values ​​at any time. The nodes will get them anyway. 221 | 222 | 223 | 224 | 225 |

(back to top)

226 | 227 | 228 | 229 | ## Roadmap 230 | 231 | - Add a multimesh bake 232 | 233 | 234 | 235 | See [open issues](https://github.com/GarikDog/autobake_tools/issues) for a full list of proposed features (and known issues). 236 | 237 |

(back to top)

238 | 239 | 240 | ## License 241 | 242 | Distributed under the APACHE-2.0 License. See [LICENSE.md](https://github.com/GarikDog/autobake_tools/blob/main/LICENSE.md) for more information. 243 | 244 |

(back to top)

245 | 246 | ## Contact 247 | 248 | Igor Subachev (GarikDog) - [Discord](https://discordapp.com/users/GarikDog#7847) - sobakapppoe@gmail.com 249 | 250 | Project Link: [https://github.com/GarikDog/autobake_tools](https://github.com/GarikDog/autobake_tools) 251 | 252 |

(back to top)

253 | 254 | 255 | ## Acknowledgments 256 | 257 | * Thanks to [Steven Wyatt](https://www.udemy.com/user/steven-wyatt-2/) for a great course on bpy development 258 | 259 | 260 |

(back to top)

261 | 262 | 263 | 264 | 265 | 266 | [contributors-shield]: https://img.shields.io/github/contributors/GarikDog/autobake_tools.svg?style=for-the-badge 267 | [contributors-url]: https://github.com/GarikDog/autobake_tools/graphs/contributors 268 | [release-url]: https://github.com/GarikDog/autobake_tools/releases/latest 269 | [release-shield]: https://img.shields.io/github/release/GarikDog/autobake_tools.svg?style=for-the-badge 270 | [stars-shield]: https://img.shields.io/github/stars/GarikDog/autobake_tools.svg?style=for-the-badge 271 | [stars-url]: https://github.com/GarikDog/autobake_tools/stargazers 272 | [issues-shield]: https://img.shields.io/github/issues/GarikDog/autobake_tools.svg?style=for-the-badge 273 | [issues-url]: https://github.com/GarikDog/autobake_tools/issues 274 | [license-shield]: https://img.shields.io/github/license/GarikDog/autobake_tools.svg?style=for-the-badge 275 | [license-url]: https://github.com/GarikDog/autobake_tools//blob/main/LICENSE.md 276 | [product-screenshot]: images/screenshot.png 277 | [product-gif-demo]: images/baking_bevel.gif 278 | 279 | [blender-url]: https://www.blender.org/ 280 | [blender.org]: https://img.shields.io/badge/blender-0769AD?style=for-the-badge&logo=blender&logoColor=orange 281 | [bpy-url]: https://pypi.org/project/bpy/ 282 | [project/bpy]: https://img.shields.io/badge/bpy-0769AD?style=for-the-badge&logo=pypi&logoColor=white 283 | 284 | 285 | 286 | 287 | 288 | [buy-shield]:https://img.shields.io/badge/Blender%20Market-Support%20with%20a%20purchase-orange?style=for-the-badge&logo=appveyor 289 | [buy-url]:https://www.blendermarket.com/products/autobake-tools 290 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | bl_info = { 18 | "name": "Auto-bake Tools", 19 | "description": "Auto-bake Tools", 20 | "author": "Igor Subachev (GarikDog)", 21 | "version": (1,2,1), 22 | "blender": (3,0,1), 23 | "location": "View3D", 24 | "category": "3D View"} 25 | 26 | 27 | 28 | def register(): 29 | from .addon.register import register_addon 30 | register_addon() 31 | 32 | 33 | 34 | def unregister(): 35 | from .addon.register import unregister_addon 36 | unregister_addon() -------------------------------------------------------------------------------- /addon/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### -------------------------------------------------------------------------------- /addon/menu/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | 19 | from .at_ui_panel import VIEW3D_PT_Autobake, VIEW3D_PT_Sampling, VIEW3D_PT_sampling_viewport, VIEW3D_PT_sampling_viewport_denoise, VIEW3D_PT_sampling_render, VIEW3D_PT_sampling_render_denoise 20 | 21 | classes = ( 22 | VIEW3D_PT_Autobake, 23 | VIEW3D_PT_Sampling, 24 | VIEW3D_PT_sampling_viewport, 25 | VIEW3D_PT_sampling_viewport_denoise, 26 | VIEW3D_PT_sampling_render, 27 | VIEW3D_PT_sampling_render_denoise 28 | ) 29 | 30 | 31 | def register_menus(): 32 | from bpy.utils import register_class 33 | for cls in classes: 34 | register_class(cls) 35 | 36 | 37 | def unregister_menus(): 38 | from bpy.utils import unregister_class 39 | for cls in reversed(classes): 40 | unregister_class(cls) -------------------------------------------------------------------------------- /addon/menu/at_ui_panel.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | # SPDX-FileCopyrightText: 2011-2022 Blender Foundation 18 | # 19 | # SPDX-License-Identifier: Apache-2.0 20 | 21 | import bpy 22 | 23 | from bpy.types import Panel 24 | from ..utility.at_utils import get_effective_preview_denoiser 25 | 26 | 27 | 28 | 29 | class VIEW3D_PT_Autobake(Panel): 30 | bl_idname = "VIEW3D_PT_Atobake" 31 | bl_label = "Auto-bake Tools" 32 | bl_space_type = 'VIEW_3D' 33 | bl_region_type = 'UI' 34 | bl_category = "Auto-bake Tools" 35 | 36 | 37 | @classmethod 38 | 39 | def poll(cls, context): 40 | if context.active_object != None: 41 | if context.active_object.type == 'MESH': 42 | return True 43 | return False 44 | 45 | 46 | def invoke(self, context, event): 47 | return {'RUNNING_MODAL'} 48 | 49 | 50 | def draw(self, context): 51 | 52 | layout = self.layout 53 | scene = bpy.context.scene 54 | attool = scene.at_tool 55 | job_statement = False 56 | 57 | box = layout.box() 58 | box.operator("at.create_environment") 59 | layout.column().prop(attool, "at_glossy_preview", text="Glossy Preview") 60 | layout.column().prop(attool, "image_width_prop_int", text="Image Width") 61 | layout.column().prop(attool, "image_height_prop_int", text="Image Height") 62 | layout.label(text="Bevel Shader:") 63 | layout.column().prop(attool, "bevel_samples_prop_int", text="Bevel Samples") 64 | layout.column().prop(attool, "bevel_radius_prop_float", text="Bevel Radius") 65 | layout.column().prop(attool, "at_dx_normal", text="DirectX Normal") 66 | 67 | box = layout.box() 68 | row = layout.split(factor=0.5, align=False) 69 | 70 | 71 | bake = box.operator("at.bake") 72 | 73 | 74 | 75 | layout.label(text="Ambient Occlusion:") 76 | layout.column().prop(attool, "at_ao_distance", text="AO Distance") 77 | layout.column().prop(attool, "at_ao_samples", text="AO Samples") 78 | layout.column().prop(attool, "at_ao_exponentiation", text="AO Exponentiation") 79 | 80 | 81 | box = layout.box() 82 | row = layout.split(factor=0.5, align=False) 83 | box.operator("at.bake_ao") 84 | 85 | class VIEW3D_PT_Sampling(Panel): 86 | bl_idname = "VIEW3D_PT_Sampling" 87 | bl_label = "Sampling" 88 | bl_space_type = 'VIEW_3D' 89 | bl_region_type = 'UI' 90 | bl_category = "Auto-bake Tools" 91 | bl_options = {'DEFAULT_CLOSED'} 92 | 93 | 94 | 95 | 96 | @classmethod 97 | 98 | def poll(cls, context): 99 | if context.active_object != None: 100 | if context.active_object.type == 'MESH' and context.scene.render.engine == 'CYCLES': 101 | return True 102 | return False 103 | 104 | 105 | def invoke(self, context, event): 106 | return {'RUNNING_MODAL'} 107 | 108 | 109 | def draw(self, context): 110 | pass 111 | 112 | class VIEW3D_PT_sampling_viewport(Panel): 113 | bl_idname = "VIEW3D_PT_sampling_viewport" 114 | bl_label = "Viewport" 115 | bl_parent_id = "VIEW3D_PT_Sampling" 116 | bl_space_type = 'VIEW_3D' 117 | bl_region_type = 'UI' 118 | bl_category = "Auto-bake Tools" 119 | 120 | 121 | 122 | 123 | @classmethod 124 | 125 | def poll(cls, context): 126 | if context.active_object != None: 127 | if context.active_object.type == 'MESH' and context.scene.render.engine == 'CYCLES': 128 | return True 129 | return False 130 | 131 | 132 | def invoke(self, context, event): 133 | return {'RUNNING_MODAL'} 134 | 135 | 136 | def draw(self, context): 137 | layout = self.layout 138 | scene = context.scene 139 | cscene = scene.cycles 140 | layout.use_property_split = True 141 | layout.use_property_decorate = False 142 | heading = layout.column(align=True, heading="Noise Threshold") 143 | row = heading.row(align=True) 144 | row.prop(cscene, "use_preview_adaptive_sampling", text="") 145 | sub = row.row() 146 | sub.active = cscene.use_preview_adaptive_sampling 147 | sub.prop(cscene, "preview_adaptive_threshold", text="") 148 | if cscene.use_preview_adaptive_sampling: 149 | col = layout.column(align=True) 150 | col.prop(cscene, "preview_samples", text="Max Samples") 151 | col.prop(cscene, "preview_adaptive_min_samples", text="Min Samples") 152 | else: 153 | layout.prop(cscene, "preview_samples", text="Samples") 154 | 155 | class VIEW3D_PT_sampling_viewport_denoise(Panel): 156 | bl_idname = "VIEW3D_PT_sampling_viewport_denoise" 157 | bl_label = "Denoise" 158 | bl_parent_id = "VIEW3D_PT_sampling_viewport" 159 | bl_space_type = 'VIEW_3D' 160 | bl_region_type = 'UI' 161 | bl_category = "Auto-bake Tools" 162 | bl_options = {'DEFAULT_CLOSED'} 163 | 164 | 165 | @classmethod 166 | 167 | def poll(cls, context): 168 | if context.active_object != None: 169 | if context.active_object.type == 'MESH' and context.scene.render.engine == 'CYCLES': 170 | return True 171 | return False 172 | 173 | 174 | def invoke(self, context, event): 175 | return {'RUNNING_MODAL'} 176 | 177 | 178 | def draw_header(self, context): 179 | scene = context.scene 180 | cscene = scene.cycles 181 | 182 | self.layout.prop(context.scene.cycles, "use_preview_denoising", text="") 183 | 184 | def draw(self, context): 185 | layout = self.layout 186 | layout.use_property_split = True 187 | layout.use_property_decorate = False 188 | 189 | scene = context.scene 190 | cscene = scene.cycles 191 | 192 | col = layout.column() 193 | col.active = cscene.use_preview_denoising 194 | col.prop(cscene, "preview_denoiser", text="Denoiser") 195 | col.prop(cscene, "preview_denoising_input_passes", text="Passes") 196 | 197 | effective_preview_denoiser = get_effective_preview_denoiser(context) 198 | if effective_preview_denoiser == 'OPENIMAGEDENOISE': 199 | col.prop(cscene, "preview_denoising_prefilter", text="Prefilter") 200 | 201 | col.prop(cscene, "preview_denoising_start_sample", text="Start Sample") 202 | 203 | 204 | class VIEW3D_PT_sampling_render(Panel): 205 | bl_idname = "VIEW3D_PT_sampling_render" 206 | bl_label = "Render" 207 | bl_parent_id = "VIEW3D_PT_Sampling" 208 | bl_space_type = 'VIEW_3D' 209 | bl_region_type = 'UI' 210 | bl_category = "Auto-bake Tools" 211 | 212 | 213 | 214 | 215 | @classmethod 216 | 217 | def poll(cls, context): 218 | if context.active_object != None: 219 | if context.active_object.type == 'MESH' and context.scene.render.engine == 'CYCLES': 220 | return True 221 | return False 222 | 223 | 224 | def invoke(self, context, event): 225 | return {'RUNNING_MODAL'} 226 | 227 | 228 | def draw(self, context): 229 | layout = self.layout 230 | 231 | scene = context.scene 232 | cscene = scene.cycles 233 | 234 | layout.use_property_split = True 235 | layout.use_property_decorate = False 236 | 237 | heading = layout.column(align=True, heading="Noise Threshold") 238 | row = heading.row(align=True) 239 | row.prop(cscene, "use_adaptive_sampling", text="") 240 | sub = row.row() 241 | sub.active = cscene.use_adaptive_sampling 242 | sub.prop(cscene, "adaptive_threshold", text="") 243 | 244 | col = layout.column(align=True) 245 | if cscene.use_adaptive_sampling: 246 | col.prop(cscene, "samples", text="Max Samples") 247 | col.prop(cscene, "adaptive_min_samples", text="Min Samples") 248 | else: 249 | col.prop(cscene, "samples", text="Samples") 250 | col.prop(cscene, "time_limit") 251 | 252 | class VIEW3D_PT_sampling_render_denoise(Panel): 253 | bl_idname = "VIEW3D_PT_sampling_render_denoise" 254 | bl_label = "Denoise" 255 | bl_parent_id = "VIEW3D_PT_sampling_render" 256 | bl_space_type = 'VIEW_3D' 257 | bl_region_type = 'UI' 258 | bl_category = "Auto-bake Tools" 259 | bl_options = {'DEFAULT_CLOSED'} 260 | 261 | 262 | @classmethod 263 | 264 | def poll(cls, context): 265 | if context.active_object != None: 266 | if context.active_object.type == 'MESH' and context.scene.render.engine == 'CYCLES': 267 | return True 268 | return False 269 | 270 | 271 | def invoke(self, context, event): 272 | return {'RUNNING_MODAL'} 273 | 274 | def draw_header(self, context): 275 | scene = context.scene 276 | cscene = scene.cycles 277 | 278 | self.layout.prop(context.scene.cycles, "use_denoising", text="") 279 | 280 | def draw(self, context): 281 | layout = self.layout 282 | layout.use_property_split = True 283 | layout.use_property_decorate = False 284 | 285 | scene = context.scene 286 | cscene = scene.cycles 287 | 288 | col = layout.column() 289 | col.active = cscene.use_denoising 290 | col.prop(cscene, "denoiser", text="Denoiser") 291 | col.prop(cscene, "denoising_input_passes", text="Passes") 292 | if cscene.denoiser == 'OPENIMAGEDENOISE': 293 | col.prop(cscene, "denoising_prefilter", text="Prefilter") -------------------------------------------------------------------------------- /addon/operator/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | 19 | from .at_create_env import AT_OP_Create_Environment 20 | from .at_bake import AT_OP_Bake 21 | from .at_bake_ao import AT_OP_Bake_ao 22 | 23 | classes = ( 24 | AT_OP_Create_Environment, AT_OP_Bake, AT_OP_Bake_ao 25 | ) 26 | 27 | 28 | def register_operators(): 29 | from bpy.utils import register_class 30 | for cls in classes: 31 | register_class(cls) 32 | 33 | 34 | def unregister_operators(): 35 | from bpy.utils import unregister_class 36 | for cls in reversed(classes): 37 | unregister_class(cls) -------------------------------------------------------------------------------- /addon/operator/at_bake.py: -------------------------------------------------------------------------------- 1 | 2 | ############################################################################### 3 | # Copyright 2023 Igor Subachev (GarikDog) # 4 | # # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); # 6 | # you may not use this file except in compliance with the License. # 7 | # You may obtain a copy of the License at # 8 | # # 9 | # http://www.apache.org/licenses/LICENSE-2.0 # 10 | # # 11 | # Unless required by applicable law or agreed to in writing, software # 12 | # distributed under the License is distributed on an "AS IS" BASIS, # 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 14 | # See the License for the specific language governing permissions and # 15 | # limitations under the License. # 16 | ############################################################################### 17 | 18 | import bpy 19 | from bpy.types import Operator 20 | 21 | from ..utility.at_utils import create_image, showMessageBox, change_bake_normal 22 | 23 | 24 | 25 | class AT_OP_Bake(Operator): 26 | bl_idname = "at.bake" 27 | bl_label = "Bake Normal and Show" 28 | bl_description = "Bake map. Then show the result image" 29 | 30 | 31 | @classmethod 32 | def poll(cls, context): 33 | obj = context.active_object 34 | atobjtool = obj.at_objtool 35 | if bpy.app.is_job_running('OBJECT_BAKE'): 36 | return False 37 | elif atobjtool.prepare_statement_prop_bool: 38 | return True 39 | return False 40 | 41 | 42 | 43 | def execute(self, context): 44 | try: 45 | change_bake_normal() 46 | image_name = create_image("_n") 47 | bpy.ops.object.bake('INVOKE_DEFAULT', type='NORMAL') 48 | 49 | 50 | 51 | 52 | def timer_to_create_image_window(): 53 | if (bpy.app.is_job_running('OBJECT_BAKE') == False): 54 | bpy.ops.wm.window_new() 55 | print(bpy.context.area) 56 | 57 | for area in bpy.context.screen.areas: 58 | area.type = 'IMAGE_EDITOR' 59 | area.spaces.active.image = bpy.data.images[image_name] 60 | bpy.app.timers.unregister(timer_to_create_image_window) 61 | return 0.1 62 | 63 | bpy.app.timers.register(timer_to_create_image_window) 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | except Exception as e: 73 | e = ("Please check Bake Environment. Please select an Object if it's not selected") 74 | showMessageBox(e, "Where am I?", 'ZOOM_ALL') 75 | 76 | 77 | return{'FINISHED'} 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /addon/operator/at_bake_ao.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | from bpy.types import Operator 19 | 20 | from ..utility.at_utils import create_image,showMessageBox, change_bake_ao 21 | 22 | 23 | class AT_OP_Bake_ao(Operator): 24 | bl_idname = "at.bake_ao" 25 | bl_label = "Bake AO and Show" 26 | bl_description = "Bake Ambient Occlusion map. Then show the result image" 27 | 28 | 29 | 30 | @classmethod 31 | 32 | def poll(cls, context): 33 | obj = context.active_object 34 | atobjtool = obj.at_objtool 35 | if bpy.app.is_job_running('OBJECT_BAKE'): 36 | return False 37 | elif atobjtool.prepare_statement_prop_bool: 38 | return True 39 | return False 40 | 41 | 42 | 43 | 44 | def execute(self, context): 45 | 46 | try: 47 | scene = bpy.context.scene 48 | attool = scene.at_tool 49 | if attool.at_glossy_preview: 50 | attool.at_glossy_preview = False 51 | change_bake_ao() 52 | image_name = create_image("_ao") 53 | bpy.ops.object.bake('INVOKE_DEFAULT', type='DIFFUSE') 54 | 55 | 56 | def timer_to_create_image_window(): 57 | 58 | if bpy.app.is_job_running('OBJECT_BAKE') == False: 59 | bpy.ops.wm.window_new() 60 | print(bpy.context.area) 61 | for area in bpy.context.screen.areas: 62 | area.type = 'IMAGE_EDITOR' 63 | area.spaces.active.image = bpy.data.images[image_name] 64 | bpy.app.timers.unregister(timer_to_create_image_window) 65 | return 0.1 66 | 67 | bpy.app.timers.register(timer_to_create_image_window) 68 | 69 | 70 | 71 | except Exception as e: 72 | e = ("Please check Bake Environment. Please select an Object if it's not selected") 73 | showMessageBox(e, "Where am I?", 'ZOOM_ALL') 74 | 75 | 76 | return{'FINISHED'} -------------------------------------------------------------------------------- /addon/operator/at_create_env.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | from bpy.types import Operator 19 | 20 | from ..utility.at_utils import (create_mat_env, create_render_env_n, 21 | create_shader_editor_env, bevel_samples_setting, viewport_shading_setting) 22 | 23 | 24 | 25 | class AT_OP_Create_Environment(Operator): 26 | bl_idname = "at.create_environment" 27 | bl_label = "Create Bake Environment" 28 | bl_description = "Prepares the scene and object for baking" 29 | 30 | 31 | def execute(self, context): 32 | obj = context.active_object 33 | atobjtool = obj.at_objtool 34 | light_intensity = 1 35 | 36 | 37 | viewport_shading_setting(light_intensity) 38 | create_render_env_n() 39 | create_mat_env() 40 | create_shader_editor_env() 41 | 42 | 43 | # Setting the value for custom statement property 44 | atobjtool.prepare_statement_prop_bool = True 45 | return{'FINISHED'} 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /addon/property/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | 19 | from .at_properties import AT_Properties 20 | from .at_obj_properties import AT_Obj_Properties 21 | 22 | classes = ( 23 | AT_Properties, AT_Obj_Properties 24 | ) 25 | 26 | 27 | def register_property(): 28 | from bpy.utils import register_class 29 | for cls in classes: 30 | register_class(cls) 31 | bpy.types.Scene.at_tool = bpy.props.PointerProperty(type=AT_Properties) 32 | bpy.types.Object.at_objtool = bpy.props.PointerProperty(type=AT_Obj_Properties) 33 | 34 | 35 | def unregister_property(): 36 | from bpy.utils import unregister_class 37 | for cls in reversed(classes): 38 | unregister_class(cls) 39 | del bpy.types.Scene.at_tool 40 | del bpy.types.Object.at_objtool -------------------------------------------------------------------------------- /addon/property/at_obj_properties.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | 19 | 20 | class AT_Obj_Properties(bpy.types.PropertyGroup): 21 | prepare_statement_prop_bool : bpy.props.BoolProperty() 22 | -------------------------------------------------------------------------------- /addon/property/at_properties.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | import bpy 18 | 19 | from ..utility.at_utils import bevel_samples_setting, bevel_radius_setting, ao_distance_setting, ao_exponentiation_setting, ao_samples_setting, change_to_glossy_shader, dx_normal_setting 20 | 21 | def get_bevel_value(self): 22 | return self.id_data.get("at_tool.bevel_samples_prop_int", int(8)) 23 | 24 | def set_bevel_value(self, value): 25 | self.id_data["at_tool.bevel_samples_prop_int"]=value 26 | try: 27 | bevel_samples_setting() 28 | except: 29 | print("there are no Nodes by now") 30 | 31 | def get_bevel_radius(self): 32 | return self.id_data.get("at_tool.bevel_radius_prop_float", float(0.02)) 33 | 34 | def set_bevel_radius(self, value): 35 | self.id_data["at_tool.bevel_radius_prop_float"]=value 36 | try: 37 | bevel_radius_setting() 38 | except: 39 | print("there are no Nodes by now") 40 | 41 | 42 | def get_at_ao_distance(self): 43 | return self.id_data.get("at_ao_distance", float(0.1)) 44 | 45 | 46 | def get_at_glossy_preview(self): 47 | return self.id_data.get("at_glossy_preview", bool(False)) 48 | 49 | def set_at_glossy_preview(self, value): 50 | self.id_data["at_glossy_preview"]=value 51 | try: 52 | change_to_glossy_shader(value) 53 | except: 54 | print("there are no Nodes by now") 55 | 56 | def set_at_ao_distance(self, value): 57 | self.id_data["at_ao_distance"]=value 58 | try: 59 | ao_distance_setting() 60 | set_at_glossy_preview(self, False) 61 | except: 62 | print("there are no Nodes by now") 63 | 64 | def get_at_ao_exponentiation(self): 65 | return self.id_data.get("at_ao_exponentiation", float(1)) 66 | 67 | def set_at_ao_exponentiation(self, value): 68 | self.id_data["at_ao_exponentiation"]=value 69 | try: 70 | ao_exponentiation_setting() 71 | set_at_glossy_preview(self, False) 72 | except: 73 | print("there are no Nodes by now") 74 | 75 | 76 | def get_at_ao_samples(self): 77 | return self.id_data.get("at_ao_samples", int(8)) 78 | 79 | def set_at_ao_samples(self, value): 80 | self.id_data["at_ao_samples"]=value 81 | try: 82 | ao_samples_setting() 83 | set_at_glossy_preview(self, False) 84 | except: 85 | print("there are no Nodes by now") 86 | 87 | def get_dx_normal(self): 88 | return self.id_data.get("at_dx_normal", bool(False)) 89 | 90 | def set_dx_normal(self, value): 91 | self.id_data["at_dx_normal"]=value 92 | try: 93 | dx_normal_setting() 94 | except: 95 | pass 96 | 97 | 98 | 99 | class AT_Properties(bpy.types.PropertyGroup): 100 | bevel_samples_prop_int : bpy.props.IntProperty(name="Bevel Samples", soft_min=2, soft_max=32, default=8, get=get_bevel_value, set=set_bevel_value) 101 | bevel_radius_prop_float : bpy.props.FloatProperty(name="Bevel Radius", soft_min=0.001, soft_max=0.5, default=0.02, step=0.001, precision=3, get=get_bevel_radius, set=set_bevel_radius) 102 | image_width_prop_int : bpy.props.IntProperty(name="Image Width", soft_min=2, soft_max=32768, default=2048) 103 | image_height_prop_int : bpy.props.IntProperty(name="Image Height", soft_min=2, soft_max=32768, default=2048) 104 | at_image_name : bpy.props.StringProperty(default="") 105 | at_ao_distance : bpy.props.FloatProperty(name="AO Distance", soft_min=0.001, soft_max=10, default=0.1, step=0.001, precision=3, get=get_at_ao_distance, set=set_at_ao_distance) 106 | at_ao_exponentiation : bpy.props.FloatProperty(name="AO Exponentiation", soft_min=0.1, soft_max=10, default=1, step=0.001, precision=3, get=get_at_ao_exponentiation, set=set_at_ao_exponentiation) 107 | at_ao_samples : bpy.props.IntProperty(name="AO Samples", soft_min=2, soft_max=32, default=8, get=get_at_ao_samples, set=set_at_ao_samples) 108 | at_glossy_preview : bpy.props.BoolProperty(name="Glossy Preview", default=False, get=get_at_glossy_preview, set=set_at_glossy_preview) 109 | at_dx_normal : bpy.props.BoolProperty(name="DX normal", default=False, get=get_dx_normal, set=set_dx_normal) 110 | -------------------------------------------------------------------------------- /addon/register/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | 17 | def register_addon(): 18 | #register 19 | from ..menu import register_menus 20 | register_menus() 21 | 22 | from ..operator import register_operators 23 | register_operators() 24 | 25 | from ..property import register_property 26 | register_property() 27 | 28 | 29 | return 30 | 31 | 32 | 33 | def unregister_addon(): 34 | #unregister 35 | from ..menu import unregister_menus 36 | unregister_menus() 37 | 38 | from ..operator import unregister_operators 39 | unregister_operators() 40 | 41 | from ..property import unregister_property 42 | unregister_property() 43 | 44 | 45 | return -------------------------------------------------------------------------------- /addon/utility/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### -------------------------------------------------------------------------------- /addon/utility/at_utils.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2023 Igor Subachev (GarikDog) # 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); # 5 | # you may not use this file except in compliance with the License. # 6 | # You may obtain a copy of the License at # 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 # 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software # 11 | # distributed under the License is distributed on an "AS IS" BASIS, # 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 13 | # See the License for the specific language governing permissions and # 14 | # limitations under the License. # 15 | ############################################################################### 16 | # SPDX-FileCopyrightText: 2011-2022 Blender Foundation 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | 21 | # Igor Subachev (GarikDog) : 22 | 23 | import bpy 24 | 25 | 26 | def create_render_env_n(): 27 | scn = bpy.context.scene 28 | attool = scn.at_tool 29 | # Set cycles render engine if not selected 30 | if not scn.render.engine == 'CYCLES': 31 | scn.render.engine = 'CYCLES' 32 | print ("Render engine setted to", scn.render.engine) 33 | 34 | # Set features set to Supported if not selected 35 | if not scn.cycles.feature_set == 'SUPPORTED': 36 | scn.cycles.feature_set = 'SUPPORTED' 37 | print ("Feature Set setted to", scn.cycles.feature_set) 38 | 39 | # Set Render Device to GPU Compute if not selected 40 | try: 41 | if not scn.cycles.device == 'GPU': 42 | scn.cycles.device = 'GPU' 43 | except: 44 | print ("Current device is", scn.cycles.device) 45 | print ("Render Device setted to", scn.cycles.device) 46 | 47 | # Set Bake Multires to False if not 48 | if not scn.render.use_bake_multires == False: 49 | scn.render.use_bake_multires = False 50 | print ("Bake Multires setted to", scn.render.use_bake_multires) 51 | 52 | # Set Bake Type to Normal if not 53 | if not scn.cycles.bake_type == 'NORMAL': 54 | scn.cycles.bake_type = 'NORMAL' 55 | print ("Bake type setted to", scn.cycles.bake_type) 56 | 57 | # Set Selected to Active to False if not 58 | if not scn.render.bake.use_selected_to_active == False: 59 | scn.render.bake.use_selected_to_active = False 60 | print ("Selected to Active setted to", scn.render.bake.use_selected_to_active) 61 | 62 | # Set custom bool dx property to correct value from Y channel 63 | try: 64 | if bpy.context.scene.render.bake.normal_g == 'NEG_Y': 65 | attool.at_dx_normal = True 66 | elif bpy.context.scene.render.bake.normal_g == 'POS_Y': 67 | attool.at_dx_normal = False 68 | except: 69 | pass 70 | 71 | 72 | 73 | def create_mat_env(): 74 | obj = bpy.context.active_object 75 | 76 | #create new material if there are not mat on obj 77 | if obj.active_material == None: 78 | matname = 'baker_material' 79 | mat = bpy.data.materials.new(matname) 80 | obj.data.materials.append(mat) 81 | 82 | #Set Use Nodes if obj arlready have a material 83 | if obj.active_material != None: 84 | if bpy.context.active_object.active_material.use_nodes == False: 85 | bpy.context.active_object.active_material.use_nodes = True 86 | 87 | print ("Object active material is", obj.active_material) 88 | 89 | 90 | 91 | def create_image(suffix): 92 | 93 | scene = bpy.context.scene 94 | attool = scene.at_tool 95 | 96 | # Get image size from custom properties 97 | im_width = attool.image_width_prop_int 98 | im_height = attool.image_height_prop_int 99 | 100 | 101 | nodes = bpy.context.active_object.active_material.node_tree.nodes 102 | for node in nodes: 103 | print (("node type is:"), (node.type)) 104 | if node.type == "TEX_IMAGE": 105 | image_texture_node = node 106 | 107 | obj = bpy.context.active_object 108 | images = bpy.data.images 109 | image_names = [] 110 | count_suffix = 1 111 | image_name = f'{obj.name}' 112 | 113 | 114 | for image in images: 115 | image_name = f'{obj.name}_{count_suffix}{suffix}' 116 | image_names.append(image.name) 117 | 118 | if image_name in image_names: 119 | count_suffix += 1 120 | image_name = f'{obj.name}_{count_suffix}{suffix}' 121 | 122 | 123 | 124 | 125 | 126 | bpy.ops.image.new(name=(image_name),width=im_width, height=im_height, generated_type='COLOR_GRID', alpha=False) 127 | 128 | 129 | print(("Image name is - "), (image_name)) 130 | # Set current texture name to the custom property 131 | attool.at_image_name = image_name 132 | 133 | # Link texture by name from custom property 134 | image_texture_node.image = bpy.data.images.get(attool.at_image_name) 135 | 136 | return image_name 137 | 138 | 139 | 140 | 141 | # set node location 142 | 143 | def setNodeLocation(node, x, y): 144 | if node.location: 145 | node.location = x, y 146 | 147 | 148 | def change_to_glossy_shader(statement: bool): 149 | links = bpy.context.active_object.active_material.node_tree.links 150 | nodes = bpy.context.active_object.active_material.node_tree.nodes 151 | for node in nodes: 152 | if node.type == 'BSDF_DIFFUSE': 153 | diffuse_node = node 154 | if node.type == 'BSDF_GLOSSY': 155 | glossy_node = node 156 | if node.type == 'OUTPUT_MATERIAL': 157 | output_node = node 158 | 159 | 160 | if statement: 161 | links.new(glossy_node.outputs[0], output_node.inputs[0]) 162 | else: 163 | links.new(diffuse_node.outputs[0], output_node.inputs[0]) 164 | 165 | 166 | def create_shader_editor_env(): 167 | 168 | 169 | scene = bpy.context.scene 170 | attool = scene.at_tool 171 | # Get nodes from node tree and clear 172 | nodes = bpy.context.active_object.active_material.node_tree.nodes 173 | nodes.clear() 174 | 175 | 176 | 177 | 178 | 179 | # Create nodes 180 | shader_node = nodes.new("ShaderNodeBsdfDiffuse") 181 | shader_node_glossy = nodes.new("ShaderNodeBsdfGlossy") 182 | mat_output = nodes.new('ShaderNodeOutputMaterial') 183 | bevel_node = nodes.new("ShaderNodeBevel") 184 | image_texture_node = nodes.new("ShaderNodeTexImage") 185 | ambient_occulusion_node = nodes.new("ShaderNodeAmbientOcclusion") 186 | math_node = nodes.new("ShaderNodeMath") 187 | 188 | # Place nodes in correct position 189 | setNodeLocation(shader_node_glossy, 0, 200) 190 | setNodeLocation(mat_output, 300, 25) 191 | setNodeLocation(bevel_node, -300, -565) 192 | setNodeLocation(image_texture_node, -900, 0) 193 | setNodeLocation(ambient_occulusion_node, -600, 0) 194 | setNodeLocation(math_node, -300, 0) 195 | 196 | # Get node links 197 | links = bpy.context.active_object.active_material.node_tree.links 198 | 199 | # Default glossy for glossy bsdf shader 200 | default_glossy = 0.2 201 | 202 | # Link nodes 203 | links.new(bevel_node.outputs['Normal'], shader_node.inputs['Normal']) 204 | links.new(bevel_node.outputs['Normal'], shader_node_glossy.inputs['Normal']) 205 | links.new(shader_node.outputs[0], mat_output.inputs[0]) 206 | math_node.operation = 'POWER' # make power operation in the Math node (it always have Add by default) 207 | shader_node_glossy.inputs['Roughness'].default_value = default_glossy 208 | math_node.inputs[1].default_value = attool.at_ao_exponentiation 209 | bevel_node.inputs['Radius'].default_value = attool.bevel_radius_prop_float 210 | bevel_node.samples = attool.bevel_samples_prop_int 211 | ambient_occulusion_node.samples = attool.at_ao_samples 212 | ambient_occulusion_node.inputs['Distance'].default_value = attool.at_ao_distance 213 | links.new(ambient_occulusion_node.outputs['Color'], math_node.inputs[0]) 214 | links.new(math_node.outputs[0], shader_node.inputs['Color']) 215 | links.new(math_node.outputs[0], shader_node_glossy.inputs['Color']) 216 | 217 | 218 | attool.at_glossy_preview = False 219 | 220 | for node in nodes: 221 | print (("I have this node:"), (node)) 222 | 223 | return image_texture_node 224 | 225 | 226 | 227 | def bevel_samples_setting (): 228 | nodes = bpy.context.active_object.active_material.node_tree.nodes 229 | 230 | for node in nodes: 231 | if node.type == 'BEVEL': 232 | bevel_node = node 233 | pass 234 | scene = bpy.context.scene 235 | 236 | attool = scene.at_tool 237 | bevel_node.samples = attool.bevel_samples_prop_int 238 | 239 | def bevel_radius_setting (): 240 | nodes = bpy.context.active_object.active_material.node_tree.nodes 241 | for node in nodes: 242 | if node.type == 'BEVEL': 243 | bevel_node = node 244 | pass 245 | scene = bpy.context.scene 246 | 247 | attool = scene.at_tool 248 | bevel_node.inputs[0].default_value = attool.bevel_radius_prop_float 249 | 250 | def ao_distance_setting (): 251 | nodes = bpy.context.active_object.active_material.node_tree.nodes 252 | 253 | for node in nodes: 254 | if node.type == 'AMBIENT_OCCLUSION': 255 | ao_node = node 256 | pass 257 | 258 | scene = bpy.context.scene 259 | attool = scene.at_tool 260 | 261 | ao_node.inputs[1].default_value = attool.at_ao_distance 262 | 263 | def ao_exponentiation_setting (): 264 | nodes = bpy.context.active_object.active_material.node_tree.nodes 265 | 266 | for node in nodes: 267 | if node.type == 'MATH' and node.operation == 'POWER': 268 | power_node = node 269 | pass 270 | scene = bpy.context.scene 271 | attool = scene.at_tool 272 | 273 | power_node.inputs[1].default_value = attool.at_ao_exponentiation 274 | 275 | def ao_samples_setting (): 276 | nodes = bpy.context.active_object.active_material.node_tree.nodes 277 | 278 | for node in nodes: 279 | print("node type is: ", node.type) 280 | if node.type == 'AMBIENT_OCCLUSION': 281 | ao_node = node 282 | pass 283 | 284 | scene = bpy.context.scene 285 | attool = scene.at_tool 286 | 287 | ao_node.samples = attool.at_ao_samples 288 | 289 | 290 | 291 | 292 | 293 | def viewport_shading_setting (intensity: float): 294 | 295 | bpy.context.space_data.shading.type = 'RENDERED' 296 | bpy.context.space_data.shading.studio_light = 'city.exr' 297 | 298 | if bpy.context.space_data.shading.studiolight_intensity != intensity: 299 | bpy.context.space_data.shading.studiolight_intensity = intensity 300 | 301 | if bpy.context.space_data.shading.use_scene_world_render: 302 | bpy.context.space_data.shading.use_scene_world_render = False 303 | 304 | 305 | def showMessageBox(message='', title='Message box', icon='INFO'): 306 | 307 | def draw(self, context): 308 | self.layout.label(text=message) 309 | 310 | bpy.context.window_manager.popup_menu(draw, title=title, icon=icon) 311 | 312 | 313 | def change_bake_normal(): 314 | scn = bpy.context.scene 315 | # Set Bake Type to Normal 316 | if not scn.cycles.bake_type == 'NORMAL': 317 | scn.cycles.bake_type = 'NORMAL' 318 | print ("Bake type setted to", scn.cycles.bake_type) 319 | 320 | # Set Selected to Active to False 321 | if not scn.render.bake.use_selected_to_active == False: 322 | scn.render.bake.use_selected_to_active = False 323 | print ("Selected to Active setted to", scn.render.bake.use_selected_to_active) 324 | 325 | def change_bake_ao(): 326 | scn = bpy.context.scene 327 | # Set Bake Type to AO 328 | if not scn.cycles.bake_type == 'DIFFUSE': 329 | scn.cycles.bake_type = 'DIFFUSE' 330 | print ("Bake type setted to", scn.cycles.bake_type) 331 | 332 | if not scn.render.bake.use_pass_direct == False: 333 | scn.render.bake.use_pass_direct = False 334 | 335 | if not scn.render.bake.use_pass_indirect == False: 336 | scn.render.bake.use_pass_indirect = False 337 | 338 | 339 | def dx_normal_setting(): 340 | scene = bpy.context.scene 341 | attool = scene.at_tool 342 | if attool.at_dx_normal: 343 | bpy.context.scene.render.bake.normal_g = 'NEG_Y' 344 | else: 345 | bpy.context.scene.render.bake.normal_g = 'POS_Y' 346 | 347 | 348 | 349 | #Blender Foundation: 350 | 351 | def get_effective_preview_denoiser(context): 352 | scene = context.scene 353 | cscene = scene.cycles 354 | 355 | if cscene.preview_denoiser != "AUTO": 356 | return cscene.preview_denoiser 357 | 358 | return 'OIDN' -------------------------------------------------------------------------------- /images/autobake_bevel_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/autobake_bevel_demo.gif -------------------------------------------------------------------------------- /images/baking_ao.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/baking_ao.gif -------------------------------------------------------------------------------- /images/baking_ao_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/baking_ao_demo.gif -------------------------------------------------------------------------------- /images/baking_bevel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/baking_bevel.gif -------------------------------------------------------------------------------- /images/baking_bevel_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/baking_bevel_2.gif -------------------------------------------------------------------------------- /images/logo_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/logo_f.png -------------------------------------------------------------------------------- /images/logo_f_2x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/logo_f_2x1.png -------------------------------------------------------------------------------- /images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/screenshot.png -------------------------------------------------------------------------------- /images/show_marmoset.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/show_marmoset.gif -------------------------------------------------------------------------------- /images/show_substance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/show_substance.gif -------------------------------------------------------------------------------- /images/substance_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GarikDog/autobake_tools/37e6a5ffc7b58f618ba2c06131901c5647f173ea/images/substance_demo.gif --------------------------------------------------------------------------------