Merge branch 'blender2.8' of git.blender.org:blender-addons into blender2.8
This commit is contained in:
commit
a97851a478
|
@ -105,8 +105,8 @@ class POSE_PT_selection_sets(Panel):
|
|||
|
||||
# add/remove/specials UI list Menu
|
||||
col = row.column(align=True)
|
||||
col.operator("pose.selection_set_add", icon='ZOOMIN', text="")
|
||||
col.operator("pose.selection_set_remove", icon='ZOOMOUT', text="")
|
||||
col.operator("pose.selection_set_add", icon='ADD', text="")
|
||||
col.operator("pose.selection_set_remove", icon='REMOVE', text="")
|
||||
col.menu("POSE_MT_selection_sets_specials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
# move up/down arrows
|
||||
|
|
|
@ -514,7 +514,7 @@ class OBJECT_PT_api_navigator(ApiNavigator, Panel):
|
|||
elif iterable == 'b':
|
||||
box = self.layout.box()
|
||||
row = box.row()
|
||||
row.label(text="Item Values", icon="OOPS")
|
||||
row.label(text="Item Values", icon='OUTLINER')
|
||||
box = box.box()
|
||||
col = box.column(align=True)
|
||||
collection = list(current_module)
|
||||
|
|
|
@ -399,7 +399,7 @@ class IV_OT_icons_show(bpy.types.Operator):
|
|||
header = header.split(factor=0.75) if self.selected_icon else \
|
||||
header.row()
|
||||
row = header.row(align=True)
|
||||
row.prop(pr, "show_matcap_icons", text="", icon='SMOOTH')
|
||||
row.prop(pr, "show_matcap_icons", text="", icon='SHADING_RENDERED')
|
||||
row.prop(pr, "show_brush_icons", text="", icon='BRUSH_DATA')
|
||||
row.prop(pr, "show_colorset_icons", text="", icon='COLOR')
|
||||
row.prop(pr, "show_event_icons", text="", icon='HAND')
|
||||
|
|
|
@ -26,10 +26,13 @@ bl_info = {
|
|||
"location": "File > Import-Export",
|
||||
"description": "Import-Export BVH from armature objects",
|
||||
"warning": "",
|
||||
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
|
||||
"Scripts/Import-Export/BVH_Importer_Exporter",
|
||||
"wiki_url": (
|
||||
"http://wiki.blender.org/index.php/Extensions:2.6/Py/"
|
||||
"Scripts/Import-Export/BVH_Importer_Exporter"
|
||||
),
|
||||
"support": 'OFFICIAL',
|
||||
"category": "Import-Export"}
|
||||
"category": "Import-Export",
|
||||
}
|
||||
|
||||
if "bpy" in locals():
|
||||
import importlib
|
||||
|
@ -213,10 +216,17 @@ class ExportBVH(bpy.types.Operator, ExportHelper):
|
|||
self.frame_start = context.scene.frame_start
|
||||
self.frame_end = context.scene.frame_end
|
||||
|
||||
keywords = self.as_keywords(ignore=("check_existing", "filter_glob"))
|
||||
keywords = self.as_keywords(
|
||||
ignore=(
|
||||
"axis_forward",
|
||||
"axis_up",
|
||||
"check_existing",
|
||||
"filter_glob",
|
||||
)
|
||||
)
|
||||
|
||||
from . import export_bvh
|
||||
return export_bvh.save(self, context, **keywords)
|
||||
return export_bvh.save(context, **keywords)
|
||||
|
||||
|
||||
def menu_func_import(self, context):
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
import bpy
|
||||
|
||||
|
||||
def write_armature(context,
|
||||
filepath,
|
||||
frame_start,
|
||||
frame_end,
|
||||
global_scale=1.0,
|
||||
rotate_mode='NATIVE',
|
||||
root_transform_only=False,
|
||||
):
|
||||
def write_armature(
|
||||
context,
|
||||
filepath,
|
||||
frame_start,
|
||||
frame_end,
|
||||
global_scale=1.0,
|
||||
rotate_mode='NATIVE',
|
||||
root_transform_only=False,
|
||||
):
|
||||
|
||||
def ensure_rot_order(rot_order_str):
|
||||
if set(rot_order_str) != {'X', 'Y', 'Z'}:
|
||||
|
@ -91,11 +92,11 @@ def write_armature(context,
|
|||
file.write("%sROOT %s\n" % (indent_str, bone_name))
|
||||
|
||||
file.write("%s{\n" % indent_str)
|
||||
file.write("%s\tOFFSET %.6f %.6f %.6f\n" % (indent_str, loc.x * global_scale, loc.y * global_scale, loc.z * global_scale))
|
||||
file.write("%s\tOFFSET %.6f %.6f %.6f\n" % (indent_str, *(loc * global_scale)))
|
||||
if (bone.use_connect or root_transform_only) and bone.parent:
|
||||
file.write("%s\tCHANNELS 3 %srotation %srotation %srotation\n" % (indent_str, rot_order_str[0], rot_order_str[1], rot_order_str[2]))
|
||||
file.write("%s\tCHANNELS 3 %srotation %srotation %srotation\n" % (indent_str, *rot_order_str))
|
||||
else:
|
||||
file.write("%s\tCHANNELS 6 Xposition Yposition Zposition %srotation %srotation %srotation\n" % (indent_str, rot_order_str[0], rot_order_str[1], rot_order_str[2]))
|
||||
file.write("%s\tCHANNELS 6 Xposition Yposition Zposition %srotation %srotation %srotation\n" % (indent_str, *rot_order_str))
|
||||
|
||||
if my_children:
|
||||
# store the location for the children
|
||||
|
@ -111,7 +112,7 @@ def write_armature(context,
|
|||
file.write("%s\tEnd Site\n" % indent_str)
|
||||
file.write("%s\t{\n" % indent_str)
|
||||
loc = bone.tail_local - node_locations[bone_name]
|
||||
file.write("%s\t\tOFFSET %.6f %.6f %.6f\n" % (indent_str, loc.x * global_scale, loc.y * global_scale, loc.z * global_scale))
|
||||
file.write("%s\t\tOFFSET %.6f %.6f %.6f\n" % (indent_str, *(loc * global_scale)))
|
||||
file.write("%s\t}\n" % indent_str)
|
||||
|
||||
file.write("%s}\n" % indent_str)
|
||||
|
@ -149,22 +150,34 @@ def write_armature(context,
|
|||
|
||||
class DecoratedBone:
|
||||
__slots__ = (
|
||||
"name", # bone name, used as key in many places
|
||||
# Bone name, used as key in many places.
|
||||
"name",
|
||||
"parent", # decorated bone parent, set in a later loop
|
||||
"rest_bone", # blender armature bone
|
||||
"pose_bone", # blender pose bone
|
||||
"pose_mat", # blender pose matrix
|
||||
"rest_arm_mat", # blender rest matrix (armature space)
|
||||
"rest_local_mat", # blender rest batrix (local space)
|
||||
"pose_imat", # pose_mat inverted
|
||||
"rest_arm_imat", # rest_arm_mat inverted
|
||||
"rest_local_imat", # rest_local_mat inverted
|
||||
"prev_euler", # last used euler to preserve euler compability in between keyframes
|
||||
"skip_position", # is the bone disconnected to the parent bone?
|
||||
# Blender armature bone.
|
||||
"rest_bone",
|
||||
# Blender pose bone.
|
||||
"pose_bone",
|
||||
# Blender pose matrix.
|
||||
"pose_mat",
|
||||
# Blender rest matrix (armature space).
|
||||
"rest_arm_mat",
|
||||
# Blender rest batrix (local space).
|
||||
"rest_local_mat",
|
||||
# Pose_mat inverted.
|
||||
"pose_imat",
|
||||
# Rest_arm_mat inverted.
|
||||
"rest_arm_imat",
|
||||
# Rest_local_mat inverted.
|
||||
"rest_local_imat",
|
||||
# Last used euler to preserve euler compability in between keyframes.
|
||||
"prev_euler",
|
||||
# Is the bone disconnected to the parent bone?
|
||||
"skip_position",
|
||||
"rot_order",
|
||||
"rot_order_str",
|
||||
"rot_order_str_reverse", # needed for the euler order when converting from a matrix
|
||||
)
|
||||
# Needed for the euler order when converting from a matrix.
|
||||
"rot_order_str_reverse",
|
||||
)
|
||||
|
||||
_eul_order_lookup = {
|
||||
'XYZ': (0, 1, 2),
|
||||
|
@ -173,7 +186,7 @@ def write_armature(context,
|
|||
'YZX': (1, 2, 0),
|
||||
'ZXY': (2, 0, 1),
|
||||
'ZYX': (2, 1, 0),
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, bone_name):
|
||||
self.name = bone_name
|
||||
|
@ -216,10 +229,7 @@ def write_armature(context,
|
|||
bones_decorated = [DecoratedBone(bone_name) for bone_name in serialized_names]
|
||||
|
||||
# Assign parents
|
||||
bones_decorated_dict = {}
|
||||
for dbone in bones_decorated:
|
||||
bones_decorated_dict[dbone.name] = dbone
|
||||
|
||||
bones_decorated_dict = {dbone.name: dbone for dbone in bones_decorated}
|
||||
for dbone in bones_decorated:
|
||||
parent = dbone.rest_bone.parent
|
||||
if parent:
|
||||
|
@ -227,7 +237,7 @@ def write_armature(context,
|
|||
del bones_decorated_dict
|
||||
# finish assigning parents
|
||||
|
||||
scene = bpy.context.scene
|
||||
scene = context.scene
|
||||
frame_current = scene.frame_current
|
||||
|
||||
file.write("MOTION\n")
|
||||
|
@ -244,7 +254,7 @@ def write_armature(context,
|
|||
trans = Matrix.Translation(dbone.rest_bone.head_local)
|
||||
itrans = Matrix.Translation(-dbone.rest_bone.head_local)
|
||||
|
||||
if dbone.parent:
|
||||
if dbone.parent:
|
||||
mat_final = dbone.parent.rest_arm_mat @ dbone.parent.pose_imat @ dbone.pose_mat @ dbone.rest_arm_imat
|
||||
mat_final = itrans @ mat_final @ trans
|
||||
loc = mat_final.to_translation() + (dbone.rest_bone.head_local - dbone.parent.rest_bone.head_local)
|
||||
|
@ -272,20 +282,21 @@ def write_armature(context,
|
|||
print("BVH Exported: %s frames:%d\n" % (filepath, frame_end - frame_start + 1))
|
||||
|
||||
|
||||
def save(operator, context, filepath="",
|
||||
frame_start=-1,
|
||||
frame_end=-1,
|
||||
global_scale=1.0,
|
||||
rotate_mode="NATIVE",
|
||||
root_transform_only=False,
|
||||
):
|
||||
|
||||
write_armature(context, filepath,
|
||||
frame_start=frame_start,
|
||||
frame_end=frame_end,
|
||||
global_scale=global_scale,
|
||||
rotate_mode=rotate_mode,
|
||||
root_transform_only=root_transform_only,
|
||||
)
|
||||
def save(
|
||||
context, filepath="",
|
||||
frame_start=-1,
|
||||
frame_end=-1,
|
||||
global_scale=1.0,
|
||||
rotate_mode="NATIVE",
|
||||
root_transform_only=False,
|
||||
):
|
||||
write_armature(
|
||||
context, filepath,
|
||||
frame_start=frame_start,
|
||||
frame_end=frame_end,
|
||||
global_scale=global_scale,
|
||||
rotate_mode=rotate_mode,
|
||||
root_transform_only=root_transform_only,
|
||||
)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -28,22 +28,41 @@ from mathutils import Vector, Euler, Matrix
|
|||
|
||||
class BVH_Node:
|
||||
__slots__ = (
|
||||
'name', # bvh joint name
|
||||
'parent', # BVH_Node type or None for no parent
|
||||
'children', # a list of children of this type.
|
||||
'rest_head_world', # worldspace rest location for the head of this node
|
||||
'rest_head_local', # localspace rest location for the head of this node
|
||||
'rest_tail_world', # worldspace rest location for the tail of this node
|
||||
'rest_tail_local', # worldspace rest location for the tail of this node
|
||||
'channels', # list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, loc triple then rot triple
|
||||
'rot_order', # a triple of indices as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
|
||||
'rot_order_str', # same as above but a string 'XYZ' format.
|
||||
'anim_data', # a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz), euler rotation ALWAYS stored xyz order, even when native used.
|
||||
'has_loc', # Convenience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 or channels[2]!=-1)
|
||||
'has_rot', # Convenience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 or channels[5]!=-1)
|
||||
'index', # index from the file, not strictly needed but nice to maintain order
|
||||
'temp', # use this for whatever you want
|
||||
)
|
||||
# Bvh joint name.
|
||||
'name',
|
||||
# BVH_Node type or None for no parent.
|
||||
'parent',
|
||||
# A list of children of this type..
|
||||
'children',
|
||||
# Worldspace rest location for the head of this node.
|
||||
'rest_head_world',
|
||||
# Localspace rest location for the head of this node.
|
||||
'rest_head_local',
|
||||
# Worldspace rest location for the tail of this node.
|
||||
'rest_tail_world',
|
||||
# Worldspace rest location for the tail of this node.
|
||||
'rest_tail_local',
|
||||
# List of 6 ints, -1 for an unused channel,
|
||||
# otherwise an index for the BVH motion data lines,
|
||||
# loc triple then rot triple.
|
||||
'channels',
|
||||
# A triple of indices as to the order rotation is applied.
|
||||
# [0,1,2] is x/y/z - [None, None, None] if no rotation..
|
||||
'rot_order',
|
||||
# Same as above but a string 'XYZ' format..
|
||||
'rot_order_str',
|
||||
# A list one tuple's one for each frame: (locx, locy, locz, rotx, roty, rotz),
|
||||
# euler rotation ALWAYS stored xyz order, even when native used.
|
||||
'anim_data',
|
||||
# Convenience function, bool, same as: (channels[0] != -1 or channels[1] != -1 or channels[2] != -1).
|
||||
'has_loc',
|
||||
# Convenience function, bool, same as: (channels[3] != -1 or channels[4] != -1 or channels[5] != -1).
|
||||
'has_rot',
|
||||
# Index from the file, not strictly needed but nice to maintain order.
|
||||
'index',
|
||||
# Use this for whatever you want.
|
||||
'temp',
|
||||
)
|
||||
|
||||
_eul_order_lookup = {
|
||||
(None, None, None): 'XYZ', # XXX Dummy one, no rotation anyway!
|
||||
|
@ -53,7 +72,7 @@ class BVH_Node:
|
|||
(1, 2, 0): 'YZX',
|
||||
(2, 0, 1): 'ZXY',
|
||||
(2, 1, 0): 'ZYX',
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order, index):
|
||||
self.name = name
|
||||
|
@ -73,16 +92,18 @@ class BVH_Node:
|
|||
|
||||
self.children = []
|
||||
|
||||
# list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
|
||||
# even if the channels aren't used they will just be zero
|
||||
#
|
||||
# List of 6 length tuples: (lx, ly, lz, rx, ry, rz)
|
||||
# even if the channels aren't used they will just be zero.
|
||||
self.anim_data = [(0, 0, 0, 0, 0, 0)]
|
||||
|
||||
def __repr__(self):
|
||||
return ("BVH name: '%s', rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)" %
|
||||
(self.name,
|
||||
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,
|
||||
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z))
|
||||
return (
|
||||
"BVH name: '%s', rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)" % (
|
||||
self.name,
|
||||
*self.rest_head_world,
|
||||
*self.rest_head_world,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def sorted_nodes(bvh_nodes):
|
||||
|
@ -107,7 +128,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
|
||||
# Create hierarchy as empties
|
||||
if file_lines[0][0].lower() == 'hierarchy':
|
||||
#print 'Importing the BVH Hierarchy for:', file_path
|
||||
# print 'Importing the BVH Hierarchy for:', file_path
|
||||
pass
|
||||
else:
|
||||
raise Exception("This is not a BVH file")
|
||||
|
@ -121,8 +142,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
|
||||
lineIdx = 0 # An index for the file.
|
||||
while lineIdx < len(file_lines) - 1:
|
||||
#...
|
||||
if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
|
||||
if file_lines[lineIdx][0].lower() in {'root', 'joint'}:
|
||||
|
||||
# Join spaces into 1 word with underscores joining it.
|
||||
if len(file_lines[lineIdx]) > 2:
|
||||
|
@ -134,10 +154,14 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
# Make sure the names are unique - Object names will match joint names exactly and both will be unique.
|
||||
name = file_lines[lineIdx][1]
|
||||
|
||||
#print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1])
|
||||
# print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1])
|
||||
|
||||
lineIdx += 2 # Increment to the next line (Offset)
|
||||
rest_head_local = Vector((float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3]))) * global_scale
|
||||
rest_head_local = global_scale * Vector((
|
||||
float(file_lines[lineIdx][1]),
|
||||
float(file_lines[lineIdx][2]),
|
||||
float(file_lines[lineIdx][3]),
|
||||
))
|
||||
lineIdx += 1 # Increment to the next line (Channels)
|
||||
|
||||
# newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
|
||||
|
@ -180,21 +204,35 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
else:
|
||||
rest_head_world = my_parent.rest_head_world + rest_head_local
|
||||
|
||||
bvh_node = bvh_nodes[name] = BVH_Node(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order, len(bvh_nodes) - 1)
|
||||
bvh_node = bvh_nodes[name] = BVH_Node(
|
||||
name,
|
||||
rest_head_world,
|
||||
rest_head_local,
|
||||
my_parent,
|
||||
my_channel,
|
||||
my_rot_order,
|
||||
len(bvh_nodes) - 1,
|
||||
)
|
||||
|
||||
# If we have another child then we can call ourselves a parent, else
|
||||
bvh_nodes_serial.append(bvh_node)
|
||||
|
||||
# Account for an end node
|
||||
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is sometimes a name after 'End Site' but we will ignore it.
|
||||
lineIdx += 2 # Increment to the next line (Offset)
|
||||
rest_tail = Vector((float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3]))) * global_scale
|
||||
# Account for an end node.
|
||||
# There is sometimes a name after 'End Site' but we will ignore it.
|
||||
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site':
|
||||
# Increment to the next line (Offset)
|
||||
lineIdx += 2
|
||||
rest_tail = global_scale * Vector((
|
||||
float(file_lines[lineIdx][1]),
|
||||
float(file_lines[lineIdx][2]),
|
||||
float(file_lines[lineIdx][3]),
|
||||
))
|
||||
|
||||
bvh_nodes_serial[-1].rest_tail_world = bvh_nodes_serial[-1].rest_head_world + rest_tail
|
||||
bvh_nodes_serial[-1].rest_tail_local = bvh_nodes_serial[-1].rest_head_local + rest_tail
|
||||
|
||||
# Just so we can remove the Parents in a uniform way - End has kids
|
||||
# so this is a placeholder
|
||||
# Just so we can remove the parents in a uniform way,
|
||||
# the end has kids so this is a placeholder.
|
||||
bvh_nodes_serial.append(None)
|
||||
|
||||
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
|
||||
|
@ -207,16 +245,18 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
# Frame Time: dt
|
||||
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
|
||||
lineIdx += 1 # Read frame count.
|
||||
if (len(file_lines[lineIdx]) == 2 and
|
||||
file_lines[lineIdx][0].lower() == 'frames:'):
|
||||
|
||||
if (
|
||||
len(file_lines[lineIdx]) == 2 and
|
||||
file_lines[lineIdx][0].lower() == 'frames:'
|
||||
):
|
||||
bvh_frame_count = int(file_lines[lineIdx][1])
|
||||
|
||||
lineIdx += 1 # Read frame rate.
|
||||
if (len(file_lines[lineIdx]) == 3 and
|
||||
file_lines[lineIdx][0].lower() == 'frame' and
|
||||
file_lines[lineIdx][1].lower() == 'time:'):
|
||||
|
||||
if (
|
||||
len(file_lines[lineIdx]) == 3 and
|
||||
file_lines[lineIdx][0].lower() == 'frame' and
|
||||
file_lines[lineIdx][1].lower() == 'time:'
|
||||
):
|
||||
bvh_frame_time = float(file_lines[lineIdx][2])
|
||||
|
||||
lineIdx += 1 # Set the cursor to the first frame
|
||||
|
@ -227,7 +267,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
|
||||
# Remove the None value used for easy parent reference
|
||||
del bvh_nodes[None]
|
||||
# Dont use anymore
|
||||
# Don't use anymore
|
||||
del bvh_nodes_serial
|
||||
|
||||
# importing world with any order but nicer to maintain order
|
||||
|
@ -237,7 +277,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
while lineIdx < len(file_lines):
|
||||
line = file_lines[lineIdx]
|
||||
for bvh_node in bvh_nodes_list:
|
||||
#for bvh_node in bvh_nodes_serial:
|
||||
# for bvh_node in bvh_nodes_serial:
|
||||
lx = ly = lz = rx = ry = rz = 0.0
|
||||
channels = bvh_node.channels
|
||||
anim_data = bvh_node.anim_data
|
||||
|
@ -279,7 +319,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0):
|
|||
bvh_node.rest_tail_local = bvh_node.rest_head_local + bvh_node.children[0].rest_head_local
|
||||
else:
|
||||
# allow this, see above
|
||||
#if not bvh_node.children:
|
||||
# if not bvh_node.children:
|
||||
# raise Exception("bvh node has no end and no children. bad file")
|
||||
|
||||
# Removed temp for now
|
||||
|
@ -364,16 +404,17 @@ def bvh_node_dict2objects(context, bvh_name, bvh_nodes, rotate_mode='NATIVE', fr
|
|||
return objects
|
||||
|
||||
|
||||
def bvh_node_dict2armature(context,
|
||||
bvh_name,
|
||||
bvh_nodes,
|
||||
bvh_frame_time,
|
||||
rotate_mode='XYZ',
|
||||
frame_start=1,
|
||||
IMPORT_LOOP=False,
|
||||
global_matrix=None,
|
||||
use_fps_scale=False,
|
||||
):
|
||||
def bvh_node_dict2armature(
|
||||
context,
|
||||
bvh_name,
|
||||
bvh_nodes,
|
||||
bvh_frame_time,
|
||||
rotate_mode='XYZ',
|
||||
frame_start=1,
|
||||
IMPORT_LOOP=False,
|
||||
global_matrix=None,
|
||||
use_fps_scale=False,
|
||||
):
|
||||
|
||||
if frame_start < 1:
|
||||
frame_start = 1
|
||||
|
@ -447,10 +488,11 @@ def bvh_node_dict2armature(context,
|
|||
bvh_node.temp.parent = bvh_node.parent.temp
|
||||
|
||||
# Set the connection state
|
||||
if((not bvh_node.has_loc) and
|
||||
(bvh_node.parent.temp.name not in ZERO_AREA_BONES) and
|
||||
(bvh_node.parent.rest_tail_local == bvh_node.rest_head_local)):
|
||||
|
||||
if(
|
||||
(not bvh_node.has_loc) and
|
||||
(bvh_node.parent.temp.name not in ZERO_AREA_BONES) and
|
||||
(bvh_node.parent.rest_tail_local == bvh_node.rest_head_local)
|
||||
):
|
||||
bvh_node.temp.use_connect = True
|
||||
|
||||
# Replace the editbone with the editbone name,
|
||||
|
@ -521,7 +563,7 @@ def bvh_node_dict2armature(context,
|
|||
for frame_i in range(1, num_frame):
|
||||
time[frame_i] += float(frame_i)
|
||||
|
||||
#print("bvh_frame_time = %f, dt = %f, num_frame = %d"
|
||||
# print("bvh_frame_time = %f, dt = %f, num_frame = %d"
|
||||
# % (bvh_frame_time, dt, num_frame]))
|
||||
|
||||
for i, bvh_node in enumerate(bvh_nodes_list):
|
||||
|
@ -537,7 +579,7 @@ def bvh_node_dict2armature(context,
|
|||
bvh_loc = bvh_node.anim_data[frame_i + skip_frame][:3]
|
||||
|
||||
bone_translate_matrix = Matrix.Translation(
|
||||
Vector(bvh_loc) - bvh_node.rest_head_local)
|
||||
Vector(bvh_loc) - bvh_node.rest_head_local)
|
||||
location[frame_i] = (bone_rest_matrix_inv @
|
||||
bone_translate_matrix).to_translation()
|
||||
|
||||
|
@ -548,8 +590,10 @@ def bvh_node_dict2armature(context,
|
|||
keyframe_points.add(num_frame)
|
||||
|
||||
for frame_i in range(num_frame):
|
||||
keyframe_points[frame_i].co = \
|
||||
(time[frame_i], location[frame_i][axis_i])
|
||||
keyframe_points[frame_i].co = (
|
||||
time[frame_i],
|
||||
location[frame_i][axis_i],
|
||||
)
|
||||
|
||||
if bvh_node.has_rot:
|
||||
data_path = None
|
||||
|
@ -572,26 +616,30 @@ def bvh_node_dict2armature(context,
|
|||
# note that the rot_order_str is reversed.
|
||||
euler = Euler(bvh_rot, bvh_node.rot_order_str[::-1])
|
||||
bone_rotation_matrix = euler.to_matrix().to_4x4()
|
||||
bone_rotation_matrix = (bone_rest_matrix_inv @
|
||||
bone_rotation_matrix @
|
||||
bone_rest_matrix)
|
||||
bone_rotation_matrix = (
|
||||
bone_rest_matrix_inv @
|
||||
bone_rotation_matrix @
|
||||
bone_rest_matrix
|
||||
)
|
||||
|
||||
if 4 == len(rotate[frame_i]):
|
||||
if len(rotate[frame_i]) == 4:
|
||||
rotate[frame_i] = bone_rotation_matrix.to_quaternion()
|
||||
else:
|
||||
rotate[frame_i] = bone_rotation_matrix.to_euler(
|
||||
pose_bone.rotation_mode, prev_euler)
|
||||
pose_bone.rotation_mode, prev_euler)
|
||||
prev_euler = rotate[frame_i]
|
||||
|
||||
# For each Euler angle x, y, z (or Quaternion w, x, y, z).
|
||||
# For each euler angle x, y, z (or quaternion w, x, y, z).
|
||||
for axis_i in range(len(rotate[0])):
|
||||
curve = action.fcurves.new(data_path=data_path, index=axis_i)
|
||||
keyframe_points = curve.keyframe_points
|
||||
curve.keyframe_points.add(num_frame)
|
||||
keyframe_points.add(num_frame)
|
||||
|
||||
for frame_i in range(0, num_frame):
|
||||
keyframe_points[frame_i].co = \
|
||||
(time[frame_i], rotate[frame_i][axis_i])
|
||||
for frame_i in range(num_frame):
|
||||
keyframe_points[frame_i].co = (
|
||||
time[frame_i],
|
||||
rotate[frame_i][axis_i],
|
||||
)
|
||||
|
||||
for cu in action.fcurves:
|
||||
if IMPORT_LOOP:
|
||||
|
@ -607,28 +655,30 @@ def bvh_node_dict2armature(context,
|
|||
return arm_ob
|
||||
|
||||
|
||||
def load(context,
|
||||
filepath,
|
||||
*,
|
||||
target='ARMATURE',
|
||||
rotate_mode='NATIVE',
|
||||
global_scale=1.0,
|
||||
use_cyclic=False,
|
||||
frame_start=1,
|
||||
global_matrix=None,
|
||||
use_fps_scale=False,
|
||||
update_scene_fps=False,
|
||||
update_scene_duration=False,
|
||||
report=print
|
||||
):
|
||||
|
||||
def load(
|
||||
context,
|
||||
filepath,
|
||||
*,
|
||||
target='ARMATURE',
|
||||
rotate_mode='NATIVE',
|
||||
global_scale=1.0,
|
||||
use_cyclic=False,
|
||||
frame_start=1,
|
||||
global_matrix=None,
|
||||
use_fps_scale=False,
|
||||
update_scene_fps=False,
|
||||
update_scene_duration=False,
|
||||
report=print,
|
||||
):
|
||||
import time
|
||||
t1 = time.time()
|
||||
print("\tparsing bvh %r..." % filepath, end="")
|
||||
|
||||
bvh_nodes, bvh_frame_time, bvh_frame_count = read_bvh(context, filepath,
|
||||
rotate_mode=rotate_mode,
|
||||
global_scale=global_scale)
|
||||
bvh_nodes, bvh_frame_time, bvh_frame_count = read_bvh(
|
||||
context, filepath,
|
||||
rotate_mode=rotate_mode,
|
||||
global_scale=global_scale,
|
||||
)
|
||||
|
||||
print("%.4f" % (time.time() - t1))
|
||||
|
||||
|
@ -637,9 +687,12 @@ def load(context,
|
|||
|
||||
# Broken BVH handling: guess frame rate when it is not contained in the file.
|
||||
if bvh_frame_time is None:
|
||||
report({'WARNING'}, "The BVH file does not contain frame duration in its MOTION "
|
||||
"section, assuming the BVH and Blender scene have the same "
|
||||
"frame rate")
|
||||
report(
|
||||
{'WARNING'},
|
||||
"The BVH file does not contain frame duration in its MOTION "
|
||||
"section, assuming the BVH and Blender scene have the same "
|
||||
"frame rate"
|
||||
)
|
||||
bvh_frame_time = scene.render.fps_base / scene.render.fps
|
||||
# No need to scale the frame rate, as they're equal now anyway.
|
||||
use_fps_scale = False
|
||||
|
@ -652,8 +705,7 @@ def load(context,
|
|||
use_fps_scale = False
|
||||
|
||||
if update_scene_duration:
|
||||
_update_scene_duration(context, report, bvh_frame_count, bvh_frame_time, frame_start,
|
||||
use_fps_scale)
|
||||
_update_scene_duration(context, report, bvh_frame_count, bvh_frame_time, frame_start, use_fps_scale)
|
||||
|
||||
t1 = time.time()
|
||||
print("\timporting to blender...", end="")
|
||||
|
@ -661,21 +713,23 @@ def load(context,
|
|||
bvh_name = bpy.path.display_name_from_filepath(filepath)
|
||||
|
||||
if target == 'ARMATURE':
|
||||
bvh_node_dict2armature(context, bvh_name, bvh_nodes, bvh_frame_time,
|
||||
rotate_mode=rotate_mode,
|
||||
frame_start=frame_start,
|
||||
IMPORT_LOOP=use_cyclic,
|
||||
global_matrix=global_matrix,
|
||||
use_fps_scale=use_fps_scale,
|
||||
)
|
||||
bvh_node_dict2armature(
|
||||
context, bvh_name, bvh_nodes, bvh_frame_time,
|
||||
rotate_mode=rotate_mode,
|
||||
frame_start=frame_start,
|
||||
IMPORT_LOOP=use_cyclic,
|
||||
global_matrix=global_matrix,
|
||||
use_fps_scale=use_fps_scale,
|
||||
)
|
||||
|
||||
elif target == 'OBJECT':
|
||||
bvh_node_dict2objects(context, bvh_name, bvh_nodes,
|
||||
rotate_mode=rotate_mode,
|
||||
frame_start=frame_start,
|
||||
IMPORT_LOOP=use_cyclic,
|
||||
# global_matrix=global_matrix, # TODO
|
||||
)
|
||||
bvh_node_dict2objects(
|
||||
context, bvh_name, bvh_nodes,
|
||||
rotate_mode=rotate_mode,
|
||||
frame_start=frame_start,
|
||||
IMPORT_LOOP=use_cyclic,
|
||||
# global_matrix=global_matrix, # TODO
|
||||
)
|
||||
|
||||
else:
|
||||
report({'ERROR'}, "Invalid target %r (must be 'ARMATURE' or 'OBJECT')" % target)
|
||||
|
@ -693,8 +747,11 @@ def _update_scene_fps(context, report, bvh_frame_time):
|
|||
|
||||
# Broken BVH handling: prevent division by zero.
|
||||
if bvh_frame_time == 0.0:
|
||||
report({'WARNING'}, "Unable to update scene frame rate, as the BVH file "
|
||||
"contains a zero frame duration in its MOTION section")
|
||||
report(
|
||||
{'WARNING'},
|
||||
"Unable to update scene frame rate, as the BVH file "
|
||||
"contains a zero frame duration in its MOTION section",
|
||||
)
|
||||
return
|
||||
|
||||
scene = context.scene
|
||||
|
@ -707,13 +764,17 @@ def _update_scene_fps(context, report, bvh_frame_time):
|
|||
scene.render.fps_base = 1.0
|
||||
|
||||
|
||||
def _update_scene_duration(context, report, bvh_frame_count, bvh_frame_time, frame_start,
|
||||
use_fps_scale):
|
||||
def _update_scene_duration(
|
||||
context, report, bvh_frame_count, bvh_frame_time, frame_start,
|
||||
use_fps_scale):
|
||||
"""Extend the scene's duration so that the BVH file fits in its entirety."""
|
||||
|
||||
if bvh_frame_count is None:
|
||||
report({'WARNING'}, "Unable to extend the scene duration, as the BVH file does not "
|
||||
"contain the number of frames in its MOTION section")
|
||||
report(
|
||||
{'WARNING'},
|
||||
"Unable to extend the scene duration, as the BVH file does not "
|
||||
"contain the number of frames in its MOTION section",
|
||||
)
|
||||
return
|
||||
|
||||
# Not likely, but it can happen when a BVH is just used to store an armature.
|
||||
|
|
|
@ -2238,8 +2238,8 @@ class ExportPaperModel(bpy.types.Operator):
|
|||
|
||||
row = layout.row(align=True)
|
||||
row.menu("VIEW3D_MT_paper_model_presets", text=bpy.types.VIEW3D_MT_paper_model_presets.bl_label)
|
||||
row.operator("export_mesh.paper_model_preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("export_mesh.paper_model_preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
row.operator("export_mesh.paper_model_preset_add", text="", icon='ADD')
|
||||
row.operator("export_mesh.paper_model_preset_add", text="", icon='REMOVE').remove_active = True
|
||||
|
||||
# a little hack: this prints out something like "Scale: 1: 72"
|
||||
layout.prop(self.properties, "scale", text="Scale: 1")
|
||||
|
|
132
io_export_pc2.py
132
io_export_pc2.py
|
@ -19,8 +19,8 @@
|
|||
bl_info = {
|
||||
"name": "Export Pointcache Format(.pc2)",
|
||||
"author": "Florian Meyer (tstscr)",
|
||||
"version": (1, 1, 1),
|
||||
"blender": (2, 71, 0),
|
||||
"version": (1, 1, 2),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "File > Export > Pointcache (.pc2)",
|
||||
"description": "Export mesh Pointcache data (.pc2)",
|
||||
"warning": "",
|
||||
|
@ -50,9 +50,11 @@ import time
|
|||
import math
|
||||
import struct
|
||||
|
||||
|
||||
def get_sampled_frames(start, end, sampling):
|
||||
return [math.modf(start + x * sampling) for x in range(int((end - start) / sampling) + 1)]
|
||||
|
||||
|
||||
def do_export(context, props, filepath):
|
||||
mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
|
||||
ob = context.active_object
|
||||
|
@ -61,13 +63,13 @@ def do_export(context, props, filepath):
|
|||
end = props.range_end
|
||||
sampling = float(props.sampling)
|
||||
apply_modifiers = props.apply_modifiers
|
||||
me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW')
|
||||
me = ob.to_mesh(context.depsgraph, apply_modifiers)
|
||||
vertCount = len(me.vertices)
|
||||
sampletimes = get_sampled_frames(start, end, sampling)
|
||||
sampleCount = len(sampletimes)
|
||||
|
||||
# Create the header
|
||||
headerFormat='<12siiffi'
|
||||
headerFormat = '<12siiffi'
|
||||
headerStr = struct.pack(headerFormat, b'POINTCACHE2\0',
|
||||
1, vertCount, start, sampling, sampleCount)
|
||||
|
||||
|
@ -75,8 +77,9 @@ def do_export(context, props, filepath):
|
|||
file.write(headerStr)
|
||||
|
||||
for frame in sampletimes:
|
||||
sc.frame_set(int(frame[1]), frame[0]) # stupid modf() gives decimal part first!
|
||||
me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW')
|
||||
# stupid modf() gives decimal part first!
|
||||
sc.frame_set(int(frame[1]), subframe=frame[0])
|
||||
me = ob.to_mesh(context.depsgraph, apply_modifiers)
|
||||
|
||||
if len(me.vertices) != vertCount:
|
||||
bpy.data.meshes.remove(me, do_unlink=True)
|
||||
|
@ -97,19 +100,18 @@ def do_export(context, props, filepath):
|
|||
|
||||
for v in me.vertices:
|
||||
thisVertex = struct.pack('<fff', float(v.co[0]),
|
||||
float(v.co[1]),
|
||||
float(v.co[2]))
|
||||
float(v.co[1]),
|
||||
float(v.co[2]))
|
||||
file.write(thisVertex)
|
||||
|
||||
bpy.data.meshes.remove(me, do_unlink=True)
|
||||
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
return True
|
||||
|
||||
|
||||
###### EXPORT OPERATOR #######
|
||||
# EXPORT OPERATOR
|
||||
class Export_pc2(bpy.types.Operator, ExportHelper):
|
||||
"""Export the active Object as a .pc2 Pointcache file"""
|
||||
bl_idname = "export_shape.pc2"
|
||||
|
@ -117,50 +119,51 @@ class Export_pc2(bpy.types.Operator, ExportHelper):
|
|||
|
||||
filename_ext = ".pc2"
|
||||
|
||||
rot_x90 = BoolProperty(name="Convert to Y-up",
|
||||
description="Rotate 90 degrees around X to convert to y-up",
|
||||
default=True,
|
||||
)
|
||||
world_space = BoolProperty(name="Export into Worldspace",
|
||||
description="Transform the Vertexcoordinates into Worldspace",
|
||||
default=False,
|
||||
)
|
||||
apply_modifiers = BoolProperty(name="Apply Modifiers",
|
||||
description="Applies the Modifiers",
|
||||
default=True,
|
||||
)
|
||||
range_start = IntProperty(name='Start Frame',
|
||||
description='First frame to use for Export',
|
||||
default=1,
|
||||
)
|
||||
range_end = IntProperty(name='End Frame',
|
||||
description='Last frame to use for Export',
|
||||
default=250,
|
||||
)
|
||||
sampling = EnumProperty(name='Sampling',
|
||||
description='Sampling --> frames per sample (0.1 yields 10 samples per frame)',
|
||||
items=(('0.01', '0.01', ''),
|
||||
('0.05', '0.05', ''),
|
||||
('0.1', '0.1', ''),
|
||||
('0.2', '0.2', ''),
|
||||
('0.25', '0.25', ''),
|
||||
('0.5', '0.5', ''),
|
||||
('1', '1', ''),
|
||||
('2', '2', ''),
|
||||
('3', '3', ''),
|
||||
('4', '4', ''),
|
||||
('5', '5', ''),
|
||||
('10', '10', ''),
|
||||
),
|
||||
default='1',
|
||||
)
|
||||
rot_x90: BoolProperty(
|
||||
name="Convert to Y-up",
|
||||
description="Rotate 90 degrees around X to convert to y-up",
|
||||
default=True,)
|
||||
world_space: BoolProperty(
|
||||
name="Export into Worldspace",
|
||||
description="Transform the Vertexcoordinates into Worldspace",
|
||||
default=False,)
|
||||
apply_modifiers: BoolProperty(
|
||||
name="Apply Modifiers",
|
||||
description="Applies the Modifiers",
|
||||
default=True,)
|
||||
range_start: IntProperty(
|
||||
name='Start Frame',
|
||||
description='First frame to use for Export',
|
||||
default=1,)
|
||||
range_end: IntProperty(
|
||||
name='End Frame',
|
||||
description='Last frame to use for Export',
|
||||
default=250,)
|
||||
sampling: EnumProperty(
|
||||
name='Sampling',
|
||||
description='Sampling --> frames per sample (0.1 yields 10 samples per frame)',
|
||||
items=(('0.01', '0.01', ''),
|
||||
('0.05', '0.05', ''),
|
||||
('0.1', '0.1', ''),
|
||||
('0.2', '0.2', ''),
|
||||
('0.25', '0.25', ''),
|
||||
('0.5', '0.5', ''),
|
||||
('1', '1', ''),
|
||||
('2', '2', ''),
|
||||
('3', '3', ''),
|
||||
('4', '4', ''),
|
||||
('5', '5', ''),
|
||||
('10', '10', ''),
|
||||
),
|
||||
default='1',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.active_object
|
||||
return (
|
||||
obj is not None and
|
||||
obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}
|
||||
obj is not None
|
||||
and obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
|
@ -173,7 +176,8 @@ class Export_pc2(bpy.types.Operator, ExportHelper):
|
|||
exported = do_export(context, props, filepath)
|
||||
|
||||
if exported:
|
||||
print('finished export in %s seconds' %((time.time() - start_time)))
|
||||
print('finished export in %s seconds' %
|
||||
((time.time() - start_time)))
|
||||
print(filepath)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
@ -183,7 +187,7 @@ class Export_pc2(bpy.types.Operator, ExportHelper):
|
|||
|
||||
if True:
|
||||
# File selector
|
||||
wm.fileselect_add(self) # will run self.execute()
|
||||
wm.fileselect_add(self) # will run self.execute()
|
||||
return {'RUNNING_MODAL'}
|
||||
elif True:
|
||||
# search the enum
|
||||
|
@ -196,23 +200,29 @@ class Export_pc2(bpy.types.Operator, ExportHelper):
|
|||
return self.execute(context)
|
||||
|
||||
|
||||
### REGISTER ###
|
||||
|
||||
def menu_func(self, context):
|
||||
def menu_func_export_button(self, context):
|
||||
self.layout.operator(Export_pc2.bl_idname, text="Pointcache (.pc2)")
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
classes = [
|
||||
Export_pc2,
|
||||
]
|
||||
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
|
||||
bpy.types.TOPBAR_MT_file_export.append(menu_func_export_button)
|
||||
#bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func_export_button)
|
||||
|
||||
bpy.types.TOPBAR_MT_file_export.append(menu_func)
|
||||
#bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export_button)
|
||||
#bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func_export_button)
|
||||
for cls in classes:
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
bpy.types.TOPBAR_MT_file_export.remove(menu_func)
|
||||
#bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
|
@ -619,7 +619,7 @@ class GIMPImageToScene(bpy.types.Operator):
|
|||
if self.OpacityMode == 'COMPO' and self.SetupCompo == False:
|
||||
box.label('Tip: Enable Node Compositing', icon='INFO')
|
||||
box.prop(self, 'AlphaMode', icon='IMAGE_RGB_ALPHA')
|
||||
box.prop(self, 'ShadelessMats', icon='SOLID')
|
||||
box.prop(self, 'ShadelessMats', icon='SHADING_SOLID')
|
||||
box.prop(self, 'LayerOffset')
|
||||
box.prop(self, 'LayerScale')
|
||||
|
||||
|
|
|
@ -44,12 +44,12 @@ def save_mesh(filepath,
|
|||
file = open(filepath, "w", encoding="utf8", newline="\n")
|
||||
fw = file.write
|
||||
|
||||
# Be sure tessface & co are available!
|
||||
if not mesh.tessfaces and mesh.polygons:
|
||||
mesh.calc_tessface()
|
||||
# Be sure tessellated loop trianlges are available!
|
||||
if not mesh.loop_triangles and mesh.polygons:
|
||||
mesh.calc_loop_triangles()
|
||||
|
||||
has_uv = bool(mesh.tessface_uv_textures)
|
||||
has_vcol = bool(mesh.tessface_vertex_colors)
|
||||
has_uv = bool(mesh.uv_layers)
|
||||
has_vcol = bool(mesh.vertex_colors)
|
||||
|
||||
if not has_uv:
|
||||
use_uv_coords = False
|
||||
|
@ -62,7 +62,7 @@ def save_mesh(filepath,
|
|||
has_vcol = False
|
||||
|
||||
if has_uv:
|
||||
active_uv_layer = mesh.tessface_uv_textures.active
|
||||
active_uv_layer = mesh.uv_layers.active
|
||||
if not active_uv_layer:
|
||||
use_uv_coords = False
|
||||
has_uv = False
|
||||
|
@ -70,7 +70,7 @@ def save_mesh(filepath,
|
|||
active_uv_layer = active_uv_layer.data
|
||||
|
||||
if has_vcol:
|
||||
active_col_layer = mesh.tessface_vertex_colors.active
|
||||
active_col_layer = mesh.vertex_colors.active
|
||||
if not active_col_layer:
|
||||
use_colors = False
|
||||
has_vcol = False
|
||||
|
@ -84,9 +84,9 @@ def save_mesh(filepath,
|
|||
ply_verts = [] # list of dictionaries
|
||||
# vdict = {} # (index, normal, uv) -> new index
|
||||
vdict = [{} for i in range(len(mesh_verts))]
|
||||
ply_faces = [[] for f in range(len(mesh.tessfaces))]
|
||||
ply_faces = [[] for f in range(len(mesh.loop_triangles))]
|
||||
vert_count = 0
|
||||
for i, f in enumerate(mesh.tessfaces):
|
||||
for i, f in enumerate(mesh.loop_triangles):
|
||||
|
||||
smooth = not use_normals or f.use_smooth
|
||||
if not smooth:
|
||||
|
@ -94,11 +94,9 @@ def save_mesh(filepath,
|
|||
normal_key = rvec3d(normal)
|
||||
|
||||
if has_uv:
|
||||
uv = active_uv_layer[i]
|
||||
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4
|
||||
uv = [active_uv_layer[l].uv[:] for l in f.loops]
|
||||
if has_vcol:
|
||||
col = active_col_layer[i]
|
||||
col = col.color1[:], col.color2[:], col.color3[:], col.color4[:]
|
||||
col = [active_col_layer[l].color[:] for l in f.loops]
|
||||
|
||||
pf = ply_faces[i]
|
||||
for j, vidx in enumerate(f.vertices):
|
||||
|
@ -156,7 +154,7 @@ def save_mesh(filepath,
|
|||
"property uchar blue\n"
|
||||
"property uchar alpha\n")
|
||||
|
||||
fw("element face %d\n" % len(mesh.tessfaces))
|
||||
fw("element face %d\n" % len(mesh.loop_triangles))
|
||||
fw("property list uchar uint vertex_indices\n")
|
||||
fw("end_header\n")
|
||||
|
||||
|
|
|
@ -263,9 +263,9 @@ def load_ply_mesh(filepath, ply_name):
|
|||
def add_face(vertices, indices, uvindices, colindices):
|
||||
mesh_faces.append(indices)
|
||||
if uvindices:
|
||||
mesh_uvs.append([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices])
|
||||
mesh_uvs.extend([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices])
|
||||
if colindices:
|
||||
mesh_colors.append([(vertices[index][colindices[0]] * colmultiply[0],
|
||||
mesh_colors.extend([(vertices[index][colindices[0]] * colmultiply[0],
|
||||
vertices[index][colindices[1]] * colmultiply[1],
|
||||
vertices[index][colindices[2]] * colmultiply[2],
|
||||
vertices[index][colindices[3]] * colmultiply[3],
|
||||
|
@ -317,35 +317,37 @@ def load_ply_mesh(filepath, ply_name):
|
|||
mesh.edges.foreach_set("vertices", [a for e in obj[b'edge'] for a in (e[eindex1], e[eindex2])])
|
||||
|
||||
if mesh_faces:
|
||||
mesh.tessfaces.add(len(mesh_faces))
|
||||
mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh_faces))
|
||||
loops_vert_idx = []
|
||||
faces_loop_start = []
|
||||
faces_loop_total = []
|
||||
lidx = 0
|
||||
for f in mesh_faces:
|
||||
nbr_vidx = len(f)
|
||||
loops_vert_idx.extend(f)
|
||||
faces_loop_start.append(lidx)
|
||||
faces_loop_total.append(nbr_vidx)
|
||||
lidx += nbr_vidx
|
||||
|
||||
if uvindices or colindices:
|
||||
if uvindices:
|
||||
uvlay = mesh.tessface_uv_textures.new()
|
||||
if colindices:
|
||||
vcol_lay = mesh.tessface_vertex_colors.new()
|
||||
mesh.loops.add(len(loops_vert_idx))
|
||||
mesh.polygons.add(len(mesh_faces))
|
||||
|
||||
if uvindices:
|
||||
for i, f in enumerate(uvlay.data):
|
||||
ply_uv = mesh_uvs[i]
|
||||
for j, uv in enumerate(f.uv):
|
||||
uv[0], uv[1] = ply_uv[j]
|
||||
mesh.loops.foreach_set("vertex_index", loops_vert_idx)
|
||||
mesh.polygons.foreach_set("loop_start", faces_loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", faces_loop_total)
|
||||
|
||||
if colindices:
|
||||
for i, f in enumerate(vcol_lay.data):
|
||||
# XXX, colors dont come in right, needs further investigation.
|
||||
ply_col = mesh_colors[i]
|
||||
if len(ply_col) == 4:
|
||||
f_col = f.color1, f.color2, f.color3, f.color4
|
||||
else:
|
||||
f_col = f.color1, f.color2, f.color3
|
||||
if uvindices:
|
||||
uv_layer = mesh.uv_layers.new()
|
||||
for i, uv in enumerate(uv_layer.data):
|
||||
uv.uv = mesh_uvs[i]
|
||||
|
||||
for j, col in enumerate(f_col):
|
||||
col[0] = ply_col[j][0]
|
||||
col[1] = ply_col[j][1]
|
||||
col[2] = ply_col[j][2]
|
||||
col[3] = ply_col[j][3]
|
||||
if colindices:
|
||||
vcol_lay = mesh.vertex_colors.new()
|
||||
|
||||
for i, col in enumerate(vcol_lay.data):
|
||||
col.color[0] = mesh_colors[i][0]
|
||||
col.color[1] = mesh_colors[i][1]
|
||||
col.color[2] = mesh_colors[i][2]
|
||||
col.color[3] = mesh_colors[i][3]
|
||||
|
||||
mesh.update()
|
||||
mesh.validate()
|
||||
|
|
|
@ -63,7 +63,7 @@ def create_and_link_mesh(name, faces, face_nors, points, global_matrix):
|
|||
obj.select_set("SELECT")
|
||||
|
||||
|
||||
def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False, triangulate=True):
|
||||
def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False):
|
||||
"""
|
||||
From an object, return a generator over a list of faces.
|
||||
|
||||
|
@ -90,26 +90,11 @@ def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False, triangulate=Tru
|
|||
mesh.transform(mat)
|
||||
if mat.is_negative:
|
||||
mesh.flip_normals()
|
||||
mesh.calc_tessface()
|
||||
|
||||
if triangulate:
|
||||
# From a list of faces, return the face triangulated if needed.
|
||||
def iter_face_index():
|
||||
for face in mesh.tessfaces:
|
||||
vertices = face.vertices[:]
|
||||
if len(vertices) == 4:
|
||||
yield vertices[0], vertices[1], vertices[2]
|
||||
yield vertices[2], vertices[3], vertices[0]
|
||||
else:
|
||||
yield vertices
|
||||
else:
|
||||
def iter_face_index():
|
||||
for face in mesh.tessfaces:
|
||||
yield face.vertices[:]
|
||||
mesh.calc_loop_triangles()
|
||||
|
||||
vertices = mesh.vertices
|
||||
|
||||
for indexes in iter_face_index():
|
||||
yield [vertices[index].co.copy() for index in indexes]
|
||||
for tri in mesh.loop_triangles:
|
||||
yield [vertices[index].co.copy() for index in tri.vertices]
|
||||
|
||||
bpy.data.meshes.remove(mesh)
|
||||
|
|
|
@ -46,10 +46,6 @@ if "bpy" in locals():
|
|||
import os
|
||||
import bpy
|
||||
|
||||
from . import export_uv_eps
|
||||
from . import export_uv_png
|
||||
from . import export_uv_svg
|
||||
|
||||
from bpy.props import (
|
||||
StringProperty,
|
||||
BoolProperty,
|
||||
|
@ -80,13 +76,14 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
default=False,
|
||||
)
|
||||
mode: EnumProperty(
|
||||
items=(('SVG', "Scalable Vector Graphic (.svg)",
|
||||
"Export the UV layout to a vector SVG file"),
|
||||
('EPS', "Encapsulate PostScript (.eps)",
|
||||
"Export the UV layout to a vector EPS file"),
|
||||
('PNG', "PNG Image (.png)",
|
||||
"Export the UV layout to a bitmap image"),
|
||||
),
|
||||
items=(
|
||||
('SVG', "Scalable Vector Graphic (.svg)",
|
||||
"Export the UV layout to a vector SVG file"),
|
||||
('EPS', "Encapsulate PostScript (.eps)",
|
||||
"Export the UV layout to a vector EPS file"),
|
||||
('PNG', "PNG Image (.png)",
|
||||
"Export the UV layout to a bitmap image"),
|
||||
),
|
||||
name="Format",
|
||||
description="File format to export the UV layout to",
|
||||
default='PNG',
|
||||
|
@ -100,14 +97,14 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
opacity: FloatProperty(
|
||||
name="Fill Opacity",
|
||||
min=0.0, max=1.0,
|
||||
default=0.5,
|
||||
description="Set amount of opacity for exported UV layout"
|
||||
default=0.25,
|
||||
description="Set amount of opacity for exported UV layout",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.active_object
|
||||
return obj is not None and obj.type == 'MESH' and len(obj.data.uv_layers) > 0
|
||||
return obj is not None and obj.type == 'MESH' and obj.data.uv_layers
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.size = self.get_image_size(context)
|
||||
|
@ -132,8 +129,8 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
return True
|
||||
|
||||
def execute(self, context):
|
||||
object = context.active_object
|
||||
is_editmode = (object.mode == 'EDIT')
|
||||
obj = context.active_object
|
||||
is_editmode = (obj.mode == 'EDIT')
|
||||
if is_editmode:
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||
|
||||
|
@ -155,26 +152,29 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
def iter_meshes_to_export(self, context):
|
||||
for object in self.iter_objects_to_export(context):
|
||||
for obj in self.iter_objects_to_export(context):
|
||||
if self.modified:
|
||||
yield object.to_mesh(context.depsgraph, apply_modifiers=True)
|
||||
yield obj.to_mesh(context.depsgraph, apply_modifiers=True)
|
||||
else:
|
||||
yield object.data
|
||||
yield obj.data
|
||||
|
||||
def iter_objects_to_export(self, context):
|
||||
for object in context.selected_objects:
|
||||
if object.type != "MESH":
|
||||
@staticmethod
|
||||
def iter_objects_to_export(context):
|
||||
for obj in context.selected_objects:
|
||||
if obj.type != 'MESH':
|
||||
continue
|
||||
mesh = object.data
|
||||
mesh = obj.data
|
||||
if mesh.uv_layers.active is None:
|
||||
continue
|
||||
yield object
|
||||
yield obj
|
||||
|
||||
def free_meshes(self, meshes):
|
||||
@staticmethod
|
||||
def free_meshes(meshes):
|
||||
for mesh in meshes:
|
||||
bpy.data.meshes.remove(mesh)
|
||||
|
||||
def currently_image_image_editor(self, context):
|
||||
@staticmethod
|
||||
def currently_image_image_editor(context):
|
||||
return isinstance(context.space_data, bpy.types.SpaceImageEditor)
|
||||
|
||||
def get_currently_opened_image(self, context):
|
||||
|
@ -207,7 +207,8 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
uvs = tuple(tuple(uv.uv) for uv in uv_layer[start:end])
|
||||
yield (uvs, self.get_polygon_color(mesh, polygon))
|
||||
|
||||
def get_polygon_color(self, mesh, polygon, default = (0.8, 0.8, 0.8)):
|
||||
@staticmethod
|
||||
def get_polygon_color(mesh, polygon, default=(0.8, 0.8, 0.8)):
|
||||
if polygon.material_index < len(mesh.materials):
|
||||
material = mesh.materials[polygon.material_index]
|
||||
if material is not None:
|
||||
|
@ -215,11 +216,14 @@ class ExportUVLayout(bpy.types.Operator):
|
|||
return default
|
||||
|
||||
def get_exporter(self):
|
||||
if self.mode == "PNG":
|
||||
if self.mode == 'PNG':
|
||||
from . import export_uv_png
|
||||
return export_uv_png.export
|
||||
elif self.mode == "EPS":
|
||||
elif self.mode == 'EPS':
|
||||
from . import export_uv_eps
|
||||
return export_uv_eps.export
|
||||
elif self.mode == "SVG":
|
||||
elif self.mode == 'SVG':
|
||||
from . import export_uv_svg
|
||||
return export_uv_svg.export
|
||||
else:
|
||||
assert False
|
||||
|
@ -233,9 +237,11 @@ def register():
|
|||
bpy.utils.register_class(ExportUVLayout)
|
||||
bpy.types.IMAGE_MT_uvs.append(menu_func)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(ExportUVLayout)
|
||||
bpy.types.IMAGE_MT_uvs.remove(menu_func)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
bl_info = {
|
||||
"name": "FBX format",
|
||||
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier",
|
||||
"version": (4, 10, 4),
|
||||
"version": (4, 11, 0),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "File > Import-Export",
|
||||
"description": "FBX IO meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions",
|
||||
|
@ -226,8 +226,6 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
|
|||
|
||||
def execute(self, context):
|
||||
keywords = self.as_keywords(ignore=("filter_glob", "directory", "ui_tab"))
|
||||
# XXX TODO get rid of this, EEVEE/Cycles use same nodal system...
|
||||
keywords["use_cycles"] = True #(context.scene.render.engine == 'CYCLES')
|
||||
|
||||
from . import import_fbx
|
||||
return import_fbx.load(self, context, **keywords)
|
||||
|
|
|
@ -1241,11 +1241,11 @@ FBXExportData = namedtuple("FBXExportData", (
|
|||
FBXImportSettings = namedtuple("FBXImportSettings", (
|
||||
"report", "to_axes", "global_matrix", "global_scale",
|
||||
"bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed",
|
||||
"use_custom_normals", "use_cycles", "use_image_search",
|
||||
"use_custom_normals", "use_image_search",
|
||||
"use_alpha_decals", "decal_offset",
|
||||
"use_anim", "anim_offset",
|
||||
"use_custom_props", "use_custom_props_enum_as_string",
|
||||
"cycles_material_wrap_map", "image_cache",
|
||||
"nodal_material_wrap_map", "image_cache",
|
||||
"ignore_leaf_bones", "force_connect_children", "automatic_bone_orientation", "bone_correction_matrix",
|
||||
"use_prepost_rot",
|
||||
))
|
||||
|
|
|
@ -1316,9 +1316,11 @@ def blen_read_shape(fbx_tmpl, fbx_sdata, fbx_bcdata, meshes, scene):
|
|||
# Material
|
||||
|
||||
def blen_read_material(fbx_tmpl, fbx_obj, settings):
|
||||
from bpy_extras import node_shader_utils
|
||||
|
||||
elem_name_utf8 = elem_name_ensure_class(fbx_obj, b'Material')
|
||||
|
||||
cycles_material_wrap_map = settings.cycles_material_wrap_map
|
||||
nodal_material_wrap_map = settings.nodal_material_wrap_map
|
||||
ma = bpy.data.materials.new(name=elem_name_utf8)
|
||||
|
||||
const_color_white = 1.0, 1.0, 1.0
|
||||
|
@ -1326,43 +1328,21 @@ def blen_read_material(fbx_tmpl, fbx_obj, settings):
|
|||
fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
|
||||
elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
|
||||
|
||||
ma_diff = elem_props_get_color_rgb(fbx_props, b'DiffuseColor', const_color_white)
|
||||
ma_spec = elem_props_get_color_rgb(fbx_props, b'SpecularColor', const_color_white)
|
||||
ma_alpha = elem_props_get_number(fbx_props, b'Opacity', 1.0)
|
||||
ma_spec_intensity = ma.specular_intensity = elem_props_get_number(fbx_props, b'SpecularFactor', 0.25) * 2.0
|
||||
ma_spec_hardness = elem_props_get_number(fbx_props, b'Shininess', 9.6)
|
||||
ma_refl_factor = elem_props_get_number(fbx_props, b'ReflectionFactor', 0.0)
|
||||
ma_refl_color = elem_props_get_color_rgb(fbx_props, b'ReflectionColor', const_color_white)
|
||||
ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False, use_nodes=True)
|
||||
ma_wrap.base_color = elem_props_get_color_rgb(fbx_props, b'DiffuseColor', const_color_white)
|
||||
# No specular color in Principled BSDF shader, assumed to be either white or take some tint from diffuse one...
|
||||
# TODO: add way to handle tint option (guesstimate from spec color + intensity...)?
|
||||
ma_wrap.specular = elem_props_get_number(fbx_props, b'SpecularFactor', 0.25) * 2.0
|
||||
# XXX Totally empirical conversion reusing previous 'hardness' computing...
|
||||
ma_wrap.roughness = 1.0 - (((elem_props_get_number(fbx_props, b'Shininess', 9.6) + 3.0) / 5.0) - 0.65)
|
||||
ma_wrap.transmission = 1.0 - elem_props_get_number(fbx_props, b'Opacity', 1.0)
|
||||
ma_wrap.metallic = elem_props_get_number(fbx_props, b'ReflectionFactor', 0.0)
|
||||
# We have no metallic (a.k.a. reflection) color...
|
||||
# elem_props_get_color_rgb(fbx_props, b'ReflectionColor', const_color_white)
|
||||
# (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5)
|
||||
ma_wrap.normalmap_strength = elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142
|
||||
|
||||
if settings.use_cycles:
|
||||
from modules import cycles_shader_compat
|
||||
# viewport color
|
||||
ma.diffuse_color = ma_diff
|
||||
|
||||
ma_wrap = cycles_shader_compat.CyclesShaderWrapper(ma)
|
||||
ma_wrap.diffuse_color_set(ma_diff)
|
||||
ma_wrap.specular_color_set([c * ma_spec_intensity for c in ma_spec])
|
||||
ma_wrap.hardness_value_set(((ma_spec_hardness + 3.0) / 5.0) - 0.65)
|
||||
ma_wrap.alpha_value_set(ma_alpha)
|
||||
ma_wrap.reflect_factor_set(ma_refl_factor)
|
||||
ma_wrap.reflect_color_set(ma_refl_color)
|
||||
|
||||
cycles_material_wrap_map[ma] = ma_wrap
|
||||
else:
|
||||
# TODO, number BumpFactor isnt used yet
|
||||
ma.diffuse_color = ma_diff
|
||||
ma.specular_color = ma_spec
|
||||
ma.alpha = ma_alpha
|
||||
if ma_alpha < 1.0:
|
||||
ma.use_transparency = True
|
||||
ma.transparency_method = 'RAYTRACE'
|
||||
ma.specular_intensity = ma_spec_intensity
|
||||
ma.specular_hardness = ma_spec_hardness * 5.10 + 1.0
|
||||
|
||||
if ma_refl_factor != 0.0:
|
||||
ma.raytrace_mirror.use = True
|
||||
ma.raytrace_mirror.reflect_factor = ma_refl_factor
|
||||
ma.mirror_color = ma_refl_color
|
||||
nodal_material_wrap_map[ma] = ma_wrap
|
||||
|
||||
if settings.use_custom_props:
|
||||
blen_read_custom_properties(fbx_obj, ma, settings)
|
||||
|
@ -1491,11 +1471,14 @@ def blen_read_light(fbx_tmpl, fbx_obj, global_scale):
|
|||
spot_blend = elem_props_get_number(fbx_props, b'HotSpot', 45.0)
|
||||
lamp.spot_blend = 1.0 - (spot_blend / spot_size)
|
||||
|
||||
# TODO, cycles
|
||||
# TODO, cycles nodes???
|
||||
lamp.color = elem_props_get_color_rgb(fbx_props, b'Color', (1.0, 1.0, 1.0))
|
||||
lamp.energy = elem_props_get_number(fbx_props, b'Intensity', 100.0) / 100.0
|
||||
lamp.distance = elem_props_get_number(fbx_props, b'DecayStart', 25.0) * global_scale
|
||||
lamp.use_shadow = elem_props_get_bool(fbx_props, b'CastShadow', True)
|
||||
if hasattr(lamp, "cycles"):
|
||||
lamp.cycles.cast_shadow = lamp.use_shadow
|
||||
# Keeping this for now, but this is not used nor exposed anymore afaik...
|
||||
lamp.shadow_color = elem_props_get_color_rgb(fbx_props, b'ShadowColor', (0.0, 0.0, 0.0))
|
||||
|
||||
return lamp
|
||||
|
@ -2246,7 +2229,6 @@ def load(operator, context, filepath="",
|
|||
global_scale=1.0,
|
||||
bake_space_transform=False,
|
||||
use_custom_normals=True,
|
||||
use_cycles=True,
|
||||
use_image_search=False,
|
||||
use_alpha_decals=False,
|
||||
decal_offset=0.0,
|
||||
|
@ -2308,10 +2290,8 @@ def load(operator, context, filepath="",
|
|||
|
||||
basedir = os.path.dirname(filepath)
|
||||
|
||||
cycles_material_wrap_map = {}
|
||||
nodal_material_wrap_map = {}
|
||||
image_cache = {}
|
||||
if not use_cycles:
|
||||
texture_cache = {}
|
||||
|
||||
# Tables: (FBX_byte_id -> [FBX_data, None or Blender_datablock])
|
||||
fbx_table_nodes = {}
|
||||
|
@ -2379,11 +2359,11 @@ def load(operator, context, filepath="",
|
|||
settings = FBXImportSettings(
|
||||
operator.report, (axis_up, axis_forward), global_matrix, global_scale,
|
||||
bake_space_transform, global_matrix_inv, global_matrix_inv_transposed,
|
||||
use_custom_normals, use_cycles, use_image_search,
|
||||
use_custom_normals, use_image_search,
|
||||
use_alpha_decals, decal_offset,
|
||||
use_anim, anim_offset,
|
||||
use_custom_props, use_custom_props_enum_as_string,
|
||||
cycles_material_wrap_map, image_cache,
|
||||
nodal_material_wrap_map, image_cache,
|
||||
ignore_leaf_bones, force_connect_children, automatic_bone_orientation, bone_correction_matrix,
|
||||
use_prepost_rot,
|
||||
)
|
||||
|
@ -2855,8 +2835,7 @@ def load(operator, context, filepath="",
|
|||
continue
|
||||
mat = fbx_item[1]
|
||||
items.append((mat, lnk_prop))
|
||||
if settings.use_cycles:
|
||||
print("WARNING! Importing material's animation is not supported for Cycles materials...")
|
||||
print("WARNING! Importing material's animation is not supported for Nodal materials...")
|
||||
for al_uuid, al_ctype in fbx_connection_map.get(acn_uuid, ()):
|
||||
if al_ctype.props[0] != b'OO':
|
||||
continue
|
||||
|
@ -2941,51 +2920,36 @@ def load(operator, context, filepath="",
|
|||
fbx_tmpl = fbx_template_get((b'Material', b'KFbxSurfacePhong'))
|
||||
# b'KFbxSurfaceLambert'
|
||||
|
||||
# textures that use this material
|
||||
def texture_bumpfac_get(fbx_obj):
|
||||
assert(fbx_obj.id == b'Material')
|
||||
fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
|
||||
elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
|
||||
# (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5)
|
||||
return elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142
|
||||
|
||||
def texture_mapping_get(fbx_obj):
|
||||
def texture_mapping_set(fbx_obj, node_texture):
|
||||
assert(fbx_obj.id == b'Texture')
|
||||
|
||||
fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
|
||||
elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
|
||||
return (elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0)),
|
||||
elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0)),
|
||||
elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0)),
|
||||
(bool(elem_props_get_enum(fbx_props, b'WrapModeU', 0)),
|
||||
bool(elem_props_get_enum(fbx_props, b'WrapModeV', 0))))
|
||||
loc = elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0))
|
||||
rot = tuple(-r for r in elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0)))
|
||||
scale = tuple(((1.0 / s) if s != 0.0 else 1.0)
|
||||
for s in elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0)))
|
||||
clamp_uv = (bool(elem_props_get_enum(fbx_props, b'WrapModeU', 0)),
|
||||
bool(elem_props_get_enum(fbx_props, b'WrapModeV', 0)))
|
||||
|
||||
if not use_cycles:
|
||||
# Simple function to make a new mtex and set defaults
|
||||
def material_mtex_new(material, image, tex_map):
|
||||
tex = texture_cache.get(image)
|
||||
if tex is None:
|
||||
tex = bpy.data.textures.new(name=image.name, type='IMAGE')
|
||||
tex.image = image
|
||||
texture_cache[image] = tex
|
||||
if (loc == (0.0, 0.0, 0.0) and
|
||||
rot == (0.0, 0.0, 0.0) and
|
||||
scale == (1.0, 1.0, 1.0) and
|
||||
clamp_uv == (False, False)):
|
||||
return
|
||||
|
||||
# copy custom properties from image object to texture
|
||||
for key, value in image.items():
|
||||
tex[key] = value
|
||||
node_texture.translation = loc
|
||||
node_texture.rotation = rot
|
||||
node_texture.scale = scale
|
||||
|
||||
# delete custom properties on the image object
|
||||
for key in image.keys():
|
||||
del image[key]
|
||||
|
||||
mtex = material.texture_slots.add()
|
||||
mtex.texture = tex
|
||||
mtex.texture_coords = 'UV'
|
||||
mtex.use_map_color_diffuse = False
|
||||
|
||||
# No rotation here...
|
||||
mtex.offset[:] = tex_map[0]
|
||||
mtex.scale[:] = tex_map[2]
|
||||
return mtex
|
||||
# awkward conversion UV clamping to min/max
|
||||
node_texture.min = (0.0, 0.0, 0.0)
|
||||
node_texture.max = (1.0, 1.0, 1.0)
|
||||
node_texture.use_min = node_texture.use_max = clamp_uv[0] or clamp_uv[1]
|
||||
if clamp_uv[0] != clamp_uv[1]:
|
||||
# use bool as index
|
||||
node_texture.min[not clamp[0]] = -1e9
|
||||
node_texture.max[not clamp[0]] = 1e9
|
||||
|
||||
for fbx_uuid, fbx_item in fbx_table_nodes.items():
|
||||
fbx_obj, blen_data = fbx_item
|
||||
|
@ -2997,127 +2961,44 @@ def load(operator, context, filepath="",
|
|||
image,
|
||||
fbx_lnk_type) in connection_filter_reverse(fbx_uuid, b'Texture'):
|
||||
|
||||
if use_cycles:
|
||||
if fbx_lnk_type.props[0] == b'OP':
|
||||
lnk_type = fbx_lnk_type.props[3]
|
||||
if fbx_lnk_type.props[0] == b'OP':
|
||||
lnk_type = fbx_lnk_type.props[3]
|
||||
|
||||
ma_wrap = cycles_material_wrap_map[material]
|
||||
ma_wrap = nodal_material_wrap_map[material]
|
||||
|
||||
# tx/rot/scale
|
||||
tex_map = texture_mapping_get(fbx_lnk)
|
||||
if (tex_map[0] == (0.0, 0.0, 0.0) and
|
||||
tex_map[1] == (0.0, 0.0, 0.0) and
|
||||
tex_map[2] == (1.0, 1.0, 1.0) and
|
||||
tex_map[3] == (False, False)):
|
||||
use_mapping = False
|
||||
else:
|
||||
use_mapping = True
|
||||
tex_map_kw = {
|
||||
"translation": tex_map[0],
|
||||
"rotation": [-i for i in tex_map[1]],
|
||||
"scale": [((1.0 / i) if i != 0.0 else 1.0) for i in tex_map[2]],
|
||||
"clamp": tex_map[3],
|
||||
}
|
||||
if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}:
|
||||
ma_wrap.base_color_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.base_color_texture)
|
||||
elif lnk_type == b'SpecularColor':
|
||||
# Intensity actually, not color...
|
||||
ma_wrap.specular_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.specular_texture)
|
||||
elif lnk_type in {b'ReflectionColor', b'3dsMax|maps|texmap_reflection'}:
|
||||
# Intensity actually, not color...
|
||||
ma_wrap.metallic_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.metallic_texture)
|
||||
elif lnk_type == b'TransparentColor':
|
||||
# Transparency... sort of...
|
||||
ma_wrap.transmission_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.transmission_texture)
|
||||
if use_alpha_decals:
|
||||
material_decals.add(material)
|
||||
elif lnk_type == b'ShininessExponent':
|
||||
# That is probably reversed compared to expected results? TODO...
|
||||
ma_wrap.roughness_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.roughness_texture)
|
||||
# XXX, applications abuse bump!
|
||||
elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}:
|
||||
ma_wrap.normalmap_texture.image = image
|
||||
texture_mapping_set(fbx_lnk, ma_wrap.normalmap_texture)
|
||||
"""
|
||||
elif lnk_type == b'Bump':
|
||||
# TODO displacement...
|
||||
"""
|
||||
else:
|
||||
print("WARNING: material link %r ignored" % lnk_type)
|
||||
|
||||
"""
|
||||
TODO for clamp:
|
||||
# awkward conversion UV clamping to minmax
|
||||
node_map.min = (0.0, 0.0, 0.0)
|
||||
node_map.max = (1.0, 1.0, 1.0)
|
||||
|
||||
if clamp in {(False, False), (True, True)}:
|
||||
node_map.use_min = node_map.use_max = clamp[0]
|
||||
else:
|
||||
node_map.use_min = node_map.use_max = True
|
||||
# use bool as index
|
||||
node_map.min[not clamp[0]] = -1000000000.0
|
||||
node_map.max[not clamp[0]] = 1000000000.0
|
||||
"""
|
||||
|
||||
if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}:
|
||||
ma_wrap.diffuse_image_set(image)
|
||||
if use_mapping:
|
||||
ma_wrap.diffuse_mapping_set(**tex_map_kw)
|
||||
elif lnk_type == b'SpecularColor':
|
||||
ma_wrap.specular_image_set(image)
|
||||
if use_mapping:
|
||||
ma_wrap.specular_mapping_set(**tex_map_kw)
|
||||
elif lnk_type in {b'ReflectionColor', b'3dsMax|maps|texmap_reflection'}:
|
||||
ma_wrap.reflect_image_set(image)
|
||||
if use_mapping:
|
||||
ma_wrap.reflect_mapping_set(**tex_map_kw)
|
||||
elif lnk_type == b'TransparentColor': # alpha
|
||||
ma_wrap.alpha_image_set(image)
|
||||
if use_mapping:
|
||||
ma_wrap.alpha_mapping_set(**tex_map_kw)
|
||||
if use_alpha_decals:
|
||||
material_decals.add(material)
|
||||
elif lnk_type == b'DiffuseFactor':
|
||||
pass # TODO
|
||||
elif lnk_type == b'ShininessExponent':
|
||||
ma_wrap.hardness_image_set(image)
|
||||
if use_mapping:
|
||||
ma_wrap.hardness_mapping_set(**tex_map_kw)
|
||||
# XXX, applications abuse bump!
|
||||
elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}:
|
||||
ma_wrap.normal_image_set(image)
|
||||
ma_wrap.normal_factor_set(texture_bumpfac_get(fbx_obj))
|
||||
if use_mapping:
|
||||
ma_wrap.normal_mapping_set(**tex_map_kw)
|
||||
"""
|
||||
elif lnk_type == b'Bump':
|
||||
ma_wrap.bump_image_set(image)
|
||||
ma_wrap.bump_factor_set(texture_bumpfac_get(fbx_obj))
|
||||
if use_mapping:
|
||||
ma_wrap.bump_mapping_set(**tex_map_kw)
|
||||
"""
|
||||
else:
|
||||
print("WARNING: material link %r ignored" % lnk_type)
|
||||
|
||||
material_images.setdefault(material, {})[lnk_type] = (image, tex_map)
|
||||
else:
|
||||
if fbx_lnk_type.props[0] == b'OP':
|
||||
lnk_type = fbx_lnk_type.props[3]
|
||||
|
||||
# tx/rot/scale (rot is ignored here!).
|
||||
tex_map = texture_mapping_get(fbx_lnk)
|
||||
|
||||
mtex = material_mtex_new(material, image, tex_map)
|
||||
|
||||
if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}:
|
||||
mtex.use_map_color_diffuse = True
|
||||
mtex.blend_type = 'MULTIPLY'
|
||||
elif lnk_type == b'SpecularColor':
|
||||
mtex.use_map_color_spec = True
|
||||
mtex.blend_type = 'MULTIPLY'
|
||||
elif lnk_type in {b'ReflectionColor', b'3dsMax|maps|texmap_reflection'}:
|
||||
mtex.use_map_raymir = True
|
||||
elif lnk_type == b'TransparentColor': # alpha
|
||||
material.use_transparency = True
|
||||
material.transparency_method = 'RAYTRACE'
|
||||
material.alpha = 0.0
|
||||
mtex.use_map_alpha = True
|
||||
mtex.alpha_factor = 1.0
|
||||
if use_alpha_decals:
|
||||
material_decals.add(material)
|
||||
elif lnk_type == b'DiffuseFactor':
|
||||
mtex.use_map_diffuse = True
|
||||
elif lnk_type == b'ShininessExponent':
|
||||
mtex.use_map_hardness = True
|
||||
# XXX, applications abuse bump!
|
||||
elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}:
|
||||
mtex.texture.use_normal_map = True # not ideal!
|
||||
mtex.use_map_normal = True
|
||||
mtex.normal_factor = texture_bumpfac_get(fbx_obj)
|
||||
"""
|
||||
elif lnk_type == b'Bump':
|
||||
mtex.use_map_normal = True
|
||||
mtex.normal_factor = texture_bumpfac_get(fbx_obj)
|
||||
"""
|
||||
else:
|
||||
print("WARNING: material link %r ignored" % lnk_type)
|
||||
|
||||
material_images.setdefault(material, {})[lnk_type] = (image, tex_map)
|
||||
material_images.setdefault(material, {})[lnk_type] = image
|
||||
|
||||
# Check if the diffuse image has an alpha channel,
|
||||
# if so, use the alpha channel.
|
||||
|
@ -3128,30 +3009,21 @@ def load(operator, context, filepath="",
|
|||
if fbx_obj.id != b'Material':
|
||||
continue
|
||||
material = fbx_table_nodes.get(fbx_uuid, (None, None))[1]
|
||||
image, tex_map = material_images.get(material, {}).get(b'DiffuseColor', (None, None))
|
||||
image = material_images.get(material, {}).get(b'DiffuseColor', None)
|
||||
# do we have alpha?
|
||||
if image and image.depth == 32:
|
||||
if use_alpha_decals:
|
||||
material_decals.add(material)
|
||||
|
||||
if use_cycles:
|
||||
ma_wrap = cycles_material_wrap_map[material]
|
||||
if ma_wrap.node_bsdf_alpha.mute:
|
||||
ma_wrap.alpha_image_set_from_diffuse()
|
||||
else:
|
||||
if not any((True for mtex in material.texture_slots if mtex and mtex.use_map_alpha)):
|
||||
mtex = material_mtex_new(material, image, tex_map)
|
||||
ma_wrap = nodal_material_wrap_map[material]
|
||||
ma_wrap.transmission_texture.use_alpha = True
|
||||
ma_wrap.transmission_texture.copy_from(ma_wrap.base_color_texture)
|
||||
|
||||
material.use_transparency = True
|
||||
material.transparency_method = 'RAYTRACE'
|
||||
material.alpha = 0.0
|
||||
mtex.use_map_alpha = True
|
||||
mtex.alpha_factor = 1.0
|
||||
|
||||
# propagate mapping from diffuse to all other channels which have none defined.
|
||||
if use_cycles:
|
||||
ma_wrap = cycles_material_wrap_map[material]
|
||||
ma_wrap.mapping_set_from_diffuse()
|
||||
# Propagate mapping from diffuse to all other channels which have none defined.
|
||||
# XXX Commenting for now, I do not really understand the logic here, why should diffuse mapping
|
||||
# be applied to all others if not defined for them???
|
||||
# ~ ma_wrap = nodal_material_wrap_map[material]
|
||||
# ~ ma_wrap.mapping_set_from_diffuse()
|
||||
|
||||
_(); del _
|
||||
|
||||
|
@ -3174,14 +3046,8 @@ def load(operator, context, filepath="",
|
|||
v.co += v.normal * decal_offset
|
||||
break
|
||||
|
||||
if use_cycles:
|
||||
for obj in (obj for obj in bpy.data.objects if obj.data == mesh):
|
||||
obj.cycles_visibility.shadow = False
|
||||
else:
|
||||
for material in mesh.materials:
|
||||
if material in material_decals:
|
||||
# recieve but dont cast shadows
|
||||
material.use_raytrace = False
|
||||
for obj in (obj for obj in bpy.data.objects if obj.data == mesh):
|
||||
obj.cycles_visibility.shadow = False
|
||||
_(); del _
|
||||
|
||||
perfmon.level_down()
|
||||
|
|
|
@ -82,7 +82,7 @@ def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict):
|
|||
fw('Ka %.6f %.6f %.6f\n' % (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
|
||||
else:
|
||||
fw('Ka %.6f %.6f %.6f\n' % (1.0, 1.0, 1.0))
|
||||
fw('Kd %.6f %.6f %.6f\n' % mat_wrap.diffuse_color[:3]) # Diffuse
|
||||
fw('Kd %.6f %.6f %.6f\n' % mat_wrap.base_color[:3]) # Diffuse
|
||||
# XXX TODO Find a way to handle tint and diffuse color, in a consistent way with import...
|
||||
fw('Ks %.6f %.6f %.6f\n' % (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular)) # Specular
|
||||
# Emission, not in original MTL standard but seems pretty common, see T45766.
|
||||
|
@ -108,7 +108,7 @@ def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict):
|
|||
|
||||
#### And now, the image textures...
|
||||
image_map = {
|
||||
"map_Kd": "diffuse_texture",
|
||||
"map_Kd": "base_color_texture",
|
||||
"map_Ka": None, # ambient...
|
||||
"map_Ks": "specular_texture",
|
||||
"map_Ns": "roughness_texture",
|
||||
|
@ -349,7 +349,7 @@ def write_file(filepath, objects, depsgraph, scene,
|
|||
# END NURBS
|
||||
|
||||
try:
|
||||
me = ob.to_mesh(depsgraph, EXPORT_APPLY_MODIFIERS, calc_tessface=False)
|
||||
me = ob.to_mesh(depsgraph, EXPORT_APPLY_MODIFIERS)
|
||||
except RuntimeError:
|
||||
me = None
|
||||
|
||||
|
@ -377,7 +377,6 @@ def write_file(filepath, objects, depsgraph, scene,
|
|||
|
||||
# Make our own list so it can be sorted to reduce context switching
|
||||
face_index_pairs = [(face, index) for index, face in enumerate(me.polygons)]
|
||||
# faces = [ f for f in me.tessfaces ]
|
||||
|
||||
if EXPORT_EDGES:
|
||||
edges = me.edges
|
||||
|
|
|
@ -133,7 +133,7 @@ def create_materials(filepath, relpath,
|
|||
|
||||
# Adds textures for materials (rendering)
|
||||
if type == 'Kd':
|
||||
_generic_tex_set(mat_wrap.diffuse_texture, image, 'UV', map_offset, map_scale)
|
||||
_generic_tex_set(mat_wrap.base_color_texture, image, 'UV', map_offset, map_scale)
|
||||
|
||||
elif type == 'Ka':
|
||||
# XXX Not supported?
|
||||
|
@ -168,8 +168,8 @@ def create_materials(filepath, relpath,
|
|||
print("WARNING, unsupported reflection type '%s', defaulting to 'sphere'"
|
||||
"" % ' '.join(i.decode() for i in map_type))
|
||||
|
||||
_generic_tex_set(mat_wrap.diffuse_texture, image, 'Reflection', map_offset, map_scale)
|
||||
mat_wrap.diffuse_texture.projection = 'SPHERE'
|
||||
_generic_tex_set(mat_wrap.base_color_texture, image, 'Reflection', map_offset, map_scale)
|
||||
mat_wrap.base_color_texture.projection = 'SPHERE'
|
||||
|
||||
else:
|
||||
raise Exception("invalid type %r" % type)
|
||||
|
@ -227,8 +227,8 @@ def create_materials(filepath, relpath,
|
|||
# from some grey), and apply the the proportion between those two as tint factor?
|
||||
# ~ spec = sum(spec_color) / 3.0
|
||||
# ~ spec_var = math.sqrt(sum((c - spec) ** 2 for c in spec_color) / 3.0)
|
||||
# ~ diff = sum(context_mat_wrap.diffuse_color[:3]) / 3.0
|
||||
# ~ diff_var = math.sqrt(sum((c - diff) ** 2 for c in context_mat_wrap.diffuse_color[:3]) / 3.0)
|
||||
# ~ diff = sum(context_mat_wrap.base_color) / 3.0
|
||||
# ~ diff_var = math.sqrt(sum((c - diff) ** 2 for c in context_mat_wrap.base_color) / 3.0)
|
||||
# ~ tint = min(1.0, spec_var / diff_var)
|
||||
context_mat_wrap.specular = spec
|
||||
context_mat_wrap.specular_tint = 0.0
|
||||
|
@ -293,7 +293,7 @@ def create_materials(filepath, relpath,
|
|||
context_material_vars.add("metallic")
|
||||
elif line_id == b'kd':
|
||||
col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
|
||||
context_mat_wrap.diffuse_color[:3] = col
|
||||
context_mat_wrap.base_color = col
|
||||
elif line_id == b'ks':
|
||||
spec_color = (float_func(line_split[1]) + float_func(line_split[2]) + float_func(line_split[3]))
|
||||
context_material_vars.add("specular")
|
||||
|
|
|
@ -163,7 +163,7 @@ def save_object(fw, global_matrix,
|
|||
if is_editmode:
|
||||
bpy.ops.object.editmode_toggle()
|
||||
|
||||
me = obj.to_mesh(scene, True, 'PREVIEW', calc_tessface=False)
|
||||
me = obj.to_mesh(scene, True, 'PREVIEW')
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(me)
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ class Extrude_and_Reshape(Operator):
|
|||
nf = bmesh.utils.face_split(f, v1, v2)
|
||||
# sp_faces2.update({f, nf[0]})
|
||||
|
||||
bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
|
||||
bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True)
|
||||
return {'FINISHED'}
|
||||
if self.cancel:
|
||||
return {'FINISHED'}
|
||||
|
@ -345,7 +345,7 @@ class Extrude_and_Reshape(Operator):
|
|||
dfaces = bmesh.ops.dissolve_edges(
|
||||
self.bm, edges=geom, use_verts=True, use_face_split=False
|
||||
)
|
||||
bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
|
||||
bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True)
|
||||
bpy.ops.transform.translate(
|
||||
'INVOKE_DEFAULT', constraint_axis=(False, False, True),
|
||||
constraint_orientation='NORMAL', release_confirm=True
|
||||
|
|
|
@ -201,7 +201,7 @@ def fillets(list_0, startv, vertlist, face, adj, n, out, flip, radius):
|
|||
bm.edges.index_update()
|
||||
bm.faces.index_update()
|
||||
|
||||
me.update(calc_edges=True, calc_tessface=True)
|
||||
me.update(calc_edges=True, calc_loop_triangles=True)
|
||||
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
@ -144,7 +144,7 @@ class VertexChamfer(Operator):
|
|||
else:
|
||||
v.co += displace * v.normal
|
||||
|
||||
me.calc_tessface()
|
||||
me.calc_loop_triangles()
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -831,7 +831,7 @@ def terminate(global_undo):
|
|||
# update editmesh cached data
|
||||
obj = bpy.context.active_object
|
||||
if obj.mode == 'EDIT':
|
||||
bmesh.update_edit_mesh(obj.data, tessface=True, destructive=True)
|
||||
bmesh.update_edit_mesh(obj.data, loop_triangles=True, destructive=True)
|
||||
|
||||
bpy.context.user_preferences.edit.use_global_undo = global_undo
|
||||
|
||||
|
@ -3367,7 +3367,7 @@ class Bridge(Operator):
|
|||
if self.remove_faces and old_selected_faces:
|
||||
bridge_remove_internal_faces(bm, old_selected_faces)
|
||||
# make sure normals are facing outside
|
||||
bmesh.update_edit_mesh(object.data, tessface=False,
|
||||
bmesh.update_edit_mesh(object.data, loop_triangles=False,
|
||||
destructive=True)
|
||||
bpy.ops.mesh.normals_make_consistent()
|
||||
|
||||
|
@ -4086,7 +4086,7 @@ class GStretch(Operator):
|
|||
lock = [self.lock_x, self.lock_y, self.lock_z]
|
||||
else:
|
||||
lock = False
|
||||
bmesh.update_edit_mesh(object.data, tessface=True, destructive=True)
|
||||
bmesh.update_edit_mesh(object.data, loop_triangles=True, destructive=True)
|
||||
move_verts(object, bm, mapping, move, lock, self.influence)
|
||||
|
||||
# cleaning up
|
||||
|
|
|
@ -355,7 +355,7 @@ def draw_line(self, obj, bm, bm_geom, location):
|
|||
|
||||
drawing_is_dirt = False
|
||||
update_edit_mesh = False
|
||||
tessface = False
|
||||
loop_triangles = False
|
||||
|
||||
if bm_geom is None:
|
||||
vert = bm.verts.new(location)
|
||||
|
@ -437,7 +437,7 @@ def draw_line(self, obj, bm, bm_geom, location):
|
|||
facesp = bmesh.utils.face_split_edgenet(face, ed_list)
|
||||
del split_faces
|
||||
update_edit_mesh = True
|
||||
tessface = True
|
||||
loop_triangles = True
|
||||
else:
|
||||
if self.intersect:
|
||||
facesp = bmesh.ops.connect_vert_pair(bm, verts=[v1, v2], verts_exclude=bm.verts)
|
||||
|
@ -450,7 +450,7 @@ def draw_line(self, obj, bm, bm_geom, location):
|
|||
for edge in facesp['edges']:
|
||||
self.list_edges.append(edge)
|
||||
update_edit_mesh = True
|
||||
tessface = True
|
||||
loop_triangles = True
|
||||
|
||||
# create face
|
||||
if self.create_face:
|
||||
|
@ -469,10 +469,10 @@ def draw_line(self, obj, bm, bm_geom, location):
|
|||
|
||||
bmesh.ops.edgenet_fill(bm, edges=list(ed_list))
|
||||
update_edit_mesh = True
|
||||
tessface = True
|
||||
loop_triangles = True
|
||||
# print('face created')
|
||||
if update_edit_mesh:
|
||||
bmesh.update_edit_mesh(obj.data, tessface = tessface)
|
||||
bmesh.update_edit_mesh(obj.data, loop_triangles = loop_triangles)
|
||||
self.sctx.update_drawn_snap_object(self.snap_obj)
|
||||
#bm.verts.index_update()
|
||||
elif drawing_is_dirt:
|
||||
|
|
|
@ -52,26 +52,15 @@ def get_bmesh_vert_co_array(bm):
|
|||
|
||||
|
||||
def get_mesh_tri_verts_array(me):
|
||||
me.calc_tessface()
|
||||
len_tessfaces = len(me.tessfaces)
|
||||
if len_tessfaces:
|
||||
tessfaces = np.empty(len_tessfaces * 4, 'i4')
|
||||
me.tessfaces.foreach_get("vertices_raw", tessfaces)
|
||||
tessfaces.shape = (-1, 4)
|
||||
|
||||
quad_indices = tessfaces[:, 3].nonzero()[0]
|
||||
tris = np.empty(((len_tessfaces + len(quad_indices)), 3), 'i4')
|
||||
|
||||
tris[:len_tessfaces] = tessfaces[:, :3]
|
||||
tris[len_tessfaces:] = tessfaces[quad_indices][:, (0, 2, 3)]
|
||||
|
||||
del tessfaces
|
||||
return tris
|
||||
me.calc_loop_triangles()
|
||||
tris = [tri.vertices[:] for tri in me.loop_triangles]
|
||||
if tris:
|
||||
return np.array(tris, 'i4')
|
||||
return None
|
||||
|
||||
|
||||
def get_bmesh_tri_verts_array(bm):
|
||||
ltris = bm.calc_tessface()
|
||||
ltris = bm.calc_loop_triangles()
|
||||
tris = [[ltri[0].vert.index, ltri[1].vert.index, ltri[2].vert.index] for ltri in ltris if not ltri[0].face.hide]
|
||||
if tris:
|
||||
return np.array(tris, 'i4')
|
||||
|
|
|
@ -3752,7 +3752,7 @@ def drawlayout(context, layout, mode='non-panel'):
|
|||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator(NWAlignNodes.bl_idname, icon='ALIGN')
|
||||
col.operator(NWAlignNodes.bl_idname, icon='CENTER_ONLY')
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
|
|
@ -914,18 +914,18 @@ class VIEW3D_MT_booltool_menu(Menu):
|
|||
layout = self.layout
|
||||
|
||||
layout.label("Auto Boolean:")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon="ROTACTIVE")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon="ROTATECOLLECTION")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon="ROTATECENTER")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon="ROTATECENTER")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon="ROTACTIVE")
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon='PIVOT_ACTIVE')
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon='PIVOT_INDIVIDUAL')
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon='PIVOT_MEDIAN')
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon='PIVOT_MEDIAN')
|
||||
layout.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon='PIVOT_ACTIVE')
|
||||
layout.separator()
|
||||
|
||||
layout.label("Brush Boolean:")
|
||||
layout.operator(BTool_Diff.bl_idname, icon="ROTACTIVE")
|
||||
layout.operator(BTool_Union.bl_idname, icon="ROTATECOLLECTION")
|
||||
layout.operator(BTool_Inters.bl_idname, icon="ROTATECENTER")
|
||||
layout.operator(BTool_Slice.bl_idname, icon="ROTATECENTER")
|
||||
layout.operator(BTool_Diff.bl_idname, icon='PIVOT_ACTIVE')
|
||||
layout.operator(BTool_Union.bl_idname, icon='PIVOT_INDIVIDUAL')
|
||||
layout.operator(BTool_Inters.bl_idname, icon='PIVOT_MEDIAN')
|
||||
layout.operator(BTool_Slice.bl_idname, icon='PIVOT_MEDIAN')
|
||||
|
||||
if (isCanvas(context.active_object)):
|
||||
layout.separator()
|
||||
|
@ -977,16 +977,16 @@ class VIEW3D_PT_booltool_tools(Panel):
|
|||
col.enabled = obs_len > 1
|
||||
col.label("Auto Boolean:", icon="MODIFIER")
|
||||
col.separator()
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon="ROTACTIVE")
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon="ROTATECOLLECTION")
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon="ROTATECENTER")
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon='PIVOT_ACTIVE')
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon='PIVOT_INDIVIDUAL')
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon='PIVOT_MEDIAN')
|
||||
|
||||
main.separator()
|
||||
|
||||
col = main.column(align=True)
|
||||
col.enabled = obs_len == 2
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon="ROTATECENTER")
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon="ROTACTIVE")
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon='PIVOT_MEDIAN')
|
||||
col.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon='PIVOT_ACTIVE')
|
||||
|
||||
main.separator()
|
||||
|
||||
|
@ -994,10 +994,10 @@ class VIEW3D_PT_booltool_tools(Panel):
|
|||
col.enabled = obs_len > 1
|
||||
col.label("Brush Boolean:", icon="MODIFIER")
|
||||
col.separator()
|
||||
col.operator(BTool_Diff.bl_idname, text="Difference", icon="ROTACTIVE")
|
||||
col.operator(BTool_Union.bl_idname, text="Union", icon="ROTATECOLLECTION")
|
||||
col.operator(BTool_Inters.bl_idname, text="Intersect", icon="ROTATECENTER")
|
||||
col.operator(BTool_Slice.bl_idname, text="Slice", icon="ROTATECENTER")
|
||||
col.operator(BTool_Diff.bl_idname, text="Difference", icon='PIVOT_ACTIVE')
|
||||
col.operator(BTool_Union.bl_idname, text="Union", icon='PIVOT_INDIVIDUAL')
|
||||
col.operator(BTool_Inters.bl_idname, text="Intersect", icon='PIVOT_MEDIAN')
|
||||
col.operator(BTool_Slice.bl_idname, text="Slice", icon='PIVOT_MEDIAN')
|
||||
|
||||
main.separator()
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ class OBJECT_PT_collections(Panel):
|
|||
row.operator("object.collection_link", text="Add to Collection")
|
||||
else:
|
||||
row.operator("object.collection_link", text="Add to Collection").collection_index = 0
|
||||
row.operator("object.collection_add", text="", icon='ZOOMIN')
|
||||
row.operator("object.collection_add", text="", icon='ADD')
|
||||
|
||||
obj_name = obj.name
|
||||
for collection in all_collections_get(context):
|
||||
|
|
|
@ -32,7 +32,7 @@ def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifier
|
|||
|
||||
if apply_modifiers and obj.modifiers:
|
||||
import bpy
|
||||
me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW', calc_tessface=False)
|
||||
me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW')
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(me)
|
||||
bpy.data.meshes.remove(me)
|
||||
|
@ -268,7 +268,6 @@ def object_merge(context, objects):
|
|||
mesh_new = obj.to_mesh(
|
||||
depsgraph=context.depsgraph,
|
||||
apply_modifiers=True,
|
||||
calc_tessface=False,
|
||||
)
|
||||
|
||||
# remove non-active uvs/vcols
|
||||
|
|
|
@ -321,8 +321,7 @@ def DefOscObjectToMesh():
|
|||
MESH = ACTOBJ.to_mesh(
|
||||
scene=bpy.context.scene,
|
||||
apply_modifiers=True,
|
||||
settings="RENDER",
|
||||
calc_tessface=True)
|
||||
settings="RENDER")
|
||||
OBJECT = bpy.data.objects.new(("%s_Freeze") % (ACTOBJ.name), MESH)
|
||||
bpy.context.scene.objects.link(OBJECT)
|
||||
|
||||
|
@ -601,7 +600,7 @@ def defPasteUvsIsland(self, uvOffset, rotateUv,context):
|
|||
bm = bmesh.from_edit_mesh(bpy.context.object.data)
|
||||
bmesh.ops.reverse_uvs(bm, faces=[f for f in bm.faces if f.select])
|
||||
bmesh.ops.rotate_uvs(bm, faces=[f for f in bm.faces if f.select])
|
||||
#bmesh.update_edit_mesh(bpy.context.object.data, tessface=False, destructive=False)
|
||||
#bmesh.update_edit_mesh(bpy.context.object.data, loop_triangles=False, destructive=False)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -462,12 +462,12 @@ def color_palette_draw(self, context):
|
|||
|
||||
row = layout.row(align=True)
|
||||
row.menu("PALETTE_MT_menu", text=PALETTE_MT_menu.bl_label)
|
||||
row.operator("palette.preset_add", text="", icon="ZOOMIN").remove_active = False
|
||||
row.operator("palette.preset_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
row.operator("palette.preset_add", text="", icon='ADD').remove_active = False
|
||||
row.operator("palette.preset_add", text="", icon='REMOVE').remove_active = True
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.operator("palette_props.add_color", icon="ZOOMIN")
|
||||
row.operator("palette_props.add_color", icon='ADD')
|
||||
row.prop(palette_props, "index")
|
||||
row.operator("palette_props.remove_color", icon="PANEL_CLOSE")
|
||||
|
||||
|
|
|
@ -517,7 +517,7 @@ class PovrayColorImageNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
@ -535,7 +535,7 @@ class PovrayColorImageNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
@ -597,7 +597,7 @@ class PovrayBumpMapNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
@ -613,7 +613,7 @@ class PovrayBumpMapNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
@ -668,7 +668,7 @@ class PovrayImagePatternNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
@ -687,7 +687,7 @@ class PovrayImagePatternNode(Node, ObjectNodeTree):
|
|||
im=image
|
||||
split = column.split(percentage=0.8,align=True)
|
||||
split.prop_search(self,"image",context.blend_data,"images",text="")
|
||||
split.operator("pov.imageopen",text="",icon="FILESEL")
|
||||
split.operator("pov.imageopen",text="",icon="FILEBROWSER")
|
||||
if im is not None:
|
||||
column.prop(im,"source",text="")
|
||||
column.prop(self,"map_type",text="")
|
||||
|
|
|
@ -2689,7 +2689,7 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
importance = ob.pov.importance_value
|
||||
if me:
|
||||
me_materials = me.materials
|
||||
me_faces = me.tessfaces[:]
|
||||
me_faces = me.loop_triangles[:]
|
||||
#if len(me_faces)==0:
|
||||
#tabWrite("\n//dummy sphere to represent empty mesh location\n")
|
||||
#tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
|
||||
|
@ -2700,16 +2700,16 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
|
||||
continue
|
||||
|
||||
uv_textures = me.tessface_uv_textures
|
||||
if len(uv_textures) > 0:
|
||||
if me.uv_textures.active and uv_textures.active.data:
|
||||
uv_layer = uv_textures.active.data
|
||||
uv_layers = me.uv_layers
|
||||
if len(uv_layers) > 0:
|
||||
if me.uv_layers.active and uv_layers.active.data:
|
||||
uv_layer = uv_layers.active.data
|
||||
else:
|
||||
uv_layer = None
|
||||
|
||||
try:
|
||||
#vcol_layer = me.vertex_colors.active.data
|
||||
vcol_layer = me.tessface_vertex_colors.active.data
|
||||
vcol_layer = me.vertex_colors.active.data
|
||||
except AttributeError:
|
||||
vcol_layer = None
|
||||
|
||||
|
@ -2717,9 +2717,6 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
faces_normals = [f.normal[:] for f in me_faces]
|
||||
verts_normals = [v.normal[:] for v in me.vertices]
|
||||
|
||||
# quads incur an extra face
|
||||
quadCount = sum(1 for f in faces_verts if len(f) == 4)
|
||||
|
||||
# Use named declaration to allow reference e.g. for baking. MR
|
||||
file.write("\n")
|
||||
tabWrite("#declare %s =\n" % povdataname)
|
||||
|
@ -2775,12 +2772,8 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
# Generate unique UV's
|
||||
uniqueUVs = {}
|
||||
#n = 0
|
||||
for fi, uv in enumerate(uv_layer):
|
||||
|
||||
if len(faces_verts[fi]) == 4:
|
||||
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2], uv_layer[fi].uv[3]
|
||||
else:
|
||||
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2]
|
||||
for f in me.faces:
|
||||
uvs = [uv_layer[l].uv[:] for l in f.loops]
|
||||
|
||||
for uv in uvs:
|
||||
uniqueUVs[uv[:]] = [-1]
|
||||
|
@ -2811,7 +2804,7 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
if me.vertex_colors:
|
||||
#Write down vertex colors as a texture for each vertex
|
||||
tabWrite("texture_list {\n")
|
||||
tabWrite("%d\n" % (((len(me_faces)-quadCount) * 3 )+ quadCount * 4)) # works only with tris and quad mesh for now
|
||||
tabWrite("%d\n" % (len(me_faces) * 3)) # assumes we have only triangles
|
||||
VcolIdx=0
|
||||
if comments:
|
||||
file.write("\n //Vertex colors: one simple pigment texture per vertex\n")
|
||||
|
@ -2824,12 +2817,7 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
material = None
|
||||
if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now
|
||||
|
||||
col = vcol_layer[fi]
|
||||
|
||||
if len(faces_verts[fi]) == 4:
|
||||
cols = col.color1, col.color2, col.color3, col.color4
|
||||
else:
|
||||
cols = col.color1, col.color2, col.color3
|
||||
cols = [vcol_layer[l].color[:] for l in f.loops]
|
||||
|
||||
for col in cols:
|
||||
key = col[0], col[1], col[2], material_index # Material index!
|
||||
|
@ -2857,135 +2845,107 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
tabWrite("\n}\n")
|
||||
# Face indices
|
||||
tabWrite("\nface_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
|
||||
for fi, f in enumerate(me_faces):
|
||||
fv = faces_verts[fi]
|
||||
material_index = f.material_index
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
if vcol_layer:
|
||||
col = vcol_layer[fi]
|
||||
|
||||
if len(fv) == 4:
|
||||
cols = col.color1, col.color2, col.color3, col.color4
|
||||
else:
|
||||
cols = col.color1, col.color2, col.color3
|
||||
cols = [vcol_layer[l].color[:] for l in f.loops]
|
||||
|
||||
if not me_materials or me_materials[material_index] is None: # No materials
|
||||
for i1, i2, i3 in indices:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
# vert count
|
||||
file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
# vert count
|
||||
file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count
|
||||
else:
|
||||
material = me_materials[material_index]
|
||||
for i1, i2, i3 in indices:
|
||||
if me.vertex_colors: #and material.use_vertex_color_paint:
|
||||
# Color per vertex - vertex color
|
||||
if me.vertex_colors: #and material.use_vertex_color_paint:
|
||||
# Color per vertex - vertex color
|
||||
|
||||
col1 = cols[i1]
|
||||
col2 = cols[i2]
|
||||
col3 = cols[i3]
|
||||
col1 = cols[0]
|
||||
col2 = cols[1]
|
||||
col3 = cols[2]
|
||||
|
||||
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
|
||||
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
|
||||
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
|
||||
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
|
||||
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
|
||||
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
|
||||
else:
|
||||
# Color per material - flat material color
|
||||
if material.subsurface_scattering.use:
|
||||
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
|
||||
else:
|
||||
# Color per material - flat material color
|
||||
if material.subsurface_scattering.use:
|
||||
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
|
||||
else:
|
||||
diffuse_color = material.diffuse_color[:]
|
||||
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
|
||||
diffuse_color[2], f.material_index][0]
|
||||
# ci are zero based index so we'll subtract 1 from them
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
|
||||
diffuse_color = material.diffuse_color[:]
|
||||
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
|
||||
diffuse_color[2], f.material_index][0]
|
||||
# ci are zero based index so we'll subtract 1 from them
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
||||
# normal_indices indices
|
||||
tabWrite("normal_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
for fi, fv in enumerate(faces_verts):
|
||||
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
for i1, i2, i3 in indices:
|
||||
if me_faces[fi].use_smooth:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[i1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i2]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[i1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i2]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
|
||||
if me_faces[fi].use_smooth:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[0]]][0],\
|
||||
uniqueNormals[verts_normals[fv[1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
|
||||
else:
|
||||
idx = uniqueNormals[faces_normals[fi]][0]
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[0]]][0],\
|
||||
uniqueNormals[verts_normals[fv[1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
|
||||
else:
|
||||
idx = uniqueNormals[faces_normals[fi]][0]
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
||||
if uv_layer:
|
||||
tabWrite("uv_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
for fi, fv in enumerate(faces_verts):
|
||||
for f in me_faces:
|
||||
uvs = [uv_layer[l].uv[:] for l in f.loops]
|
||||
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[0]][0],\
|
||||
uniqueUVs[uvs[1]][0],\
|
||||
uniqueUVs[uvs[2]][0]))
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
uv = uv_layer[fi]
|
||||
if len(faces_verts[fi]) == 4:
|
||||
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:]
|
||||
else:
|
||||
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:]
|
||||
|
||||
for i1, i2, i3 in indices:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[i1]][0],\
|
||||
uniqueUVs[uvs[i2]][0],\
|
||||
uniqueUVs[uvs[i3]][0]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[i1]][0],\
|
||||
uniqueUVs[uvs[i2]][0],\
|
||||
uniqueUVs[uvs[i3]][0]))
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[0]][0],\
|
||||
uniqueUVs[uvs[1]][0],\
|
||||
uniqueUVs[uvs[2]][0]))
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
@ -3108,140 +3068,111 @@ def write_pov(filename, scene=None, info_callback=None):
|
|||
|
||||
# Face indices
|
||||
tabWrite("face_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
|
||||
for fi, f in enumerate(me_faces):
|
||||
fv = faces_verts[fi]
|
||||
material_index = f.material_index
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
if vcol_layer:
|
||||
col = vcol_layer[fi]
|
||||
|
||||
if len(fv) == 4:
|
||||
cols = col.color1, col.color2, col.color3, col.color4
|
||||
else:
|
||||
cols = col.color1, col.color2, col.color3
|
||||
cols = [vcol_layer[l].color[:] for l in f.loops]
|
||||
|
||||
if not me_materials or me_materials[material_index] is None: # No materials
|
||||
for i1, i2, i3 in indices:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
# vert count
|
||||
file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
# vert count
|
||||
file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count
|
||||
else:
|
||||
material = me_materials[material_index]
|
||||
for i1, i2, i3 in indices:
|
||||
ci1 = ci2 = ci3 = f.material_index
|
||||
if me.vertex_colors: #and material.use_vertex_color_paint:
|
||||
# Color per vertex - vertex color
|
||||
ci1 = ci2 = ci3 = f.material_index
|
||||
if me.vertex_colors: #and material.use_vertex_color_paint:
|
||||
# Color per vertex - vertex color
|
||||
|
||||
col1 = cols[i1]
|
||||
col2 = cols[i2]
|
||||
col3 = cols[i3]
|
||||
col1 = cols[0]
|
||||
col2 = cols[1]
|
||||
col3 = cols[2]
|
||||
|
||||
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
|
||||
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
|
||||
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
|
||||
elif material.pov.material_use_nodes:
|
||||
ci1 = ci2 = ci3 = 0
|
||||
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
|
||||
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
|
||||
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
|
||||
elif material.pov.material_use_nodes:
|
||||
ci1 = ci2 = ci3 = 0
|
||||
else:
|
||||
# Color per material - flat material color
|
||||
if material.subsurface_scattering.use:
|
||||
diffuse_color = [i * j for i, j in
|
||||
zip(material.subsurface_scattering.color[:],
|
||||
material.diffuse_color[:])]
|
||||
else:
|
||||
# Color per material - flat material color
|
||||
if material.subsurface_scattering.use:
|
||||
diffuse_color = [i * j for i, j in
|
||||
zip(material.subsurface_scattering.color[:],
|
||||
material.diffuse_color[:])]
|
||||
else:
|
||||
diffuse_color = material.diffuse_color[:]
|
||||
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
|
||||
diffuse_color[2], f.material_index][0]
|
||||
diffuse_color = material.diffuse_color[:]
|
||||
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
|
||||
diffuse_color[2], f.material_index][0]
|
||||
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>, %d,%d,%d" % \
|
||||
(fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
||||
# normal_indices indices
|
||||
tabWrite("normal_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
for fi, fv in enumerate(faces_verts):
|
||||
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
for i1, i2, i3 in indices:
|
||||
if me_faces[fi].use_smooth:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[i1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i2]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[i1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i2]]][0],\
|
||||
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
|
||||
if me_faces[fi].use_smooth:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[0]]][0],\
|
||||
uniqueNormals[verts_normals[fv[1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
|
||||
else:
|
||||
idx = uniqueNormals[faces_normals[fi]][0]
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" %\
|
||||
(uniqueNormals[verts_normals[fv[0]]][0],\
|
||||
uniqueNormals[verts_normals[fv[1]]][0],\
|
||||
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
|
||||
else:
|
||||
idx = uniqueNormals[faces_normals[fi]][0]
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
||||
if uv_layer:
|
||||
tabWrite("uv_indices {\n")
|
||||
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
|
||||
tabWrite("%d" % (len(me_faces))) # faces count
|
||||
tabStr = tab * tabLevel
|
||||
for fi, fv in enumerate(faces_verts):
|
||||
for f in me_faces:
|
||||
uvs = [uv_layer[l].uv[:] for l in f.loops]
|
||||
|
||||
if len(fv) == 4:
|
||||
indices = (0, 1, 2), (0, 2, 3)
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[0]][0],\
|
||||
uniqueUVs[uvs[1]][0],\
|
||||
uniqueUVs[uvs[2]][0]))
|
||||
else:
|
||||
indices = ((0, 1, 2),)
|
||||
|
||||
uv = uv_layer[fi]
|
||||
if len(faces_verts[fi]) == 4:
|
||||
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:]
|
||||
else:
|
||||
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:]
|
||||
|
||||
for i1, i2, i3 in indices:
|
||||
if linebreaksinlists:
|
||||
file.write(",\n")
|
||||
file.write(tabStr + "<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[i1]][0],\
|
||||
uniqueUVs[uvs[i2]][0],\
|
||||
uniqueUVs[uvs[i3]][0]))
|
||||
else:
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[i1]][0],\
|
||||
uniqueUVs[uvs[i2]][0],\
|
||||
uniqueUVs[uvs[i3]][0]))
|
||||
file.write(", ")
|
||||
file.write("<%d,%d,%d>" % (
|
||||
uniqueUVs[uvs[0]][0],\
|
||||
uniqueUVs[uvs[1]][0],\
|
||||
uniqueUVs[uvs[2]][0]))
|
||||
|
||||
file.write("\n")
|
||||
tabWrite("}\n")
|
||||
|
|
|
@ -252,7 +252,7 @@ class VIEW3D_PT_3dnavigationPanel(Panel):
|
|||
col.operator("view3d.view_selected", text="View to Selected")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Cursor:", icon="CURSOR")
|
||||
col.label(text="Cursor:", icon='PIVOT_CURSOR')
|
||||
row = col.row(align=True)
|
||||
row.operator("view3d.snap_cursor_to_center", text="Center")
|
||||
row.operator("view3d.view_center_cursor", text="View")
|
||||
|
@ -299,8 +299,8 @@ class VIEW3D_PT_pan_navigation1(Panel):
|
|||
row = layout.row()
|
||||
row.label(text="Zoom:")
|
||||
row = layout.row()
|
||||
row.operator("opr.zoom_in_view1", text="In", icon="ZOOMIN")
|
||||
row.operator("opr.zoom_out_view1", text="Out", icon="ZOOMOUT")
|
||||
row.operator("opr.zoom_in_view1", text="In", icon='ADD')
|
||||
row.operator("opr.zoom_out_view1", text="Out", icon='REMOVE')
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="Roll:")
|
||||
|
|
|
@ -95,7 +95,7 @@ class AreaTypePieOther(Menu):
|
|||
# 4 - LEFT
|
||||
self.layout.operator(SetAreaType.bl_idname, text="Logic Editor", icon="LOGIC").types = "LOGIC_EDITOR"
|
||||
# 6 - RIGHT
|
||||
self.layout.operator(SetAreaType.bl_idname, text="File Browser", icon="FILESEL").types = "FILE_BROWSER"
|
||||
self.layout.operator(SetAreaType.bl_idname, text="File Browser", icon="FILEBROWSER").types = "FILE_BROWSER"
|
||||
# 2 - BOTTOM
|
||||
self.layout.operator(SetAreaType.bl_idname, text="Python Console", icon="CONSOLE").types = "CONSOLE"
|
||||
# 8 - TOP
|
||||
|
|
|
@ -64,8 +64,8 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_AddMenu", icon='OBJECT_DATAMODE')
|
||||
layout.menu("VIEW3D_MT_View_Directions", icon='ZOOM_ALL')
|
||||
layout.menu("VIEW3D_MT_View_Navigation", icon='ROTATE')
|
||||
layout.menu("VIEW3D_MT_View_Toggle", icon='SPLITSCREEN')
|
||||
layout.menu("VIEW3D_MT_View_Navigation", icon='PIVOT_BOUNDBOX')
|
||||
layout.menu("VIEW3D_MT_View_Toggle", icon='WORKSPACE')
|
||||
layout.operator("view3d.snap_cursor_to_center",
|
||||
text="Cursor to Center")
|
||||
layout.operator("view3d.snap_cursor_to_grid",
|
||||
|
@ -91,9 +91,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -126,11 +126,11 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuEdit", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_EditCursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_EditCursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_UV_Map", icon='MOD_UVPROJECT')
|
||||
layout.menu("VIEW3D_MT_edit_mesh_specials", icon='SOLO_OFF')
|
||||
layout.menu("VIEW3D_MT_edit_mesh_extrude", icon='ORTHO')
|
||||
layout.menu("VIEW3D_MT_edit_mesh_extrude", icon='XRAY')
|
||||
UseSeparator(self, context)
|
||||
layout.operator_menu_enum("object.modifier_add", "type", icon='MODIFIER')
|
||||
layout.operator_menu_enum("object.constraint_add",
|
||||
|
@ -230,9 +230,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -265,7 +265,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
layout.menu("VIEW3D_MT_EditCurveCtrlpoints",
|
||||
icon='CURVE_BEZCURVE')
|
||||
layout.menu("VIEW3D_MT_EditCurveSpecials",
|
||||
|
@ -294,9 +294,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -325,7 +325,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
icon='OUTLINER_OB_SURFACE')
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.prop_menu_enum(settings, "proportional_edit",
|
||||
icon="PROP_CON")
|
||||
|
@ -357,9 +357,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -388,7 +388,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
icon='OUTLINER_OB_META')
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.prop_menu_enum(settings, "proportional_edit",
|
||||
icon="PROP_CON")
|
||||
|
@ -418,9 +418,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -470,9 +470,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
layout.menu("VIEW3D_MT_Object", icon='VIEW3D')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -501,9 +501,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
layout.menu("VIEW3D_MT_Object", icon='VIEW3D')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -533,9 +533,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuArmature", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -570,8 +570,8 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuArmatureEdit", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_armature_specials", icon='SOLO_OFF')
|
||||
layout.menu("VIEW3D_MT_edit_armature_roll",
|
||||
icon='BONE_DATA')
|
||||
|
@ -599,7 +599,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
layout.menu("VIEW3D_MT_TransformMenuArmaturePose", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_pose_transform", icon='EMPTY_DATA')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
layout.menu("VIEW3D_MT_PoseCopy", icon='FILE')
|
||||
|
||||
if arm.display_type in {'BBONE', 'ENVELOPE'}:
|
||||
|
@ -635,9 +635,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -666,7 +666,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.prop_menu_enum(settings, "proportional_edit",
|
||||
icon="PROP_CON")
|
||||
|
@ -695,9 +695,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF')
|
||||
|
@ -726,9 +726,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
layout.menu("VIEW3D_MT_Object", icon='VIEW3D')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
|
||||
layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE')
|
||||
layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
|
||||
UseSeparator(self, context)
|
||||
layout.operator_menu_enum("object.constraint_add",
|
||||
|
@ -754,7 +754,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu):
|
|||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
|
||||
layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR')
|
||||
layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR')
|
||||
UseSeparator(self, context)
|
||||
layout.prop_menu_enum(settings, "proportional_edit",
|
||||
icon="PROP_CON")
|
||||
|
@ -1351,7 +1351,7 @@ class VIEW3D_MT_Edit_Multi(Menu):
|
|||
|
||||
prop = layout.operator("wm.context_set_value",
|
||||
text="Vertex & Face Select",
|
||||
icon='ORTHO')
|
||||
icon='XRAY')
|
||||
prop.value = "(True, False, True)"
|
||||
prop.data_path = "tool_settings.mesh_select_mode"
|
||||
|
||||
|
@ -2228,7 +2228,7 @@ class VIEW3D_MT_Shade(Menu):
|
|||
layout.operator("OBJECT_OT_shade_flat")
|
||||
|
||||
UseSeparator(self, context)
|
||||
layout.operator("view3d.display_wire_all", text="Wire all", icon='WIRE')
|
||||
layout.operator("view3d.display_wire_all", text="Wire all", icon='SHADING_WIRE')
|
||||
layout.prop(context.object, "show_in_front", text="X-Ray", icon="META_CUBE")
|
||||
|
||||
UseSeparator(self, context)
|
||||
|
|
|
@ -179,8 +179,8 @@ def _property_chart_draw(self, context):
|
|||
col.label(text="Properties")
|
||||
row = col.row(align=True)
|
||||
row.menu("SCENE_MT_properties_presets", text=bpy.types.SCENE_MT_properties_presets.bl_label)
|
||||
row.operator("scene.properties_preset_add", text="", icon="ZOOMIN")
|
||||
row.operator("scene.properties_preset_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
row.operator("scene.properties_preset_add", text="", icon='ADD')
|
||||
row.operator("scene.properties_preset_add", text="", icon='REMOVE').remove_active = True
|
||||
# edit the display props
|
||||
col.prop(id_storage, self._PROP_STORAGE_ID, text="")
|
||||
|
||||
|
|
|
@ -580,8 +580,8 @@ class SCENE_PT_namedlayer_groups(Panel):
|
|||
row.template_list("SCENE_UL_namedlayer_groups", "", scene, "layergroups", scene, "layergroups_index")
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("scene.namedlayer_group_add", icon='ZOOMIN', text="").layers = scene.layers
|
||||
col.operator("scene.namedlayer_group_remove", icon='ZOOMOUT', text="").group_idx = group_idx
|
||||
col.operator("scene.namedlayer_group_add", icon='ADD', text="").layers = scene.layers
|
||||
col.operator("scene.namedlayer_group_remove", icon='REMOVE', text="").group_idx = group_idx
|
||||
|
||||
if bool(scene.layergroups):
|
||||
layout.prop(scene.layergroups[group_idx], "layers", text="", toggle=True)
|
||||
|
|
|
@ -95,8 +95,8 @@ class TexAtl_Main(Panel):
|
|||
row.template_list("UI_UL_list", "template_list_controls", scene,
|
||||
"ms_lightmap_groups", scene, "ms_lightmap_groups_index", rows=2, maxrows=5)
|
||||
col = row.column(align=True)
|
||||
col.operator("scene.ms_add_lightmap_group", icon='ZOOMIN', text="")
|
||||
col.operator("scene.ms_del_lightmap_group", icon='ZOOMOUT', text="")
|
||||
col.operator("scene.ms_add_lightmap_group", icon='ADD', text="")
|
||||
col.operator("scene.ms_del_lightmap_group", icon='REMOVE', text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
|
||||
|
|
Loading…
Reference in New Issue