634 lines
23 KiB
Python
634 lines
23 KiB
Python
import bpy
|
|
|
|
|
|
import bmesh
|
|
|
|
from ..constants import COMPONENT_OUTPUT_NODES
|
|
from ..utils import get_cache_dir, get_use_link, select_object
|
|
from ..bioxel.io import load_container, save_container
|
|
from ..bioxelutils.container import container_to_obj, obj_to_container
|
|
from ..bioxelutils.node import add_node_to_graph
|
|
from ..bioxelutils.common import (get_container_layer_objs, get_container_obj, get_node_type,
|
|
get_nodes_by_type, get_output_node, is_missing_layer,
|
|
move_node_between_nodes,
|
|
move_node_to_node,
|
|
get_all_layer_objs)
|
|
from .layer import RemoveLayers, SaveLayersCache
|
|
|
|
|
|
class SaveContainer(bpy.types.Operator):
|
|
bl_idname = "bioxelnodes.save_container"
|
|
bl_label = "Save Container (.bioxel) (BETA)"
|
|
bl_description = "Clean all caches saved in temp"
|
|
|
|
filepath: bpy.props.StringProperty(
|
|
subtype="FILE_PATH"
|
|
) # type: ignore
|
|
|
|
filename_ext = ".bioxel"
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
container = obj_to_container(container_obj)
|
|
save_path = f"{self.filepath.split('.')[0]}.bioxel"
|
|
save_container(container, save_path, overwrite=True)
|
|
|
|
self.report({"INFO"}, f"Successfully save to {save_path}")
|
|
return {'FINISHED'}
|
|
|
|
def invoke(self, context, event):
|
|
context.window_manager.fileselect_add(self)
|
|
return {'RUNNING_MODAL'}
|
|
|
|
|
|
class LoadContainer(bpy.types.Operator):
|
|
bl_idname = "bioxelnodes.load_container"
|
|
bl_label = "Load Container (.bioxel) (BETA)"
|
|
bl_description = "Clean all caches saved in temp"
|
|
|
|
filepath: bpy.props.StringProperty(
|
|
subtype="FILE_PATH"
|
|
) # type: ignore
|
|
|
|
filename_ext = ".bioxel"
|
|
|
|
def execute(self, context):
|
|
load_path = self.filepath
|
|
container = load_container(self.filepath)
|
|
is_first_import = len(get_all_layer_objs()) == 0
|
|
|
|
container_obj = container_to_obj(container,
|
|
scene_scale=0.01,
|
|
cache_dir=get_cache_dir())
|
|
select_object(container_obj)
|
|
|
|
if is_first_import:
|
|
bpy.ops.bioxelnodes.render_setting_preset('EXEC_DEFAULT',
|
|
preset="preview_c")
|
|
|
|
self.report({"INFO"}, f"Successfully load {load_path}")
|
|
return {'FINISHED'}
|
|
|
|
def invoke(self, context, event):
|
|
context.window_manager.fileselect_add(self)
|
|
return {'RUNNING_MODAL'}
|
|
|
|
|
|
class ExtractNodeObject():
|
|
bl_options = {'UNDO'}
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
# nodes = [node for node in context.selected_nodes
|
|
# if get_node_type(node).removeprefix("BioxelNodes_") in COMPONENT_OUTPUT_NODES]
|
|
|
|
if len(context.selected_nodes) == 0:
|
|
self.report({"WARNING"}, "No node selected.")
|
|
return {'FINISHED'}
|
|
|
|
selected_node = context.selected_nodes[0]
|
|
container_node_group = container_obj.modifiers[0].node_group
|
|
|
|
container_output_node = get_output_node(container_node_group)
|
|
|
|
if len(container_output_node.inputs[0].links) == 0:
|
|
pre_socket = None
|
|
else:
|
|
pre_socket = container_output_node.inputs[0].links[0].from_socket
|
|
|
|
container_node_group.links.new(selected_node.outputs[0],
|
|
container_output_node.inputs[0])
|
|
|
|
bpy.ops.mesh.primitive_cube_add(
|
|
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
obj = bpy.context.active_object
|
|
|
|
obj.name = f"{container_obj.name}_{self.object_type}"
|
|
|
|
bpy.ops.node.new_geometry_nodes_modifier()
|
|
modifier = obj.modifiers[0]
|
|
node_group = modifier.node_group
|
|
|
|
output_node = get_nodes_by_type(node_group, 'NodeGroupOutput')[0]
|
|
fetch_mesh_node = add_node_to_graph(f"Fetch{self.object_type}",
|
|
node_group,
|
|
node_label=f"Fetch {self.object_type}",
|
|
use_link=get_use_link())
|
|
|
|
fetch_mesh_node.inputs[0].default_value = container_obj
|
|
node_group.links.new(fetch_mesh_node.outputs[0], output_node.inputs[0])
|
|
|
|
for modifier in obj.modifiers:
|
|
bpy.ops.object.modifier_apply(modifier=modifier.name)
|
|
|
|
obj.data.materials.clear()
|
|
|
|
if pre_socket:
|
|
container_node_group.links.new(pre_socket,
|
|
container_output_node.inputs[0])
|
|
|
|
select_object(obj)
|
|
|
|
self.report({"INFO"}, f"Successfully picked")
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class ExtractNodeMesh(bpy.types.Operator, ExtractNodeObject):
|
|
bl_idname = "bioxelnodes.extract_node_mesh"
|
|
bl_label = "Extract Mesh"
|
|
bl_description = "Extract Mesh"
|
|
bl_icon = "OUTLINER_OB_MESH"
|
|
object_type = "Mesh"
|
|
|
|
|
|
class ExtractNodeVolume(bpy.types.Operator, ExtractNodeObject):
|
|
bl_idname = "bioxelnodes.extract_node_volume"
|
|
bl_label = "Extract Volume"
|
|
bl_description = "Extract Volume"
|
|
bl_icon = "OUTLINER_OB_VOLUME"
|
|
object_type = "Volume"
|
|
|
|
|
|
class ExtractNodeShapeWire(bpy.types.Operator, ExtractNodeObject):
|
|
bl_idname = "bioxelnodes.extract_node_shape_wire"
|
|
bl_label = "Extract Shape Wire"
|
|
bl_description = "Extract Shape Wire"
|
|
bl_icon = "FILE_VOLUME"
|
|
object_type = "ShapeWire"
|
|
|
|
|
|
class ExtractNodeBboxWire(bpy.types.Operator, ExtractNodeObject):
|
|
bl_idname = "bioxelnodes.extract_node_bbox_wire"
|
|
bl_label = "Extract Bbox Wire"
|
|
bl_description = "Extract Bbox Wire"
|
|
bl_icon = "MESH_CUBE"
|
|
object_type = "BboxWire"
|
|
|
|
|
|
class ExtractObject():
|
|
bl_options = {'UNDO'}
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
bpy.ops.mesh.primitive_cube_add(
|
|
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
obj = bpy.context.active_object
|
|
|
|
obj.name = f"{container_obj.name}_{self.object_type}"
|
|
|
|
bpy.ops.node.new_geometry_nodes_modifier()
|
|
modifier = obj.modifiers[0]
|
|
node_group = modifier.node_group
|
|
|
|
output_node = get_output_node(node_group)
|
|
|
|
fetch_mesh_node = add_node_to_graph(f"Fetch{self.object_type}",
|
|
node_group,
|
|
node_label=f"Fetch {self.object_type}",
|
|
use_link=get_use_link())
|
|
|
|
fetch_mesh_node.inputs[0].default_value = container_obj
|
|
node_group.links.new(fetch_mesh_node.outputs[0], output_node.inputs[0])
|
|
|
|
for modifier in obj.modifiers:
|
|
bpy.ops.object.modifier_apply(modifier=modifier.name)
|
|
|
|
obj.data.materials.clear()
|
|
|
|
select_object(obj)
|
|
|
|
self.report({"INFO"}, f"Successfully picked")
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class ExtractMesh(bpy.types.Operator, ExtractObject):
|
|
bl_idname = "bioxelnodes.extract_mesh"
|
|
bl_label = "Extract Mesh"
|
|
bl_description = "Extract Mesh"
|
|
bl_icon = "OUTLINER_OB_MESH"
|
|
object_type = "Mesh"
|
|
|
|
|
|
class ExtractVolume(bpy.types.Operator, ExtractObject):
|
|
bl_idname = "bioxelnodes.extract_volume"
|
|
bl_label = "Extract Volume"
|
|
bl_description = "Extract Volume"
|
|
bl_icon = "OUTLINER_OB_VOLUME"
|
|
object_type = "Volume"
|
|
|
|
|
|
class ExtractShapeWire(bpy.types.Operator, ExtractObject):
|
|
bl_idname = "bioxelnodes.extract_shape_wire"
|
|
bl_label = "Extract Shape Wire"
|
|
bl_description = "Extract Shape Wire"
|
|
bl_icon = "FILE_VOLUME"
|
|
object_type = "ShapeWire"
|
|
|
|
|
|
class ExtractBboxWire(bpy.types.Operator, ExtractObject):
|
|
bl_idname = "bioxelnodes.extract_bbox_wire"
|
|
bl_label = "Extract Bbox Wire"
|
|
bl_description = "Extract Bbox Wire"
|
|
bl_icon = "MESH_CUBE"
|
|
object_type = "BboxWire"
|
|
|
|
|
|
class AddCutter():
|
|
bl_options = {'UNDO'}
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
# TODO: do not use operator to create obj
|
|
if self.cutter_type == "plane":
|
|
bpy.ops.mesh.primitive_plane_add(
|
|
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
elif self.cutter_type == "cylinder":
|
|
bpy.ops.mesh.primitive_cylinder_add(
|
|
radius=1, depth=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
bpy.context.object.rotation_euler[0] = container_obj.rotation_euler[0]
|
|
elif self.cutter_type == "cube":
|
|
bpy.ops.mesh.primitive_cube_add(
|
|
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
elif self.cutter_type == "sphere":
|
|
bpy.ops.mesh.primitive_ico_sphere_add(
|
|
radius=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
elif self.cutter_type == "pie":
|
|
bpy.ops.mesh.primitive_plane_add(
|
|
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
|
pie_obj = bpy.context.active_object
|
|
orig_data = pie_obj.data
|
|
|
|
# Create mesh
|
|
pie_mesh = bpy.data.meshes.new('Pie')
|
|
pie_obj.data = pie_mesh
|
|
bpy.data.meshes.remove(orig_data)
|
|
|
|
# # Create object
|
|
# pie = bpy.data.objects.new('Pie', pie_mesh)
|
|
|
|
# # Link object to scene
|
|
# bpy.context.scene.collection.objects.link(pie)
|
|
|
|
# Get a BMesh representation
|
|
bm = bmesh.new() # create an empty BMesh
|
|
bm.from_mesh(pie_mesh) # fill it in from a Mesh
|
|
|
|
# Hot to create vertices
|
|
v_0 = bm.verts.new((0.0, -1.0, 0.0))
|
|
v_1 = bm.verts.new((-1.0, -1.0, 1.0))
|
|
v_2 = bm.verts.new((0.0, 1.0, 0.0))
|
|
v_3 = bm.verts.new((-1.0, 1.0, 1.0))
|
|
v_4 = bm.verts.new((1.0, -1.0, 1.0))
|
|
v_5 = bm.verts.new((1.0, 1.0, 1.0))
|
|
|
|
# Initialize the index values of this sequence.
|
|
bm.verts.index_update()
|
|
|
|
# How to create a face
|
|
# it's not necessary to create the edges before, I made it only to show how create
|
|
# edges too
|
|
bm.faces.new((v_0, v_1, v_3, v_2))
|
|
bm.faces.new((v_0, v_2, v_5, v_4))
|
|
|
|
# Finish up, write the bmesh back to the mesh
|
|
bm.to_mesh(pie_mesh)
|
|
# bpy.context.view_layer.objects.active = pie
|
|
|
|
cutter_obj = bpy.context.active_object
|
|
|
|
# vcos = [container_obj.matrix_world @
|
|
# v.co for v in container_obj.data.vertices]
|
|
|
|
# def find_center(l): return (max(l) + min(l)) / 2
|
|
|
|
# x, y, z = [[v[i] for v in vcos] for i in range(3)]
|
|
# center = [find_center(axis) for axis in [x, y, z]]
|
|
|
|
# cutter_obj.location = center
|
|
name = f"{self.cutter_type.capitalize()}_Cutter"
|
|
cutter_obj.name = name
|
|
cutter_obj.data.name = name
|
|
cutter_obj.visible_camera = False
|
|
cutter_obj.visible_diffuse = False
|
|
cutter_obj.visible_glossy = False
|
|
cutter_obj.visible_transmission = False
|
|
cutter_obj.visible_volume_scatter = False
|
|
cutter_obj.visible_shadow = False
|
|
cutter_obj.hide_render = True
|
|
cutter_obj.display_type = 'WIRE'
|
|
cutter_obj.lineart.usage = 'EXCLUDE'
|
|
|
|
select_object(container_obj)
|
|
|
|
modifier = container_obj.modifiers[0]
|
|
node_group = modifier.node_group
|
|
|
|
cut_nodes = get_nodes_by_type(node_group,
|
|
'BioxelNodes_Cut')
|
|
if len(cut_nodes) == 0:
|
|
cutter_node = add_node_to_graph("ObjectCutter",
|
|
node_group,
|
|
node_label=name,
|
|
use_link=get_use_link())
|
|
cutter_node.inputs[0].default_value = self.cutter_type.capitalize()
|
|
cutter_node.inputs[1].default_value = cutter_obj
|
|
|
|
cut_node = add_node_to_graph("Cut",
|
|
node_group,
|
|
use_link=get_use_link())
|
|
|
|
output_node = get_output_node(node_group)
|
|
|
|
if len(output_node.inputs[0].links) == 0:
|
|
node_group.links.new(cut_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_to_node(cut_node, output_node, (-300, 0))
|
|
else:
|
|
pre_output_node = output_node.inputs[0].links[0].from_node
|
|
node_group.links.new(pre_output_node.outputs[0],
|
|
cut_node.inputs[0])
|
|
node_group.links.new(cut_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_between_nodes(cut_node,
|
|
[pre_output_node, output_node])
|
|
|
|
node_group.links.new(cutter_node.outputs[0],
|
|
cut_node.inputs[1])
|
|
|
|
move_node_to_node(cutter_node, cut_node, (-300, -300))
|
|
else:
|
|
bpy.ops.bioxelnodes.add_node('EXEC_DEFAULT',
|
|
node_name="ObjectCutter",
|
|
node_label=name)
|
|
node = bpy.context.active_node
|
|
node.inputs[0].default_value = self.cutter_type.capitalize()
|
|
node.inputs[1].default_value = cutter_obj
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class AddPlaneCutter(bpy.types.Operator, AddCutter):
|
|
bl_idname = "bioxelnodes.add_plane_cutter"
|
|
bl_label = "Add a Plane Cutter"
|
|
bl_description = "Add a plane cutter to current container"
|
|
bl_icon = "MESH_PLANE"
|
|
cutter_type = "plane"
|
|
|
|
|
|
class AddCylinderCutter(bpy.types.Operator, AddCutter):
|
|
bl_idname = "bioxelnodes.add_cylinder_cutter"
|
|
bl_label = "Add a Cylinder Cutter"
|
|
bl_description = "Add a cylinder cutter to current container"
|
|
bl_icon = "MESH_CYLINDER"
|
|
cutter_type = "cylinder"
|
|
|
|
|
|
class AddCubeCutter(bpy.types.Operator, AddCutter):
|
|
bl_idname = "bioxelnodes.add_cube_cutter"
|
|
bl_label = "Add a Cube Cutter"
|
|
bl_description = "Add a cube cutter to current container"
|
|
bl_icon = "MESH_CUBE"
|
|
cutter_type = "cube"
|
|
|
|
|
|
class AddSphereCutter(bpy.types.Operator, AddCutter):
|
|
bl_idname = "bioxelnodes.add_sphere_cutter"
|
|
bl_label = "Add a Sphere Cutter"
|
|
bl_description = "Add a sphere cutter to current container"
|
|
bl_icon = "MESH_UVSPHERE"
|
|
cutter_type = "sphere"
|
|
|
|
|
|
class AddPieCutter(bpy.types.Operator, AddCutter):
|
|
bl_idname = "bioxelnodes.add_pie_cutter"
|
|
bl_label = "Add a Pie Cutter"
|
|
bl_description = "Add a pie cutter to current container"
|
|
bl_icon = "MESH_CONE"
|
|
cutter_type = "pie"
|
|
|
|
|
|
class AddSlicer(bpy.types.Operator):
|
|
bl_idname = "bioxelnodes.add_slicer"
|
|
bl_label = "Add a Slicer"
|
|
bl_description = "Add a slicer to current container"
|
|
bl_icon = "TEXTURE"
|
|
bl_options = {'UNDO'}
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
bpy.ops.mesh.primitive_plane_add(size=2,
|
|
enter_editmode=False,
|
|
align='WORLD',
|
|
location=(0, 0, 0),
|
|
scale=(1, 1, 1))
|
|
|
|
slicer_obj = bpy.context.active_object
|
|
slicer_obj.name = "Slicer"
|
|
slicer_obj.data.name = "Slicer"
|
|
|
|
slicer_obj.visible_camera = False
|
|
slicer_obj.visible_diffuse = False
|
|
slicer_obj.visible_glossy = False
|
|
slicer_obj.visible_transmission = False
|
|
slicer_obj.visible_volume_scatter = False
|
|
slicer_obj.visible_shadow = False
|
|
slicer_obj.hide_render = True
|
|
slicer_obj.display_type = 'WIRE'
|
|
slicer_obj.lineart.usage = 'EXCLUDE'
|
|
|
|
select_object(container_obj)
|
|
|
|
modifier = container_obj.modifiers[0]
|
|
node_group = modifier.node_group
|
|
|
|
slice_node = add_node_to_graph("Slice",
|
|
node_group,
|
|
use_link=get_use_link())
|
|
|
|
slice_node.inputs[1].default_value = slicer_obj
|
|
|
|
output_node = get_output_node(node_group)
|
|
|
|
if len(output_node.inputs[0].links) == 0:
|
|
node_group.links.new(slice_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_to_node(slice_node, output_node, (-300, 0))
|
|
else:
|
|
pre_output_node = output_node.inputs[0].links[0].from_node
|
|
node_group.links.new(pre_output_node.outputs[0],
|
|
slice_node.inputs[0])
|
|
node_group.links.new(slice_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_between_nodes(slice_node,
|
|
[pre_output_node, output_node])
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class AddLocator(bpy.types.Operator):
|
|
bl_idname = "bioxelnodes.add_locator"
|
|
bl_label = "Add a Locator"
|
|
bl_description = "Add a locator to current container"
|
|
bl_icon = "EMPTY_AXIS"
|
|
bl_options = {'UNDO'}
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
bpy.ops.object.empty_add(type='ARROWS',
|
|
align='WORLD',
|
|
location=(0, 0, 0),
|
|
scale=(1, 1, 1))
|
|
|
|
locator_obj = bpy.context.active_object
|
|
locator_obj.name = "Locator"
|
|
select_object(container_obj)
|
|
|
|
modifier = container_obj.modifiers[0]
|
|
node_group = modifier.node_group
|
|
|
|
parent_node = add_node_to_graph("TransformParent",
|
|
node_group,
|
|
node_label="Transform Parent",
|
|
use_link=get_use_link())
|
|
|
|
parent_node.inputs[1].default_value = locator_obj
|
|
|
|
output_node = get_output_node(node_group)
|
|
|
|
if len(output_node.inputs[0].links) == 0:
|
|
node_group.links.new(parent_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_to_node(parent_node, output_node, (-300, 0))
|
|
else:
|
|
pre_output_node = output_node.inputs[0].links[0].from_node
|
|
node_group.links.new(pre_output_node.outputs[0],
|
|
parent_node.inputs[0])
|
|
node_group.links.new(parent_node.outputs[0],
|
|
output_node.inputs[0])
|
|
move_node_between_nodes(parent_node,
|
|
[pre_output_node, output_node])
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class ContainerProps(bpy.types.Operator):
|
|
bl_idname = "bioxelnodes.container_props"
|
|
bl_label = "Change Container Properties"
|
|
bl_description = "Change current ontainer properties"
|
|
bl_icon = "FILE_TICK"
|
|
|
|
scene_scale: bpy.props.FloatProperty(name="Scene Scale",
|
|
soft_min=0.0001, soft_max=10.0,
|
|
min=1e-6, max=1e6,
|
|
default=0.01) # type: ignore
|
|
|
|
step_size: bpy.props.FloatProperty(name="Step Size",
|
|
soft_min=0.1, soft_max=100.0,
|
|
min=0.1, max=1e2,
|
|
default=1) # type: ignore
|
|
|
|
def execute(self, context):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
|
return {'FINISHED'}
|
|
|
|
container_obj.scale[0] = self.scene_scale
|
|
container_obj.scale[1] = self.scene_scale
|
|
container_obj.scale[2] = self.scene_scale
|
|
container_obj["scene_scale"] = self.scene_scale
|
|
container_obj["step_size"] = self.step_size
|
|
|
|
for layer_obj in get_container_layer_objs(container_obj):
|
|
layer_obj.data.render.space = 'WORLD'
|
|
layer_obj.data.render.step_size = self.scene_scale * self.step_size
|
|
|
|
return {'FINISHED'}
|
|
|
|
def invoke(self, context, event):
|
|
container_obj = get_container_obj(context.object)
|
|
|
|
if container_obj is None:
|
|
return self.execute(context)
|
|
else:
|
|
self.scene_scale = container_obj.get("scene_scale") or 0.01
|
|
self.step_size = container_obj.get("step_size") or 1
|
|
context.window_manager.invoke_props_dialog(self)
|
|
return {'RUNNING_MODAL'}
|
|
|
|
|
|
def get_container_layers(context, layer_filter=None):
|
|
def _layer_filter(layer_obj, context):
|
|
return True
|
|
|
|
layer_filter = layer_filter or _layer_filter
|
|
container_obj = context.object
|
|
layer_objs = get_container_layer_objs(container_obj)
|
|
return [obj for obj in layer_objs if layer_filter(obj, context)]
|
|
|
|
|
|
class SaveContainerLayersCache(bpy.types.Operator, SaveLayersCache):
|
|
bl_idname = "bioxelnodes.save_container_layers_cache"
|
|
bl_label = "Save Container Layers' Cache"
|
|
bl_description = "Save all current container layers' cache to directory."
|
|
bl_icon = "FILE_TICK"
|
|
|
|
success_msg = "Successfully saved all container layers."
|
|
|
|
def get_layers(self, context):
|
|
def is_not_missing(layer_obj, context):
|
|
return not is_missing_layer(layer_obj)
|
|
return get_container_layers(context, is_not_missing)
|
|
|
|
|
|
class RemoveContainerMissingLayers(bpy.types.Operator, RemoveLayers):
|
|
bl_idname = "bioxelnodes.remove_container_missing_layers"
|
|
bl_label = "Remove Container Missing Layers"
|
|
bl_description = "Remove all current container missing layers"
|
|
bl_icon = "BRUSH_DATA"
|
|
|
|
success_msg = "Successfully removed all container missing layers."
|
|
|
|
def get_layers(self, context):
|
|
def is_missing(layer_obj, context):
|
|
return is_missing_layer(layer_obj)
|
|
return get_container_layers(context, is_missing)
|
|
|
|
def invoke(self, context, event):
|
|
context.window_manager.invoke_confirm(self,
|
|
event,
|
|
message=f"Are you sure to remove all **Missing** layers?")
|
|
return {'RUNNING_MODAL'}
|