object_fracture_crack/__init__.py: move to contrib: T63750 T61901

This commit is contained in:
Brendon Murphy 2019-07-24 00:30:35 +10:00
parent beb30514b4
commit 05af39acf8
4 changed files with 0 additions and 567 deletions

View File

@ -1,148 +0,0 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Cell Fracture Crack It",
"author": "Nobuyuki Hirakata",
"version": (0, 1, 2),
"blender": (2, 78, 5),
"location": "View3D > Toolshelf > Create Tab",
"description": "Displaced Cell Fracture Addon",
"warning": "Make sure to enable 'Object: Cell Fracture' Addon",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
"Py/Scripts/Object/CrackIt",
"category": "Object"
}
if 'bpy' in locals():
import importlib
importlib.reload(operator)
else:
from . import operator
import bpy
from bpy.types import PropertyGroup
from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
PointerProperty,
)
import os
class CrackItProperties(PropertyGroup):
# Input on toolshelf before execution
# In Panel subclass, In bpy.types.Operator subclass,
# reference them by context.scene.crackit
fracture_childverts: BoolProperty(
name="From Child Verts",
description="Use child object's vertices and position for origin of crack",
default=False
)
fracture_scalex: FloatProperty(
name="Scale X",
description="Scale X",
default=1.00,
min=0.00,
max=1.00
)
fracture_scaley: FloatProperty(
name="Scale Y",
description="Scale Y",
default=1.00,
min=0.00,
max=1.00
)
fracture_scalez: FloatProperty(
name="Scale Z",
description="Scale Z",
default=1.00,
min=0.00,
max=1.00
)
fracture_div: IntProperty(
name="Max Crack",
description="Max Crack",
default=100,
min=0,
max=10000
)
fracture_margin: FloatProperty(
name="Margin Size",
description="Margin Size",
default=0.001,
min=0.000,
max=1.000
)
extrude_offset: FloatProperty(
name="Offset",
description="Extrude Offset",
default=0.10,
min=0.00,
max=2.00
)
extrude_random: FloatProperty(
name="Random",
description="Extrude Random",
default=0.30,
min=-1.00,
max=1.00
)
# Path of the addon
material_addonpath = os.path.dirname(__file__)
# Selection of material preset
# Note: you can choose the original name in the library blend
# or the prop name
material_preset: EnumProperty(
name="Preset",
description="Material Preset",
items=[
('crackit_organic_mud', "Organic Mud", "Mud material"),
('crackit_mud1', "Mud", "Mud material"),
('crackit_tree1_moss1', "Tree Moss", "Tree Material"),
('crackit_tree2_dry1', "Tree Dry", "Tree Material"),
('crackit_tree3_red1', "Tree Red", "Tree Material"),
('crackit_rock1', "Rock", "Rock Material")
]
)
material_lib_name: BoolProperty(
name="Library Name",
description="Use the original Material name from the .blend library\n"
"instead of the one defined in the Preset",
default=True
)
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.crackit = PointerProperty(
type=CrackItProperties
)
def unregister():
del bpy.types.Scene.crackit
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()

View File

@ -1,255 +0,0 @@
# gpl: author Nobuyuki Hirakata
import bpy
import bmesh
from random import (
gauss,
seed,
)
from math import radians
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
def error_handlers(self, op_name, error, reports="ERROR", func=False):
if self and reports:
self.report({'WARNING'}, reports + " (See Console for more info)")
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
active_name = bpy.context.view_layer.objects.active.name
active_layer = bpy.context.scene.active_layer
# 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
)
_makeJoin(active_name, active_layer)
# Join fractures into an object
def _makeJoin(active_name, active_layer):
# 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
if fractures:
# Execute join
bpy.context.view_layer.objects.active = fractures[0]
fractures[0].select_set(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.view_layer.objects.active.name = active_name + '_crack'
# Change origin
bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')
# 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):
obj = bpy.context.object
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
# bmesh operations
bpy.ops.object.mode_set()
bm = bmesh.new()
bm.from_mesh(obj.data)
sel = [f for f in bm.faces if f.select]
# faces loop
for i, of in enumerate(sel):
rot = _vrot(r=i, ran=ran, rotx=rotx, var2=var2, roty=roty, rotz=rotz)
off = _vloc(r=i, ran=ran, off=off, var1=var1)
of.normal_update()
# extrusion loop
for r in range(num):
nf = of.copy()
nf.normal_update()
no = nf.normal.copy()
ce = nf.calc_center_bounds()
s = _vsca(r=i + r, ran=ran, var3=var3, sca=sca)
for v in nf.verts:
v.co -= ce
v.co.rotate(rot)
v.co += ce + no * off
v.co = v.co.lerp(ce, 1 - s)
# 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.normal_update()
bm.faces.remove(of)
of = nf
for v in bm.verts:
v.select = False
for e in bm.edges:
e.select = False
bm.to_mesh(obj.data)
obj.data.update()
def _vloc(r, ran, off, var1):
seed(ran + r)
return off * (1 + gauss(0, var1 / 3))
def _vrot(r, ran, rotx, var2, roty, rotz):
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):
seed(ran + r)
return sca * (1 + gauss(0, var3 / 3))
# 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)
# Retrieve the original state of the object
def _volver(obj, copia, om, msm, msv):
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, 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
last_material = _getAppendedMaterial(material_name)
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
def _getAppendedMaterial(material_name):
# Get material name list
material_names = [m.name for m in bpy.data.materials if material_name in m.name]
if material_names:
# Return last material in the sorted order
material_names.sort()
return material_names[-1]
return None

