object_fracture_crack/__init__.py: move to contrib: T63750 T61901
This commit is contained in:
parent
beb30514b4
commit
05af39acf8
|
@ -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()
|
|
@ -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
|
Binary file not shown.
|
@ -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)
|
Loading…
Reference in New Issue