Merge pull request #1 from OmooLab/feature/dev
feat: vdb in RAS not LPS
This commit is contained in:
BIN
bioxelnodes/assets/Nodes.blend
LFS
BIN
bioxelnodes/assets/Nodes.blend
LFS
Binary file not shown.
@@ -84,6 +84,7 @@ class CustomNodes():
|
|||||||
op.node_label = item.get('label') or ""
|
op.node_label = item.get('label') or ""
|
||||||
op.node_description = item.get(
|
op.node_description = item.get(
|
||||||
'node_description') or "Add Custom Node."
|
'node_description') or "Add Custom Node."
|
||||||
|
op.node_link = item.get('link') or True
|
||||||
op.node_callback = item.get('node_callback') or ""
|
op.node_callback = item.get('node_callback') or ""
|
||||||
|
|
||||||
menu_classes.append(Menu)
|
menu_classes.append(Menu)
|
||||||
@@ -111,6 +112,7 @@ class CustomNodes():
|
|||||||
op.nodes_file = self.nodes_file
|
op.nodes_file = self.nodes_file
|
||||||
op.node_type = item['node_type']
|
op.node_type = item['node_type']
|
||||||
op.node_label = item.get('label') or ""
|
op.node_label = item.get('label') or ""
|
||||||
|
op.node_link = item.get('link') or True
|
||||||
op.node_callback = item.get('node_callback') or ""
|
op.node_callback = item.get('node_callback') or ""
|
||||||
return op.add_node(node_tree)
|
return op.add_node(node_tree)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ class AddCustomNode():
|
|||||||
subtype="NONE"
|
subtype="NONE"
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
node_link: bpy.props.BoolProperty(
|
||||||
|
name='node_link',
|
||||||
|
default=True
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
node_callback: bpy.props.StringProperty(
|
node_callback: bpy.props.StringProperty(
|
||||||
name='node_callback',
|
name='node_callback',
|
||||||
default=''
|
default=''
|
||||||
@@ -50,7 +55,7 @@ class AddCustomNode():
|
|||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def get_node_tree(self, node_type):
|
def get_node_tree(self, node_type, node_link):
|
||||||
# try to get node from current file if exists
|
# try to get node from current file if exists
|
||||||
node_tree = bpy.data.node_groups.get(node_type)
|
node_tree = bpy.data.node_groups.get(node_type)
|
||||||
# if not exists, get it from asset file.
|
# if not exists, get it from asset file.
|
||||||
@@ -59,7 +64,7 @@ class AddCustomNode():
|
|||||||
'EXEC_DEFAULT',
|
'EXEC_DEFAULT',
|
||||||
directory=f"{self.nodes_file}/NodeTree",
|
directory=f"{self.nodes_file}/NodeTree",
|
||||||
filename=node_type,
|
filename=node_type,
|
||||||
link=False,
|
link=node_link,
|
||||||
use_recursive=True
|
use_recursive=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,10 +86,8 @@ class AddCustomNode():
|
|||||||
...
|
...
|
||||||
|
|
||||||
def add_node(self, node_tree):
|
def add_node(self, node_tree):
|
||||||
self.get_node_tree(self.node_type)
|
self.get_node_tree(self.node_type, self.node_link)
|
||||||
|
|
||||||
node = node_tree.new("GeometryNodeGroup")
|
node = node_tree.new("GeometryNodeGroup")
|
||||||
|
|
||||||
self.assign_node_tree(node)
|
self.assign_node_tree(node)
|
||||||
|
|
||||||
return node
|
return node
|
||||||
@@ -96,7 +99,7 @@ class CUSTOMNODES_OT_Add_Custom_Node(bpy.types.Operator, AddCustomNode):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
self.get_node_tree(self.node_type)
|
self.get_node_tree(self.node_type, self.node_link)
|
||||||
|
|
||||||
# intended to be called upon button press in the node tree
|
# intended to be called upon button press in the node tree
|
||||||
prev_context = bpy.context.area.type
|
prev_context = bpy.context.area.type
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import mathutils
|
|||||||
from .utils import calc_bbox_verts, extract_last_number, get_bioxels_obj, show_message
|
from .utils import calc_bbox_verts, extract_last_number, get_bioxels_obj, show_message
|
||||||
from .nodes import custom_nodes
|
from .nodes import custom_nodes
|
||||||
|
|
||||||
SUPPORT_EXTS = ['.dcm', '.tif', '.tiff', '.png', '.bmp']
|
SUPPORT_EXTS = ['.dcm', '.tif', '.tiff', '.png', '.bmp', '', '.jpg']
|
||||||
|
|
||||||
|
|
||||||
def get_data_files(filepath: str):
|
def get_data_files(filepath: str):
|
||||||
@@ -84,13 +84,6 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
default=(100, 100, 100)
|
default=(100, 100, 100)
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
bioxels_scale: bpy.props.FloatProperty(
|
|
||||||
name="Bioxel Size Scale",
|
|
||||||
soft_min=0.001, soft_max=100.0,
|
|
||||||
min=1e-6, max=1e6,
|
|
||||||
default=0.01,
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
bioxel_size: bpy.props.FloatProperty(
|
bioxel_size: bpy.props.FloatProperty(
|
||||||
name="Bioxel Size",
|
name="Bioxel Size",
|
||||||
soft_min=0.1, soft_max=10.0,
|
soft_min=0.1, soft_max=10.0,
|
||||||
@@ -117,6 +110,13 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
options={'HIDDEN'}
|
options={'HIDDEN'}
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
scene_scale: bpy.props.FloatProperty(
|
||||||
|
name="Scene Scale",
|
||||||
|
soft_min=0.001, soft_max=100.0,
|
||||||
|
min=1e-6, max=1e6,
|
||||||
|
default=0.01,
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
do_add_segmentnode: bpy.props.BoolProperty(
|
do_add_segmentnode: bpy.props.BoolProperty(
|
||||||
name="Add Segment Node",
|
name="Add Segment Node",
|
||||||
default=True,
|
default=True,
|
||||||
@@ -178,25 +178,10 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
image = sitk.DICOMOrient(image, 'LPS')
|
image = sitk.DICOMOrient(image, 'RAS')
|
||||||
except:
|
except:
|
||||||
...
|
...
|
||||||
|
|
||||||
image_origin = image.GetOrigin()
|
|
||||||
bioxels_scale = float(self.bioxels_scale)
|
|
||||||
bioxel_size *= bioxels_scale
|
|
||||||
bioxels_origin = (
|
|
||||||
image_origin[0] * bioxels_scale,
|
|
||||||
image_origin[1] * bioxels_scale,
|
|
||||||
image_origin[2] * bioxels_scale,
|
|
||||||
)
|
|
||||||
bioxels_size = (
|
|
||||||
bioxels_shape[0] * bioxel_size,
|
|
||||||
bioxels_shape[1] * bioxel_size,
|
|
||||||
bioxels_shape[2] * bioxel_size,
|
|
||||||
)
|
|
||||||
direction = image.GetDirection()
|
|
||||||
|
|
||||||
array = sitk.GetArrayFromImage(image)
|
array = sitk.GetArrayFromImage(image)
|
||||||
orig_dtype = str(array.dtype)
|
orig_dtype = str(array.dtype)
|
||||||
print(f"Coverting Dtype {orig_dtype} -> float")
|
print(f"Coverting Dtype {orig_dtype} -> float")
|
||||||
@@ -206,26 +191,51 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
# https://www.slicer.org/wiki/Coordinate_systems
|
# https://www.slicer.org/wiki/Coordinate_systems
|
||||||
|
|
||||||
# ITK Numpy 3D
|
# ITK Numpy 3D
|
||||||
# L (eft) i -> k -> x
|
# R (ight) i -> k -> x
|
||||||
# P (osterior) j -> j -> y
|
# A (nterior) j -> j -> y
|
||||||
# S (uperior) k -> i -> z
|
# S (uperior) k -> i -> z
|
||||||
|
|
||||||
array = np.transpose(array)
|
array = np.transpose(array)
|
||||||
value_max = float(np.max(array))
|
bioxels_max = float(np.max(array))
|
||||||
value_min = float(np.min(array))
|
bioxels_min = float(np.min(array))
|
||||||
|
|
||||||
value_offset = 0.0
|
bioxels_offset = 0.0
|
||||||
if value_min < 0 and orig_dtype[0] != "u":
|
if bioxels_min < 0 and orig_dtype[0] != "u":
|
||||||
value_offset = -value_min
|
bioxels_offset = -bioxels_min
|
||||||
array = array + np.full_like(array, value_offset)
|
array = array + np.full_like(array, bioxels_offset)
|
||||||
value_max = float(np.max(array))
|
bioxels_max = float(np.max(array))
|
||||||
value_min = float(np.min(array))
|
bioxels_min = float(np.min(array))
|
||||||
print("Offseted Max:", value_max)
|
print("Offseted Max:", bioxels_max)
|
||||||
print("Offseted Min:", value_min)
|
print("Offseted Min:", bioxels_min)
|
||||||
|
|
||||||
# Build VDB
|
# Build VDB
|
||||||
grid = vdb.FloatGrid()
|
grid = vdb.FloatGrid()
|
||||||
grid.copyFromArray(array.copy())
|
grid.copyFromArray(array.copy())
|
||||||
|
|
||||||
|
# After sitk.DICOMOrient(), origin and direction will also orient base on LPS
|
||||||
|
# so we need to convert them into RAS
|
||||||
|
mat_lps2ras = axis_conversion(
|
||||||
|
from_forward='-Z',
|
||||||
|
from_up='-Y',
|
||||||
|
to_forward='-Z',
|
||||||
|
to_up='Y'
|
||||||
|
).to_4x4()
|
||||||
|
|
||||||
|
mat_location = mathutils.Matrix.Translation(
|
||||||
|
mathutils.Vector(image.GetOrigin())
|
||||||
|
)
|
||||||
|
|
||||||
|
mat_rotation = mathutils.Matrix(
|
||||||
|
np.array(image.GetDirection()).reshape((3, 3))
|
||||||
|
).to_4x4()
|
||||||
|
|
||||||
|
mat_scale = mathutils.Matrix.Scale(
|
||||||
|
bioxel_size, 4
|
||||||
|
)
|
||||||
|
|
||||||
|
transfrom = mat_lps2ras @ mat_location @ mat_rotation @ mat_scale
|
||||||
|
|
||||||
|
grid.transform = vdb.createLinearTransform(transfrom.transposed())
|
||||||
grid.name = "value"
|
grid.name = "value"
|
||||||
|
|
||||||
preferences = context.preferences.addons[__package__].preferences
|
preferences = context.preferences.addons[__package__].preferences
|
||||||
@@ -244,28 +254,26 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
bioxels_obj = bpy.context.active_object
|
bioxels_obj = bpy.context.active_object
|
||||||
|
|
||||||
# Set props to VDB object
|
# Set props to VDB object
|
||||||
bioxels_obj.name = f"{name}_Values"
|
bioxels_obj.name = f"{name}_Bioxels"
|
||||||
bioxels_obj.data.name = f"{name}_Values"
|
bioxels_obj.data.name = f"{name}_Bioxels"
|
||||||
|
|
||||||
# Make transformation
|
# Make transformation
|
||||||
|
scene_scale = float(self.scene_scale)
|
||||||
|
|
||||||
# (S)uperior -Z -> Y
|
# (S)uperior -Z -> Y
|
||||||
# (P)osterior -Y -> Z
|
# (A)osterior Y -> Z
|
||||||
axis_rot = axis_conversion(
|
mat_ras2blender = axis_conversion(
|
||||||
from_forward='-Z',
|
from_forward='-Z',
|
||||||
from_up='-Y',
|
from_up='Y',
|
||||||
to_forward='Y',
|
to_forward='Y',
|
||||||
to_up='Z'
|
to_up='Z'
|
||||||
).to_4x4()
|
).to_4x4()
|
||||||
|
|
||||||
mat_loc = mathutils.Matrix.Translation(
|
mat_scene_scale = mathutils.Matrix.Scale(
|
||||||
mathutils.Vector(bioxels_origin))
|
scene_scale, 4
|
||||||
mat_sca = mathutils.Matrix.Scale(bioxel_size, 4)
|
)
|
||||||
mat_rot = mathutils.Matrix(
|
|
||||||
np.array(direction).reshape((3, 3))
|
|
||||||
).to_4x4()
|
|
||||||
|
|
||||||
bioxels_obj.matrix_world = axis_rot @ mat_loc @ mat_rot @ mat_sca
|
bioxels_obj.matrix_world = mat_ras2blender @ mat_scene_scale
|
||||||
|
|
||||||
bioxels_obj.lock_location[0] = True
|
bioxels_obj.lock_location[0] = True
|
||||||
bioxels_obj.lock_location[1] = True
|
bioxels_obj.lock_location[1] = True
|
||||||
@@ -277,16 +285,7 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
bioxels_obj.lock_scale[1] = True
|
bioxels_obj.lock_scale[1] = True
|
||||||
bioxels_obj.lock_scale[2] = True
|
bioxels_obj.lock_scale[2] = True
|
||||||
bioxels_obj.hide_select = True
|
bioxels_obj.hide_select = True
|
||||||
bioxels_obj['value_max'] = value_max
|
bioxels_obj['bioxels'] = True
|
||||||
bioxels_obj['value_min'] = value_min
|
|
||||||
bioxels_obj['value_offset'] = value_offset
|
|
||||||
bioxels_obj['image_origin'] = mathutils.Vector(
|
|
||||||
bioxels_origin) / bioxel_size
|
|
||||||
bioxels_obj['bioxel_size'] = bioxel_size
|
|
||||||
bioxels_obj['bioxels_shape'] = bioxels_shape
|
|
||||||
bioxels_obj['bioxels_size'] = bioxels_size
|
|
||||||
bioxels_obj['bioxels_origin'] = bioxels_origin
|
|
||||||
bioxels_obj['bioxels_values'] = True
|
|
||||||
|
|
||||||
bpy.ops.node.new_geometry_nodes_modifier()
|
bpy.ops.node.new_geometry_nodes_modifier()
|
||||||
node_tree = bioxels_obj.modifiers[0].node_group
|
node_tree = bioxels_obj.modifiers[0].node_group
|
||||||
@@ -296,14 +295,16 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1)
|
enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1)
|
||||||
)
|
)
|
||||||
container_obj = bpy.context.active_object
|
container_obj = bpy.context.active_object
|
||||||
|
bbox_verts = calc_bbox_verts((0, 0, 0), bioxels_shape)
|
||||||
bbox_verts = calc_bbox_verts(bioxels_origin, bioxels_size)
|
|
||||||
for index, vert in enumerate(container_obj.data.vertices):
|
for index, vert in enumerate(container_obj.data.vertices):
|
||||||
vert.co = bbox_verts[index]
|
co = transfrom @ mathutils.Vector(bbox_verts[index])
|
||||||
|
co = mat_ras2blender @ co
|
||||||
|
co = mat_scene_scale @ co
|
||||||
|
vert.co = co
|
||||||
|
|
||||||
bioxels_obj.parent = container_obj
|
bioxels_obj.parent = container_obj
|
||||||
container_obj.name = name
|
container_obj.name = name
|
||||||
container_obj.data.name = f"{name}_Container"
|
container_obj.data.name = name
|
||||||
container_obj.visible_camera = False
|
container_obj.visible_camera = False
|
||||||
container_obj.visible_diffuse = False
|
container_obj.visible_diffuse = False
|
||||||
container_obj.visible_glossy = False
|
container_obj.visible_glossy = False
|
||||||
@@ -311,7 +312,13 @@ class ImportDICOMDialog(bpy.types.Operator):
|
|||||||
container_obj.visible_volume_scatter = False
|
container_obj.visible_volume_scatter = False
|
||||||
container_obj.visible_shadow = False
|
container_obj.visible_shadow = False
|
||||||
container_obj.display_type = 'WIRE'
|
container_obj.display_type = 'WIRE'
|
||||||
container_obj['bioxels'] = True
|
container_obj['bioxels_container'] = True
|
||||||
|
container_obj['scene_scale'] = scene_scale
|
||||||
|
container_obj['bioxel_size'] = bioxel_size
|
||||||
|
container_obj['bioxels_max'] = bioxels_max
|
||||||
|
container_obj['bioxels_min'] = bioxels_min
|
||||||
|
container_obj['bioxels_offset'] = bioxels_offset
|
||||||
|
container_obj['bioxels_shape'] = bioxels_shape
|
||||||
|
|
||||||
bpy.ops.object.modifier_add(type='NODES')
|
bpy.ops.object.modifier_add(type='NODES')
|
||||||
container_obj.modifiers[0].node_group = node_tree
|
container_obj.modifiers[0].node_group = node_tree
|
||||||
@@ -440,8 +447,8 @@ class BIOXELNODES_FH_ImportDicom(bpy.types.FileHandler):
|
|||||||
|
|
||||||
class ExportVDB(bpy.types.Operator):
|
class ExportVDB(bpy.types.Operator):
|
||||||
bl_idname = "bioxelnodes.export_vdb"
|
bl_idname = "bioxelnodes.export_vdb"
|
||||||
bl_label = "Biovels as VDB"
|
bl_label = "Bioxels as VDB"
|
||||||
bl_description = "Export Biovels original VDB data."
|
bl_description = "Export Bioxels original VDB data."
|
||||||
bl_options = {'UNDO'}
|
bl_options = {'UNDO'}
|
||||||
|
|
||||||
filepath: bpy.props.StringProperty(
|
filepath: bpy.props.StringProperty(
|
||||||
@@ -451,13 +458,12 @@ class ExportVDB(bpy.types.Operator):
|
|||||||
filename_ext = ".vdb"
|
filename_ext = ".vdb"
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
bioxels_objs = []
|
bioxels_obj = None
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
bioxels_obj = get_bioxels_obj(obj)
|
bioxels_obj = get_bioxels_obj(obj)
|
||||||
if bioxels_obj:
|
break
|
||||||
bioxels_objs.append(bioxels_obj)
|
|
||||||
|
|
||||||
if len(bioxels_objs) > 0:
|
if bioxels_obj:
|
||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
else:
|
else:
|
||||||
@@ -465,14 +471,13 @@ class ExportVDB(bpy.types.Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
bioxels_objs = []
|
bioxels_obj = None
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
bioxels_obj = get_bioxels_obj(obj)
|
bioxels_obj = get_bioxels_obj(obj)
|
||||||
if bioxels_obj:
|
break
|
||||||
bioxels_objs.append(bioxels_obj)
|
|
||||||
|
|
||||||
bioxels_obj = bioxels_objs[0]
|
filepath = f"{self.filepath.split('.')[0]}.vdb"
|
||||||
output_path: Path = Path(self.filepath).resolve()
|
output_path: Path = Path(filepath).resolve()
|
||||||
source_path: Path = Path(bioxels_obj.data.filepath).resolve()
|
source_path: Path = Path(bioxels_obj.data.filepath).resolve()
|
||||||
# print('output_path', output_path)
|
# print('output_path', output_path)
|
||||||
# print('source_path', source_path)
|
# print('source_path', source_path)
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ def add_driver_to_node_factory(source_prop, target_prop):
|
|||||||
import bpy
|
import bpy
|
||||||
from bioxelnodes.utils import add_direct_driver, get_bioxels_obj
|
from bioxelnodes.utils import add_direct_driver, get_bioxels_obj
|
||||||
bioxels_obj = get_bioxels_obj(bpy.context.active_object)
|
bioxels_obj = get_bioxels_obj(bpy.context.active_object)
|
||||||
|
container_obj = bioxels_obj.parent
|
||||||
if bioxels_obj:
|
if bioxels_obj:
|
||||||
add_direct_driver(
|
add_direct_driver(
|
||||||
target=node,
|
target=node,
|
||||||
target_prop='{target_prop}',
|
target_prop='{target_prop}',
|
||||||
source=bioxels_obj,
|
source=container_obj,
|
||||||
source_prop='{source_prop}'
|
source_prop='{source_prop}'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -22,6 +23,20 @@ else:
|
|||||||
return callback_str
|
return callback_str
|
||||||
|
|
||||||
|
|
||||||
|
def set_prop_to_node_factory(source_prop, target_prop):
|
||||||
|
callback_str = f"""
|
||||||
|
import bpy
|
||||||
|
from bioxelnodes.utils import get_bioxels_obj
|
||||||
|
bioxels_obj = get_bioxels_obj(bpy.context.active_object)
|
||||||
|
container_obj = bioxels_obj.parent
|
||||||
|
if bioxels_obj:
|
||||||
|
node.inputs.get('{target_prop}').default_value = container_obj.get('{source_prop}')
|
||||||
|
else:
|
||||||
|
print('Cannot find any bioxels.')
|
||||||
|
"""
|
||||||
|
return callback_str
|
||||||
|
|
||||||
|
|
||||||
MENU_ITEMS = [
|
MENU_ITEMS = [
|
||||||
{
|
{
|
||||||
'label': 'Present',
|
'label': 'Present',
|
||||||
@@ -32,7 +47,20 @@ MENU_ITEMS = [
|
|||||||
'icon': 'OUTLINER_OB_META',
|
'icon': 'OUTLINER_OB_META',
|
||||||
'node_type': 'BioxelNodes_Segment',
|
'node_type': 'BioxelNodes_Segment',
|
||||||
'node_description': '',
|
'node_description': '',
|
||||||
'node_callback': add_driver_to_node_factory("value_offset", "Offset")
|
'node_callback': "\n".join([
|
||||||
|
set_prop_to_node_factory("bioxel_size", "Detail Size"),
|
||||||
|
set_prop_to_node_factory("bioxels_offset", "Offset"),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': 'Anatomy',
|
||||||
|
'icon': 'OUTLINER_OB_META',
|
||||||
|
'node_type': 'BioxelNodes_Anatomy',
|
||||||
|
'node_description': '',
|
||||||
|
'node_callback': "\n".join([
|
||||||
|
set_prop_to_node_factory("bioxel_size", "Detail Size"),
|
||||||
|
set_prop_to_node_factory("bioxels_offset", "Offset"),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -45,21 +73,30 @@ MENU_ITEMS = [
|
|||||||
'icon': 'AREA_JOIN',
|
'icon': 'AREA_JOIN',
|
||||||
'node_type': 'BioxelNodes_SegmentByLevel',
|
'node_type': 'BioxelNodes_SegmentByLevel',
|
||||||
'node_description': '',
|
'node_description': '',
|
||||||
'node_callback': add_driver_to_node_factory("value_offset", "Offset")
|
'node_callback': "\n".join([
|
||||||
|
set_prop_to_node_factory("bioxel_size", "Detail Size"),
|
||||||
|
set_prop_to_node_factory("bioxels_offset", "Offset"),
|
||||||
|
])
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': 'Segment by Range',
|
'label': 'Segment by Range',
|
||||||
'icon': 'AREA_SWAP',
|
'icon': 'AREA_SWAP',
|
||||||
'node_type': 'BioxelNodes_SegmentByRange',
|
'node_type': 'BioxelNodes_SegmentByRange',
|
||||||
'node_description': '',
|
'node_description': '',
|
||||||
'node_callback': add_driver_to_node_factory("value_offset", "Offset")
|
'node_callback': "\n".join([
|
||||||
|
set_prop_to_node_factory("bioxel_size", "Detail Size"),
|
||||||
|
set_prop_to_node_factory("bioxels_offset", "Offset"),
|
||||||
|
])
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': 'Segment by Layers',
|
'label': 'Segment by Layers',
|
||||||
'icon': 'OUTLINER_OB_FORCE_FIELD',
|
'icon': 'OUTLINER_OB_FORCE_FIELD',
|
||||||
'node_type': 'BioxelNodes_SegmentsByLayers',
|
'node_type': 'BioxelNodes_SegmentsByLayers',
|
||||||
'node_description': '',
|
'node_description': '',
|
||||||
'node_callback': add_driver_to_node_factory("value_offset", "Offset")
|
'node_callback': "\n".join([
|
||||||
|
set_prop_to_node_factory("bioxel_size", "Detail Size"),
|
||||||
|
set_prop_to_node_factory("bioxels_offset", "Offset"),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -80,11 +117,10 @@ MENU_ITEMS = [
|
|||||||
'icon': 'CLIPUV_DEHLT',
|
'icon': 'CLIPUV_DEHLT',
|
||||||
'items': [
|
'items': [
|
||||||
{
|
{
|
||||||
'label': 'LPS Slicer',
|
'label': 'RAS Slicer',
|
||||||
'icon': 'EMPTY_DATA',
|
'icon': 'EMPTY_DATA',
|
||||||
'node_type': 'BioxelNodes_LPS-Slicer',
|
'node_type': 'BioxelNodes_RAS-Slicer',
|
||||||
'node_description': '',
|
'node_description': ''
|
||||||
'node_callback': add_driver_to_node_factory("image_origin", "Origin")
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': 'Axis Slicer',
|
'label': 'Axis Slicer',
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ def show_message(message="", title="Message Box", icon='INFO'):
|
|||||||
|
|
||||||
def calc_bbox_verts(origin, size):
|
def calc_bbox_verts(origin, size):
|
||||||
bbox_origin = mathutils.Vector(
|
bbox_origin = mathutils.Vector(
|
||||||
(-origin[0], -origin[2], -origin[1]))
|
(origin[0], origin[1], origin[2]))
|
||||||
bbox_size = mathutils.Vector(
|
bbox_size = mathutils.Vector(
|
||||||
(-size[0], -size[2], -size[1]))
|
(size[0], size[1], size[2]))
|
||||||
bbox_verts = [
|
bbox_verts = [
|
||||||
(
|
(
|
||||||
bbox_origin[0] + 0,
|
bbox_origin[0] + 0,
|
||||||
@@ -62,17 +62,17 @@ def calc_bbox_verts(origin, size):
|
|||||||
|
|
||||||
def get_bioxels_obj(current_obj):
|
def get_bioxels_obj(current_obj):
|
||||||
bioxels_obj = None
|
bioxels_obj = None
|
||||||
if current_obj.get('bioxels'):
|
if current_obj.get('bioxels_container'):
|
||||||
bioxels_values = []
|
bioxels_values = []
|
||||||
for obj in bpy.data.objects:
|
for obj in bpy.data.objects:
|
||||||
if obj.parent == current_obj and obj.get('bioxels_values'):
|
if obj.parent == current_obj and obj.get('bioxels'):
|
||||||
bioxels_values.append(obj)
|
bioxels_values.append(obj)
|
||||||
|
|
||||||
if len(bioxels_values) > 0:
|
if len(bioxels_values) > 0:
|
||||||
bioxels_obj = bioxels_values[0]
|
bioxels_obj = bioxels_values[0]
|
||||||
|
|
||||||
elif current_obj.get('bioxels_values') and current_obj.parent:
|
elif current_obj.get('bioxels') and current_obj.parent:
|
||||||
if current_obj.parent.get('bioxels'):
|
if current_obj.parent.get('bioxels_container'):
|
||||||
bioxels_obj = current_obj
|
bioxels_obj = current_obj
|
||||||
|
|
||||||
return bioxels_obj
|
return bioxels_obj
|
||||||
|
|||||||
Reference in New Issue
Block a user