View File

@ -1,164 +0,0 @@
# gpl: author Nobuyuki Hirakata
import bpy
from bpy.types import (
Operator,
Panel,
)
from . import crack_it
def check_object_cell_fracture():
if "object_fracture_cell" in bpy.context.preferences.addons.keys():
return True
return False
# Access by bpy.ops.mesh.crackit_fracture
class FractureOperation(Operator):
bl_idname = "mesh.crackit_fracture"
bl_label = "Crack it!"
bl_description = ("Make cracks using the cell fracture add-on\n"
"Needs only one Selected Mesh Object")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
obj = context.active_object
sel_obj = len(context.selected_objects) == 1
return (obj is not None and obj.type == "MESH" and sel_obj)
def execute(self, context):
if check_object_cell_fracture():
crackit = context.scene.crackit
try:
crack_it.makeFracture(
child_verts=crackit.fracture_childverts,
division=crackit.fracture_div, scaleX=crackit.fracture_scalex,
scaleY=crackit.fracture_scaley, scaleZ=crackit.fracture_scalez,
margin=crackit.fracture_margin
)
crack_it.addModifiers()
crack_it.multiExtrude(
off=crackit.extrude_offset,
var2=crackit.extrude_random, var3=crackit.extrude_random
)
bpy.ops.object.shade_smooth()
except Exception as e:
crack_it.error_handlers(
self, "mesh.crackit_fracture", e, "Crack It! could not be completed."
)
return {"CANCELLED"}
else:
self.report({'WARNING'},
"Depends on Object: Cell Fracture addon. Please enable it first. "
"Operation Cancelled"
)
return {"CANCELLED"}
return {'FINISHED'}
# Apply material preset
# Access by bpy.ops.mesh.crackit_material
class MaterialOperation(Operator):
bl_idname = "mesh.crackit_material"
bl_label = "Apply Material"
bl_description = ("Apply a preset material\n"
"The Material will be applied to the Active Object\n"
"from the type of Mesh, Curve, Surface, Font, Meta")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
obj = context.active_object
# included - type that can have materials
included = ['MESH', 'CURVE', 'SURFACE', 'FONT', 'META']
return (obj is not None and obj.type in included)
def execute(self, context):
crackit = context.scene.crackit
mat_name = crackit.material_preset
mat_lib_name = crackit.material_lib_name
mat_ui_name = crack_it.get_ui_mat_name(mat_name) if not mat_lib_name else mat_name
try:
crack_it.appendMaterial(
addon_path=crackit.material_addonpath,
material_name=mat_name,
mat_ui_names=mat_ui_name
)
except Exception as e:
crack_it.error_handlers(
self, "mesh.crackit_material", e,
"The active Object could not have the Material {} applied".format(mat_ui_name)
)
return {"CANCELLED"}
return {'FINISHED'}
# Menu settings
class crackitPanel(Panel):
bl_label = "Crack it!"
bl_idname = 'crack_it'
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Create"
bl_context = 'objectmode'
bl_options = {"DEFAULT_CLOSED"}
def draw(self, context):
crackit = context.scene.crackit
layout = self.layout
# Crack input
box = layout.box()
row = box.row()
# Warning if the fracture cell addon is not enabled
if not check_object_cell_fracture():
col = box.column()
col.label(text="Please enable Object: Cell Fracture addon", icon="INFO")
col.separator()
col.operator("preferences.addon_show",
text="Go to Cell Fracture addon",
icon="PREFERENCES").module = "object_fracture_cell"
layout.separator()
return
else:
row.operator(FractureOperation.bl_idname, icon="SPLITSCREEN")
row = box.row()
row.prop(crackit, "fracture_childverts")
col = box.column(align=True)
col.prop(crackit, "fracture_scalex")
col.prop(crackit, "fracture_scaley")
col.prop(crackit, "fracture_scalez")
col = box.column(align=True)
col.label(text="Settings:")
col.prop(crackit, "fracture_div")
col.prop(crackit, "fracture_margin")
col = box.column(align=True)
col.label(text="Extrude:")
col.prop(crackit, "extrude_offset")
col.prop(crackit, "extrude_random")
# material Preset:
box = layout.box()
row = box.row()
row.label(text="Material Preset:")
row_sub = row.row()
row_sub.prop(crackit, "material_lib_name", text="",
toggle=True, icon="LONGDISPLAY")
row = box.row()
row.prop(crackit, "material_preset")
row = box.row()
row.operator(MaterialOperation.bl_idname)