Skip to content

Commit 80883fd

Browse files
committed
Adding Ch8 source
1 parent 99f7310 commit 80883fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+5028
-0
lines changed

SourceCode/Ch8/extension/projection_painting_helper_4.2/__init__.py

+397
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# GNU GPLv3, 29 June 2007
4+
#
5+
# Examples from Ch8 of the book "Blender Scripting with Python" by Isabel Lupiani.
6+
# Copyright (C) 2024 Isabel Lupiani, Apress.
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
# ##### END GPL LICENSE BLOCK #####
22+
23+
__all__ = (
24+
"apply_all_modifiers",
25+
"apply_given_modifier",
26+
)
27+
28+
import bpy
29+
30+
from .view_fit import get_context_override
31+
32+
def apply_all_modifiers(context, obj_to_apply_modifier):
33+
for obj in context.view_layer.objects:
34+
obj.select_set(False)
35+
context.view_layer.objects.active = obj_to_apply_modifier
36+
obj_to_apply_modifier.select_set(True)
37+
38+
context_override, override_succesful = get_context_override(context, 'VIEW_3D', 'WINDOW')
39+
if override_succesful:
40+
with bpy.context.temp_override(**context_override):
41+
bpy.ops.object.mode_set(mode='OBJECT')
42+
43+
context_override, override_succesful = get_context_override(context, 'VIEW_3D', 'WINDOW')
44+
if override_succesful:
45+
with bpy.context.temp_override(**context_override):
46+
for m in obj_to_apply_modifier.modifiers:
47+
try:
48+
bpy.ops.object.modifier_apply(modifier=m.name)
49+
except RuntimeError:
50+
continue
51+
52+
def apply_given_modifier(context, obj_to_apply_modifier, modifier_type, modifier_name):
53+
for obj in context.view_layer.objects:
54+
obj.select_set(False)
55+
context.view_layer.objects.active = obj_to_apply_modifier
56+
obj_to_apply_modifier.select_set(True)
57+
58+
context_override, override_succesful = get_context_override(context, 'VIEW_3D', 'WINDOW')
59+
if override_succesful:
60+
with bpy.context.temp_override(**context_override):
61+
bpy.ops.object.mode_set(mode='OBJECT')
62+
63+
context_override, override_succesful = get_context_override(context, 'VIEW_3D', 'WINDOW')
64+
if override_succesful:
65+
with bpy.context.temp_override(**context_override):
66+
for m in obj_to_apply_modifier.modifiers:
67+
if m.type==modifier_type and m.name==modifier_name:
68+
try:
69+
bpy.ops.object.modifier_apply(modifier=m.name)
70+
except RuntimeError:
71+
return
72+
return
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
schema_version = "1.0.0"
2+
3+
id = "projection_painting_helper"
4+
version = "2.0.0"
5+
name = "Projection Painting Helper"
6+
tagline = "Ch8 Examples of Blender Scripting with Python by Isabel Lupiani"
7+
maintainer = "Isabel Lupiani <[email protected]>"
8+
type = "add-on"
9+
10+
tags = ["Paint", "UV"]
11+
12+
blender_version_min = "4.2.0"
13+
14+
# License conforming to https://spdx.org/licenses/ (use "SPDX: prefix)
15+
# https://docs.blender.org/manual/en/dev/advanced/extensions/licenses.html
16+
license = [
17+
"SPDX:GPL-2.0-or-later",
18+
]
19+
20+
copyright = [
21+
"2018-2024 Isabel Lupiani",
22+
"2024 Apress",
23+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# GNU GPLv3, 29 June 2007
4+
#
5+
# Examples from Ch8 of the book "Blender Scripting with Python" by Isabel Lupiani.
6+
# Copyright (C) 2024 Isabel Lupiani, Apress.
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
# ##### END GPL LICENSE BLOCK #####
22+
23+
__all__ = (
24+
"create_image_data_block",
25+
"save_image_to_file",
26+
)
27+
28+
import bpy
29+
import os
30+
31+
# if "bpy" in locals():
32+
# import importlib
33+
# importlib.reload(split_screen_area)
34+
# importlib.reload(uv_settings)
35+
# importlib.reload(view_fit)
36+
# else:
37+
# from . import split_screen_area
38+
# from . import uv_settings
39+
# from . import view_fit
40+
41+
from .split_screen_area import split_screen_area
42+
from .uv_settings import get_image_editor, get_uv_editor
43+
from .view_fit import get_context_override
44+
45+
def create_image_data_block(context, name, image_type='UV_GRID', color=(0, 0, 0, 1), image_filepath='', display_image=True, area_ui_type='IMAGE_EDITOR'):
46+
image_block = None
47+
if bpy.data.images.find(name) < 0 or not bpy.data.images[name].has_data:
48+
if os.path.isfile(image_filepath):
49+
image_block = bpy.data.images.load(image_filepath)
50+
image_block.name = name
51+
else:
52+
bpy.data.images.new(name=name, width=1024, height=1024, alpha=True, float_buffer=False, stereo3d=False)
53+
image_block = bpy.data.images[name]
54+
else:
55+
image_block = bpy.data.images[name]
56+
57+
image_block.generated_color = color
58+
image_block.generated_type = image_type
59+
60+
if not display_image:
61+
return image_block, None
62+
63+
[image_editor_area, image_editor_space, uv_editor] = [None, None, None]
64+
if area_ui_type=='IMAGE_EDITOR':
65+
[image_editor_area, image_editor_space] = get_image_editor(context, name)
66+
else:
67+
[image_editor_area, image_editor_space, uv_editor] = get_uv_editor(context, name)
68+
69+
if image_editor_space:
70+
image_editor_space.image = image_block
71+
else:
72+
image_editor_area = split_screen_area(context, 'VERTICAL', 0.5, 'IMAGE_EDITOR', area_ui_type, False)
73+
for s in image_editor_area.spaces:
74+
if s.type == 'IMAGE_EDITOR':
75+
image_editor_space = s
76+
image_editor_space.image = image_block
77+
if area_ui_type == 'UV':
78+
uv_editor = s.uv_editor
79+
break
80+
81+
image_editor_context_override, override_successful = get_context_override(context, 'IMAGE_EDITOR', 'WINDOW', image_editor_area.x, name)
82+
if override_successful:
83+
with bpy.context.temp_override(**image_editor_context_override):
84+
bpy.ops.image.view_all(fit_view=True)
85+
86+
return image_block, uv_editor
87+
88+
def save_image_to_file(context, name, dirpath):
89+
if bpy.data.images.find(name) < 0:
90+
print("No image by the name " + name + " exists.")
91+
return
92+
93+
image = bpy.data.images[name]
94+
image.filepath_raw = dirpath + '\\' + name + '.png'
95+
image.file_format = 'PNG'
96+
image.save()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# GNU GPLv3, 29 June 2007
4+
#
5+
# Examples from Ch8 of the book "Blender Scripting with Python" by Isabel Lupiani.
6+
# Copyright (C) 2024 Isabel Lupiani, Apress.
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
# ##### END GPL LICENSE BLOCK #####
22+
23+
__all__ = (
24+
"load_image_empty",
25+
"rename_empty",
26+
"load_reference_or_background_image"
27+
)
28+
29+
import bpy
30+
from mathutils import Euler
31+
from math import radians
32+
33+
# if "bpy" in locals():
34+
# import importlib
35+
# importlib.reload(view_fit)
36+
# else:
37+
# from . import view_fit
38+
39+
from .view_fit import get_context_override
40+
41+
def load_image_empty(context, name, image_file_path, location, rotation_degrees, depth, side, transparency):
42+
empty = bpy.data.objects.new(name, None)
43+
empty.empty_display_type = 'IMAGE'
44+
empty.data = bpy.data.images.load(image_file_path)
45+
empty.location = location
46+
empty.rotation_euler = Euler((radians(d) for d in rotation_degrees), 'XYZ')
47+
empty.empty_image_depth = depth
48+
empty.empty_image_side = side
49+
empty.color[3] = transparency
50+
empty.empty_display_size = 5
51+
context.collection.objects.link(empty)
52+
53+
def rename_empty(context, name):
54+
active_obj = context.view_layer.objects.active
55+
if active_obj and active_obj.type == 'EMPTY':
56+
active_obj.name = name
57+
else:
58+
num_objs = len(context.view_layer.objects)
59+
for i in range(num_objs - 1, -1, -1):
60+
obj = context.view_layer.objects[i]
61+
if obj.type == 'EMPTY':
62+
obj.name = name
63+
context.view_layer.objects.active = obj
64+
break
65+
66+
def load_reference_or_background_image(context, filepath, name, location, rotation_degrees=(90,0,0), is_background=False):
67+
rotation_rads = [radians(d) for d in rotation_degrees]
68+
context_override = get_context_override(context, 'VIEW_3D', 'WINDOW')
69+
with bpy.context.temp_override(**context_override):
70+
bpy.ops.object.empty_image_add(filepath=filepath, relative_path=False, align='VIEW', \
71+
location=location, rotation=rotation_rads, scale=(1,1,1), background=is_background)
72+
rename_empty(context, name)
73+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# GNU GPLv3, 29 June 2007
4+
#
5+
# Examples from Ch8 of the book "Blender Scripting with Python" by Isabel Lupiani.
6+
# Copyright (C) 2024 Isabel Lupiani, Apress.
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
# ##### END GPL LICENSE BLOCK #####
22+
23+
__all__ = (
24+
"split_screen_area",
25+
)
26+
27+
import bpy
28+
29+
def split_screen_area(context, split_dir, split_ratio, type_of_new_area, ui_type_of_new_area, check_existing=False):
30+
existing_areas = list(context.screen.areas)
31+
32+
if check_existing:
33+
for area in existing_areas:
34+
# Found an existing area of matching type
35+
if area.type == type_of_new_area and area.ui_type == ui_type_of_new_area:
36+
return area
37+
38+
bpy.ops.screen.area_split(direction=split_dir, factor=split_ratio)
39+
40+
for area in context.screen.areas:
41+
if area not in existing_areas:
42+
area.type = type_of_new_area
43+
area.ui_type = ui_type_of_new_area
44+
return area
45+

0 commit comments

Comments
 (0)