1 # gpl: author Nobuyuki Hirakata
10 from math
import radians
11 from mathutils
import Euler
14 # Allow changing the original material names from the .blend file
15 # by replacing them with the UI Names from the EnumProperty
16 def get_ui_mat_name(mat_name
):
17 mat_ui_name
= "CrackIt Material"
19 # access the Scene type directly to get the name from the enum
20 mat_items
= bpy
.types
.Scene
.crackit
[1]["type"].bl_rna
.material_preset
[1]["items"]
21 for mat_id
, mat_list
in enumerate(mat_items
):
22 if mat_name
in mat_list
:
23 mat_ui_name
= mat_items
[mat_id
][1]
26 except Exception as e
:
28 False, "get_ui_mat_name", e
,
29 "Retrieving the EnumProperty key UI Name could not be completed", True
36 def error_handlers(self
, op_name
, error
, reports
="ERROR", func
=False):
38 self
.report({'WARNING'}, reports
+ " (See Console for more info)")
40 is_func
= "Function" if func
else "Operator"
41 print("\n[Cell Fracture Crack It]\n{}: {}\nError: "
42 "{}\nReport: {}\n".format(is_func
, op_name
, error
, reports
))
45 # -------------------- Crack -------------------
46 # Cell fracture and post-process:
47 def makeFracture(child_verts
=False, division
=100, noise
=0.00,
48 scaleX
=1.00, scaleY
=1.00, scaleZ
=1.00, recursion
=0, margin
=0.001):
50 # Get active object name and active layer
51 active_name
= bpy
.context
.scene
.objects
.active
.name
52 active_layer
= bpy
.context
.scene
.active_layer
54 # source method of whether use child verts
55 if child_verts
is True:
56 crack_source
= 'VERT_CHILD'
58 crack_source
= 'PARTICLE_OWN'
60 bpy
.ops
.object.add_fracture_cell_objects(
61 source
={crack_source}
, source_limit
=division
, source_noise
=noise
,
62 cell_scale
=(scaleX
, scaleY
, scaleZ
), recursion
=recursion
,
63 recursion_source_limit
=8, recursion_clamp
=250, recursion_chance
=0.25,
64 recursion_chance_select
='SIZE_MIN', use_smooth_faces
=False,
65 use_sharp_edges
=False, use_sharp_edges_apply
=True, use_data_match
=True,
66 use_island_split
=True, margin
=margin
, material_index
=0,
67 use_interior_vgroup
=False, mass_mode
='VOLUME', mass
=1, use_recenter
=True,
68 use_remove_original
=True, use_layer_index
=0, use_layer_next
=False,
69 group_name
="", use_debug_points
=False, use_debug_redraw
=True, use_debug_bool
=False
72 _makeJoin(active_name
, active_layer
)
75 # Join fractures into an object
76 def _makeJoin(active_name
, active_layer
):
78 bpy
.ops
.object.select_all(action
='DESELECT')
79 bpy
.ops
.object.select_pattern(pattern
=active_name
+ '_cell*')
80 fractures
= bpy
.context
.selected_objects
84 bpy
.context
.scene
.objects
.active
= fractures
[0]
85 fractures
[0].select
= True
89 False, "_makeJoin", "if fractures condition has not passed",
90 "Warning: No objects could be joined", True
94 bpy
.context
.scene
.objects
.active
.name
= active_name
+ '_crack'
97 bpy
.ops
.object.origin_set(type='GEOMETRY_ORIGIN')
100 # Add modifier and setting
102 bpy
.ops
.object.modifier_add(type='DECIMATE')
103 decimate
= bpy
.context
.object.modifiers
[-1]
104 decimate
.name
= 'DECIMATE_crackit'
107 bpy
.ops
.object.modifier_add(type='SUBSURF')
108 subsurf
= bpy
.context
.object.modifiers
[-1]
109 subsurf
.name
= 'SUBSURF_crackit'
111 bpy
.ops
.object.modifier_add(type='SMOOTH')
112 smooth
= bpy
.context
.object.modifiers
[-1]
113 smooth
.name
= 'SMOOTH_crackit'
116 # -------------- multi extrude --------------------
117 # var1=random offset, var2=random rotation, var3=random scale
118 def multiExtrude(off
=0.1, rotx
=0, roty
=0, rotz
=0, sca
=1.0,
119 var1
=0.01, var2
=0.3, var3
=0.3, num
=1, ran
=0):
121 obj
= bpy
.context
.object
122 bpy
.context
.tool_settings
.mesh_select_mode
= [False, False, True]
125 bpy
.ops
.object.mode_set()
127 bm
.from_mesh(obj
.data
)
128 sel
= [f
for f
in bm
.faces
if f
.select
]
131 for i
, of
in enumerate(sel
):
132 rot
= _vrot(r
=i
, ran
=ran
, rotx
=rotx
, var2
=var2
, roty
=roty
, rotz
=rotz
)
133 off
= _vloc(r
=i
, ran
=ran
, off
=off
, var1
=var1
)
140 no
= nf
.normal
.copy()
141 ce
= nf
.calc_center_bounds()
142 s
= _vsca(r
=i
+ r
, ran
=ran
, var3
=var3
, sca
=sca
)
147 v
.co
+= ce
+ no
* off
148 v
.co
= v
.co
.lerp(ce
, 1 - s
)
150 # extrude code from TrumanBlending
151 for a
, b
in zip(of
.loops
, nf
.loops
):
152 sf
= bm
.faces
.new((a
.vert
, a
.link_loop_next
.vert
,
153 b
.link_loop_next
.vert
, b
.vert
))
169 def _vloc(r
, ran
, off
, var1
):
171 return off
* (1 + gauss(0, var1
/ 3))
174 def _vrot(r
, ran
, rotx
, var2
, roty
, rotz
):
176 return Euler((radians(rotx
) + gauss(0, var2
/ 3),
177 radians(roty
) + gauss(0, var2
/ 3),
178 radians(rotz
) + gauss(0, var2
/ 3)), 'XYZ')
181 def _vsca(r
, ran
, sca
, var3
):
183 return sca
* (1 + gauss(0, var3
/ 3))
186 # Centroid of a selection of vertices
188 vvv
= [v
for v
in ver
if v
.select
]
189 if not vvv
or len(vvv
) == len(ver
):
192 x
= sum([round(v
.co
[0], 4) for v
in vvv
]) / len(vvv
)
193 y
= sum([round(v
.co
[1], 4) for v
in vvv
]) / len(vvv
)
194 z
= sum([round(v
.co
[2], 4) for v
in vvv
]) / len(vvv
)
199 # Retrieve the original state of the object
200 def _volver(obj
, copia
, om
, msm
, msv
):
202 obj
.data
.vertices
[i
].select
= True
203 bpy
.context
.tool_settings
.mesh_select_mode
= msm
205 for i
in range(len(msv
)):
206 obj
.modifiers
[i
].show_viewport
= msv
[i
]
209 # -------------- Material preset --------------------------
210 def appendMaterial(addon_path
, material_name
, mat_ui_names
="Nameless Material"):
211 # Load material from the addon directory
212 file_path
= _makeFilePath(addon_path
=addon_path
)
213 bpy
.ops
.wm
.append(filename
=material_name
, directory
=file_path
)
215 # If material is loaded some times, select the last-loaded material
216 last_material
= _getAppendedMaterial(material_name
)
219 mat
= bpy
.data
.materials
[last_material
]
220 # skip renaming if the prop is True
221 if not bpy
.context
.scene
.crackit
.material_lib_name
:
222 mat
.name
= mat_ui_names
224 # Apply Only one material in the material slot
225 for m
in bpy
.context
.object.data
.materials
:
226 bpy
.ops
.object.material_slot_remove()
228 bpy
.context
.object.data
.materials
.append(mat
)
235 # Make file path of addon
236 def _makeFilePath(addon_path
):
237 material_folder
= "/materials"
238 blend_file
= "/materials1.blend"
239 category
= "\\Material\\"
241 file_path
= addon_path
+ material_folder
+ blend_file
+ category
245 # Get last-loaded material, such as ~.002
246 def _getAppendedMaterial(material_name
):
247 # Get material name list
248 material_names
= [m
.name
for m
in bpy
.data
.materials
if material_name
in m
.name
]
250 # Return last material in the sorted order
251 material_names
.sort()
253 return material_names
[-1]