├── README.md ├── enabling_addons ├── enabling_addons_example_3_1.py ├── enabling_addons_example_3_2.py ├── enabling_addons_example_2.py ├── enabling_addons_example_1.py └── enabling_addons_example_4.py ├── LICENSE ├── clean_scene ├── clean_scene_example_1.py ├── clean_scene_example_2.py ├── clean_scene_example_3.py └── clean_scene_example_4.py ├── .gitignore └── hex_color_to_rgba ├── hex_color_to_rgba_example_1.py ├── hex_color_to_rgba_example_2.py ├── hex_color_to_rgba_example_3.py └── hex_color_to_rgba_example_4.py /README.md: -------------------------------------------------------------------------------- 1 | # bpy Building Blocks examples 2 | 3 | Example code for the bpy Building Blocks Python package. 4 | 5 | ## Summary 6 | This git repository contains example code used in the bpy Building Blocks explanation videos. 7 | 8 | ## Links 9 | 10 | * [bpy Building Blocks Python package on GitHub](https://github.com/CGArtPython/bpy_building_blocks) 11 | * [bpy Building Blocks Python package as a Blender add-on](https://github.com/CGArtPython/bpy_building_blocks_addon) 12 | * [[Video] How to install bpy Building Blocks Python package](https://www.youtube.com/watch?v=_irmuKXjhS0) 13 | 14 | -------------------------------------------------------------------------------- /enabling_addons/enabling_addons_example_3_1.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import addon_utils 3 | 4 | 5 | def enable_addon(addon_module_name): 6 | 7 | loaded_default, loaded_state = addon_utils.check(addon_module_name) 8 | 9 | if not loaded_state: 10 | addon_utils.enable(addon_module_name) 11 | 12 | 13 | ########################################################## 14 | # _____ _ _ _ _____ 15 | # | ___| | | _| || |_ |____ | 16 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 17 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 18 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 19 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 20 | # | | 21 | # |_| 22 | ########################################################## 23 | 24 | enable_addon(addon_module_name="io_import_images_as_planes") 25 | 26 | image_path = r"c:\tmp\learn_python.png" 27 | bpy.ops.import_image.to_plane(files=[{"name": image_path}]) 28 | -------------------------------------------------------------------------------- /enabling_addons/enabling_addons_example_3_2.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import addon_utils 3 | 4 | 5 | def enable_addon(addon_module_name): 6 | 7 | loaded_default, loaded_state = addon_utils.check(addon_module_name) 8 | 9 | if not loaded_state: 10 | addon_utils.enable(addon_module_name) 11 | 12 | 13 | ########################################################## 14 | # _____ _ _ _ _____ 15 | # | ___| | | _| || |_ |____ | 16 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 17 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 18 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 19 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 20 | # | | 21 | # |_| 22 | ########################################################## 23 | 24 | enable_addon(addon_module_name="io_import_images_as_planes") 25 | 26 | image_path = r"c:\tmp\365_loop.mp4" 27 | 28 | bpy.ops.import_image.to_plane(files=[{"name": image_path}]) 29 | -------------------------------------------------------------------------------- /enabling_addons/enabling_addons_example_2.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import addon_utils 3 | 4 | 5 | def enable_addon(addon_module_name): 6 | 7 | loaded_default, loaded_state = addon_utils.check(addon_module_name) 8 | 9 | if not loaded_state: 10 | addon_utils.enable(addon_module_name) 11 | 12 | 13 | ########################################################## 14 | # _____ _ _ _ _____ 15 | # | ___| | | _| || |_ / __ \ 16 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `' / /' 17 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ / / 18 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| ./ /___ 19 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \_____/ 20 | # | | 21 | # |_| 22 | ########################################################## 23 | 24 | enable_addon(addon_module_name="add_mesh_extra_objects") 25 | 26 | for i in range(10): 27 | bpy.ops.mesh.primitive_solid_add(source='12', size=i*0.1) 28 | bpy.ops.object.modifier_add(type='WIREFRAME') 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 CGArtPython 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /enabling_addons/enabling_addons_example_1.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import addon_utils 3 | 4 | 5 | def enable_addon(addon_module_name): 6 | 7 | loaded_default, loaded_state = addon_utils.check(addon_module_name) 8 | 9 | if not loaded_state: 10 | addon_utils.enable(addon_module_name) 11 | 12 | 13 | ########################################################## 14 | # _____ _ _ _ __ 15 | # | ___| | | _| || |_ / | 16 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `| | 17 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ | | 18 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| _| |_ 19 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \___/ 20 | # | | 21 | # |_| 22 | ########################################################## 23 | 24 | 25 | enable_addon(addon_module_name="add_curve_extra_objects") 26 | 27 | bpy.ops.curve.spirals( 28 | spiral_type="LOG", 29 | radius=1.42, 30 | turns=265, 31 | steps=128, 32 | dif_z=0.1, 33 | B_force=0.99, 34 | edit_mode=False, 35 | ) 36 | 37 | bpy.context.object.data.bevel_depth = 0.01 38 | -------------------------------------------------------------------------------- /enabling_addons/enabling_addons_example_4.py: -------------------------------------------------------------------------------- 1 | """ 2 | To run this you will need the bpybb Python package. 3 | 4 | You can watch this video for detailed instructions on how to get the bpybb Python package: 5 | https://cgpython.com/bpybb-install 6 | 7 | or 8 | 9 | You can install the package as a Blender add-on by following 10 | this link https://cgpython.com/bpybb 11 | to the latest version of the add-on 12 | 13 | If you know how to install Python packages into the embedded Python via pip 14 | you can use the following link to get the pip instructions 15 | https://pypi.org/project/bpy-building-blocks/ 16 | 17 | """ 18 | 19 | import bpy 20 | import addon_utils 21 | 22 | from bpybb.addon import enable_addon 23 | 24 | # def enable_addon(addon_module_name): 25 | 26 | # loaded_default, loaded_state = addon_utils.check(addon_module_name) 27 | 28 | # if not loaded_state: 29 | # addon_utils.enable(addon_module_name) 30 | 31 | 32 | ########################################################## 33 | # _____ _ _ _ _____ 34 | # | ___| | | _| || |_ |____ | 35 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 36 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 37 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 38 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 39 | # | | 40 | # |_| 41 | ########################################################## 42 | 43 | enable_addon(addon_module_name="io_import_images_as_planes") 44 | 45 | image_path = r"c:\tmp\365_loop.mp4" 46 | 47 | bpy.ops.import_image.to_plane(files=[{"name": image_path}]) 48 | -------------------------------------------------------------------------------- /clean_scene/clean_scene_example_1.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | 3 | 4 | def purge_orphans(): 5 | if bpy.app.version >= (3, 0, 0): 6 | bpy.ops.outliner.orphans_purge( 7 | do_local_ids=True, do_linked_ids=True, do_recursive=True 8 | ) 9 | else: 10 | # call purge_orphans() recursively until there are no more orphan data blocks to purge 11 | result = bpy.ops.outliner.orphans_purge() 12 | if result.pop() != "CANCELLED": 13 | purge_orphans() 14 | 15 | 16 | def clean_scene(): 17 | """ 18 | Removing all of the objects, collection, materials, particles, 19 | textures, images, curves, meshes, actions, nodes, and worlds from the scene 20 | """ 21 | if bpy.context.active_object and bpy.context.active_object.mode == "EDIT": 22 | bpy.ops.object.editmode_toggle() 23 | 24 | for obj in bpy.data.objects: 25 | obj.hide_set(False) 26 | obj.hide_select = False 27 | obj.hide_viewport = False 28 | 29 | bpy.ops.object.select_all(action="SELECT") 30 | bpy.ops.object.delete() 31 | 32 | collection_names = [col.name for col in bpy.data.collections] 33 | for name in collection_names: 34 | bpy.data.collections.remove(bpy.data.collections[name]) 35 | 36 | # in the case when you modify the world shader 37 | world_names = [world.name for world in bpy.data.worlds] 38 | for name in world_names: 39 | bpy.data.worlds.remove(bpy.data.worlds[name]) 40 | # create a new world data block 41 | bpy.ops.world.new() 42 | bpy.context.scene.world = bpy.data.worlds["World"] 43 | 44 | purge_orphans() 45 | 46 | 47 | ########################################################## 48 | # _____ _ _ _ __ 49 | # | ___| | | _| || |_ / | 50 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `| | 51 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ | | 52 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| _| |_ 53 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \___/ 54 | # | | 55 | # |_| 56 | ########################################################## 57 | 58 | clean_scene() 59 | 60 | bpy.ops.mesh.primitive_ico_sphere_add() 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /clean_scene/clean_scene_example_2.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import random 3 | import math 4 | 5 | 6 | def purge_orphans(): 7 | if bpy.app.version >= (3, 0, 0): 8 | bpy.ops.outliner.orphans_purge( 9 | do_local_ids=True, do_linked_ids=True, do_recursive=True 10 | ) 11 | else: 12 | # call purge_orphans() recursively until there are no more orphan data blocks to purge 13 | result = bpy.ops.outliner.orphans_purge() 14 | if result.pop() != "CANCELLED": 15 | purge_orphans() 16 | 17 | 18 | def clean_scene(): 19 | """ 20 | Removing all of the objects, collection, materials, particles, 21 | textures, images, curves, meshes, actions, nodes, and worlds from the scene 22 | """ 23 | if bpy.context.active_object and bpy.context.active_object.mode == "EDIT": 24 | bpy.ops.object.editmode_toggle() 25 | 26 | for obj in bpy.data.objects: 27 | obj.hide_set(False) 28 | obj.hide_select = False 29 | obj.hide_viewport = False 30 | 31 | bpy.ops.object.select_all(action="SELECT") 32 | bpy.ops.object.delete() 33 | 34 | collection_names = [col.name for col in bpy.data.collections] 35 | for name in collection_names: 36 | bpy.data.collections.remove(bpy.data.collections[name]) 37 | 38 | # in the case when you modify the world shader 39 | world_names = [world.name for world in bpy.data.worlds] 40 | for name in world_names: 41 | bpy.data.worlds.remove(bpy.data.worlds[name]) 42 | # create a new world data block 43 | bpy.ops.world.new() 44 | bpy.context.scene.world = bpy.data.worlds["World"] 45 | 46 | purge_orphans() 47 | 48 | 49 | ########################################################## 50 | # _____ _ _ _ _____ 51 | # | ___| | | _| || |_ / __ \ 52 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `' / /' 53 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ / / 54 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| ./ /___ 55 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \_____/ 56 | # | | 57 | # |_| 58 | ########################################################## 59 | 60 | clean_scene() 61 | 62 | max_rotation = math.radians(360) 63 | 64 | for i in range(33): 65 | random_size = random.uniform(0.1, 2.0) 66 | random_location = ( 67 | random.uniform(-5, 5), 68 | random.uniform(-5, 5), 69 | random.uniform(-5, 5), 70 | ) 71 | random_rotation = ( 72 | random.uniform(-max_rotation, max_rotation), 73 | random.uniform(-max_rotation, max_rotation), 74 | random.uniform(-max_rotation, max_rotation), 75 | ) 76 | 77 | bpy.ops.mesh.primitive_monkey_add( 78 | size=random_size, location=random_location, rotation=random_rotation 79 | ) 80 | -------------------------------------------------------------------------------- /clean_scene/clean_scene_example_3.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | import random 3 | import math 4 | 5 | 6 | def purge_orphans(): 7 | if bpy.app.version >= (3, 0, 0): 8 | bpy.ops.outliner.orphans_purge( 9 | do_local_ids=True, do_linked_ids=True, do_recursive=True 10 | ) 11 | else: 12 | # call purge_orphans() recursively until there are no more orphan data blocks to purge 13 | result = bpy.ops.outliner.orphans_purge() 14 | if result.pop() != "CANCELLED": 15 | purge_orphans() 16 | 17 | 18 | def clean_scene(): 19 | """ 20 | Removing all of the objects, collection, materials, particles, 21 | textures, images, curves, meshes, actions, nodes, and worlds from the scene 22 | """ 23 | if bpy.context.active_object and bpy.context.active_object.mode == "EDIT": 24 | bpy.ops.object.editmode_toggle() 25 | 26 | for obj in bpy.data.objects: 27 | obj.hide_set(False) 28 | obj.hide_select = False 29 | obj.hide_viewport = False 30 | 31 | bpy.ops.object.select_all(action="SELECT") 32 | bpy.ops.object.delete() 33 | 34 | collection_names = [col.name for col in bpy.data.collections] 35 | for name in collection_names: 36 | bpy.data.collections.remove(bpy.data.collections[name]) 37 | 38 | # in the case when you modify the world shader 39 | world_names = [world.name for world in bpy.data.worlds] 40 | for name in world_names: 41 | bpy.data.worlds.remove(bpy.data.worlds[name]) 42 | # create a new world data block 43 | bpy.ops.world.new() 44 | bpy.context.scene.world = bpy.data.worlds["World"] 45 | 46 | purge_orphans() 47 | 48 | 49 | ########################################################## 50 | # _____ _ _ _ _____ 51 | # | ___| | | _| || |_ |____ | 52 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 53 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 54 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 55 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 56 | # | | 57 | # |_| 58 | ########################################################## 59 | 60 | clean_scene() 61 | 62 | max_rotation = math.radians(360) 63 | 64 | for i in range(33): 65 | random_size = random.uniform(0.1, 2.0) 66 | random_location = ( 67 | random.uniform(-5, 5), 68 | random.uniform(-5, 5), 69 | random.uniform(-5, 5), 70 | ) 71 | random_rotation = ( 72 | random.uniform(-max_rotation, max_rotation), 73 | random.uniform(-max_rotation, max_rotation), 74 | random.uniform(-max_rotation, max_rotation), 75 | ) 76 | 77 | bpy.ops.mesh.primitive_monkey_add( 78 | size=random_size, location=random_location, rotation=random_rotation 79 | ) 80 | 81 | material = bpy.data.materials.new(name=f"monkey_material_{i}") 82 | material.use_nodes = True 83 | bsdf_node = material.node_tree.nodes["Principled BSDF"] 84 | red = random.random() 85 | green = random.random() 86 | blue = random.random() 87 | bsdf_node.inputs["Base Color"].default_value = (red, green, blue, 1) 88 | 89 | active_object = bpy.context.active_object 90 | active_object.data.materials.append(material) 91 | -------------------------------------------------------------------------------- /hex_color_to_rgba/hex_color_to_rgba_example_1.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | 3 | import math 4 | 5 | 6 | def hex_color_to_rgb(hex_color): 7 | """ 8 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 9 | to a Linear RGB 10 | 11 | Supports: "#RRGGBB" or "RRGGBB" 12 | 13 | Note: We are converting into Linear RGB since Blender uses a Linear Color Space internally 14 | https://docs.blender.org/manual/en/latest/render/color_management.html 15 | """ 16 | # remove the leading '#' symbol if present 17 | if hex_color.startswith("#"): 18 | hex_color = hex_color[1:] 19 | 20 | assert len(hex_color) == 6, f"RRGGBB is the supported hex color format: {hex_color}" 21 | 22 | # extracting the Red color component - RRxxxx 23 | red = int(hex_color[:2], 16) 24 | # dividing by 255 to get a number between 0.0 and 1.0 25 | srgb_red = red / 255 26 | linear_red = convert_srgb_to_linear_rgb(srgb_red) 27 | 28 | # extracting the Green color component - xxGGxx 29 | green = int(hex_color[2:4], 16) 30 | # dividing by 255 to get a number between 0.0 and 1.0 31 | srgb_green = green / 255 32 | linear_green = convert_srgb_to_linear_rgb(srgb_green) 33 | 34 | # extracting the Blue color component - xxxxBB 35 | blue = int(hex_color[4:6], 16) 36 | # dividing by 255 to get a number between 0.0 and 1.0 37 | srgb_blue = blue / 255 38 | linear_blue = convert_srgb_to_linear_rgb(srgb_blue) 39 | 40 | return tuple([linear_red, linear_green, linear_blue]) 41 | 42 | 43 | def hex_color_to_rgba(hex_color, alpha=1.0): 44 | """ 45 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 46 | to a Linear RGB with an Alpha passed as a parameter 47 | 48 | Supports: "#RRGGBB" or "RRGGBB" 49 | """ 50 | linear_red, linear_green, linear_blue = hex_color_to_rgb(hex_color) 51 | return tuple([linear_red, linear_green, linear_blue, alpha]) 52 | 53 | 54 | def convert_srgb_to_linear_rgb(srgb_color_component): 55 | """ 56 | Converting from sRGB to Linear RGB 57 | based on https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ 58 | """ 59 | if srgb_color_component <= 0.04045: 60 | linear_color_component = srgb_color_component / 12.92 61 | else: 62 | linear_color_component = math.pow((srgb_color_component + 0.055) / 1.055, 2.4) 63 | 64 | return linear_color_component 65 | 66 | 67 | ########################################################## 68 | # _____ _ _ _ __ 69 | # | ___| | | _| || |_ / | 70 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `| | 71 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ | | 72 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| _| |_ 73 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \___/ 74 | # | | 75 | # |_| 76 | ########################################################## 77 | 78 | 79 | hex_color = "#F23030" 80 | rgba_color = hex_color_to_rgba(hex_color) 81 | 82 | # add a plane into the scene 83 | bpy.ops.mesh.primitive_plane_add() 84 | 85 | # create a new material 86 | material = bpy.data.materials.new(name=f"hex_color_{hex_color}") 87 | material.diffuse_color = rgba_color 88 | 89 | # add material to object 90 | bpy.context.active_object.data.materials.append(material) 91 | -------------------------------------------------------------------------------- /hex_color_to_rgba/hex_color_to_rgba_example_2.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | 3 | import math 4 | 5 | 6 | def hex_color_to_rgb(hex_color): 7 | """ 8 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 9 | to a Linear RGB 10 | 11 | Supports: "#RRGGBB" or "RRGGBB" 12 | 13 | Note: We are converting into Linear RGB since Blender uses a Linear Color Space internally 14 | https://docs.blender.org/manual/en/latest/render/color_management.html 15 | """ 16 | # remove the leading '#' symbol if present 17 | if hex_color.startswith("#"): 18 | hex_color = hex_color[1:] 19 | 20 | assert len(hex_color) == 6, f"RRGGBB is the supported hex color format: {hex_color}" 21 | 22 | # extracting the Red color component - RRxxxx 23 | red = int(hex_color[:2], 16) 24 | # dividing by 255 to get a number between 0.0 and 1.0 25 | srgb_red = red / 255 26 | linear_red = convert_srgb_to_linear_rgb(srgb_red) 27 | 28 | # extracting the Green color component - xxGGxx 29 | green = int(hex_color[2:4], 16) 30 | # dividing by 255 to get a number between 0.0 and 1.0 31 | srgb_green = green / 255 32 | linear_green = convert_srgb_to_linear_rgb(srgb_green) 33 | 34 | # extracting the Blue color component - xxxxBB 35 | blue = int(hex_color[4:6], 16) 36 | # dividing by 255 to get a number between 0.0 and 1.0 37 | srgb_blue = blue / 255 38 | linear_blue = convert_srgb_to_linear_rgb(srgb_blue) 39 | 40 | return tuple([linear_red, linear_green, linear_blue]) 41 | 42 | 43 | def hex_color_to_rgba(hex_color, alpha=1.0): 44 | """ 45 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 46 | to a Linear RGB with an Alpha passed as a parameter 47 | 48 | Supports: "#RRGGBB" or "RRGGBB" 49 | """ 50 | linear_red, linear_green, linear_blue = hex_color_to_rgb(hex_color) 51 | return tuple([linear_red, linear_green, linear_blue, alpha]) 52 | 53 | 54 | def convert_srgb_to_linear_rgb(srgb_color_component): 55 | """ 56 | Converting from sRGB to Linear RGB 57 | based on https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ 58 | """ 59 | if srgb_color_component <= 0.04045: 60 | linear_color_component = srgb_color_component / 12.92 61 | else: 62 | linear_color_component = math.pow((srgb_color_component + 0.055) / 1.055, 2.4) 63 | 64 | return linear_color_component 65 | 66 | 67 | ########################################################## 68 | # _____ _ _ _ _____ 69 | # | ___| | | _| || |_ / __ \ 70 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| `' / /' 71 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ / / 72 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| ./ /___ 73 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \_____/ 74 | # | | 75 | # |_| 76 | ########################################################## 77 | 78 | # add an ico sphere and shade it smooth 79 | bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=5) 80 | bpy.ops.object.shade_smooth() 81 | 82 | # set the Background color to Black 83 | bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[0].default_value = (0, 0, 0, 1) 84 | 85 | # set the render engine to CYCLES 86 | bpy.context.scene.render.engine = "CYCLES" 87 | 88 | # add a area light with the energy set to 100 and color #FF4858" 89 | bpy.ops.object.light_add(type="AREA", radius=5, location=(0, -2, 0), rotation=(math.radians(90), 0, 0)) 90 | bpy.context.object.data.energy = 100 91 | bpy.context.object.data.color = hex_color_to_rgb("#FF4858") 92 | 93 | # add a area light with the energy set to 100 and color #F2CB05 94 | bpy.ops.object.light_add(type="AREA", radius=5, location=(0, 2, 0), rotation=(math.radians(-90), 0, 0)) 95 | bpy.context.object.data.energy = 100 96 | bpy.context.object.data.color = hex_color_to_rgb("#F2CB05") 97 | -------------------------------------------------------------------------------- /clean_scene/clean_scene_example_4.py: -------------------------------------------------------------------------------- 1 | """ 2 | To run this you will need the bpybb Python package. 3 | 4 | You can watch this video for detailed instructions on how to get the bpybb Python package: 5 | https://cgpython.com/bpybb-install 6 | 7 | or 8 | 9 | You can install the package as a Blender add-on by following 10 | this link https://cgpython.com/bpybb 11 | to the latest version of the add-on 12 | 13 | If you know how to install Python packages into the embedded Python via pip 14 | you can use the following link to get the pip instructions 15 | https://pypi.org/project/bpy-building-blocks/ 16 | 17 | """ 18 | import bpy 19 | import random 20 | import math 21 | 22 | from bpybb.utils import clean_scene 23 | 24 | 25 | # def purge_orphans(): 26 | # if bpy.app.version >= (3, 0, 0): 27 | # bpy.ops.outliner.orphans_purge( 28 | # do_local_ids=True, do_linked_ids=True, do_recursive=True 29 | # ) 30 | # else: 31 | # # call purge_orphans() recursively until there are no more orphan data blocks to purge 32 | # result = bpy.ops.outliner.orphans_purge() 33 | # if result.pop() != "CANCELLED": 34 | # purge_orphans() 35 | 36 | 37 | # def clean_scene(): 38 | # """ 39 | # Removing all of the objects, collection, materials, particles, 40 | # textures, images, curves, meshes, actions, nodes, and worlds from the scene 41 | # """ 42 | # if bpy.context.active_object and bpy.context.active_object.mode == "EDIT": 43 | # bpy.ops.object.editmode_toggle() 44 | 45 | # for obj in bpy.data.objects: 46 | # obj.hide_set(False) 47 | # obj.hide_select = False 48 | # obj.hide_viewport = False 49 | # bpy.ops.object.select_all(action="SELECT") 50 | # bpy.ops.object.delete() 51 | 52 | # collection_names = [col.name for col in bpy.data.collections] 53 | # for name in collection_names: 54 | # bpy.data.collections.remove(bpy.data.collections[name]) 55 | 56 | # # in the case when you modify the world shader 57 | # world_names = [col.name for col in bpy.data.worlds] 58 | # for name in world_names: 59 | # bpy.data.worlds.remove(bpy.data.worlds[name]) 60 | # # create a new world data block 61 | # bpy.ops.world.new() 62 | # bpy.context.scene.world = bpy.data.worlds["World"] 63 | 64 | # purge_orphans() 65 | 66 | 67 | ########################################################## 68 | # _____ _ _ _ _____ 69 | # | ___| | | _| || |_ |____ | 70 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 71 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 72 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 73 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 74 | # | | 75 | # |_| 76 | ########################################################## 77 | 78 | clean_scene() 79 | 80 | max_rotation = math.radians(360) 81 | 82 | for i in range(33): 83 | random_size = random.uniform(0.1, 2.0) 84 | random_location = ( 85 | random.uniform(-5, 5), 86 | random.uniform(-5, 5), 87 | random.uniform(-5, 5), 88 | ) 89 | random_rotation = ( 90 | random.uniform(-max_rotation, max_rotation), 91 | random.uniform(-max_rotation, max_rotation), 92 | random.uniform(-max_rotation, max_rotation), 93 | ) 94 | 95 | bpy.ops.mesh.primitive_monkey_add( 96 | size=random_size, location=random_location, rotation=random_rotation 97 | ) 98 | 99 | material = bpy.data.materials.new(name=f"monkey_material_{i}") 100 | material.use_nodes = True 101 | bsdf_node = material.node_tree.nodes["Principled BSDF"] 102 | red = random.random() 103 | green = random.random() 104 | blue = random.random() 105 | bsdf_node.inputs["Base Color"].default_value = (red, green, blue, 1) 106 | 107 | active_object = bpy.context.active_object 108 | active_object.data.materials.append(material) 109 | -------------------------------------------------------------------------------- /hex_color_to_rgba/hex_color_to_rgba_example_3.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | 3 | import math 4 | 5 | import random 6 | 7 | 8 | def hex_color_to_rgb(hex_color): 9 | """ 10 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 11 | to a Linear RGB 12 | 13 | Supports: "#RRGGBB" or "RRGGBB" 14 | 15 | Note: We are converting into Linear RGB since Blender uses a Linear Color Space internally 16 | https://docs.blender.org/manual/en/latest/render/color_management.html 17 | """ 18 | # remove the leading '#' symbol if present 19 | if hex_color.startswith("#"): 20 | hex_color = hex_color[1:] 21 | 22 | assert len(hex_color) == 6, f"RRGGBB is the supported hex color format: {hex_color}" 23 | 24 | # extracting the Red color component - RRxxxx 25 | red = int(hex_color[:2], 16) 26 | # dividing by 255 to get a number between 0.0 and 1.0 27 | srgb_red = red / 255 28 | linear_red = convert_srgb_to_linear_rgb(srgb_red) 29 | 30 | # extracting the Green color component - xxGGxx 31 | green = int(hex_color[2:4], 16) 32 | # dividing by 255 to get a number between 0.0 and 1.0 33 | srgb_green = green / 255 34 | linear_green = convert_srgb_to_linear_rgb(srgb_green) 35 | 36 | # extracting the Blue color component - xxxxBB 37 | blue = int(hex_color[4:6], 16) 38 | # dividing by 255 to get a number between 0.0 and 1.0 39 | srgb_blue = blue / 255 40 | linear_blue = convert_srgb_to_linear_rgb(srgb_blue) 41 | 42 | return tuple([linear_red, linear_green, linear_blue]) 43 | 44 | 45 | def hex_color_to_rgba(hex_color, alpha=1.0): 46 | """ 47 | Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 48 | to a Linear RGB with an Alpha passed as a parameter 49 | 50 | Supports: "#RRGGBB" or "RRGGBB" 51 | """ 52 | linear_red, linear_green, linear_blue = hex_color_to_rgb(hex_color) 53 | return tuple([linear_red, linear_green, linear_blue, alpha]) 54 | 55 | 56 | def convert_srgb_to_linear_rgb(srgb_color_component): 57 | """ 58 | Converting from sRGB to Linear RGB 59 | based on https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ 60 | """ 61 | if srgb_color_component <= 0.04045: 62 | linear_color_component = srgb_color_component / 12.92 63 | else: 64 | linear_color_component = math.pow((srgb_color_component + 0.055) / 1.055, 2.4) 65 | 66 | return linear_color_component 67 | 68 | 69 | ########################################################## 70 | # _____ _ _ _ _____ 71 | # | ___| | | _| || |_ |____ | 72 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 73 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 74 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 75 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 76 | # | | 77 | # |_| 78 | ########################################################## 79 | 80 | # make a list of colors 81 | hex_colors = ["#970FF2", "#0597F2", "#49D907", "#EAF205", "#F24607"] 82 | 83 | 84 | materials = [] 85 | 86 | for hex_color in hex_colors: 87 | # convert a hex color 88 | rgba_color = hex_color_to_rgba(hex_color) 89 | 90 | # create a new material 91 | material = bpy.data.materials.new(name=f"hex_color_{hex_color}") 92 | material.diffuse_color = rgba_color 93 | 94 | # add new material to a list 95 | materials.append(material) 96 | 97 | 98 | # initialize parameters 99 | count = 32 100 | angle_step = math.tau / count 101 | 102 | radius = 1.0 103 | 104 | for r in range(1, 5): 105 | radius = 0.2 * r 106 | for i in range(count): 107 | 108 | # calculate current current_angle 109 | current_angle = angle_step * i 110 | 111 | # calculate coordinate 112 | x = radius * math.cos(current_angle) 113 | z = radius * math.sin(current_angle) 114 | 115 | # visualize what we are doing 116 | bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1 - 0.08 / r, subdivisions=5, location=(x, 0, z)) 117 | bpy.ops.object.shade_smooth() 118 | 119 | # select a random material 120 | material = random.choice(materials) 121 | 122 | # add material to object 123 | bpy.context.active_object.data.materials.append(material) 124 | -------------------------------------------------------------------------------- /hex_color_to_rgba/hex_color_to_rgba_example_4.py: -------------------------------------------------------------------------------- 1 | """ 2 | To run this you will need the bpybb Python package. 3 | 4 | You can watch this video for detailed instructions on how to get the bpybb Python package: 5 | https://cgpython.com/bpybb-install 6 | 7 | or 8 | 9 | You can install the package as a Blender add-on by following 10 | this link https://cgpython.com/bpybb 11 | to the latest version of the add-on 12 | 13 | If you know how to install Python packages into the embedded Python via pip 14 | you can use the following link to get the pip instructions 15 | https://pypi.org/project/bpy-building-blocks/ 16 | 17 | """ 18 | 19 | import bpy 20 | 21 | import math 22 | 23 | import random 24 | 25 | from bpybb.color import hex_color_to_rgba 26 | 27 | 28 | # def hex_color_to_rgb(hex_color): 29 | # """ 30 | # Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 31 | # to a Linear RGB 32 | 33 | # Supports: "#RRGGBB" or "RRGGBB" 34 | 35 | # Note: We are converting into Linear RGB since Blender uses a Linear Color Space internally 36 | # https://docs.blender.org/manual/en/latest/render/color_management.html 37 | # """ 38 | # # remove the leading '#' symbol if present 39 | # if hex_color.startswith("#"): 40 | # hex_color = hex_color[1:] 41 | 42 | # assert len(hex_color) == 6, f"RRGGBB is the supported hex color format: {hex_color}" 43 | 44 | # # extracting the Red color component - RRxxxx 45 | # red = int(hex_color[:2], 16) 46 | # # dividing by 255 to get a number between 0.0 and 1.0 47 | # srgb_red = red / 255 48 | # linear_red = convert_srgb_to_linear_rgb(srgb_red) 49 | 50 | # # extracting the Green color component - xxGGxx 51 | # green = int(hex_color[2:4], 16) 52 | # # dividing by 255 to get a number between 0.0 and 1.0 53 | # srgb_green = green / 255 54 | # linear_green = convert_srgb_to_linear_rgb(srgb_green) 55 | 56 | # # extracting the Blue color component - xxxxBB 57 | # blue = int(hex_color[4:6], 16) 58 | # # dividing by 255 to get a number between 0.0 and 1.0 59 | # srgb_blue = blue / 255 60 | # linear_blue = convert_srgb_to_linear_rgb(srgb_blue) 61 | 62 | # return tuple([linear_red, linear_green, linear_blue]) 63 | 64 | 65 | # def hex_color_to_rgba(hex_color, alpha=1.0): 66 | # """ 67 | # Converting from a color in the form of a hex triplet string (en.wikipedia.org/wiki/Web_colors#Hex_triplet) 68 | # to a Linear RGB with an Alpha passed as a parameter 69 | 70 | # Supports: "#RRGGBB" or "RRGGBB" 71 | # """ 72 | # linear_red, linear_green, linear_blue = hex_color_to_rgb(hex_color) 73 | # return tuple([linear_red, linear_green, linear_blue, alpha]) 74 | 75 | 76 | # def convert_srgb_to_linear_rgb(srgb_color_component): 77 | # """ 78 | # Converting from sRGB to Linear RGB 79 | # based on https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ 80 | # """ 81 | # if srgb_color_component <= 0.04045: 82 | # linear_color_component = srgb_color_component / 12.92 83 | # else: 84 | # linear_color_component = math.pow((srgb_color_component + 0.055) / 1.055, 2.4) 85 | 86 | # return linear_color_component 87 | 88 | 89 | ########################################################## 90 | # _____ _ _ _ _____ 91 | # | ___| | | _| || |_ |____ | 92 | # | |____ ____ _ _ __ ___ _ __ | | ___ |_ __ _| / / 93 | # | __\ \/ / _` | '_ ` _ \| '_ \| |/ _ \ _| || |_ \ \ 94 | # | |___> < (_| | | | | | | |_) | | __/ |_ __ _| .___/ / 95 | # \____/_/\_\__,_|_| |_| |_| .__/|_|\___| |_||_| \____/ 96 | # | | 97 | # |_| 98 | ########################################################## 99 | 100 | # make a list of colors 101 | hex_colors = ["#970FF2", "#0597F2", "#49D907", "#EAF205", "#F24607"] 102 | 103 | materials = [] 104 | 105 | for hex_color in hex_colors: 106 | # convert a hex color 107 | rgba_color = hex_color_to_rgba(hex_color) 108 | 109 | # create a new material 110 | material = bpy.data.materials.new(name=f"hex_color_{hex_color}") 111 | material.diffuse_color = rgba_color 112 | 113 | # add new material to a list 114 | materials.append(material) 115 | 116 | 117 | # initialize parameters 118 | count = 32 119 | angle_step = math.tau / count 120 | 121 | radius = 1.0 122 | 123 | for r in range(1, 5): 124 | radius = 0.2 * r 125 | for i in range(count): 126 | 127 | # calculate current current_angle 128 | current_angle = angle_step * i 129 | 130 | # calculate coordinate 131 | x = radius * math.cos(current_angle) 132 | z = radius * math.sin(current_angle) 133 | 134 | # visualize what we are doing 135 | bpy.ops.mesh.primitive_ico_sphere_add(radius=0.1 - 0.08 / r, subdivisions=5, location=(x, 0, z)) 136 | bpy.ops.object.shade_smooth() 137 | 138 | # select a random material 139 | material = random.choice(materials) 140 | 141 | # add material to object 142 | bpy.context.active_object.data.materials.append(material) 143 | --------------------------------------------------------------------------------