diff options
Diffstat (limited to 'object_fracture_crack/crack_it.py')
-rw-r--r-- | object_fracture_crack/crack_it.py | 240 |
1 files changed, 156 insertions, 84 deletions
diff --git a/object_fracture_crack/crack_it.py b/object_fracture_crack/crack_it.py index 6d0cd571..489d2c87 100644 --- a/object_fracture_crack/crack_it.py +++ b/object_fracture_crack/crack_it.py @@ -1,77 +1,124 @@ +# gpl: author Nobuyuki Hirakata + import bpy -import bmesh, mathutils, random -from random import gauss +import bmesh +from random import ( + gauss, + seed, + ) from math import radians -from mathutils import Euler, Vector +from mathutils import Euler + + +# Allow changing the original material names from the .blend file +# by replacing them with the UI Names from the EnumProperty +def get_ui_mat_name(mat_name): + mat_ui_name = "CrackIt Material" + try: + # access the Scene type directly to get the name from the enum + mat_items = bpy.types.Scene.crackit[1]["type"].bl_rna.material_preset[1]["items"] + for mat_id, mat_list in enumerate(mat_items): + if mat_name in mat_list: + mat_ui_name = mat_items[mat_id][1] + break + del mat_items + except Exception as e: + error_handlers( + False, "get_ui_mat_name", e, + "Retrieving the EnumProperty key UI Name could not be completed", True + ) + pass + + return mat_ui_name + -import addon_utils +def error_handlers(self, op_name, error, reports="ERROR", func=False): + if self and reports: + self.report({'WARNING'}, reports + " (See Console for more info)") -# ---------------------Crack------------------- + is_func = "Function" if func else "Operator" + print("\n[Cell Fracture Crack It]\n{}: {}\nError: " + "{}\nReport: {}\n".format(is_func, op_name, error, reports)) + + +# -------------------- Crack ------------------- # Cell fracture and post-process: -def makeFracture(child_verts=False, division=100, noise=0.00, scaleX=1.00, scaleY=1.00, scaleZ=1.00, recursion=0, margin=0.001): - # Get active object name and active layer. +def makeFracture(child_verts=False, division=100, noise=0.00, + scaleX=1.00, scaleY=1.00, scaleZ=1.00, recursion=0, margin=0.001): + + # Get active object name and active layer active_name = bpy.context.scene.objects.active.name active_layer = bpy.context.scene.active_layer - - # source method of whether use child verts. - if child_verts == True: - crack_source = 'VERT_CHILD' + + # source method of whether use child verts + if child_verts is True: + crack_source = 'VERT_CHILD' else: - crack_source = 'PARTICLE_OWN' - - bpy.ops.object.add_fracture_cell_objects(source={crack_source}, source_limit=division, source_noise=noise, - cell_scale=(scaleX, scaleY, scaleZ), recursion=recursion, recursion_source_limit=8, recursion_clamp=250, recursion_chance=0.25, recursion_chance_select='SIZE_MIN', - use_smooth_faces=False, use_sharp_edges=False, use_sharp_edges_apply=True, use_data_match=True, use_island_split=True, - margin=margin, material_index=0, use_interior_vgroup=False, mass_mode='VOLUME', mass=1, use_recenter=True, use_remove_original=True, use_layer_index=0, use_layer_next=False, - group_name="", use_debug_points=False, use_debug_redraw=True, use_debug_bool=False) + crack_source = 'PARTICLE_OWN' + + bpy.ops.object.add_fracture_cell_objects( + source={crack_source}, source_limit=division, source_noise=noise, + cell_scale=(scaleX, scaleY, scaleZ), recursion=recursion, + recursion_source_limit=8, recursion_clamp=250, recursion_chance=0.25, + recursion_chance_select='SIZE_MIN', use_smooth_faces=False, + use_sharp_edges=False, use_sharp_edges_apply=True, use_data_match=True, + use_island_split=True, margin=margin, material_index=0, + use_interior_vgroup=False, mass_mode='VOLUME', mass=1, use_recenter=True, + use_remove_original=True, use_layer_index=0, use_layer_next=False, + group_name="", use_debug_points=False, use_debug_redraw=True, use_debug_bool=False + ) _makeJoin(active_name, active_layer) -# Join fractures into an object. + +# Join fractures into an object def _makeJoin(active_name, active_layer): - # Get object by name. - #bpy.context.scene.layers[active_layer+1] = True + # Get object by name bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=active_name + '_cell*') fractures = bpy.context.selected_objects - - # Execute join. - bpy.context.scene.objects.active = fractures[0] - fractures[0].select = True - bpy.ops.object.join() - - # Change name. + + if fractures: + # Execute join + bpy.context.scene.objects.active = fractures[0] + fractures[0].select = True + bpy.ops.object.join() + else: + error_handlers( + False, "_makeJoin", "if fractures condition has not passed", + "Warning: No objects could be joined", True + ) + + # Change name bpy.context.scene.objects.active.name = active_name + '_crack' - - # Change origin. + + # Change origin bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN') - - # Turn off the layer where original object is. - #bpy.context.scene.layers[active_layer] = False -# Add modifier and setting. + +# Add modifier and setting def addModifiers(): bpy.ops.object.modifier_add(type='DECIMATE') decimate = bpy.context.object.modifiers[-1] decimate.name = 'DECIMATE_crackit' decimate.ratio = 0.4 - + bpy.ops.object.modifier_add(type='SUBSURF') subsurf = bpy.context.object.modifiers[-1] subsurf.name = 'SUBSURF_crackit' - + bpy.ops.object.modifier_add(type='SMOOTH') smooth = bpy.context.object.modifiers[-1] smooth.name = 'SMOOTH_crackit' +# -------------- multi extrude -------------------- +# var1=random offset, var2=random rotation, var3=random scale +def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=1.0, + var1=0.01, var2=0.3, var3=0.3, num=1, ran=0): -# --------------multi extrude-------------------- -# var1=random offset, var2=random rotation, var3=random scale. -def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=1.0, var1=0.01, var2=0.3, var3=0.3, num=1, ran=0): obj = bpy.context.object - data, om = obj.data, obj.mode bpy.context.tool_settings.mesh_select_mode = [False, False, True] # bmesh operations @@ -92,7 +139,7 @@ def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=1.0, var1=0.01, var2=0.3, nf.normal_update() no = nf.normal.copy() ce = nf.calc_center_bounds() - s = _vsca(r=i+r, ran=ran, var3=var3, sca=sca) + s = _vsca(r=i + r, ran=ran, var3=var3, sca=sca) for v in nf.verts: v.co -= ce @@ -102,82 +149,107 @@ def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=1.0, var1=0.01, var2=0.3, # extrude code from TrumanBlending for a, b in zip(of.loops, nf.loops): - sf = bm.faces.new((a.vert, a.link_loop_next.vert, \ - b.link_loop_next.vert, b.vert)) + sf = bm.faces.new((a.vert, a.link_loop_next.vert, + b.link_loop_next.vert, b.vert)) sf.normal_update() bm.faces.remove(of) of = nf - for v in bm.verts: v.select = False - for e in bm.edges: e.select = False + for v in bm.verts: + v.select = False + + for e in bm.edges: + e.select = False + bm.to_mesh(obj.data) obj.data.update() - if not len(sel): - self.report({'INFO'}, "Select one or more faces...") - return{'FINISHED'} def _vloc(r, ran, off, var1): - random.seed(ran + r) - return off * (1 + random.gauss(0, var1 / 3)) + seed(ran + r) + return off * (1 + gauss(0, var1 / 3)) + def _vrot(r, ran, rotx, var2, roty, rotz): - random.seed(ran + r) - return Euler((radians(rotx) + random.gauss(0, var2 / 3), \ - radians(roty) + random.gauss(0, var2 / 3), \ - radians(rotz) + random.gauss(0, var2 / 3)), 'XYZ') + seed(ran + r) + return Euler((radians(rotx) + gauss(0, var2 / 3), + radians(roty) + gauss(0, var2 / 3), + radians(rotz) + gauss(0, var2 / 3)), 'XYZ') + def _vsca(r, ran, sca, var3): - random.seed(ran + r) - return sca * (1 + random.gauss(0, var3 / 3)) + seed(ran + r) + return sca * (1 + gauss(0, var3 / 3)) + -# centroide de una seleccion de vertices +# Centroid of a selection of vertices def _centro(ver): vvv = [v for v in ver if v.select] - if not vvv or len(vvv) == len(ver): return ('error') - x = sum([round(v.co[0],4) for v in vvv]) / len(vvv) - y = sum([round(v.co[1],4) for v in vvv]) / len(vvv) - z = sum([round(v.co[2],4) for v in vvv]) / len(vvv) - return (x,y,z) + if not vvv or len(vvv) == len(ver): + return ('error') + + x = sum([round(v.co[0], 4) for v in vvv]) / len(vvv) + y = sum([round(v.co[1], 4) for v in vvv]) / len(vvv) + z = sum([round(v.co[2], 4) for v in vvv]) / len(vvv) + + return (x, y, z) + -# recuperar el estado original del objeto +# Retrieve the original state of the object def _volver(obj, copia, om, msm, msv): - for i in copia: obj.data.vertices[i].select = True + for i in copia: + obj.data.vertices[i].select = True bpy.context.tool_settings.mesh_select_mode = msm + for i in range(len(msv)): obj.modifiers[i].show_viewport = msv[i] - -# --------------Material preset-------------------------- -def appendMaterial(addon_path, material_name): - # Load material from the addon directory. +# -------------- Material preset -------------------------- +def appendMaterial(addon_path, material_name, mat_ui_names="Nameless Material"): + # Load material from the addon directory file_path = _makeFilePath(addon_path=addon_path) bpy.ops.wm.append(filename=material_name, directory=file_path) - - # If material is loaded some times, select the last-loaded material. + + # If material is loaded some times, select the last-loaded material last_material = _getAppendedMaterial(material_name) - mat = bpy.data.materials[last_material] - - # Apply Only one material in the material slot. - for m in bpy.context.object.data.materials: - bpy.ops.object.material_slot_remove() - bpy.context.object.data.materials.append(mat) - -# Make file path of addon. + + if last_material: + mat = bpy.data.materials[last_material] + # skip renaming if the prop is True + if not bpy.context.scene.crackit.material_lib_name: + mat.name = mat_ui_names + + # Apply Only one material in the material slot + for m in bpy.context.object.data.materials: + bpy.ops.object.material_slot_remove() + + bpy.context.object.data.materials.append(mat) + + return True + + return False + + +# Make file path of addon def _makeFilePath(addon_path): material_folder = "/materials" blend_file = "/materials1.blend" category = "\\Material\\" - + file_path = addon_path + material_folder + blend_file + category return file_path -# Get last-loaded material, such as ~.002. + +# Get last-loaded material, such as ~.002 def _getAppendedMaterial(material_name): - # Get material name list. + # Get material name list material_names = [m.name for m in bpy.data.materials if material_name in m.name] - # Return last material in the sorted order. - material_names.sort() - return material_names[-1] + if material_names: + # Return last material in the sorted order + material_names.sort() + + return material_names[-1] + + return None |