diff --git a/object_fracture_cell/__init__.py b/object_fracture_cell/__init__.py
index 794c2fe17c02aefba749b3ba59891c3d9585db75..e1fcb41f838a6545407e1c5ce126bd1bf406df04 100644
--- a/object_fracture_cell/__init__.py
+++ b/object_fracture_cell/__init__.py
@@ -18,23 +18,20 @@
 
 bl_info = {
     "name": "Cell Fracture",
-    "author": "ideasman42, phymec, Sergey Sharybin, Nobuyuki Hirakata",
-    "version": (1, 0, 2),
-    "blender": (2, 80, 0),
-    "location": "View3D > Sidebar > Transform tab",
-    "description": "Fractured Object, or Cracked Surface",
-    "warning": "Work in Progress",
+    "author": "ideasman42, phymec, Sergey Sharybin",
+    "version": (0, 1),
+    "blender": (2, 70, 0),
+    "location": "Edit panel of Tools tab, in Object mode, 3D View tools",
+    "description": "Fractured Object, Bomb, Projectile, Recorder",
+    "warning": "",
     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
                 "Scripts/Object/CellFracture",
     "category": "Object"}
 
 
-if "bpy" in locals():
-    import importlib
-    importlib.reload(operator)
-
-else:
-    from . import operator
+#if "bpy" in locals():
+#    import importlib
+#    importlib.reload(fracture_cell_setup)
 
 import bpy
 from bpy.props import (
@@ -44,114 +41,244 @@ from bpy.props import (
         FloatProperty,
         FloatVectorProperty,
         EnumProperty,
-        BoolVectorProperty,
-        PointerProperty,
         )
 
-from bpy.types import (
-        Panel,
-        PropertyGroup,
-        )
+from bpy.types import Operator
 
+def main_object(context, obj, level, **kw):
+    import random
 
-class FRACTURE_PT_Menu(Panel):
-    bl_idname = 'FRACTURE_PT_Menu'
-    bl_label = "Fracture Cell"
-    bl_space_type = "VIEW_3D"
-    bl_region_type = "UI"
-    bl_category = "Create"
-    bl_context = 'objectmode'
-    bl_options = {"DEFAULT_CLOSED"}
+    # pull out some args
+    kw_copy = kw.copy()
+    use_recenter = kw_copy.pop("use_recenter")
+    use_remove_original = kw_copy.pop("use_remove_original")
+    recursion = kw_copy.pop("recursion")
+    recursion_source_limit = kw_copy.pop("recursion_source_limit")
+    recursion_clamp = kw_copy.pop("recursion_clamp")
+    recursion_chance = kw_copy.pop("recursion_chance")
+    recursion_chance_select = kw_copy.pop("recursion_chance_select")
+    use_layer_next = kw_copy.pop("use_layer_next")
+    use_layer_index = kw_copy.pop("use_layer_index")
+    group_name = kw_copy.pop("group_name")
+    use_island_split = kw_copy.pop("use_island_split")
+    use_debug_bool = kw_copy.pop("use_debug_bool")
+    use_interior_vgroup = kw_copy.pop("use_interior_vgroup")
+    use_sharp_edges = kw_copy.pop("use_sharp_edges")
+    use_sharp_edges_apply = kw_copy.pop("use_sharp_edges_apply")
+
+    collection = context.collection
+
+    if level != 0:
+        kw_copy["source_limit"] = recursion_source_limit
+
+    from . import fracture_cell_setup
+
+    # not essential but selection is visual distraction.
+    obj.select_set(False)
+
+    if kw_copy["use_debug_redraw"]:
+        obj_display_type_prev = obj.display_type
+        obj.display_type = 'WIRE'
+
+    objects = fracture_cell_setup.cell_fracture_objects(context, obj, **kw_copy)
+    objects = fracture_cell_setup.cell_fracture_boolean(context, obj, objects,
+                                                        use_island_split=use_island_split,
+                                                        use_interior_hide=(use_interior_vgroup or use_sharp_edges),
+                                                        use_debug_bool=use_debug_bool,
+                                                        use_debug_redraw=kw_copy["use_debug_redraw"],
+                                                        level=level,
+                                                        )
+
+    # must apply after boolean.
+    if use_recenter:
+        bpy.ops.object.origin_set({"selected_editable_objects": objects},
+                                  type='ORIGIN_GEOMETRY', center='MEDIAN')
+
+    if level == 0:
+        for level_sub in range(1, recursion + 1):
+
+            objects_recurse_input = [(i, o) for i, o in enumerate(objects)]
+
+            if recursion_chance != 1.0:
+                from mathutils import Vector
+                if recursion_chance_select == 'RANDOM':
+                    random.shuffle(objects_recurse_input)
+                elif recursion_chance_select in {'SIZE_MIN', 'SIZE_MAX'}:
+                    objects_recurse_input.sort(key=lambda ob_pair:
+                        (Vector(ob_pair[1].bound_box[0]) -
+                         Vector(ob_pair[1].bound_box[6])).length_squared)
+                    if recursion_chance_select == 'SIZE_MAX':
+                        objects_recurse_input.reverse()
+                elif recursion_chance_select in {'CURSOR_MIN', 'CURSOR_MAX'}:
+                    c = scene.cursor.location.copy()
+                    objects_recurse_input.sort(key=lambda ob_pair:
+                        (ob_pair[1].location - c).length_squared)
+                    if recursion_chance_select == 'CURSOR_MAX':
+                        objects_recurse_input.reverse()
+
+                objects_recurse_input[int(recursion_chance * len(objects_recurse_input)):] = []
+                objects_recurse_input.sort()
+
+            # reverse index values so we can remove from original list.
+            objects_recurse_input.reverse()
+
+            objects_recursive = []
+            for i, obj_cell in objects_recurse_input:
+                assert(objects[i] is obj_cell)
+                objects_recursive += main_object(context, obj_cell, level_sub, **kw)
+                if use_remove_original:
+                    collection.objects.unlink(obj_cell)
+                    del objects[i]
+                if recursion_clamp and len(objects) + len(objects_recursive) >= recursion_clamp:
+                    break
+            objects.extend(objects_recursive)
+
+            if recursion_clamp and len(objects) > recursion_clamp:
+                break
+
+    #--------------
+    # Level Options
+    if level == 0:
+        # import pdb; pdb.set_trace()
+        if use_interior_vgroup or use_sharp_edges:
+            fracture_cell_setup.cell_fracture_interior_handle(objects,
+                                                              use_interior_vgroup=use_interior_vgroup,
+                                                              use_sharp_edges=use_sharp_edges,
+                                                              use_sharp_edges_apply=use_sharp_edges_apply,
+                                                              )
+
+    #--------------
+    # Scene Options
+
+    # layer
+    layers_new = None
+    if use_layer_index != 0:
+        layers_new = [False] * 20
+        layers_new[use_layer_index - 1] = True
+    elif use_layer_next:
+        layers_new = [False] * 20
+        layers_new[(obj.layers[:].index(True) + 1) % 20] = True
+
+    if layers_new is not None:
+        for obj_cell in objects:
+            obj_cell.layers = layers_new
+
+    # group
+    if group_name:
+        group = bpy.data.collections.get(group_name)
+        if group is None:
+            group = bpy.data.collections.new(group_name)
+        group_objects = group.objects[:]
+        for obj_cell in objects:
+            if obj_cell not in group_objects:
+                group.objects.link(obj_cell)
+
+    if kw_copy["use_debug_redraw"]:
+        obj.display_type = obj_display_type_prev
+
+    # testing only!
+    # obj.hide = True
+    return objects
+
+
+def main(context, **kw):
+    import time
+    t = time.time()
+    objects_context = context.selected_editable_objects
+
+    kw_copy = kw.copy()
+
+    # mass
+    mass_mode = kw_copy.pop("mass_mode")
+    mass = kw_copy.pop("mass")
+
+    objects = []
+    for obj in objects_context:
+        if obj.type == 'MESH':
+            objects += main_object(context, obj, 0, **kw_copy)
+
+    bpy.ops.object.select_all(action='DESELECT')
+    for obj_cell in objects:
+        obj_cell.select_set(True)
+
+    if mass_mode == 'UNIFORM':
+        for obj_cell in objects:
+            obj_cell.game.mass = mass
+    elif mass_mode == 'VOLUME':
+        from mathutils import Vector
+        def _get_volume(obj_cell):
+            def _getObjectBBMinMax():
+                min_co = Vector((1000000.0, 1000000.0, 1000000.0))
+                max_co = -min_co
+                matrix = obj_cell.matrix_world
+                for i in range(0, 8):
+                    bb_vec = obj_cell.matrix_world * Vector(obj_cell.bound_box[i])
+                    min_co[0] = min(bb_vec[0], min_co[0])
+                    min_co[1] = min(bb_vec[1], min_co[1])
+                    min_co[2] = min(bb_vec[2], min_co[2])
+                    max_co[0] = max(bb_vec[0], max_co[0])
+                    max_co[1] = max(bb_vec[1], max_co[1])
+                    max_co[2] = max(bb_vec[2], max_co[2])
+                return (min_co, max_co)
+
+            def _getObjectVolume():
+                min_co, max_co = _getObjectBBMinMax()
+                x = max_co[0] - min_co[0]
+                y = max_co[1] - min_co[1]
+                z = max_co[2] - min_co[2]
+                volume = x * y * z
+                return volume
+
+            return _getObjectVolume()
+
+
+        obj_volume_ls = [_get_volume(obj_cell) for obj_cell in objects]
+        obj_volume_tot = sum(obj_volume_ls)
+        if obj_volume_tot > 0.0:
+            mass_fac = mass / obj_volume_tot
+            for i, obj_cell in enumerate(objects):
+                obj_cell.game.mass = obj_volume_ls[i] * mass_fac
+    else:
+        assert(0)
+
+    print("Done! %d objects in %.4f sec" % (len(objects), time.time() - t))
+
+
+class FractureCell(Operator):
+    bl_idname = "object.add_fracture_cell_objects"
+    bl_label = "Cell fracture selected mesh objects"
+    bl_options = {'PRESET'}
 
-    def draw(self, context):
-        # Show pop-upped menu when the button is hit.
-        layout = self.layout
-        #layout.label(text="Cell Fracture:")
-        layout.operator(operator.FRACTURE_OT_Cell.bl_idname,
-                    text="1. Cell Fracture")
-        layout.operator(operator.FRACTURE_OT_Crack.bl_idname,
-                    text="2. Cell to Crack")
-
-        material_props = context.window_manager.fracture_material_props
-        layout.separator()
-        box = layout.box()
-        col = box.column()
-        row = col.row(align=True)
-        row.label(text="Material Preset:")
-        '''
-        row_sub = row.row()
-        row_sub.prop(material_props, "material_lib_name", text="",
-                     toggle=True, icon="LONGDISPLAY")
-        '''
-        row = box.row()
-        row.prop(material_props, "material_preset", text="")
-
-        row = box.row()
-        row.operator(operator.FRACTURE_OT_Material.bl_idname, icon="MATERIAL_DATA",
-                    text="Append Material")
-
-
-class FractureCellProperties(PropertyGroup):
     # -------------------------------------------------------------------------
     # Source Options
-    source_vert_own: IntProperty(
-            name="Own Verts",
-            description="Use own vertices",
-            min=0, max=2000,
-            default=100,
-            )
-    source_vert_child: IntProperty(
-            name="Child Verts",
-            description="Use child object vertices",
-            min=0, max=2000,
-            default=0,
-            )
-    source_particle_own: IntProperty(
-            name="Own Particles",
-            description="All particle systems of the source object",
-            min=0, max=2000,
-            default=0,
-            )
-    source_particle_child: IntProperty(
-            name="Child Particles",
-            description="All particle systems of the child objects",
-            min=0, max=2000,
-            default=0,
-            )
-    source_pencil: IntProperty(
-            name="Annotation Pencil",
-            description="Annotation Grease Pencil",
-            min=0, max=2000,
-            default=0,
-            )
-    source_random: IntProperty(
-            name="Random",
-            description="Random seed position",
-            min=0, max=2000,
-            default=0,
+    source: EnumProperty(
+            name="Source",
+            items=(('VERT_OWN', "Own Verts", "Use own vertices"),
+                   ('VERT_CHILD', "Child Verts", "Use child object vertices"),
+                   ('PARTICLE_OWN', "Own Particles", ("All particle systems of the "
+                                                      "source object")),
+                   ('PARTICLE_CHILD', "Child Particles", ("All particle systems of the "
+                                                          "child objects")),
+                   ('PENCIL', "Grease Pencil", "This object's grease pencil"),
+                   ),
+            options={'ENUM_FLAG'},
+            default={'PARTICLE_OWN'},
             )
-    '''
+
     source_limit: IntProperty(
             name="Source Limit",
             description="Limit the number of input points, 0 for unlimited",
             min=0, max=5000,
             default=100,
             )
-    '''
-    # -------------------------------------------------------------------------
-    # Transform
+
     source_noise: FloatProperty(
             name="Noise",
             description="Randomize point distribution",
             min=0.0, max=1.0,
             default=0.0,
             )
-    margin: FloatProperty(
-            name="Margin",
-            description="Gaps for the fracture (gives more stable physics)",
-            min=0.0, max=1.0,
-            default=0.001,
-            )
+
     cell_scale: FloatVectorProperty(
             name="Scale",
             description="Scale Cell Shape",
@@ -159,51 +286,40 @@ class FractureCellProperties(PropertyGroup):
             min=0.0, max=1.0,
             default=(1.0, 1.0, 1.0),
             )
-    pre_simplify : FloatProperty(
-            name="Simplify Base Mesh",
-            description="Simplify base mesh before making cell. Lower face size, faster calculation",
-            default=0.00,
-            min=0.00,
-            max=1.00
-            )
-    use_recenter: BoolProperty(
-            name="Recenter",
-            description="Recalculate the center points after splitting",
-            default=True,
-            )
-    use_island_split: BoolProperty(
-            name="Split Islands",
-            description="Split disconnected meshes",
-            default=True,
-            )
+
     # -------------------------------------------------------------------------
     # Recursion
+
     recursion: IntProperty(
             name="Recursion",
             description="Break shards recursively",
-            min=0, max=2000,
+            min=0, max=5000,
             default=0,
             )
+
     recursion_source_limit: IntProperty(
-            name="Fracture Each",
+            name="Source Limit",
             description="Limit the number of input points, 0 for unlimited (applies to recursion only)",
-            min=2, max=2000, # Oviously, dividing in more than two objects is needed, to avoid no fracture object.
+            min=0, max=5000,
             default=8,
             )
+
     recursion_clamp: IntProperty(
-            name="Max Fracture",
+            name="Clamp Recursion",
             description="Finish recursion when this number of objects is reached (prevents recursing for extended periods of time), zero disables",
             min=0, max=10000,
             default=250,
             )
+
     recursion_chance: FloatProperty(
-            name="Rec Chance",
+            name="Random Factor",
             description="Likelihood of recursion",
             min=0.0, max=1.0,
-            default=1.00,
+            default=0.25,
             )
+
     recursion_chance_select: EnumProperty(
-            name="Target",
+            name="Recurse Over",
             items=(('RANDOM', "Random", ""),
                    ('SIZE_MIN', "Small", "Recursively subdivide smaller objects"),
                    ('SIZE_MAX', "Big", "Recursively subdivide bigger objects"),
@@ -212,77 +328,61 @@ class FractureCellProperties(PropertyGroup):
                    ),
             default='SIZE_MIN',
             )
+
     # -------------------------------------------------------------------------
-    # Interior Meshes Options
+    # Mesh Data Options
+
     use_smooth_faces: BoolProperty(
             name="Smooth Faces",
-            description="Smooth Faces of inner side",
             default=False,
             )
+
     use_sharp_edges: BoolProperty(
-            name="Mark Sharp Edges",
+            name="Sharp Edges",
             description="Set sharp edges when disabled",
-            default=False,
+            default=True,
             )
+
     use_sharp_edges_apply: BoolProperty(
-            name="Edge Split Modifier",
-            description="Add edge split modofier for sharp edges",
-            default=False,
+            name="Apply Split Edge",
+            description="Split sharp hard edges",
+            default=True,
             )
+
     use_data_match: BoolProperty(
-            name="Copy Original Data",
+            name="Match Data",
             description="Match original mesh materials and data layers",
             default=True,
             )
+
+    use_island_split: BoolProperty(
+            name="Split Islands",
+            description="Split disconnected meshes",
+            default=True,
+            )
+
+    margin: FloatProperty(
+            name="Margin",
+            description="Gaps for the fracture (gives more stable physics)",
+            min=0.0, max=1.0,
+            default=0.001,
+            )
+
     material_index: IntProperty(
-            name="Interior Material Slot",
+            name="Material",
             description="Material index for interior faces",
             default=0,
             )
+
     use_interior_vgroup: BoolProperty(
-            name="Vertex Group",
+            name="Interior VGroup",
             description="Create a vertex group for interior verts",
             default=False,
             )
+
     # -------------------------------------------------------------------------
-    # Scene Options
-    use_collection: BoolProperty(
-            name="Use Collection",
-            description="Use collection to organize fracture objects",
-            default=True,
-            )
-    new_collection: BoolProperty(
-            name="Use New",
-            description="Make new collection for fracture objects",
-            default=True,
-            )
-    collection_name: StringProperty(
-            name="Name",
-            description="Collection name.",
-            default="Fracture",
-            )
-    original_hide: BoolProperty(
-            name="Hide Original",
-            description="Hide original object after cell fracture.",
-            default=False,
-            )
-    cell_relocate : BoolProperty(
-            name="Move Beside Original",
-            description="Move cells beside the original object.",
-            default=False,
-            )
-    # -------------------------------------------------------------------------
-    # Custom Property Options
-    use_mass: BoolProperty(
-        name="Mass",
-        description="Append mass data on custom properties of cell objects.",
-        default=False,
-        )
-    mass_name: StringProperty(
-        name="Property Name",
-        description="Name for custome properties.",
-        default="mass",
-        )
+    # Physics Options
+
     mass_mode: EnumProperty(
             name="Mass Mode",
             items=(('VOLUME', "Volume", "Objects get part of specified mass based on their volume"),
@@ -290,12 +390,55 @@ class FractureCellProperties(PropertyGroup):
                    ),
             default='VOLUME',
             )
+
     mass: FloatProperty(
-            name="Mass Factor",
+            name="Mass",
             description="Mass to give created objects",
             min=0.001, max=1000.0,
             default=1.0,
             )
+
+
+    # -------------------------------------------------------------------------
+    # Object Options
+
+    use_recenter: BoolProperty(
+            name="Recenter",
+            description="Recalculate the center points after splitting",
+            default=True,
+            )
+
+    use_remove_original: BoolProperty(
+            name="Remove Original",
+            description="Removes the parents used to create the shatter",
+            default=True,
+            )
+
+    # -------------------------------------------------------------------------
+    # Scene Options
+    #
+    # .. different from object options in that this controls how the objects
+    #    are setup in the scene.
+
+    use_layer_index: IntProperty(
+            name="Layer Index",
+            description="Layer to add the objects into or 0 for existing",
+            default=0,
+            min=0, max=20,
+            )
+
+    use_layer_next: BoolProperty(
+            name="Next Layer",
+            description="At the object into the next layer (layer index overrides)",
+            default=True,
+            )
+
+    group_name: StringProperty(
+            name="Group",
+            description="Create objects int a group "
+                        "(use existing or create new)",
+            )
+
     # -------------------------------------------------------------------------
     # Debug
     use_debug_points: BoolProperty(
@@ -307,7 +450,7 @@ class FractureCellProperties(PropertyGroup):
     use_debug_redraw: BoolProperty(
             name="Show Progress Realtime",
             description="Redraw as fracture is done",
-            default=False,
+            default=True,
             )
 
     use_debug_bool: BoolProperty(
@@ -316,109 +459,110 @@ class FractureCellProperties(PropertyGroup):
             default=False,
             )
 
+    def execute(self, context):
+        keywords = self.as_keywords()  # ignore=("blah",)
 
-class FractureCrackProperties(PropertyGroup):
-    modifier_decimate : FloatProperty(
-        name="Reduce Faces",
-        description="Apply Decimate Modifier to reduce face number",
-        default=0.40,
-        min=0.00,
-        max=1.00
-        )
-    modifier_smooth : FloatProperty(
-            name="Loose | Tight",
-            description="Smooth Modifier",
-            default=-0.50,
-            min=-3.00,
-            max=3.00
-            )
-    extrude_scale : FloatProperty(
-            name="Extrude Blob",
-            description="Extrude Scale",
-            default=0.00,
-            min=0.00,
-            max=5.00
-            )
-    extrude_var : FloatProperty(
-            name="Extrude Random ",
-            description="Extrude Varriant",
-            default=0.01,
-            min=-4.00,
-            max=4.00
-            )
-    extrude_num : IntProperty(
-            name="Extrude Num",
-            description="Extrude Number",
-            default=1,
-            min=0,
-            max=10
-            )
-    modifier_wireframe : BoolProperty(
-            name="Wireframe Modifier",
-            description="Wireframe Modifier",
-            default=False
-            )
+        main(context, **keywords)
 
+        return {'FINISHED'}
 
-class FractureMaterialProperties(PropertyGroup):
-    # 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_mud', "Mud", "Mud material"),
-                ('crackit_tree_moss', "Tree Moss", "Tree Material"),
-                ('crackit_tree_dry', "Tree Dry", "Tree Material"),
-                ('crackit_tree_red', "Tree Red", "Tree Material"),
-                ('crackit_rock', "Rock", "Rock Material"),
-                ('crackit_lava', "Lava", "Lava Material"),
-                ('crackit_wet-paint', "Wet Paint", "Paint Material"),
-                ('crackit_soap', "Soap", "Soap 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
-            )
 
-classes = (
-    FractureCellProperties,
-    FractureCrackProperties,
-    FractureMaterialProperties,
-    operator.FRACTURE_OT_Cell,
-    operator.FRACTURE_OT_Crack,
-    operator.FRACTURE_OT_Material,
-    FRACTURE_PT_Menu,
-    )
+    def invoke(self, context, event):
+        print(self.recursion_chance_select)
+        wm = context.window_manager
+        return wm.invoke_props_dialog(self, width=600)
+
+    def draw(self, context):
+        layout = self.layout
+        box = layout.box()
+        col = box.column()
+        col.label(text="Point Source")
+        rowsub = col.row()
+        rowsub.prop(self, "source")
+        rowsub = col.row()
+        rowsub.prop(self, "source_limit")
+        rowsub.prop(self, "source_noise")
+        rowsub = col.row()
+        rowsub.prop(self, "cell_scale")
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Recursive Shatter")
+        rowsub = col.row(align=True)
+        rowsub.prop(self, "recursion")
+        rowsub.prop(self, "recursion_source_limit")
+        rowsub.prop(self, "recursion_clamp")
+        rowsub = col.row()
+        rowsub.prop(self, "recursion_chance")
+        rowsub.prop(self, "recursion_chance_select", expand=True)
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Mesh Data")
+        rowsub = col.row()
+        rowsub.prop(self, "use_smooth_faces")
+        rowsub.prop(self, "use_sharp_edges")
+        rowsub.prop(self, "use_sharp_edges_apply")
+        rowsub.prop(self, "use_data_match")
+        rowsub = col.row()
+
+        # on same row for even layout but infact are not all that related
+        rowsub.prop(self, "material_index")
+        rowsub.prop(self, "use_interior_vgroup")
+
+        # could be own section, control how we subdiv
+        rowsub.prop(self, "margin")
+        rowsub.prop(self, "use_island_split")
+
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Physics")
+        rowsub = col.row(align=True)
+        rowsub.prop(self, "mass_mode")
+        rowsub.prop(self, "mass")
+
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Object")
+        rowsub = col.row(align=True)
+        rowsub.prop(self, "use_recenter")
+
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Scene")
+        rowsub = col.row(align=True)
+        rowsub.prop(self, "use_layer_index")
+        rowsub.prop(self, "use_layer_next")
+        rowsub.prop(self, "group_name")
+
+        box = layout.box()
+        col = box.column()
+        col.label(text="Debug")
+        rowsub = col.row(align=True)
+        rowsub.prop(self, "use_debug_redraw")
+        rowsub.prop(self, "use_debug_points")
+        rowsub.prop(self, "use_debug_bool")
+
+
+def menu_func(self, context):
+    layout = self.layout
+    layout.label(text="Cell Fracture:")
+    layout.operator("object.add_fracture_cell_objects",
+                    text="Cell Fracture")
+
 
 def register():
-    from bpy.utils import register_class
-    for cls in classes:
-        register_class(cls)
-
-    bpy.types.WindowManager.fracture_cell_props = PointerProperty(
-        type=FractureCellProperties
-    )
-    bpy.types.WindowManager.fracture_crack_props = PointerProperty(
-        type=FractureCrackProperties
-    )
-    bpy.types.WindowManager.fracture_material_props = PointerProperty(
-        type=FractureMaterialProperties
-    )
+    bpy.utils.register_class(FractureCell)
+    bpy.types.VIEW3D_PT_tools_object.append(menu_func)
+
 
 def unregister():
-    del bpy.types.WindowManager.fracture_material_props
-    del bpy.types.WindowManager.fracture_crack_props
-    del bpy.types.WindowManager.fracture_cell_props
+    bpy.utils.unregister_class(FractureCell)
+    bpy.types.VIEW3D_PT_tools_object.remove(menu_func)
 
-    from bpy.utils import unregister_class
-    for cls in reversed(classes):
-        unregister_class(cls)
 
 if __name__ == "__main__":
-	register()
-
+    register()
diff --git a/object_fracture_cell/fracture_cell_calc.py b/object_fracture_cell/fracture_cell_calc.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e6f0de5fa04345c28394b9849a6a49c6bd91548
--- /dev/null
+++ b/object_fracture_cell/fracture_cell_calc.py
@@ -0,0 +1,120 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+# Script copyright (C) Blender Foundation 2012
+
+
+def points_as_bmesh_cells(verts,
+                          points,
+                          points_scale=None,
+                          margin_bounds=0.05,
+                          margin_cell=0.0):
+    from math import sqrt
+    import mathutils
+    from mathutils import Vector
+
+    cells = []
+
+    points_sorted_current = [p for p in points]
+    plane_indices = []
+    vertices = []
+
+    if points_scale is not None:
+        points_scale = tuple(points_scale)
+    if points_scale == (1.0, 1.0, 1.0):
+        points_scale = None
+
+    # there are many ways we could get planes - convex hull for eg
+    # but it ends up fastest if we just use bounding box
+    if 1:
+        xa = [v[0] for v in verts]
+        ya = [v[1] for v in verts]
+        za = [v[2] for v in verts]
+
+        xmin, xmax = min(xa) - margin_bounds, max(xa) + margin_bounds
+        ymin, ymax = min(ya) - margin_bounds, max(ya) + margin_bounds
+        zmin, zmax = min(za) - margin_bounds, max(za) + margin_bounds
+        convexPlanes = [
+            Vector((+1.0, 0.0, 0.0, -xmax)),
+            Vector((-1.0, 0.0, 0.0, +xmin)),
+            Vector((0.0, +1.0, 0.0, -ymax)),
+            Vector((0.0, -1.0, 0.0, +ymin)),
+            Vector((0.0, 0.0, +1.0, -zmax)),
+            Vector((0.0, 0.0, -1.0, +zmin)),
+            ]
+
+    for i, point_cell_current in enumerate(points):
+        planes = [None] * len(convexPlanes)
+        for j in range(len(convexPlanes)):
+            planes[j] = convexPlanes[j].copy()
+            planes[j][3] += planes[j].xyz.dot(point_cell_current)
+        distance_max = 10000000000.0  # a big value!
+
+        points_sorted_current.sort(key=lambda p: (p - point_cell_current).length_squared)
+
+        for j in range(1, len(points)):
+            normal = points_sorted_current[j] - point_cell_current
+            nlength = normal.length
+
+            if points_scale is not None:
+                normal_alt = normal.copy()
+                normal_alt.x *= points_scale[0]
+                normal_alt.y *= points_scale[1]
+                normal_alt.z *= points_scale[2]
+
+                # rotate plane to new distance
+                # should always be positive!! - but abs incase
+                scalar = normal_alt.normalized().dot(normal.normalized())
+                # assert(scalar >= 0.0)
+                nlength *= scalar
+                normal = normal_alt
+
+            if nlength > distance_max:
+                break
+
+            plane = normal.normalized()
+            plane.resize_4d()
+            plane[3] = (-nlength / 2.0) + margin_cell
+            planes.append(plane)
+
+            vertices[:], plane_indices[:] = mathutils.geometry.points_in_planes(planes)
+            if len(vertices) == 0:
+                break
+
+            if len(plane_indices) != len(planes):
+                planes[:] = [planes[k] for k in plane_indices]
+
+            # for comparisons use length_squared and delay
+            # converting to a real length until the end.
+            distance_max = 10000000000.0  # a big value!
+            for v in vertices:
+                distance = v.length_squared
+                if distance_max < distance:
+                    distance_max = distance
+            distance_max = sqrt(distance_max)  # make real length
+            distance_max *= 2.0
+
+        if len(vertices) == 0:
+            continue
+
+        cells.append((point_cell_current, vertices[:]))
+        del vertices[:]
+
+    return cells
diff --git a/object_fracture_cell/fracture_cell_setup.py b/object_fracture_cell/fracture_cell_setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..fcafa2474c7e46353f57757989cbb31347a5bd4a
--- /dev/null
+++ b/object_fracture_cell/fracture_cell_setup.py
@@ -0,0 +1,459 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+# Script copyright (C) Blender Foundation 2012
+
+import bpy
+import bmesh
+
+
+def _redraw_yasiamevil():
+    _redraw_yasiamevil.opr(**_redraw_yasiamevil.arg)
+_redraw_yasiamevil.opr = bpy.ops.wm.redraw_timer
+_redraw_yasiamevil.arg = dict(type='DRAW_WIN_SWAP', iterations=1)
+
+
+def _points_from_object(obj, source):
+
+    _source_all = {
+        'PARTICLE_OWN', 'PARTICLE_CHILD',
+        'PENCIL',
+        'VERT_OWN', 'VERT_CHILD',
+        }
+
+    print(source - _source_all)
+    print(source)
+    assert(len(source | _source_all) == len(_source_all))
+    assert(len(source))
+
+    points = []
+
+    def edge_center(mesh, edge):
+        v1, v2 = edge.vertices
+        return (mesh.vertices[v1].co + mesh.vertices[v2].co) / 2.0
+
+    def poly_center(mesh, poly):
+        from mathutils import Vector
+        co = Vector()
+        tot = 0
+        for i in poly.loop_indices:
+            co += mesh.vertices[mesh.loops[i].vertex_index].co
+            tot += 1
+        return co / tot
+
+    def points_from_verts(obj):
+        """Takes points from _any_ object with geometry"""
+        if obj.type == 'MESH':
+            mesh = obj.data
+            matrix = obj.matrix_world.copy()
+            points.extend([matrix * v.co for v in mesh.vertices])
+        else:
+            depsgraph = bpy.context.evaluated_depsgraph_get()
+            ob_eval = ob.evaluated_get(depsgraph)
+            try:
+                mesh = ob_eval.to_mesh()
+            except:
+                mesh = None
+
+            if mesh is not None:
+                matrix = obj.matrix_world.copy()
+                points.extend([matrix * v.co for v in mesh.vertices])
+                ob_eval.to_mesh_clear()
+
+    def points_from_particles(obj):
+        points.extend([p.location.copy()
+                       for psys in obj.particle_systems
+                       for p in psys.particles])
+
+    # geom own
+    if 'VERT_OWN' in source:
+        points_from_verts(obj)
+
+    # geom children
+    if 'VERT_CHILD' in source:
+        for obj_child in obj.children:
+            points_from_verts(obj_child)
+
+    # geom particles
+    if 'PARTICLE_OWN' in source:
+        points_from_particles(obj)
+
+    if 'PARTICLE_CHILD' in source:
+        for obj_child in obj.children:
+            points_from_particles(obj_child)
+
+    # grease pencil
+    def get_points(stroke):
+        return [point.co.copy() for point in stroke.points]
+
+    def get_splines(gp):
+        if gp.layers.active:
+            frame = gp.layers.active.active_frame
+            return [get_points(stroke) for stroke in frame.strokes]
+        else:
+            return []
+
+    if 'PENCIL' in source:
+        gp = obj.grease_pencil
+        if gp:
+            points.extend([p for spline in get_splines(gp)
+                             for p in spline])
+
+    print("Found %d points" % len(points))
+
+    return points
+
+
+def cell_fracture_objects(context, obj,
+                          source={'PARTICLE_OWN'},
+                          source_limit=0,
+                          source_noise=0.0,
+                          clean=True,
+                          # operator options
+                          use_smooth_faces=False,
+                          use_data_match=False,
+                          use_debug_points=False,
+                          margin=0.0,
+                          material_index=0,
+                          use_debug_redraw=False,
+                          cell_scale=(1.0, 1.0, 1.0),
+                          ):
+
+    from . import fracture_cell_calc
+    collection = context.collection
+    view_layer = context.view_layer
+
+    # -------------------------------------------------------------------------
+    # GET POINTS
+
+    points = _points_from_object(obj, source)
+
+    if not points:
+        # print using fallback
+        points = _points_from_object(obj, {'VERT_OWN'})
+
+    if not points:
+        print("no points found")
+        return []
+
+    # apply optional clamp
+    if source_limit != 0 and source_limit < len(points):
+        import random
+        random.shuffle(points)
+        points[source_limit:] = []
+
+    # saddly we cant be sure there are no doubles
+    from mathutils import Vector
+    to_tuple = Vector.to_tuple
+    points = list({to_tuple(p, 4): p for p in points}.values())
+    del to_tuple
+    del Vector
+
+    # end remove doubles
+    # ------------------
+
+    if source_noise > 0.0:
+        from random import random
+        # boundbox approx of overall scale
+        from mathutils import Vector
+        matrix = obj.matrix_world.copy()
+        bb_world = [matrix * Vector(v) for v in obj.bound_box]
+        scalar = source_noise * ((bb_world[0] - bb_world[6]).length / 2.0)
+
+        from mathutils.noise import random_unit_vector
+
+        points[:] = [p + (random_unit_vector() * (scalar * random())) for p in points]
+
+    if use_debug_points:
+        bm = bmesh.new()
+        for p in points:
+            bm.verts.new(p)
+        mesh_tmp = bpy.data.meshes.new(name="DebugPoints")
+        bm.to_mesh(mesh_tmp)
+        bm.free()
+        obj_tmp = bpy.data.objects.new(name=mesh_tmp.name, object_data=mesh_tmp)
+        collection.objects.link(obj_tmp)
+        del obj_tmp, mesh_tmp
+
+    mesh = obj.data
+    matrix = obj.matrix_world.copy()
+    verts = [matrix * v.co for v in mesh.vertices]
+
+    cells = fracture_cell_calc.points_as_bmesh_cells(verts,
+                                                     points,
+                                                     cell_scale,
+                                                     margin_cell=margin)
+
+    # some hacks here :S
+    cell_name = obj.name + "_cell"
+
+    objects = []
+
+    for center_point, cell_points in cells:
+
+        # ---------------------------------------------------------------------
+        # BMESH
+
+        # create the convex hulls
+        bm = bmesh.new()
+
+        # WORKAROUND FOR CONVEX HULL BUG/LIMIT
+        # XXX small noise
+        import random
+        def R():
+            return (random.random() - 0.5) * 0.001
+        # XXX small noise
+
+        for i, co in enumerate(cell_points):
+
+            # XXX small noise
+            co.x += R()
+            co.y += R()
+            co.z += R()
+            # XXX small noise
+
+            bm_vert = bm.verts.new(co)
+
+        import mathutils
+        bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.005)
+        try:
+            bmesh.ops.convex_hull(bm, input=bm.verts)
+        except RuntimeError:
+            import traceback
+            traceback.print_exc()
+
+        if clean:
+            bm.normal_update()
+            try:
+                bmesh.ops.dissolve_limit(bm, verts=bm.verts, angle_limit=0.001)
+            except RuntimeError:
+                import traceback
+                traceback.print_exc()
+
+        if use_smooth_faces:
+            for bm_face in bm.faces:
+                bm_face.smooth = True
+
+        if material_index != 0:
+            for bm_face in bm.faces:
+                bm_face.material_index = material_index
+
+
+        # ---------------------------------------------------------------------
+        # MESH
+        mesh_dst = bpy.data.meshes.new(name=cell_name)
+
+        bm.to_mesh(mesh_dst)
+        bm.free()
+        del bm
+
+        if use_data_match:
+            # match materials and data layers so boolean displays them
+            # currently only materials + data layers, could do others...
+            mesh_src = obj.data
+            for mat in mesh_src.materials:
+                mesh_dst.materials.append(mat)
+            for lay_attr in ("vertex_colors", "uv_textures"):
+                lay_src = getattr(mesh_src, lay_attr)
+                lay_dst = getattr(mesh_dst, lay_attr)
+                for key in lay_src.keys():
+                    lay_dst.new(name=key)
+
+        # ---------------------------------------------------------------------
+        # OBJECT
+
+        obj_cell = bpy.data.objects.new(name=cell_name, object_data=mesh_dst)
+        collection.objects.link(obj_cell)
+        # scene.objects.active = obj_cell
+        obj_cell.location = center_point
+
+        objects.append(obj_cell)
+
+        # support for object materials
+        if use_data_match:
+            for i in range(len(mesh_dst.materials)):
+                slot_src = obj.material_slots[i]
+                slot_dst = obj_cell.material_slots[i]
+
+                slot_dst.link = slot_src.link
+                slot_dst.material = slot_src.material
+
+        if use_debug_redraw:
+            view_layer.update()
+            _redraw_yasiamevil()
+
+    view_layer.update()
+
+    # move this elsewhere...
+    for obj_cell in objects:
+        game = obj_cell.game
+        game.physics_type = 'RIGID_BODY'
+        game.use_collision_bounds = True
+        game.collision_bounds_type = 'CONVEX_HULL'
+
+    return objects
+
+
+def cell_fracture_boolean(context, obj, objects,
+                          use_debug_bool=False,
+                          clean=True,
+                          use_island_split=False,
+                          use_interior_hide=False,
+                          use_debug_redraw=False,
+                          level=0,
+                          remove_doubles=True
+                          ):
+
+    objects_boolean = []
+    collection = context.collection
+    scene = context.scene
+    view_layer = context.view_layer
+    depsgraph = context.evaluated_depsgraph_get()
+
+    if use_interior_hide and level == 0:
+        # only set for level 0
+        obj.data.polygons.foreach_set("hide", [False] * len(obj.data.polygons))
+
+    for obj_cell in objects:
+        mod = obj_cell.modifiers.new(name="Boolean", type='BOOLEAN')
+        mod.object = obj
+        mod.operation = 'INTERSECT'
+
+        if not use_debug_bool:
+
+            if use_interior_hide:
+                obj_cell.data.polygons.foreach_set("hide", [True] * len(obj_cell.data.polygons))
+
+            obj_cell_eval = obj_cell.evaluated_get(depsgraph)
+            mesh_new = bpy.data.meshes.new_from_object(obj_cell_eval)
+            mesh_old = obj_cell.data
+            obj_cell.data = mesh_new
+            obj_cell.modifiers.remove(mod)
+
+            # remove if not valid
+            if not mesh_old.users:
+                bpy.data.meshes.remove(mesh_old)
+            if not mesh_new.vertices:
+                collection.objects.unlink(obj_cell)
+                if not obj_cell.users:
+                    bpy.data.objects.remove(obj_cell)
+                    obj_cell = None
+                    if not mesh_new.users:
+                        bpy.data.meshes.remove(mesh_new)
+                        mesh_new = None
+
+            # avoid unneeded bmesh re-conversion
+            if mesh_new is not None:
+                bm = None
+
+                if clean:
+                    if bm is None:  # ok this will always be true for now...
+                        bm = bmesh.new()
+                        bm.from_mesh(mesh_new)
+                    bm.normal_update()
+                    try:
+                        bmesh.ops.dissolve_limit(bm, verts=bm.verts, edges=bm.edges, angle_limit=0.001)
+                    except RuntimeError:
+                        import traceback
+                        traceback.print_exc()
+
+                if remove_doubles:
+                    if bm is None:
+                        bm = bmesh.new()
+                        bm.from_mesh(mesh_new)
+                    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.005)
+
+                if bm is not None:
+                    bm.to_mesh(mesh_new)
+                    bm.free()
+
+            del mesh_new
+            del mesh_old
+
+        if obj_cell is not None:
+            objects_boolean.append(obj_cell)
+
+            if use_debug_redraw:
+                _redraw_yasiamevil()
+
+    if (not use_debug_bool) and use_island_split:
+        # this is ugly and Im not proud of this - campbell
+        for ob in view_layer.objects:
+            ob.select_set(True)
+        for obj_cell in objects_boolean:
+            obj_cell.select_set(True)
+
+        bpy.ops.mesh.separate(type='LOOSE')
+
+        objects_boolean[:] = [obj_cell for obj_cell in scene.objects if obj_cell.select]
+
+    context.view_layer.update()
+
+    return objects_boolean
+
+
+def cell_fracture_interior_handle(objects,
+                                  use_interior_vgroup=False,
+                                  use_sharp_edges=False,
+                                  use_sharp_edges_apply=False,
+                                  ):
+    """Run after doing _all_ booleans"""
+
+    assert(use_interior_vgroup or use_sharp_edges or use_sharp_edges_apply)
+
+    for obj_cell in objects:
+        mesh = obj_cell.data
+        bm = bmesh.new()
+        bm.from_mesh(mesh)
+
+        if use_interior_vgroup:
+            for bm_vert in bm.verts:
+                bm_vert.tag = True
+            for bm_face in bm.faces:
+                if not bm_face.hide:
+                    for bm_vert in bm_face.verts:
+                        bm_vert.tag = False
+
+            # now add all vgroups
+            defvert_lay = bm.verts.layers.deform.verify()
+            for bm_vert in bm.verts:
+                if bm_vert.tag:
+                    bm_vert[defvert_lay][0] = 1.0
+
+            # add a vgroup
+            obj_cell.vertex_groups.new(name="Interior")
+
+        if use_sharp_edges:
+            mesh.show_edge_sharp = True
+            for bm_edge in bm.edges:
+                if len({bm_face.hide for bm_face in bm_edge.link_faces}) == 2:
+                    bm_edge.smooth = False
+
+            if use_sharp_edges_apply:
+                edges = [edge for edge in bm.edges if edge.smooth is False]
+                if edges:
+                    bm.normal_update()
+                    bmesh.ops.split_edges(bm, edges=edges)
+
+        for bm_face in bm.faces:
+            bm_face.hide = False
+
+        bm.to_mesh(mesh)
+        bm.free()
diff --git a/object_fracture_cell/operator.py b/object_fracture_cell/operator.py
deleted file mode 100644
index c01e866a66e6d49c7295d9cd357bd910818e7d07..0000000000000000000000000000000000000000
--- a/object_fracture_cell/operator.py
+++ /dev/null
@@ -1,284 +0,0 @@
-
-if "bpy" in locals():
-    import importlib
-    importlib.reload(cell_main)
-    importlib.reload(crack_functions)
-    importlib.reload(material_functions)
-    importlib.reload(utilities)
-
-else:
-    from .process import cell_main
-    from .process import crack_functions
-    from .process import material_functions
-    from . import utilities
-
-import bpy
-
-from bpy.types import (
-        Operator,
-        )
-
-class FRACTURE_OT_Cell(Operator):
-    bl_idname = "object.add_fracture_cell"
-    bl_label = "Cell fracture"
-    bl_description = "Make fractured cells from selected object."
-    bl_options = {'REGISTER', 'UNDO'}
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.active_object
-        return obj and obj.type == "MESH"
-
-    def execute(self, context):
-        #keywords = self.as_keywords()  # ignore=("blah",)
-
-        fracture_cell_props = context.window_manager.fracture_cell_props
-        cell_keywords = utilities._cell_props_to_dict(fracture_cell_props)
-
-        originals = context.selected_editable_objects
-        for original in originals:
-            cell_main.main(context, original, **cell_keywords)
-
-        return {'FINISHED'}
-
-    def invoke(self, context, event):
-        wm = context.window_manager
-        return wm.invoke_props_dialog(self, width=350)
-
-    def draw(self, context):
-        cell_props = context.window_manager.fracture_cell_props
-
-        layout = self.layout
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Fracture From")
-        row = col.row()
-        #row.prop(cell_props, "source")
-        row.prop(cell_props, "source_vert_own")
-        row.prop(cell_props, "source_vert_child")
-        row = col.row()
-        row.prop(cell_props, "source_particle_own")
-        row.prop(cell_props, "source_particle_child")
-        row = col.row()
-        row.prop(cell_props, "source_random")
-        row.prop(cell_props, "source_pencil")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Transform")
-        row = col.row()
-        row.prop(cell_props, "pre_simplify")
-        row.prop(cell_props, "source_noise")
-        row = col.row(align=True)
-        row.prop(cell_props, "margin")
-        row.prop(cell_props, "use_recenter")
-        row = col.row(align=True)
-        row.prop(cell_props, "cell_scale")
-        # could be own section, control how we subdiv
-        #row.prop(cell_props, "use_island_split")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Recursive Shatter")
-        row = col.row(align=True)
-        row.prop(cell_props, "recursion")
-        row.prop(cell_props, "recursion_chance")
-        row = col.row(align=True)
-        if cell_props.recursion > 0:
-            row.enabled = True
-        else:
-            row.enabled = False
-        row.prop(cell_props, "recursion_source_limit")
-        row.prop(cell_props, "recursion_clamp")
-        row = col.row()
-        row.prop(cell_props, "recursion_chance_select")#, expand=True)
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Interior Meshes")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_data_match")
-        row.prop(cell_props, "use_interior_vgroup")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_smooth_faces")
-        row.prop(cell_props, "use_sharp_edges")
-        if cell_props.use_sharp_edges == True:
-            row.prop(cell_props, "use_sharp_edges_apply")
-
-        row = col.row()
-        if cell_props.use_data_match == True:
-            row.enabled = True
-        else:
-            row.enabled = False
-        row.alignment = 'LEFT'
-        # on same row for even layout but infact are not all that related
-        row.prop(cell_props, "material_index")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Custom Properties")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_mass")
-        if cell_props.use_mass:
-            row = col.row(align=True)
-            row.prop(cell_props, "mass_name")
-            row = col.row(align=True)
-            row.prop(cell_props, "mass_mode")
-            row.prop(cell_props, "mass")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Object Management")
-        row = col.row(align=True)
-        row.prop(cell_props, "original_hide")
-        row.prop(cell_props, "cell_relocate")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Collections:")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_collection")
-        if cell_props.use_collection:
-            row.prop(cell_props, "new_collection")
-            row.prop(cell_props, "collection_name")
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Debug")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_debug_points")
-        row.prop(cell_props, "use_debug_bool")
-        row = col.row(align=True)
-        row.prop(cell_props, "use_debug_redraw")
-
-class FRACTURE_OT_Crack(Operator):
-    bl_idname = "object.add_fracture_crack"
-    bl_label = "Cell To Crack"
-    bl_description = "Make a cracked object from cell objects"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.active_object
-        return obj and obj.type == "MESH"
-
-    def invoke(self, context, event):
-        wm = context.window_manager
-        return wm.invoke_props_dialog(self, width=350)
-
-    def execute(self, context):
-        crack_props = context.window_manager.fracture_crack_props
-
-        cells = context.selected_editable_objects
-        object = None
-
-        if cells:
-            # clear sharp edges for correct crack surface.
-            bpy.context.view_layer.objects.active = cells[0]
-            bpy.ops.object.mode_set(mode='EDIT')
-            bpy.ops.mesh.reveal()
-
-            bpy.ops.mesh.mark_sharp(clear=True, use_verts=True)
-            bpy.ops.object.mode_set(mode='OBJECT')
-
-            for cell in cells:
-                bpy.context.view_layer.objects.active = cell
-                bpy.ops.object.modifier_remove(modifier="EDGE_SPLIT_cell")
-                bpy.context.object.vertex_groups.clear()
-
-            bpy.context.view_layer.objects.active = cells[0]
-            object = crack_functions.make_join(cells)
-
-        if object:
-            bpy.context.view_layer.objects.active = object
-
-            crack_functions.add_modifiers()
-            bpy.context.object.modifiers['DECIMATE_crackit'].ratio = crack_props.modifier_decimate
-            bpy.context.object.modifiers['SMOOTH_crackit'].factor = crack_props.modifier_smooth
-
-            crack_functions.multiExtrude(
-                off=0.1,
-                rotx=0, roty=0, rotz=0,
-                sca=crack_props.extrude_scale,
-                var1=crack_props.extrude_var, var2=crack_props.extrude_var, var3=crack_props.extrude_var,
-                num=crack_props.extrude_num, ran=0
-                )
-            bpy.ops.object.modifier_apply(apply_as='DATA', modifier='DECIMATE_crackit')
-            bpy.ops.object.shade_smooth()
-
-            if crack_props.modifier_wireframe == True:
-                bpy.ops.object.modifier_add(type='WIREFRAME')
-                wireframe = bpy.context.object.modifiers[-1]
-                wireframe.name = 'WIREFRAME_crackit'
-                wireframe.use_even_offset = False
-                wireframe.thickness = 0.01
-        else:
-            assert("Joining into One object had been failed. Mesh object can only be joined.")
-
-        return {'FINISHED'}
-
-    def draw(self, context):
-        cell_props = context.window_manager.fracture_cell_props
-        crack_props = context.window_manager.fracture_crack_props
-        layout = self.layout
-
-        box = layout.box()
-        col = box.column()
-        col.label(text='* Execute After "1. Cell Fracture"')
-
-        box = layout.box()
-        col = box.column()
-        col.label(text="Surface:")
-        row = col.row(align=True)
-        row.alignment = 'LEFT'
-        row.prop(crack_props, "modifier_decimate")
-        row.prop(crack_props, "modifier_smooth")
-
-        col = box.column()
-        col.label(text="Extrude:")
-        row = col.row(align=True)
-        row.prop(crack_props, "extrude_scale")
-        row.prop(crack_props, "extrude_var")
-        row.prop(crack_props, "extrude_num")
-
-        col = box.column()
-        col.label(text="Post Processing")
-        row = col.row(align=True)
-        row.prop(crack_props, "modifier_wireframe")
-
-
-class FRACTURE_OT_Material(Operator):
-    bl_idname = "object.add_fracture_material"
-    bl_label = "Material Preset"
-    bl_description = ("Material preset for cracked object")
-    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):
-        material_props = context.window_manager.fracture_material_props
-
-        mat_name = material_props.material_preset
-        mat_lib_name = material_props.material_lib_name
-        mat_ui_name = material_props.get_ui_mat_name(mat_name) if not mat_lib_name else mat_name
-
-        try:
-            material_functions.appendMaterial(
-                    mat_lib_name = mat_lib_name,
-                    mat_name = mat_name,
-                    mat_ui_names = mat_ui_name
-                    )
-        except Exception as e:
-            material_functions.error_handlers(
-                    self, "mesh.crackit_material", e,
-                    "The active Object could not have the Material {} applied".format(mat_ui_name)
-                    )
-            return {"CANCELLED"}
-
-        return {'FINISHED'}
\ No newline at end of file
diff --git a/object_fracture_cell/process/cell_calc.py b/object_fracture_cell/process/cell_calc.py
deleted file mode 100644
index 9541e5f57847ba1415483a3d91bd6d574b193a61..0000000000000000000000000000000000000000
--- a/object_fracture_cell/process/cell_calc.py
+++ /dev/null
@@ -1,149 +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 #####
-
-# <pep8 compliant>
-
-# Script copyright (C) Blender Foundation 2012
-
-
-def points_to_verts(original_xyz_minmax,
-                    points,
-                    points_scale=None,
-                    margin_bounds=0.05,
-                    margin_cell=0.0):
-
-    from math import sqrt
-    import mathutils
-    from mathutils import Vector
-
-    cells = []
-    plane_indices = []
-    vertices = []
-
-    if points_scale is not None:
-        points_scale = tuple(points_scale)
-    if points_scale == (1.0, 1.0, 1.0):
-        points_scale = None
-
-    # there are many ways we could get planes - convex hull for eg
-    # but it ends up fastest if we just use bounding box
-    if 1:
-        xmin, xmax = original_xyz_minmax["x"]
-        ymin, ymax = original_xyz_minmax["y"]
-        zmin, zmax = original_xyz_minmax["z"]
-
-        xmin -= margin_bounds
-        xmax += margin_bounds
-        ymin -= margin_bounds
-        ymax += margin_bounds
-        zmin -= margin_bounds
-        zmax += margin_bounds
-
-        # (x,y,z,scaler) for plane. xyz is normaliized direction. scaler is scale for plane.
-        # Plane will be made at the perpendicular direction of the normal vector.
-        convexPlanes = [
-            Vector((+1.0, 0.0, 0.0, -xmax)),
-            Vector((-1.0, 0.0, 0.0, +xmin)),
-            Vector((0.0, +1.0, 0.0, -ymax)),
-            Vector((0.0, -1.0, 0.0, +ymin)),
-            Vector((0.0, 0.0, +1.0, -zmax)),
-            Vector((0.0, 0.0, -1.0, +zmin)),
-            ]
-
-    if len(points) > 1:
-        points_dist_sorted = [(Vector(p[0]), p[1]) for p in points]
-
-        for i, point_current in enumerate(points):
-            planes = [None] * len(convexPlanes)
-            for j in range(len(convexPlanes)):
-                planes[j] = convexPlanes[j].copy()
-                # e.g. Dot product point's (xyz) with convex's (+1.0,0.0,0.0) detects x value of the point.
-                # e.g. Then, x scaler += point's x value.
-                planes[j][3] += planes[j].xyz.dot(point_current[0])
-
-            distance_max = 10000000000.0  # a big value!
-
-            points_dist_sorted_current = points_dist_sorted.copy()
-            # Closer points to the current point are earlier order. Of course, current point is the first.
-            points_dist_sorted_current.sort(key=lambda p: (p[0] - point_current[0]).length_squared)
-
-            # The point itself is removed.
-            points_dist_sorted_current.pop(0)
-
-            # Compare the current point with other points.
-            for j in range(len(points_dist_sorted_current)):
-
-                point_target = points_dist_sorted_current[j]
-                normal = 0
-                normal = point_target[0] - point_current[0]
-                nlength = normal.length # is sqrt(X^2+y^2+z^2).
-
-                if points_scale is not None:
-                    normal_alt = normal.copy()
-                    normal_alt.x *= points_scale[0]
-                    normal_alt.y *= points_scale[1]
-                    normal_alt.z *= points_scale[2]
-
-                    # -rotate plane to new distance
-                    # -should always be positive!! - but abs incase
-                    # Scale rate (normal_alt/normal). If these are the same, dot product is 1.
-                    scalar = normal_alt.normalized().dot(normal.normalized())
-                    # assert(scalar >= 0.0)
-                    nlength *= scalar
-                    normal = normal_alt
-
-                if nlength > distance_max:
-                    break
-
-                # 4D vector, the same form as convexPlanes. (x,y,z,scaler).
-                plane = normal.normalized()
-                plane.resize_4d()
-                plane[3] = (-nlength / 2.0) + margin_cell
-                planes.append(plane)
-
-                # Make vertex points of cell, by crossing point of planes.
-                vertices[:], plane_indices[:] = mathutils.geometry.points_in_planes(planes)
-                #if len(vertices) == 0:
-                #    break
-
-                if len(plane_indices) != len(planes):
-                    planes[:] = [planes[k] for k in plane_indices]
-
-                # for comparisons use length_squared and delay
-                # converting to a real length until the end.
-                distance_max = 10000000000.0  # a big value!
-                for v in vertices:
-                    distance = v.length_squared
-                    if distance_max < distance:
-                        distance_max = distance
-                distance_max = sqrt(distance_max)  # make real length ここでルートでマックスを下げているのか?でも下で2倍にしているが。
-                distance_max *= 2.0
-
-            if len(vertices) == 0:
-                continue
-
-            cells.append((point_current[0], vertices[:]))
-            del vertices[:]
-
-    else:
-        vertices[:], plane_indices[:] = mathutils.geometry.points_in_planes(convexPlanes)
-        #convex_center = Vector(((xmin-xmax)/2, (ymin-ymax)/2, (zmin-zmax)/2))
-        convex_center = Vector((0,0,0))
-        cells.append((convex_center, vertices[:]))
-
-    return cells
\ No newline at end of file
diff --git a/object_fracture_cell/process/cell_functions.py b/object_fracture_cell/process/cell_functions.py
deleted file mode 100644
index 026bdc534d4b28951ae09589219b12c94f20c476..0000000000000000000000000000000000000000
--- a/object_fracture_cell/process/cell_functions.py
+++ /dev/null
@@ -1,601 +0,0 @@
-import bpy
-import bmesh
-
-
-def _redraw_yasiamevil():
-    _redraw_yasiamevil.opr(**_redraw_yasiamevil.arg)
-_redraw_yasiamevil.opr = bpy.ops.wm.redraw_timer
-_redraw_yasiamevil.arg = dict(type='DRAW_WIN_SWAP', iterations=1)
-
-def _limit_source(points, source_limit):
-    if source_limit != 0 and source_limit < len(points):
-        import random
-        random.shuffle(points)
-        points[source_limit:] = []
-        return points
-    else:
-        return points
-
-
-def simplify_original(original, pre_simplify):
-    bpy.context.view_layer.objects.active = original
-    bpy.ops.object.modifier_add(type='DECIMATE')
-    decimate = bpy.context.object.modifiers[-1]
-    decimate.name = 'DECIMATE_crackit_original'
-    decimate.ratio = 1-pre_simplify
-
-def desimplify_original(original):
-    bpy.context.view_layer.objects.active = original
-    if 'DECIMATE_crackit_original' in bpy.context.object.modifiers.keys():
-        bpy.ops.object.modifier_remove(modifier='DECIMATE_crackit_original')
-
-def original_minmax(original_verts):
-    xa = [v[0] for v in original_verts]
-    ya = [v[1] for v in original_verts]
-    za = [v[2] for v in original_verts]
-    xmin, xmax = min(xa), max(xa)
-    ymin, ymax = min(ya), max(ya)
-    zmin, zmax = min(za), max(za)
-    return {"x":(xmin,xmax), "y":(ymin,ymax), "z":(zmin,zmax)}
-
-def points_from_object(original, original_xyz_minmax,
-                       source_vert_own=100,
-                       source_vert_child=0,
-                       source_particle_own=0,
-                       source_particle_child=0,
-                       source_pencil=0,
-                       source_random=0):
-
-    points = []
-
-    # This is not used by anywhere
-    def edge_center(mesh, edge):
-        v1, v2 = edge.vertices
-        return (mesh.vertices[v1].co + mesh.vertices[v2].co) / 2.0
-
-    # This is not used by anywhere
-    def poly_center(mesh, poly):
-        from mathutils import Vector
-        co = Vector()
-        tot = 0
-        for i in poly.loop_indices:
-            co += mesh.vertices[mesh.loops[i].vertex_index].co
-            tot += 1
-        return co / tot
-
-    def points_from_verts(original):
-        """Takes points from _any_ object with geometry"""
-        if original.type == 'MESH':
-            mesh = original.data
-            matrix = original.matrix_world.copy()
-            p = [(matrix @ v.co, 'VERTS') for v in mesh.vertices]
-            return p
-        else:
-            depsgraph = bpy.context.evaluated_depsgraph_get()
-            ob_eval = original.evaluated_get(depsgraph)
-            try:
-                mesh = ob_eval.to_mesh()
-            except:
-                mesh = None
-
-            if mesh is not None:
-                matrix = original.matrix_world.copy()
-                p =  [(matrix @ v.co, 'VERTS') for v in mesh.vertices]
-                ob_eval.to_mesh_clear()
-                return p
-
-    def points_from_particles(original):
-        depsgraph = bpy.context.evaluated_depsgraph_get()
-        obj_eval = original.evaluated_get(depsgraph)
-
-        p = [(particle.location.copy(), 'PARTICLE')
-               for psys in obj_eval.particle_systems
-               for particle in psys.particles]
-        return p
-
-    def points_from_random(original, original_xyz_minmax):
-        xmin, xmax = original_xyz_minmax["x"]
-        ymin, ymax = original_xyz_minmax["y"]
-        zmin, zmax = original_xyz_minmax["z"]
-
-        from random import uniform
-        from mathutils import Vector
-
-        p = []
-        for i in range(source_random):
-            new_pos = Vector( (uniform(xmin, xmax), uniform(ymin, ymax), uniform(zmin, zmax)) )
-            p.append((new_pos, 'RANDOM'))
-        return p
-
-     # geom own
-    if source_vert_own > 0:
-        new_points = points_from_verts(original)
-        new_points = _limit_source(new_points, source_vert_own)
-        points.extend(new_points)
-
-    # random
-    if source_random > 0:
-        new_points = points_from_random(original, original_xyz_minmax)
-        points.extend(new_points)
-
-
-    # geom children
-    if source_vert_child > 0:
-        for original_child in original.children:
-            new_points  = points_from_verts(original_child)
-            new_points = _limit_source(new_points, source_vert_child)
-            points.extend(new_points)
-
-    # geom particles
-    if source_particle_own > 0:
-        new_points = points_from_particles(original)
-        new_points = _limit_source(new_points, source_particle_own)
-        points.extend(new_points)
-
-    if source_particle_child > 0:
-        for original_child in original.children:
-            new_points = points_from_particles(original_child)
-            new_points = _limit_source(new_points, source_particle_child)
-            points.extend(new_points)
-
-    # grease pencil
-    def get_points(stroke):
-        return [point.co.copy() for point in stroke.points]
-
-    def get_splines(gp):
-        gpl = gp.layers.active
-        if gpl:
-            fr = gpl.active_frame
-            if not fr:
-                current = bpy.context.scene.frame_current
-                gpl.frames.new(current)
-                gpl.active_frame = current
-                fr = gpl.active_frame
-
-            return [get_points(stroke) for stroke in fr.strokes]
-        else:
-            return []
-
-    if source_pencil > 0:
-        gp = bpy.context.scene.grease_pencil
-        if gp:
-            line_points = []
-            line_points = [(p, 'PENCIL') for spline in get_splines(gp)
-                             for p in spline]
-            if len(line_points) > 0:
-                line_points = _limit_source(line_points, source_pencil)
-
-                # Make New point between the line point and the closest point.
-                if not points:
-                    points.extend(line_points)
-
-                else:
-                    for lp in line_points:
-                        # Make vector between the line point and its closest point.
-                        points.sort(key=lambda p: (p[0] - lp[0]).length_squared)
-                        closest_point = points[0]
-                        normal = lp[0].xyz - closest_point[0].xyz
-
-                        new_point = (lp[0], lp[1])
-                        new_point[0].xyz +=  normal / 2
-
-                        points.append(new_point)
-    #print("Found %d points" % len(points))
-    return points
-
-
-def points_to_cells(context, original, original_xyz_minmax, points,
-                    source_limit=0,
-                    source_noise=0.0,
-                    use_smooth_faces=False,
-                    use_data_match=False,
-                    use_debug_points=False,
-                    margin=0.0,
-                    material_index=0,
-                    use_debug_redraw=False,
-                    cell_scale=(1.0, 1.0, 1.0),
-                    clean=True):
-
-    from . import cell_calc
-    collection = context.collection
-    view_layer = context.view_layer
-
-    # apply optional clamp
-    if source_limit != 0 and source_limit < len(points):
-        points = _limit_source(points, source_limit)
-
-    # saddly we cant be sure there are no doubles
-    from mathutils import Vector
-    to_tuple = Vector.to_tuple
-
-    # To remove doubles, round the values.
-    points = [(Vector(to_tuple(p[0], 4)),p[1]) for p in points]
-    del to_tuple
-    del Vector
-
-    if source_noise > 0.0:
-        from random import random
-        # boundbox approx of overall scale
-        from mathutils import Vector
-        matrix = original.matrix_world.copy()
-        bb_world = [matrix @ Vector(v) for v in original.bound_box]
-        scalar = source_noise * ((bb_world[0] - bb_world[6]).length / 2.0)
-
-        from mathutils.noise import random_unit_vector
-        points[:] = [(p[0] + (random_unit_vector() * (scalar * random())), p[1]) for p in points]
-
-    if use_debug_points:
-        bm = bmesh.new()
-        for p in points:
-            bm.verts.new(p[0])
-        mesh_tmp = bpy.data.meshes.new(name="DebugPoints")
-        bm.to_mesh(mesh_tmp)
-        bm.free()
-        obj_tmp = bpy.data.objects.new(name=mesh_tmp.name, object_data=mesh_tmp)
-        collection.objects.link(obj_tmp)
-        del obj_tmp, mesh_tmp
-
-    cells_verts = cell_calc.points_to_verts(original_xyz_minmax,
-                                            points,
-                                            cell_scale,
-                                            margin_cell=margin)
-    # some hacks here :S
-    cell_name = original.name + "_cell"
-    cells = []
-    for center_point, cell_verts in cells_verts:
-        # ---------------------------------------------------------------------
-        # BMESH
-        # create the convex hulls
-        bm = bmesh.new()
-
-        # WORKAROUND FOR CONVEX HULL BUG/LIMIT
-        # XXX small noise
-        import random
-        def R():
-            return (random.random() - 0.5) * 0.001
-
-        for i, co in enumerate(cell_verts):
-            co.x += R()
-            co.y += R()
-            co.z += R()
-            bm_vert = bm.verts.new(co)
-
-        import mathutils
-        bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.005)
-        try:
-            # Making cell meshes as convex full here!
-            bmesh.ops.convex_hull(bm, input=bm.verts)
-        except RuntimeError:
-            import traceback
-            traceback.print_exc()
-
-        if clean:
-            bm.normal_update()
-            try:
-                bmesh.ops.dissolve_limit(bm, verts=bm.verts, angle_limit=0.001)
-            except RuntimeError:
-                import traceback
-                traceback.print_exc()
-        # smooth faces will remain only inner faces, after appling boolean modifier.
-        if use_smooth_faces:
-            for bm_face in bm.faces:
-                bm_face.smooth = True
-
-        if material_index != 0:
-            for bm_face in bm.faces:
-                bm_face.material_index = material_index
-
-        # ---------------------------------------------------------------------
-        # MESH
-        mesh_dst = bpy.data.meshes.new(name=cell_name)
-
-        bm.to_mesh(mesh_dst)
-        bm.free()
-        del bm
-
-        if use_data_match:
-            # match materials and data layers so boolean displays them
-            # currently only materials + data layers, could do others...
-            mesh_src = original.data
-            for mat in mesh_src.materials:
-                mesh_dst.materials.append(mat)
-            for lay_attr in ("vertex_colors", "uv_layers"):
-                lay_src = getattr(mesh_src, lay_attr)
-                lay_dst = getattr(mesh_dst, lay_attr)
-                for key in lay_src.keys():
-                    lay_dst.new(name=key)
-
-        # ---------------------------------------------------------------------
-        # OBJECT
-        cell = bpy.data.objects.new(name=cell_name, object_data=mesh_dst)
-        collection.objects.link(cell)
-        cell.location = center_point
-        cells.append(cell)
-
-        # support for object materials
-        if use_data_match:
-            for i in range(len(mesh_dst.materials)):
-                slot_src = original.material_slots[i]
-                slot_dst = cell.material_slots[i]
-
-                slot_dst.link = slot_src.link
-                slot_dst.material = slot_src.material
-
-        if use_debug_redraw:
-            view_layer.update()
-            _redraw_yasiamevil()
-
-    view_layer.update()
-    # move this elsewhere...
-    # Blender 2.8: BGE integration was disabled, --
-    # -- because BGE was deleted in Blender 2.8.
-    '''
-    for cell in cells:
-        game = cell.game
-        game.physics_type = 'RIGID_BODY'
-        game.use_collision_bounds = True
-        game.collision_bounds_type = 'CONVEX_HULL'
-    '''
-    return cells
-
-
-def cell_boolean(context, original, cells,
-                use_debug_bool=False,
-                clean=True,
-                use_island_split=False,
-                use_interior_hide=False,
-                use_debug_redraw=False,
-                level=0,
-                remove_doubles=True
-                ):
-
-    cells_boolean = []
-    collection = context.collection
-    scene = context.scene
-    view_layer = context.view_layer
-
-    if use_interior_hide and level == 0:
-        # only set for level 0
-        original.data.polygons.foreach_set("hide", [False] * len(original.data.polygons))
-
-    # The first object can't be applied by bool, so it is used as a no-effect first straw-man.
-    bpy.ops.mesh.primitive_cube_add(enter_editmode=False, location=(original.location.x+10000000000.0, 0, 0))
-    temp_cell = bpy.context.active_object
-    cells.insert(0, temp_cell)
-
-    bpy.ops.object.select_all(action='DESELECT')
-    for i, cell in enumerate(cells):
-        mod = cell.modifiers.new(name="Boolean", type='BOOLEAN')
-        mod.object = original
-        mod.operation = 'INTERSECT'
-
-        if not use_debug_bool:
-            if use_interior_hide:
-                cell.data.polygons.foreach_set("hide", [True] * len(cell.data.polygons))
-
-            # mesh_old should be made before appling boolean modifier.
-            mesh_old = cell.data
-
-            original.select_set(True)
-            cell.select_set(True)
-            bpy.context.view_layer.objects.active = cell
-            bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
-
-            if i == 0:
-                bpy.data.objects.remove(cell, do_unlink=True)
-                continue
-
-            cell = bpy.context.active_object
-            cell.select_set(False)
-
-            # depsgraph sould be gotten after applied boolean modifier, for new_mesh.
-            depsgraph = context.evaluated_depsgraph_get()
-            cell_eval = cell.evaluated_get(depsgraph)
-
-            mesh_new = bpy.data.meshes.new_from_object(cell_eval)
-            cell.data = mesh_new
-
-            '''
-            check_hide = [11] * len(cell.data.polygons)
-            cell.data.polygons.foreach_get("hide", check_hide)
-            print(check_hide)
-            '''
-
-            # remove if not valid
-            if not mesh_old.users:
-                bpy.data.meshes.remove(mesh_old)
-            if not mesh_new.vertices:
-                collection.objects.unlink(cell)
-                if not cell.users:
-                    bpy.data.objects.remove(cell)
-                    cell = None
-                    if not mesh_new.users:
-                        bpy.data.meshes.remove(mesh_new)
-                        mesh_new = None
-
-            # avoid unneeded bmesh re-conversion
-            if mesh_new is not None:
-                bm = None
-
-                if clean:
-                    if bm is None:  # ok this will always be true for now...
-                        bm = bmesh.new()
-                        bm.from_mesh(mesh_new)
-                    bm.normal_update()
-                    try:
-                        bmesh.ops.dissolve_limit(bm, verts=bm.verts, edges=bm.edges, angle_limit=0.001)
-                    except RuntimeError:
-                        import traceback
-                        traceback.print_exc()
-
-                if remove_doubles:
-                    if bm is None:
-                        bm = bmesh.new()
-                        bm.from_mesh(mesh_new)
-                    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.005)
-
-                if bm is not None:
-                    bm.to_mesh(mesh_new)
-                    bm.free()
-
-            del mesh_new
-            del mesh_old
-
-        if cell is not None:
-            cells_boolean.append(cell)
-
-            if use_debug_redraw:
-                _redraw_yasiamevil()
-
-    bpy.context.view_layer.objects.active = original
-
-    if (not use_debug_bool) and use_island_split:
-        # this is ugly and Im not proud of this - campbell
-        for ob in view_layer.objects:
-            ob.select_set(False)
-        for cell in cells_boolean:
-            cell.select_set(True)
-        # If new separated meshes are made, selected objects is increased.
-        if cells_boolean:
-            bpy.ops.mesh.separate(type='LOOSE')
-
-        cells_boolean[:] = [cell for cell in scene.objects if cell.select_get()]
-
-    context.view_layer.update()
-    return cells_boolean
-
-
-def interior_handle(cells,
-                    use_interior_vgroup=False,
-                    use_sharp_edges=False,
-                    use_sharp_edges_apply=False,
-                    ):
-    """Run after doing _all_ booleans"""
-
-    assert(use_interior_vgroup or use_sharp_edges or use_sharp_edges_apply)
-
-    for cell in cells:
-        mesh = cell.data
-        bm = bmesh.new()
-        bm.from_mesh(mesh)
-
-        if use_interior_vgroup:
-            for bm_vert in bm.verts:
-                bm_vert.tag = True
-            for bm_face in bm.faces:
-                if not bm_face.hide:
-                    for bm_vert in bm_face.verts:
-                        bm_vert.tag = False
-
-            # now add all vgroups
-            defvert_lay = bm.verts.layers.deform.verify()
-            for bm_vert in bm.verts:
-                if bm_vert.tag:
-                    bm_vert[defvert_lay][0] = 1.0
-
-            # add a vgroup
-            cell.vertex_groups.new(name="Interior")
-
-        if use_sharp_edges:
-            bpy.context.space_data.overlay.show_edge_sharp = True
-
-            for bm_edge in bm.edges:
-                if len({bm_face.hide for bm_face in bm_edge.link_faces}) == 2:
-                    bm_edge.smooth = False
-
-            if use_sharp_edges_apply:
-                bpy.context.view_layer.objects.active = cell
-                bpy.ops.object.modifier_add(type='EDGE_SPLIT')
-
-                edge_split = bpy.context.object.modifiers[-1]
-                edge_split.name = 'EDGE_SPLIT_cell'
-                edge_split.use_edge_angle = False
-
-                '''
-                edges = [edge for edge in bm.edges if edge.smooth is False]
-                if edges:
-                    bm.normal_update()
-                    bmesh.ops.split_edges(bm, edges=edges)
-                '''
-
-        for bm_face in bm.faces:
-            bm_face.hide = False
-
-        bm.to_mesh(mesh)
-        bm.free()
-
-
-def post_process(cells,
-                use_collection=False,
-                new_collection=False,
-                collection_name="Fracture",
-                use_mass=False,
-                mass=1.0,
-                mass_mode='VOLUME', mass_name='mass',
-                ):
-
-    """Run after Interiro handle"""
-    #--------------
-    # Collection Options
-    if use_collection:
-        colle = None
-        if not new_collection:
-            colle = bpy.data.collections.get(collection_name)
-
-        if colle is None:
-            colle = bpy.data.collections.new(collection_name)
-
-        # THe collection should be children of master collection to show in outliner.
-        child_names = [m.name for m in bpy.context.scene.collection.children]
-        if colle.name not in child_names:
-            bpy.context.scene.collection.children.link(colle)
-
-        # Cell objects are only link to the collection.
-        bpy.ops.collection.objects_remove_all() # For all selected object.
-        for colle_obj in cells:
-            colle.objects.link(colle_obj)
-
-    #--------------
-    # Mass Options
-    if use_mass:
-        # Blender 2.8:  Mass for BGE was no more available.--
-        # -- Instead, Mass values is used for custom properies on cell objects.
-        if mass_mode == 'UNIFORM':
-            for cell in cells:
-                #cell.game.mass = mass
-                cell[mass_name] = mass
-        elif mass_mode == 'VOLUME':
-            from mathutils import Vector
-            def _get_volume(cell):
-                def _getObjectBBMinMax():
-                    min_co = Vector((1000000.0, 1000000.0, 1000000.0))
-                    max_co = -min_co
-                    matrix = cell.matrix_world
-                    for i in range(0, 8):
-                        bb_vec = cell.matrix_world @ Vector(cell.bound_box[i])
-                        min_co[0] = min(bb_vec[0], min_co[0])
-                        min_co[1] = min(bb_vec[1], min_co[1])
-                        min_co[2] = min(bb_vec[2], min_co[2])
-                        max_co[0] = max(bb_vec[0], max_co[0])
-                        max_co[1] = max(bb_vec[1], max_co[1])
-                        max_co[2] = max(bb_vec[2], max_co[2])
-                    return (min_co, max_co)
-
-                def _getObjectVolume():
-                    min_co, max_co = _getObjectBBMinMax()
-                    x = max_co[0] - min_co[0]
-                    y = max_co[1] - min_co[1]
-                    z = max_co[2] - min_co[2]
-                    volume = x * y * z
-                    return volume
-
-                return _getObjectVolume()
-
-            cell_volume_ls = [_get_volume(cell) for cell in cells]
-            cell_volume_tot = sum(cell_volume_ls)
-            if cell_volume_tot > 0.0:
-                mass_fac = mass / cell_volume_tot
-                for i, cell in enumerate(cells):
-                    cell[mass_name] = cell_volume_ls[i] * mass_fac
-        else:
-            assert(0)
\ No newline at end of file
diff --git a/object_fracture_cell/process/cell_main.py b/object_fracture_cell/process/cell_main.py
deleted file mode 100644
index eefa18c9d11b785267ebb0436a49623592f59e75..0000000000000000000000000000000000000000
--- a/object_fracture_cell/process/cell_main.py
+++ /dev/null
@@ -1,208 +0,0 @@
-if "bpy" in locals():
-    import importlib
-    importlib.reload(cell_functions)
-
-else:
-    from . import cell_functions
-
-import bpy
-
-
-def main_object(context, original, level, **kw):
-    import random
-
-    # pull out some args
-    kw_copy = kw.copy()
-    source_vert_own = kw_copy.pop("source_vert_own")
-    source_vert_child = kw_copy.pop("source_vert_child")
-    source_particle_own = kw_copy.pop("source_particle_own")
-    source_particle_child = kw_copy.pop("source_particle_child")
-    source_pencil = kw_copy.pop("source_pencil")
-    source_random = kw_copy.pop("source_random")
-
-    use_recenter = kw_copy.pop("use_recenter")
-    recursion = kw_copy.pop("recursion")
-    recursion_source_limit = kw_copy.pop("recursion_source_limit")
-    recursion_clamp = kw_copy.pop("recursion_clamp")
-    recursion_chance = kw_copy.pop("recursion_chance")
-    recursion_chance_select = kw_copy.pop("recursion_chance_select")
-    use_island_split = kw_copy.pop("use_island_split")
-    use_debug_bool = kw_copy.pop("use_debug_bool")
-    use_interior_vgroup = kw_copy.pop("use_interior_vgroup")
-    use_sharp_edges = kw_copy.pop("use_sharp_edges")
-    use_sharp_edges_apply = kw_copy.pop("use_sharp_edges_apply")
-
-    cell_relocate = kw_copy.pop("cell_relocate")
-
-    collection = context.collection
-    scene = context.scene
-
-    if level != 0:
-        kw_copy["source_limit"] = recursion_source_limit
-
-    from . import cell_functions
-
-    # not essential but selection is visual distraction.
-    original.select_set(False)
-
-    if kw_copy["use_debug_redraw"]:
-        original_display_type_prev = original.display_type
-        original.display_type = 'WIRE'
-
-    original_mesh = original.data
-    original_matrix = original.matrix_world.copy()
-    original_verts = [original_matrix @ v.co for v in original_mesh.vertices]
-    original_xyz_minmax = cell_functions.original_minmax(original_verts)
-
-    cells = []
-    points = cell_functions.points_from_object(original, original_xyz_minmax,
-                                               source_vert_own=source_vert_own,
-                                               source_vert_child=source_vert_child,
-                                               source_particle_own=source_particle_own,
-                                               source_particle_child=source_particle_child,
-                                               source_pencil=source_pencil,
-                                               source_random=source_random)
-
-    cells = cell_functions.points_to_cells(context, original, original_xyz_minmax, points, **kw_copy)
-    cells = cell_functions.cell_boolean(context, original, cells,
-                                        use_island_split=use_island_split,
-                                        use_interior_hide=(use_interior_vgroup or use_sharp_edges),
-                                        use_debug_bool=use_debug_bool,
-                                        use_debug_redraw=kw_copy["use_debug_redraw"],
-                                        level=level,
-                                        )
-
-    # must apply after boolean.
-    if use_recenter:
-        bpy.ops.object.origin_set({"selected_editable_objects": cells},
-                                  type='ORIGIN_GEOMETRY', center='MEDIAN')
-
-    #--------------
-    # Recursion.
-    if level == 0:
-        for level_sub in range(1, recursion + 1):
-
-            objects_recurse_input = [(i, o) for i, o in enumerate(cells)]
-            if recursion_chance != 1.0:
-                from mathutils import Vector
-                if recursion_chance_select == 'RANDOM':
-                    random.shuffle(objects_recurse_input)
-                elif recursion_chance_select in {'SIZE_MIN', 'SIZE_MAX'}:
-                    objects_recurse_input.sort(key=lambda ob_pair:
-                        (Vector(ob_pair[1].bound_box[0]) -
-                         Vector(ob_pair[1].bound_box[6])).length_squared)
-                    if recursion_chance_select == 'SIZE_MAX':
-                        objects_recurse_input.reverse()
-                elif recursion_chance_select in {'CURSOR_MIN', 'CURSOR_MAX'}:
-                    c = scene.cursor.location.copy()
-                    objects_recurse_input.sort(key=lambda ob_pair:
-                        (ob_pair[1].location - c).length_squared)
-                    if recursion_chance_select == 'CURSOR_MAX':
-                        objects_recurse_input.reverse()
-
-                objects_recurse_input[int(recursion_chance * len(objects_recurse_input)):] = []
-                objects_recurse_input.sort()
-
-            # reverse index values so we can remove from original list.
-            objects_recurse_input.reverse()
-
-            objects_recursive = []
-            for i, obj_cell in objects_recurse_input:
-                assert(cells[i] is obj_cell)
-                # Repeat main_object() here.
-                objects_recursive += main_object(context, obj_cell, level_sub, **kw)
-                #if original_remove:
-                collection.objects.unlink(obj_cell)
-                del cells[i]
-                if recursion_clamp and len(cells) + len(objects_recursive) >= recursion_clamp:
-                    break
-            cells.extend(objects_recursive)
-
-            if recursion_clamp and len(cells) > recursion_clamp:
-                break
-
-    #--------------
-    # Level Options
-    if level == 0:
-        # import pdb; pdb.set_trace()
-        if use_interior_vgroup or use_sharp_edges:
-            cell_functions.interior_handle(cells,
-                                           use_interior_vgroup=use_interior_vgroup,
-                                           use_sharp_edges=use_sharp_edges,
-                                           use_sharp_edges_apply=use_sharp_edges_apply,
-                                           )
-
-    if cell_relocate:
-        for cell in cells:
-            cell.location.x += (original_xyz_minmax["x"][1] - original_xyz_minmax["x"][0]) + 1
-
-    if kw_copy["use_debug_redraw"]:
-        original.display_type = original_display_type_prev
-
-    return cells
-
-
-def main(context, original, **kw):
-    '''
-    import time
-    t = time.time()
-    '''
-
-    kw_copy = kw.copy()
-
-    # Pre_Simplify
-    pre_simplify = kw_copy.pop("pre_simplify")
-    # collection
-    use_collection = kw_copy.pop("use_collection")
-    new_collection = kw_copy.pop("new_collection")
-    collection_name = kw_copy.pop("collection_name")
-    # object visibility
-    original_hide = kw_copy.pop("original_hide")
-    # mass
-    use_mass = kw_copy.pop("use_mass")
-    mass_name = kw_copy.pop("mass_name")
-    mass_mode = kw_copy.pop("mass_mode")
-    mass = kw_copy.pop("mass")
-
-    cells = []
-
-    if original.type == 'MESH':
-        if pre_simplify > 0.0:
-            cell_functions.simplify_original(original=original, pre_simplify=pre_simplify)
-
-        cells += main_object(context, original, 0, **kw_copy)
-
-        if pre_simplify > 0.0:
-            cell_functions.desimplify_original(original=original)
-    else:
-        assert obj.type == 'MESH', "No MESH object selected."
-
-    bpy.ops.object.select_all(action='DESELECT')
-
-    for cell in cells:
-        cell.select_set(True)
-
-    cell_functions.post_process(cells,
-                                use_collection=use_collection,
-                                new_collection=new_collection,
-                                collection_name=collection_name,
-                                use_mass=use_mass,
-                                mass=mass,
-                                mass_mode=mass_mode,
-                                mass_name=mass_name,
-                                )
-
-    # To avoid select both original object and cells in EDIT mode.
-    bpy.context.view_layer.objects.active = cells[0]
-
-    # de-hide all objects and meshes.
-    bpy.ops.object.mode_set(mode='EDIT')
-    bpy.ops.mesh.reveal()
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    if original_hide:
-        original.hide_set(True)
-
-    #print("Done! %d objects in %.4f sec" % (len(cells), time.time() - t))
-    #print("Done!")
-    return (original, cells)
\ No newline at end of file
diff --git a/object_fracture_cell/process/crack_functions.py b/object_fracture_cell/process/crack_functions.py
deleted file mode 100644
index ffc513b620cd686a97159dd4ba2ef20ae0ddc44c..0000000000000000000000000000000000000000
--- a/object_fracture_cell/process/crack_functions.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# gpl: author Nobuyuki Hirakata
-
-import bpy
-
-import bmesh
-from random import (
-        gauss,
-        seed,
-        )
-from math import radians, pi
-from mathutils import Euler
-
-
-# Join fractures into an object
-def make_join(cells):
-
-    # Execute join
-    bpy.context.view_layer.objects.active = cells[0]
-    cells[0].select_set(state=True)
-    bpy.ops.object.join()
-
-    bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')
-
-    joined = bpy.context.active_object
-
-    suffix_index = joined.name.rfind("_cell")
-    if suffix_index != -1:
-        joined.name = joined.name[:suffix_index] + "_crack"
-
-    return bpy.context.active_object
-
-
-# Add modifier and setting
-def add_modifiers(decimate_val=0.4, smooth_val=0.5):
-    bpy.ops.object.modifier_add(type='DECIMATE')
-    decimate = bpy.context.object.modifiers[-1]
-    decimate.name = 'DECIMATE_crackit'
-    decimate.ratio = decimate_val
-
-    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'
-    smooth.factor = smooth_val
-
-
-# -------------- multi extrude --------------------
-# var1=random offset, var2=random rotation, var3=random scale
-def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=0.0,
-                var1=0.01, var2=0.01, var3=0.01, 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]
-'''
diff --git a/object_fracture_cell/process/material_functions.py b/object_fracture_cell/process/material_functions.py
deleted file mode 100644
index a2b2d80341f4c6e8a51ffe6825b1ebfcaf91b0a2..0000000000000000000000000000000000000000
--- a/object_fracture_cell/process/material_functions.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# gpl: author Nobuyuki Hirakata
-
-import bpy
-import os
-
-
-# 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
-
-
-# error_type='ERROR' for popup massage
-def error_handlers(self, op_name, error, reports="ERROR", func=False, error_type='WARNING'):
-    if self and reports:
-        self.report({error_type}, 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))
-
-
-def appendMaterial(mat_lib_name, mat_name, mat_ui_names="Nameless Material"):
-    file_path = _makeFilePath(os.path.dirname(__file__))
-    bpy.ops.wm.append(filename=mat_name, directory=file_path)
-
-    # If material is loaded some times, select the last-loaded material
-    last_material = _getAppendedMaterial(mat_name)
-
-    if last_material:
-        mat = bpy.data.materials[last_material]
-        # skip renaming if the prop is True
-        if not mat_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
diff --git a/object_fracture_cell/process/materials/materials1.blend b/object_fracture_cell/process/materials/materials1.blend
deleted file mode 100644
index df865ee87056b972ccee393db54364d8cab3298e..0000000000000000000000000000000000000000
Binary files a/object_fracture_cell/process/materials/materials1.blend and /dev/null differ
diff --git a/object_fracture_cell/utilities.py b/object_fracture_cell/utilities.py
deleted file mode 100644
index 0e87a967e713e3ded0fa54dd24ffa9776ef96bae..0000000000000000000000000000000000000000
--- a/object_fracture_cell/utilities.py
+++ /dev/null
@@ -1,42 +0,0 @@
-
-def _cell_props_to_dict(fracture_cell_props):
-    cell_keywords = {
-        'source_vert_own': fracture_cell_props.source_vert_own,
-        'source_vert_child': fracture_cell_props.source_vert_child,
-        'source_particle_own': fracture_cell_props.source_particle_own,
-        'source_particle_child': fracture_cell_props.source_particle_child,
-        'source_pencil': fracture_cell_props.source_pencil,
-        'source_random': fracture_cell_props.source_random,
-        'source_noise': fracture_cell_props.source_noise,
-        'margin': fracture_cell_props.margin,
-        'cell_scale': fracture_cell_props.cell_scale,
-        'pre_simplify': fracture_cell_props.pre_simplify,
-        'use_recenter': fracture_cell_props.use_recenter,
-        'use_island_split': fracture_cell_props.use_island_split,
-        'recursion': fracture_cell_props.recursion,
-        'recursion_source_limit': fracture_cell_props.recursion_source_limit,
-        'recursion_clamp': fracture_cell_props.recursion_clamp,
-        'recursion_chance': fracture_cell_props.recursion_chance,
-        'recursion_chance_select': fracture_cell_props.recursion_chance_select,
-        'use_smooth_faces': fracture_cell_props.use_smooth_faces,
-        'use_sharp_edges': fracture_cell_props.use_sharp_edges,
-        'use_sharp_edges_apply': fracture_cell_props.use_sharp_edges_apply,
-        'use_data_match': fracture_cell_props.use_data_match,
-        'material_index': fracture_cell_props.material_index,
-        'use_interior_vgroup': fracture_cell_props.use_interior_vgroup,
-
-        'use_collection': fracture_cell_props.use_collection,
-        'new_collection': fracture_cell_props.new_collection,
-        'collection_name': fracture_cell_props.collection_name,
-        'original_hide': fracture_cell_props.original_hide,
-        'cell_relocate': fracture_cell_props.cell_relocate,
-        'use_mass': fracture_cell_props.use_mass,
-        'mass_name': fracture_cell_props.mass_name,
-        'mass_mode': fracture_cell_props.mass_mode,
-        'mass': fracture_cell_props.mass,
-
-        'use_debug_points': fracture_cell_props.use_debug_points,
-        'use_debug_redraw': fracture_cell_props.use_debug_redraw,
-        'use_debug_bool': fracture_cell_props.use_debug_bool
-    }
-    return cell_keywords
diff --git a/object_fracture_crack/__init__.py b/object_fracture_crack/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e3ec838fd82061ef527d089fe43d76e3f984345
--- /dev/null
+++ b/object_fracture_crack/__init__.py
@@ -0,0 +1,148 @@
+# ##### 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()
diff --git a/object_fracture_crack/crack_it.py b/object_fracture_crack/crack_it.py
new file mode 100644
index 0000000000000000000000000000000000000000..68857908b1e39b8bbce1e9952f5dc9e27cd83ca9
--- /dev/null
+++ b/object_fracture_crack/crack_it.py
@@ -0,0 +1,255 @@
+# 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
diff --git a/object_fracture_crack/materials/materials1.blend b/object_fracture_crack/materials/materials1.blend
new file mode 100644
index 0000000000000000000000000000000000000000..969f2068412dd5be9c815932df96d0ccba45cac2
Binary files /dev/null and b/object_fracture_crack/materials/materials1.blend differ
diff --git a/object_fracture_crack/operator.py b/object_fracture_crack/operator.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0dbc5fdee6199500fed407dd12e877404347d4b
--- /dev/null
+++ b/object_fracture_crack/operator.py
@@ -0,0 +1,164 @@
+# 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)