├── .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 | [](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 |
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 | -
38 | About The Project
39 |
42 |
43 | -
44 | Getting Started
45 |
49 |
50 | - Usage
51 | - Explanation of what the addon code does
52 | - Roadmap
53 | - License
54 | - Contact
55 | - Acknowledgments
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 | 
74 | 
75 | 
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 | 
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
--------------------------------------------------------------------------------