Newer
Older
Pablo Vazquez
committed
else:
space.show_only_render = True
return {'FINISHED'}
# FEATURE: Display Active Image Node on Image Editor
# Made by Sergey Sharybin, tweaks from Bassam Kurdali
image_nodes = {"CompositorNodeImage",
"ShaderNodeTexImage",
"ShaderNodeTexEnvironment"}
class AMTH_NODE_OT_show_active_node_image(Operator):
Pablo Vazquez
committed
"""Show active image node image in the image editor"""
bl_idname = "node.show_active_node_image"
bl_label = "Show Active Node Node"
bl_options = {'UNDO'}
def execute(self, context):
preferences = context.user_preferences.addons[__name__].preferences
if preferences.use_image_node_display:
if context.active_node:
active_node = context.active_node
if active_node.bl_idname in image_nodes and active_node.image:
for area in context.screen.areas:
if area.type == "IMAGE_EDITOR":
for space in area.spaces:
if space.type == "IMAGE_EDITOR":
space.image = active_node.image
break
Pablo Vazquez
committed
return {'FINISHED'}
# // FEATURE: Display Active Image Node on Image Editor
# FEATURE: Select Meshlights
class AMTH_OBJECT_OT_select_meshlights(Operator):
Pablo Vazquez
committed
"""Select light emitting meshes"""
bl_idname = "object.select_meshlights"
bl_label = "Select Meshlights"
bl_options = {'UNDO'}
@classmethod
def poll(cls, context):
return context.scene.render.engine == 'CYCLES'
def execute(self, context):
# Deselect everything first
bpy.ops.object.select_all(action='DESELECT')
for ob in context.scene.objects:
if cycles_is_emission(context, ob):
ob.select = True
context.scene.objects.active = ob
Pablo Vazquez
committed
if not context.selected_objects and not context.scene.objects.active:
self.report({'INFO'}, "No meshlights to select")
return {'FINISHED'}
def button_select_meshlights(self, context):
if cycles_exists and context.scene.render.engine == 'CYCLES':
Pablo Vazquez
committed
self.layout.operator('object.select_meshlights', icon="LAMP_SUN")
# // FEATURE: Select Meshlights
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
"""
Find asymmetric vertices
"""
bl_idname = "mesh.find_asymmetric"
bl_label = "Find Asymmetric"
bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
object = context.object
if object:
return object.mode == 'EDIT' and object.type == 'MESH'
return False
def execute(self, context):
threshold = 1e-6
object = context.object
bm = bmesh.from_edit_mesh(object.data)
# Deselect all the vertices
for v in bm.verts:
v.select = False
for v1 in bm.verts:
if abs(v1.co[0]) < threshold:
continue
mirror_found = False
for v2 in bm.verts:
if v1 == v2:
continue
if v1.co[0] * v2.co[0] > 0.0:
continue
mirror_coord = Vector(v2.co)
mirror_coord[0] *= -1
if (mirror_coord - v1.co).length_squared < threshold:
mirror_found = True
break
if not mirror_found:
v1.select = True
bm.select_flush_mode()
bmesh.update_edit_mesh(object.data)
return {'FINISHED'}
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
"""
Make symmetric
"""
bl_idname = "mesh.make_symmetric"
bl_label = "Make Symmetric"
bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
object = context.object
if object:
return object.mode == 'EDIT' and object.type == 'MESH'
return False
def execute(self, context):
threshold = 1e-6
object = context.object
bm = bmesh.from_edit_mesh(object.data)
for v1 in bm.verts:
if v1.co[0] < threshold:
continue
if not v1.select:
continue
closest_vert = None
closest_distance = -1
for v2 in bm.verts:
if v1 == v2:
continue
if v2.co[0] > threshold:
continue
if not v2.select:
continue
mirror_coord = Vector(v2.co)
mirror_coord[0] *= -1
distance = (mirror_coord - v1.co).length_squared
if closest_vert is None or distance < closest_distance:
closest_distance = distance
closest_vert = v2
if closest_vert:
closest_vert.select = False
closest_vert.co = Vector(v1.co)
closest_vert.co[0] *= -1
v1.select = False
for v1 in bm.verts:
if v1.select:
closest_vert = None
closest_distance = -1
for v2 in bm.verts:
if v1 != v2:
mirror_coord = Vector(v2.co)
mirror_coord[0] *= -1
distance = (mirror_coord - v1.co).length_squared
if closest_vert is None or distance < closest_distance:
closest_distance = distance
closest_vert = v2
if closest_vert:
v1.select = False
v1.co = Vector(closest_vert.co)
v1.co[0] *= -1
bm.select_flush_mode()
bmesh.update_edit_mesh(object.data)
return {'FINISHED'}
# // FEATURE: Mesh Symmetry Tools by Sergey Sharybin
def render_cycles_scene_samples(self, context):
layout = self.layout
scenes = bpy.data.scenes
scene = context.scene
if cycles_exists:
cscene = scene.cycles
list_sampling = scene.amaranth_cycles_list_sampling
# Set Render Samples
if cycles_exists and cscene.progressive == 'BRANCHED_PATH':
layout.separator()
split = layout.split()
col = split.column()
col.operator(
AMTH_RENDER_OT_cycles_samples_percentage_set.bl_idname,
text="%s" % 'Set as Render Samples' if cscene.use_samples_final else 'Set New Render Samples',
icon="%s" % 'PINNED' if cscene.use_samples_final else 'UNPINNED')
col = split.column()
row = col.row(align=True)
row.enabled = True if scene.get('amth_cycles_samples_final') else False
row.operator(
AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
text="100%").percent=100
row.operator(
AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
text="75%").percent=75
row.operator(
AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
text="50%").percent=50
row.operator(
AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
text="25%").percent=25
if (len(scene.render.layers) > 1) or \
(len(bpy.data.scenes) > 1):
box = layout.box()
row = box.row(align=True)
col = row.column(align=True)
row.alignment = 'LEFT'
row.prop(scene, 'amaranth_cycles_list_sampling',
icon="%s" % 'TRIA_DOWN' if list_sampling else 'TRIA_RIGHT',
emboss=False)
if list_sampling:
if len(scene.render.layers) == 1 and \
render.layers[0].samples == 0:
pass
else:
col.separator()
col.label(text="RenderLayers:", icon='RENDERLAYERS')
for rl in scene.render.layers:
row = col.row(align=True)
row.label(rl.name, icon='BLANK1')
row.prop(rl, "samples", text="%s" %
"Samples" if rl.samples > 0 else "Automatic (%s)" % (
cscene.aa_samples if cscene.progressive == 'BRANCHED_PATH' else cscene.samples))
if (len(bpy.data.scenes) > 1):
col.separator()
col.label(text="Scenes:", icon='SCENE_DATA')
if cycles_exists and cscene.progressive == 'PATH':
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
for s in bpy.data.scenes:
if s != scene:
row = col.row(align=True)
if s.render.engine == 'CYCLES':
cscene = s.cycles
row.label(s.name)
row.prop(cscene, "samples", icon='BLANK1')
else:
row.label(text="Scene: '%s' is not using Cycles" % s.name)
else:
for s in bpy.data.scenes:
if s != scene:
row = col.row(align=True)
if s.render.engine == 'CYCLES':
cscene = s.cycles
row.label(s.name, icon='BLANK1')
row.prop(cscene, "aa_samples",
text="AA Samples")
else:
row.label(text="Scene: '%s' is not using Cycles" % s.name)
CoDEmanX
committed
"""Clear motion paths from all bones"""
bl_idname = "pose.paths_clear_all"
bl_label = "Clear All Motion Paths"
bl_options = {'UNDO'}
CoDEmanX
committed
@classmethod
def poll(cls, context):
return context.mode == 'POSE'
def execute(self, context):
#silly but works
for b in context.object.data.bones:
b.select = True
bpy.ops.pose.paths_clear()
b.select = False
return {'FINISHED'}
"""Match Start/End frame of scene to motion path range"""
bl_idname = "pose.paths_frame_match"
bl_label = "Match Frame Range"
bl_options = {'UNDO'}
def execute(self, context):
avs = context.object.pose.animation_visualization
scene = context.scene
if avs.motion_path.type == 'RANGE':
if scene.use_preview_range:
avs.motion_path.frame_start = scene.frame_preview_start
avs.motion_path.frame_end = scene.frame_preview_end
else:
avs.motion_path.frame_start = scene.frame_start
avs.motion_path.frame_end = scene.frame_end
CoDEmanX
committed
if scene.use_preview_range:
avs.motion_path.frame_before = scene.frame_preview_start
avs.motion_path.frame_after = scene.frame_preview_end
else:
avs.motion_path.frame_before = scene.frame_start
avs.motion_path.frame_after = scene.frame_end
CoDEmanX
committed
return {'FINISHED'}
def pose_motion_paths_ui(self, context):
CoDEmanX
committed
layout = self.layout
scene = context.scene
avs = context.object.pose.animation_visualization
if context.active_pose_bone:
mpath = context.active_pose_bone.motion_path
layout.separator()
layout.label(text="Motion Paths Extras:")
CoDEmanX
committed
split = layout.split()
col = split.column(align=True)
if context.selected_pose_bones:
if mpath:
sub = col.row(align=True)
sub.operator("pose.paths_update", text="Update Path", icon='BONE_DATA')
sub.operator("pose.paths_clear", text="", icon='X')
else:
col.operator("pose.paths_calculate", text="Calculate Path", icon='BONE_DATA')
else:
col.label(text="Select Bones First", icon="ERROR")
col = split.column(align=True)
col.operator(AMTH_POSE_OT_paths_frame_match.bl_idname,
text="{}".format( "Set Preview Frame Range"
if scene.use_preview_range else "Set Frame Range"),
icon="{}".format("PREVIEW_RANGE"
if scene.use_preview_range else "TIME"))
col = layout.column()
row = col.row(align=True)
if avs.motion_path.type == 'RANGE':
row.prop(avs.motion_path, "frame_start", text="Start")
row.prop(avs.motion_path, "frame_end", text="End")
else:
row.prop(avs.motion_path, "frame_before", text="Before")
row.prop(avs.motion_path, "frame_after", text="After")
layout.separator()
layout.operator(AMTH_POSE_OT_paths_clear_all.bl_idname, icon="X")
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
# // FEATURE: Motion Paths Extras
# FEATURE: Final Render Resolution Display
def render_final_resolution_ui(self, context):
rd = context.scene.render
layout = self.layout
final_res_x = (rd.resolution_x * rd.resolution_percentage) / 100
final_res_y = (rd.resolution_y * rd.resolution_percentage) / 100
if rd.use_border:
final_res_x_border = round((final_res_x * (rd.border_max_x - rd.border_min_x)))
final_res_y_border = round((final_res_y * (rd.border_max_y - rd.border_min_y)))
layout.label(text="Final Resolution: {} x {} [Border: {} x {}]".format(
str(final_res_x)[:-2], str(final_res_y)[:-2],
str(final_res_x_border), str(final_res_y_border)))
else:
layout.label(text="Final Resolution: {} x {}".format(
str(final_res_x)[:-2], str(final_res_y)[:-2]))
# // FEATURE: Final Render Resolution Display
# FEATURE: Shader Nodes Extra Info
def node_shader_extra(self, context):
if context.space_data.tree_type == 'ShaderNodeTree':
ob = context.active_object
snode = context.space_data
layout = self.layout
if ob and snode.shader_type != 'WORLD':
if ob.type == 'LAMP':
layout.label(text="%s" % ob.name,
icon="LAMP_%s" % ob.data.type)
else:
layout.label(text="%s" % ob.name,
icon="OUTLINER_DATA_%s" % ob.type)
# // FEATURE: Shader Nodes Extra Info
# FEATURE: Scene Debug
class AMTH_SCENE_OT_cycles_shader_list_nodes(Operator):
"""List Cycles materials containing a specific shader"""
bl_idname = "scene.cycles_list_nodes"
bl_label = "List Materials"
@classmethod
def poll(cls, context):
return cycles_exists and context.scene.render.engine == 'CYCLES'
def execute(self, context):
node_type = context.scene.amaranth_cycles_node_types
roughness = False
shaders_roughness = ['BSDF_GLOSSY','BSDF_DIFFUSE','BSDF_GLASS']
print("\n=== Cycles Shader Type: %s === \n" % node_type)
for ma in bpy.data.materials:
if ma.node_tree:
nodes = ma.node_tree.nodes
print_unconnected = ('Note: \nOutput from "%s" node' % node_type,
'in material "%s"' % ma.name, 'not connected\n')
for no in nodes:
if no.type == node_type:
for ou in no.outputs:
if ou.links:
connected = True
if no.type in shaders_roughness:
roughness = 'R: %.4f' % no.inputs['Roughness'].default_value
else:
roughness = False
else:
self.__class__.materials.append('%s%s [%s] %s%s%s' % (
'[L] ' if ma.library else '',
ma.name, ma.users,
'[F]' if ma.use_fake_user else '',
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
' - [%s]' % roughness if roughness else '',
' * Output not connected' if not connected else ''))
elif no.type == 'GROUP':
if no.node_tree:
for nog in no.node_tree.nodes:
if nog.type == node_type:
for ou in nog.outputs:
if ou.links:
connected = True
if nog.type in shaders_roughness:
roughness = 'R: %.4f' % nog.inputs['Roughness'].default_value
else:
roughness = False
else:
connected = False
print(print_unconnected)
if ma.name not in self.__class__.materials:
self.__class__.materials.append('%s%s%s [%s] %s%s%s' % (
'[L] ' if ma.library else '',
'Node Group: %s%s -> ' % (
'[L] ' if no.node_tree.library else '',
no.node_tree.name),
ma.name, ma.users,
'[F]' if ma.use_fake_user else '',
' - [%s]' % roughness if roughness else '',
' * Output not connected' if not connected else ''))
self.__class__.materials = sorted(list(set(self.__class__.materials)))
self.report({"INFO"}, "No materials with nodes type %s found" % node_type)
print("* A total of %d %s using %s was found \n" % (
len(self.__class__.materials),
"material" if len(self.__class__.materials) == 1 else "materials",
print('%02d. %s' % (count+1, self.__class__.materials[count]))
self.__class__.materials = sorted(list(set(self.__class__.materials)))
class AMTH_SCENE_OT_cycles_shader_list_nodes_clear(Operator):
"""Clear the list below"""
bl_idname = "scene.cycles_list_nodes_clear"
bl_label = "Clear Materials List"
@classmethod
def poll(cls, context):
return cycles_exists
AMTH_SCENE_OT_cycles_shader_list_nodes.materials[:] = []
class AMTH_SCENE_OT_amaranth_object_select(Operator):
'''Select object'''
bl_idname = "scene.amaranth_object_select"
bl_label = "Select Object"
object = bpy.props.StringProperty()
if self.object:
object = bpy.data.objects[self.object]
bpy.ops.object.select_all(action='DESELECT')
object.select = True
context.scene.objects.active = object
class AMTH_SCENE_OT_list_missing_node_links(Operator):
'''Print a list of missing node links'''
bl_idname = "scene.list_missing_node_links"
bl_label = "List Missing Node Links"
self.__class__.count_groups = 0
self.__class__.count_images = 0
for ma in bpy.data.materials:
if ma.node_tree:
for no in ma.node_tree.nodes:
if no.type == 'GROUP':
if not no.node_tree:
self.__class__.count_groups += 1
users_ngroup = []
for ob in bpy.data.objects:
if ob.material_slots and ma.name in ob.material_slots:
users_ngroup.append("%s%s%s" % (
"[L] " if ob.library else "",
"[F] " if ob.use_fake_user else "",
ob.name))
missing_groups.append("MA: %s%s%s [%s]%s%s%s\n" % (
"[L] " if ma.library else "",
"[F] " if ma.use_fake_user else "",
ma.name, ma.users,
"\nLI: %s" %
ma.library.filepath if ma.library else "",
"\nOB: %s" % ', '.join(users_ngroup) if users_ngroup else ""))
if ma.library:
libraries.append(ma.library.filepath)
outputs_empty = not no.outputs['Color'].is_linked and not no.outputs['Alpha'].is_linked
if no.image:
import os.path
image_path_exists = os.path.exists(
bpy.path.abspath(
no.image.filepath, library=no.image.library))
if outputs_empty or not \
no.image or not \
image_path_exists:
users_images = []
for ob in bpy.data.objects:
if ob.material_slots and ma.name in ob.material_slots:
users_images.append("%s%s%s" % (
"[L] " if ob.library else "",
"[F] " if ob.use_fake_user else "",
ob.name))
if outputs_empty:
self.__class__.count_image_node_unlinked += 1
image_nodes_unlinked.append("%s%s%s%s%s [%s]%s%s%s%s%s\n" % (
"NO: %s" % no.name,
"\nMA: ",
"[L] " if ma.library else "",
"[F] " if ma.use_fake_user else "",
ma.name, ma.users,
"\nLI: %s" %
ma.library.filepath if ma.library else "",
"\nIM: %s" % no.image.name if no.image else "",
"\nLI: %s" % no.image.filepath if no.image and no.image.filepath else "",
"\nOB: %s" % ', '.join(users_images) if users_images else ""))
if not no.image or not image_path_exists:
self.__class__.count_images += 1
missing_images.append("MA: %s%s%s [%s]%s%s%s%s%s\n" % (
"[L] " if ma.library else "",
"[F] " if ma.use_fake_user else "",
ma.name, ma.users,
"\nLI: %s" %
ma.library.filepath if ma.library else "",
"\nIM: %s" % no.image.name if no.image else "",
"\nLI: %s" % no.image.filepath if no.image and no.image.filepath else "",
"\nOB: %s" % ', '.join(users_images) if users_images else ""))
if ma.library:
libraries.append(ma.library.filepath)
# Remove duplicates and sort
missing_groups = sorted(list(set(missing_groups)))
missing_images = sorted(list(set(missing_images)))
image_nodes_unlinked = sorted(list(set(image_nodes_unlinked)))
print("\n\n== %s missing image %s, %s missing node %s and %s image %s unlinked ==" %
("No" if self.__class__.count_images == 0 else str(self.__class__.count_images),
"node" if self.__class__.count_images == 1 else "nodes",
"no" if self.__class__.count_groups == 0 else str(self.__class__.count_groups),
"group" if self.__class__.count_groups == 1 else "groups",
"no" if self.__class__.count_image_node_unlinked == 0 else str(self.__class__.count_image_node_unlinked),
"node" if self.__class__.count_groups == 1 else "nodes"))
# List Missing Node Groups
if missing_groups:
for mig in missing_groups:
print(mig)
# List Missing Image Nodes
if missing_images:
# List Image Nodes with its outputs unlinked
if image_nodes_unlinked:
for nou in image_nodes_unlinked:
print(nou)
if missing_groups or \
missing_images or \
image_nodes_unlinked:
"this library" if len(libraries) == 1 else "these libraries"))
for li in libraries:
print(li)
else:
self.report({"INFO"}, "Yay! No missing node links")
print("\n")
if missing_groups and missing_images:
self.report({"WARNING"}, "%d missing image %s and %d missing node %s found" %
(self.__class__.count_images, "node" if self.__class__.count_images == 1 else "nodes",
self.__class__.count_groups, "group" if self.__class__.count_groups == 1 else "groups"))
return{'FINISHED'}
class AMTH_SCENE_OT_list_missing_material_slots(Operator):
'''List objects with empty material slots'''
bl_idname = "scene.list_missing_material_slots"
bl_label = "List Empty Material Slots"
def execute(self, context):
self.__class__.objects = []
for ob in bpy.data.objects:
for ma in ob.material_slots:
if not ma.material:
self.__class__.objects.append('%s%s' % (
'[L] ' if ob.library else '',
ob.name))
if ob.library:
self.__class__.libraries.append(ob.library.filepath)
self.__class__.objects = sorted(list(set(self.__class__.objects)))
self.__class__.libraries = sorted(list(set(self.__class__.libraries)))
if len(self.__class__.objects) == 0:
self.report({"INFO"}, "No objects with empty material slots found")
else:
print("\n* A total of %d %s with empty material slots was found \n" % (
len(self.__class__.objects),
"object" if len(self.__class__.objects) == 1 else "objects"))
count = 0
print('%02d. %s' % (
count+1, self.__class__.objects[count]))
if self.__class__.libraries:
print("\n\n* Check %s:\n" %
("this library" if len(self.__class__.libraries) == 1
else "these libraries"))
for libs in self.__class__.libraries:
print('%02d. %s' % (
count_lib+1, self.__class__.libraries[count_lib]))
count_lib += 1
class AMTH_SCENE_OT_list_missing_material_slots_clear(Operator):
"""Clear the list below"""
bl_idname = "scene.list_missing_material_slots_clear"
bl_label = "Clear Empty Material Slots List"
def execute(self, context):
AMTH_SCENE_OT_list_missing_material_slots.objects[:] = []
print("* Cleared Empty Material Slots List")
return {'FINISHED'}
class AMTH_SCENE_OT_blender_instance_open(Operator):
'''Open in a new Blender instance'''
bl_idname = "scene.blender_instance_open"
bl_label = "Open Blender Instance"
filepath = bpy.props.StringProperty()
import os.path
filepath = os.path.normpath(bpy.path.abspath(self.filepath))
import subprocess
try:
subprocess.Popen([bpy.app.binary_path, filepath])
except:
print("Error on the new Blender instance")
import traceback
traceback.print_exc()
'''Scene Debug'''
bl_label = 'Scene Debug'
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw_header(self, context):
layout = self.layout
layout.label(text="", icon="RADIO")
def draw(self, context):
layout = self.layout
scene = context.scene
objects = bpy.data.objects
ob_act = context.active_object
images = bpy.data.images
lamps = bpy.data.lamps
images_missing = []
list_missing_images = scene.amaranth_debug_scene_list_missing_images
materials = AMTH_SCENE_OT_cycles_shader_list_nodes.materials
materials_count = len(AMTH_SCENE_OT_cycles_shader_list_nodes.materials)
missing_material_slots_obs = AMTH_SCENE_OT_list_missing_material_slots.objects
missing_material_slots_count = len(AMTH_SCENE_OT_list_missing_material_slots.objects)
missing_material_slots_lib = AMTH_SCENE_OT_list_missing_material_slots.libraries
engine = scene.render.engine
# List Missing Images
box = layout.box()
row = box.row(align=True)
split = row.split()
col = split.column()
if images:
import os.path
for im in images:
if im.type not in ['UV_TEST', 'RENDER_RESULT', 'COMPOSITING']:
if not os.path.exists(bpy.path.abspath(im.filepath, library=im.library)):
images_missing.append(["%s%s [%s]%s" % (
'[L] ' if im.library else '',
im.name, im.users,
' [F]' if im.use_fake_user else ''),
im.filepath if im.filepath else 'No Filepath',
im.library.filepath if im.library else ''])
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
if images_missing:
row = col.row(align=True)
row.alignment = 'LEFT'
row.prop(scene, 'amaranth_debug_scene_list_missing_images',
icon="%s" % 'TRIA_DOWN' if list_missing_images else 'TRIA_RIGHT',
emboss=False)
split = split.split()
col = split.column()
col.label(text="%s missing %s" % (
str(len(images_missing)),
'image' if len(images_missing) == 1 else 'images'),
icon="ERROR")
if list_missing_images:
col = box.column(align=True)
for mis in images_missing:
col.label(text=mis[0],
icon="IMAGE_DATA")
col.label(text=mis[1], icon="LIBRARY_DATA_DIRECT")
if mis[2]:
row = col.row(align=True)
row.alignment = "LEFT"
row.operator(AMTH_SCENE_OT_blender_instance_open.bl_idname,
text=mis[2],
icon="LINK_BLEND",
emboss=False).filepath=mis[2]
col.separator()
else:
row = col.row(align=True)
row.alignment = 'LEFT'
row.label(text="Great! No missing images", icon="RIGHTARROW_THIN")
split = split.split()
col = split.column()
col.label(text="%s %s loading correctly" % (
str(len(images)),
'image' if len(images) == 1 else 'images'),
icon="IMAGE_DATA")
else:
row = col.row(align=True)
row.alignment = 'LEFT'
row.label(text="No images loaded yet", icon="RIGHTARROW_THIN")
# List Cycles Materials by Shader
box = layout.box()
split = box.split()
col = split.column(align=True)
col.prop(scene, 'amaranth_cycles_node_types',
icon="MATERIAL")
row = split.row(align=True)
row.operator(AMTH_SCENE_OT_cycles_shader_list_nodes.bl_idname,
icon="SORTSIZE",
text="List Materials Using Shader")
if materials_count != 0:
row.operator(AMTH_SCENE_OT_cycles_shader_list_nodes_clear.bl_idname,
icon="X", text="")
col.separator()
try:
materials
except NameError:
pass
else:
if materials_count != 0:
count = 0
col.label(text="%s %s found" % (materials_count,
'material' if materials_count == 1 else 'materials'), icon="INFO")
for mat in materials:
count += 1
col.label(text='%s' % (materials[count-1]), icon="MATERIAL")
# List Missing Node Trees
box = layout.box()
row = box.row(align=True)
split = row.split()
col = split.column(align=True)
split = col.split()
split.label(text="Node Links")
split.operator(AMTH_SCENE_OT_list_missing_node_links.bl_idname,
if AMTH_SCENE_OT_list_missing_node_links.count_groups != 0 or \
AMTH_SCENE_OT_list_missing_node_links.count_images != 0 or \
AMTH_SCENE_OT_list_missing_node_links.count_image_node_unlinked != 0:
col.label(text="Warning! Check Console", icon="ERROR")
if AMTH_SCENE_OT_list_missing_node_links.count_groups != 0:
str(AMTH_SCENE_OT_list_missing_node_links.count_groups),
"group" if AMTH_SCENE_OT_list_missing_node_links.count_groups == 1 else "groups")),
if AMTH_SCENE_OT_list_missing_node_links.count_images != 0:
str(AMTH_SCENE_OT_list_missing_node_links.count_images),
"node" if AMTH_SCENE_OT_list_missing_node_links.count_images == 1 else "nodes")),
if AMTH_SCENE_OT_list_missing_node_links.count_image_node_unlinked != 0:
col.label(text="%s" % ("%s image %s with no output conected" % (
str(AMTH_SCENE_OT_list_missing_node_links.count_image_node_unlinked),
"node" if AMTH_SCENE_OT_list_missing_node_links.count_image_node_unlinked == 1 else "nodes")),
icon="NODE")
# List Empty Materials Slots
box = layout.box()
split = box.split()
col = split.column(align=True)
col.label(text="Material Slots")
row = split.row(align=True)
row.operator(AMTH_SCENE_OT_list_missing_material_slots.bl_idname,
icon="MATERIAL",
text="List Empty Materials Slots")
if missing_material_slots_count != 0:
row.operator(AMTH_SCENE_OT_list_missing_material_slots_clear.bl_idname,
icon="X", text="")
col.separator()
try:
missing_material_slots_obs
except NameError:
pass
else:
if missing_material_slots_count != 0:
col = box.column(align=True)
count = 0
col.label(text="%s %s with empty material slots found" % (
missing_material_slots_count,
'object' if missing_material_slots_count == 1 else 'objects'),
icon="INFO")
for obs in missing_material_slots_obs:
count += 1
row.label(text='%s' % missing_material_slots_obs[count-1],
icon="OBJECT_DATA")
if missing_material_slots_lib:
col.separator()
col.label("Check %s:" % (
"this library" if
len(missing_material_slots_lib) == 1
else "these libraries"))
for libs in missing_material_slots_lib:
count_lib += 1
row = col.row(align=True)
row.alignment = "LEFT"
row.operator(AMTH_SCENE_OT_blender_instance_open.bl_idname,
text=missing_material_slots_lib[count_lib-1],
icon="LINK_BLEND",
emboss=False).filepath=missing_material_slots_lib[count_lib-1]
# FEATURE: Dupli Group Path
def ui_dupli_group_library_path(self, context):
row = self.layout.row()
row.alignment = 'LEFT'