|
@@ -90,7 +90,7 @@ TEMPLATE_SCENE_ASCII = """\
|
|
|
"formatVersion" : 3.2,
|
|
|
"type" : "scene",
|
|
|
"sourceFile" : "%(fname)s",
|
|
|
- "generatedBy" : "Blender 2.65 Exporter",
|
|
|
+ "generatedBy" : "Blender 2.7 Exporter",
|
|
|
"objects" : %(nobjects)s,
|
|
|
"geometries" : %(ngeometries)s,
|
|
|
"materials" : %(nmaterials)s,
|
|
@@ -269,7 +269,7 @@ TEMPLATE_FILE_ASCII = """\
|
|
|
"metadata" :
|
|
|
{
|
|
|
"formatVersion" : 3.1,
|
|
|
- "generatedBy" : "Blender 2.65 Exporter",
|
|
|
+ "generatedBy" : "Blender 2.7 Exporter",
|
|
|
"vertices" : %(nvertex)d,
|
|
|
"faces" : %(nface)d,
|
|
|
"normals" : %(nnormal)d,
|
|
@@ -308,7 +308,7 @@ TEMPLATE_MODEL_ASCII = """\
|
|
|
|
|
|
"skinWeights" : [%(weights)s],
|
|
|
|
|
|
- "animations" : [%(animations)s]
|
|
|
+ "animations" : [%(animations)s]
|
|
|
"""
|
|
|
|
|
|
TEMPLATE_VERTEX = "%g,%g,%g"
|
|
@@ -762,44 +762,56 @@ def get_armature():
|
|
|
# (only the first armature will exported)
|
|
|
# ##############################################################################
|
|
|
|
|
|
-def generate_bones(option_bones, flipyz):
|
|
|
+def generate_bones(meshes, option_bones, flipyz):
|
|
|
|
|
|
if not option_bones:
|
|
|
return "", 0
|
|
|
|
|
|
- armature, armatureObject = get_armature()
|
|
|
- if armature is None or armatureObject is None:
|
|
|
+ armature, armature_object = get_armature()
|
|
|
+ if armature_object is None:
|
|
|
return "", 0
|
|
|
|
|
|
hierarchy = []
|
|
|
+ armature_matrix = armature_object.matrix_world
|
|
|
+ pose_bones = armature_object.pose.bones
|
|
|
+ #pose_bones = armature.bones
|
|
|
|
|
|
- TEMPLATE_BONE = '{"parent":%d,"name":"%s","pos":[%g,%g,%g],"rotq":[0,0,0,1]}'
|
|
|
+ TEMPLATE_BONE = '{"parent":%d,"name":"%s","pos":[%g,%g,%g],"rotq":[%g,%g,%g,%g],"scl":[%g,%g,%g]}'
|
|
|
|
|
|
- for bone in armature.bones:
|
|
|
- bonePos = None
|
|
|
+ for pose_bone in pose_bones:
|
|
|
+ armature_bone = pose_bone.bone
|
|
|
+ #armature_bone = pose_bone
|
|
|
+ bonePos = armature_matrix * armature_bone.head_local
|
|
|
boneIndex = None
|
|
|
- if bone.parent is None:
|
|
|
- bonePos = bone.head_local
|
|
|
- boneIndex = -1
|
|
|
+
|
|
|
+ if armature_bone.parent is None:
|
|
|
+ bone_matrix = armature_matrix * armature_bone.matrix_local
|
|
|
+ bone_index = -1
|
|
|
else:
|
|
|
- bonePos = bone.head_local - bone.parent.head_local
|
|
|
- boneIndex = i = 0
|
|
|
- for parent in armature.bones:
|
|
|
- if parent.name == bone.parent.name:
|
|
|
- boneIndex = i
|
|
|
+ parent_matrix = armature_matrix * armature_bone.parent.matrix_local
|
|
|
+ bone_matrix = armature_matrix * armature_bone.matrix_local
|
|
|
+ bone_matrix = parent_matrix.inverted() * bone_matrix
|
|
|
+
|
|
|
+ bone_index = i = 0
|
|
|
+ for pose_parent in pose_bones:
|
|
|
+ armature_parent = pose_parent.bone
|
|
|
+ #armature_parent = pose_parent
|
|
|
+ if armature_parent.name == armature_bone.parent.name:
|
|
|
+ bone_index = i
|
|
|
i += 1
|
|
|
|
|
|
- bonePosWorld = armatureObject.matrix_world * bonePos
|
|
|
+ pos, rot, scl = bone_matrix.decompose()
|
|
|
+
|
|
|
if flipyz:
|
|
|
- joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.z, -bonePosWorld.y)
|
|
|
+ joint = TEMPLATE_BONE % (bone_index, armature_bone.name, pos.x, pos.z, -pos.y, rot.x, rot.z, -rot.y, rot.w, scl.x, scl.z, scl.y)
|
|
|
hierarchy.append(joint)
|
|
|
else:
|
|
|
- joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.y, bonePosWorld.z)
|
|
|
+ joint = TEMPLATE_BONE % (bone_index, armature_bone.name, pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, rot.w, scl.x, scl.y, scl.z)
|
|
|
hierarchy.append(joint)
|
|
|
-
|
|
|
- bones_string = ",".join(hierarchy)
|
|
|
|
|
|
- return bones_string, len(armature.bones)
|
|
|
+ bones_string = ",".join(hierarchy)
|
|
|
+
|
|
|
+ return bones_string, len(pose_bones)
|
|
|
|
|
|
|
|
|
# ##############################################################################
|
|
@@ -814,7 +826,7 @@ def generate_indices_and_weights(meshes, option_skinning):
|
|
|
indices = []
|
|
|
weights = []
|
|
|
|
|
|
- armature, armatureObject = get_armature()
|
|
|
+ armature, armature_object = get_armature()
|
|
|
|
|
|
for mesh, object in meshes:
|
|
|
|
|
@@ -845,9 +857,9 @@ def generate_indices_and_weights(meshes, option_skinning):
|
|
|
weight = group.weight
|
|
|
|
|
|
bone_array.append( (index, weight) )
|
|
|
-
|
|
|
+
|
|
|
bone_array.sort(key = operator.itemgetter(1), reverse=True)
|
|
|
-
|
|
|
+
|
|
|
# select first N bones
|
|
|
|
|
|
for i in range(MAX_INFLUENCES):
|
|
@@ -859,7 +871,7 @@ def generate_indices_and_weights(meshes, option_skinning):
|
|
|
index = bone_proxy[0]
|
|
|
weight = bone_proxy[1]
|
|
|
|
|
|
- for j, bone in enumerate(armature.bones):
|
|
|
+ for j, bone in enumerate(armature_object.pose.bones):
|
|
|
if object.vertex_groups[index].name == bone.name:
|
|
|
indices.append('%d' % j)
|
|
|
weights.append('%g' % weight)
|
|
@@ -873,8 +885,8 @@ def generate_indices_and_weights(meshes, option_skinning):
|
|
|
else:
|
|
|
indices.append('0')
|
|
|
weights.append('0')
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
indices_string = ",".join(indices)
|
|
|
weights_string = ",".join(weights)
|
|
|
|
|
@@ -886,23 +898,33 @@ def generate_indices_and_weights(meshes, option_skinning):
|
|
|
# (only the first action will exported)
|
|
|
# ##############################################################################
|
|
|
|
|
|
-def generate_animation(option_animation_skeletal, option_frame_step, flipyz, action_index):
|
|
|
+def generate_animation(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time, index):
|
|
|
|
|
|
- if not option_animation_skeletal or len(bpy.data.actions) == 0 or len(bpy.data.actions) == 0:
|
|
|
+ if not option_animation_skeletal or len(bpy.data.actions) == 0:
|
|
|
return ""
|
|
|
|
|
|
# TODO: Add scaling influences
|
|
|
|
|
|
- action = bpy.data.actions[action_index]
|
|
|
- armature, armatureObject = get_armature()
|
|
|
- if armature is None or armatureObject is None:
|
|
|
+ action = bpy.data.actions[index]
|
|
|
+
|
|
|
+ # get current context and then switch to dopesheet temporarily
|
|
|
+
|
|
|
+ current_context = bpy.context.area.type
|
|
|
+
|
|
|
+ bpy.context.area.type = "DOPESHEET_EDITOR"
|
|
|
+ bpy.context.space_data.mode = "ACTION"
|
|
|
+
|
|
|
+ # set active action
|
|
|
+ bpy.context.area.spaces.active.action = action
|
|
|
+
|
|
|
+ armature, armature_object = get_armature()
|
|
|
+ if armature_object is None or armature is None:
|
|
|
return "", 0
|
|
|
- armatureMat = armatureObject.matrix_world
|
|
|
- l,r,s = armatureMat.decompose()
|
|
|
- armatureRotMat = r.to_matrix()
|
|
|
-
|
|
|
- parents = []
|
|
|
- parent_index = -1
|
|
|
+
|
|
|
+ #armature_object = bpy.data.objects['marine_rig']
|
|
|
+
|
|
|
+
|
|
|
+ armature_matrix = armature_object.matrix_world
|
|
|
|
|
|
fps = bpy.data.scenes[0].render.fps
|
|
|
|
|
@@ -911,75 +933,180 @@ def generate_animation(option_animation_skeletal, option_frame_step, flipyz, act
|
|
|
|
|
|
frame_length = end_frame - start_frame
|
|
|
|
|
|
- TEMPLATE_KEYFRAME_FULL = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g],"scl":[1,1,1]}'
|
|
|
- TEMPLATE_KEYFRAME = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g]}'
|
|
|
- TEMPLATE_KEYFRAME_POS = '{"time":%g,"pos":[%g,%g,%g]}'
|
|
|
- TEMPLATE_KEYFRAME_ROT = '{"time":%g,"rot":[%g,%g,%g,%g]}'
|
|
|
+ used_frames = int(frame_length / option_frame_step) + 1
|
|
|
|
|
|
- for hierarchy in armature.bones:
|
|
|
+ TEMPLATE_KEYFRAME_FULL = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g],"scl":[%g,%g,%g]}'
|
|
|
+ TEMPLATE_KEYFRAME_BEGIN = '{"time":%g'
|
|
|
+ TEMPLATE_KEYFRAME_END = '}'
|
|
|
+ TEMPLATE_KEYFRAME_POS = ',"pos":[%g,%g,%g]'
|
|
|
+ TEMPLATE_KEYFRAME_ROT = ',"rot":[%g,%g,%g,%g]'
|
|
|
+ TEMPLATE_KEYFRAME_SCL = ',"scl":[%g,%g,%g]'
|
|
|
|
|
|
- keys = []
|
|
|
+ keys = []
|
|
|
+ channels_location = []
|
|
|
+ channels_rotation = []
|
|
|
+ channels_scale = []
|
|
|
+
|
|
|
+ # Precompute per-bone data
|
|
|
+ for pose_bone in armature_object.pose.bones:
|
|
|
+ armature_bone = pose_bone.bone
|
|
|
+ keys.append([])
|
|
|
+ channels_location.append( find_channels(action, armature_bone, "location"))
|
|
|
+ channels_rotation.append( find_channels(action, armature_bone, "rotation_quaternion"))
|
|
|
+ channels_rotation.append( find_channels(action, armature_bone, "rotation_euler"))
|
|
|
+ channels_scale.append( find_channels(action, armature_bone, "scale"))
|
|
|
+
|
|
|
+ # Process all frames
|
|
|
+ for frame_i in range(0, used_frames):
|
|
|
+
|
|
|
+ #print("Processing frame %d/%d" % (frame_i, used_frames))
|
|
|
+ # Compute the index of the current frame (snap the last index to the end)
|
|
|
+ frame = start_frame + frame_i * option_frame_step
|
|
|
+ if frame_i == used_frames-1:
|
|
|
+ frame = end_frame
|
|
|
+
|
|
|
+ # Compute the time of the frame
|
|
|
+ if option_frame_index_as_time:
|
|
|
+ time = frame - start_frame
|
|
|
+ else:
|
|
|
+ time = (frame - start_frame) / fps
|
|
|
|
|
|
- for frame in range(int(start_frame), int(end_frame / option_frame_step) + 1):
|
|
|
+ # Let blender compute the pose bone transformations
|
|
|
+ bpy.data.scenes[0].frame_set(frame)
|
|
|
|
|
|
- pos, pchange = position(hierarchy, frame * option_frame_step, action, armatureMat)
|
|
|
- rot, rchange = rotation(hierarchy, frame * option_frame_step, action, armatureRotMat)
|
|
|
+ # Process all bones for the current frame
|
|
|
+ bone_index = 0
|
|
|
+ for pose_bone in armature_object.pose.bones:
|
|
|
+
|
|
|
+ # Extract the bone transformations
|
|
|
+ if pose_bone.parent is None:
|
|
|
+ bone_matrix = armature_matrix * pose_bone.matrix
|
|
|
+ else:
|
|
|
+ parent_matrix = armature_matrix * pose_bone.parent.matrix
|
|
|
+ bone_matrix = armature_matrix * pose_bone.matrix
|
|
|
+ bone_matrix = parent_matrix.inverted() * bone_matrix
|
|
|
+ pos, rot, scl = bone_matrix.decompose()
|
|
|
+
|
|
|
+ pchange = True or has_keyframe_at(channels_location[bone_index], frame)
|
|
|
+ rchange = True or has_keyframe_at(channels_rotation[bone_index], frame)
|
|
|
+ schange = True or has_keyframe_at(channels_scale[bone_index], frame)
|
|
|
|
|
|
if flipyz:
|
|
|
px, py, pz = pos.x, pos.z, -pos.y
|
|
|
rx, ry, rz, rw = rot.x, rot.z, -rot.y, rot.w
|
|
|
+ sx, sy, sz = scl.x, scl.z, scl.y
|
|
|
else:
|
|
|
px, py, pz = pos.x, pos.y, pos.z
|
|
|
rx, ry, rz, rw = rot.x, rot.y, rot.z, rot.w
|
|
|
+ sx, sy, sz = scl.x, scl.y, scl.z
|
|
|
|
|
|
# START-FRAME: needs pos, rot and scl attributes (required frame)
|
|
|
|
|
|
- if frame == int(start_frame):
|
|
|
+ if frame == start_frame:
|
|
|
|
|
|
- time = (frame * option_frame_step - start_frame) / fps
|
|
|
- keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw)
|
|
|
- keys.append(keyframe)
|
|
|
+ keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw, sx, sy, sz)
|
|
|
+ keys[bone_index].append(keyframe)
|
|
|
|
|
|
# END-FRAME: needs pos, rot and scl attributes with animation length (required frame)
|
|
|
|
|
|
- elif frame == int(end_frame / option_frame_step):
|
|
|
+ elif frame == end_frame:
|
|
|
|
|
|
- time = frame_length / fps
|
|
|
- keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw)
|
|
|
- keys.append(keyframe)
|
|
|
+ keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw, sx, sy, sz)
|
|
|
+ keys[bone_index].append(keyframe)
|
|
|
|
|
|
# MIDDLE-FRAME: needs only one of the attributes, can be an empty frame (optional frame)
|
|
|
|
|
|
elif pchange == True or rchange == True:
|
|
|
|
|
|
- time = (frame * option_frame_step - start_frame) / fps
|
|
|
-
|
|
|
- if pchange == True and rchange == True:
|
|
|
- keyframe = TEMPLATE_KEYFRAME % (time, px, py, pz, rx, ry, rz, rw)
|
|
|
- elif pchange == True:
|
|
|
- keyframe = TEMPLATE_KEYFRAME_POS % (time, px, py, pz)
|
|
|
- elif rchange == True:
|
|
|
- keyframe = TEMPLATE_KEYFRAME_ROT % (time, rx, ry, rz, rw)
|
|
|
+ keyframe = TEMPLATE_KEYFRAME_BEGIN % time
|
|
|
+ if pchange == True:
|
|
|
+ keyframe = keyframe + TEMPLATE_KEYFRAME_POS % (px, py, pz)
|
|
|
+ if rchange == True:
|
|
|
+ keyframe = keyframe + TEMPLATE_KEYFRAME_ROT % (rx, ry, rz, rw)
|
|
|
+ if schange == True:
|
|
|
+ keyframe = keyframe + TEMPLATE_KEYFRAME_SCL % (sx, sy, sz)
|
|
|
+ keyframe = keyframe + TEMPLATE_KEYFRAME_END
|
|
|
|
|
|
- keys.append(keyframe)
|
|
|
+ keys[bone_index].append(keyframe)
|
|
|
+ bone_index += 1
|
|
|
|
|
|
- keys_string = ",".join(keys)
|
|
|
+ # Gather data
|
|
|
+ parents = []
|
|
|
+ bone_index = 0
|
|
|
+ for pose_bone in armature_object.pose.bones:
|
|
|
+ keys_string = ",".join(keys[bone_index])
|
|
|
+ parent_index = bone_index - 1 # WTF? Also, this property is not used by three.js
|
|
|
parent = '{"parent":%d,"keys":[%s]}' % (parent_index, keys_string)
|
|
|
- parent_index += 1
|
|
|
+ bone_index += 1
|
|
|
parents.append(parent)
|
|
|
-
|
|
|
hierarchy_string = ",".join(parents)
|
|
|
- animation_string = '"name":"%s","fps":%d,"length":%g,"hierarchy":[%s]' % (action.name, fps, (frame_length / fps), hierarchy_string)
|
|
|
|
|
|
+ if option_frame_index_as_time:
|
|
|
+ length = frame_length
|
|
|
+ else:
|
|
|
+ length = frame_length / fps
|
|
|
+
|
|
|
+ animation_string = '"name":"%s","fps":%d,"length":%g,"hierarchy":[%s]' % (action.name, fps, length, hierarchy_string)
|
|
|
+
|
|
|
+ bpy.data.scenes[0].frame_set(start_frame)
|
|
|
+
|
|
|
+ # reset context
|
|
|
+
|
|
|
+ bpy.context.area.type = current_context
|
|
|
+
|
|
|
return animation_string
|
|
|
|
|
|
-def generate_all_animations(option_animation_skeletal, option_frame_step, flipyz):
|
|
|
+def find_channels(action, bone, channel_type):
|
|
|
+ bone_name = bone.name
|
|
|
+ ngroups = len(action.groups)
|
|
|
+ result = []
|
|
|
+
|
|
|
+ # Variant 1: channels grouped by bone names
|
|
|
+ if ngroups > 0:
|
|
|
+
|
|
|
+ # Find the channel group for the given bone
|
|
|
+ group_index = -1
|
|
|
+ for i in range(ngroups):
|
|
|
+ if action.groups[i].name == bone_name:
|
|
|
+ group_index = i
|
|
|
+
|
|
|
+ # Get all desired channels in that group
|
|
|
+ if group_index > -1:
|
|
|
+ for channel in action.groups[group_index].channels:
|
|
|
+ if channel_type in channel.data_path:
|
|
|
+ result.append(channel)
|
|
|
+
|
|
|
+ # Variant 2: no channel groups, bone names included in channel names
|
|
|
+ else:
|
|
|
+
|
|
|
+ bone_label = '"%s"' % bone_name
|
|
|
+
|
|
|
+ for channel in action.fcurves:
|
|
|
+ data_path = channel.data_path
|
|
|
+ if bone_label in data_path and channel_type in data_path:
|
|
|
+ result.append(channel)
|
|
|
+
|
|
|
+ return result
|
|
|
+
|
|
|
+def find_keyframe_at(channel, frame):
|
|
|
+ for keyframe in channel.keyframe_points:
|
|
|
+ if keyframe.co[0] == frame:
|
|
|
+ return keyframe
|
|
|
+ return None
|
|
|
+
|
|
|
+def has_keyframe_at(channels, frame):
|
|
|
+ for channel in channels:
|
|
|
+ if not find_keyframe_at(channel, frame) is None:
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+
|
|
|
+def generate_all_animations(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time):
|
|
|
all_animations_string = ""
|
|
|
if option_animation_skeletal:
|
|
|
for index in range(0, len(bpy.data.actions)):
|
|
|
if index != 0 :
|
|
|
all_animations_string += ", \n"
|
|
|
- all_animations_string += "{" + generate_animation(option_animation_skeletal, option_frame_step, flipyz, index) + "}"
|
|
|
+ all_animations_string += "{" + generate_animation(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time,index) + "}"
|
|
|
return all_animations_string
|
|
|
|
|
|
def handle_position_channel(channel, frame, position):
|
|
@@ -1036,7 +1163,7 @@ def position(bone, frame, action, armatureMatrix):
|
|
|
|
|
|
position = position * bone.matrix_local.inverted()
|
|
|
|
|
|
- if bone.parent is None:
|
|
|
+ if bone.parent == None:
|
|
|
|
|
|
position.x += bone.head.x
|
|
|
position.y += bone.head.y
|
|
@@ -1344,6 +1471,7 @@ def generate_ascii_model(meshes, morphs,
|
|
|
filepath,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
+ option_frame_index_as_time,
|
|
|
option_frame_step):
|
|
|
|
|
|
vertices = []
|
|
@@ -1421,7 +1549,7 @@ def generate_ascii_model(meshes, morphs,
|
|
|
|
|
|
faces_string, nfaces = generate_faces(normals, uv_layers, colors, meshes, option_normals, option_colors, option_uv_coords, option_materials, option_faces)
|
|
|
|
|
|
- bones_string, nbone = generate_bones(option_bones, flipyz)
|
|
|
+ bones_string, nbone = generate_bones(meshes, option_bones, flipyz)
|
|
|
indices_string, weights_string = generate_indices_and_weights(meshes, option_skinning)
|
|
|
|
|
|
materials_string = ",\n\n".join(materials)
|
|
@@ -1444,7 +1572,7 @@ def generate_ascii_model(meshes, morphs,
|
|
|
"bones" : bones_string,
|
|
|
"indices" : indices_string,
|
|
|
"weights" : weights_string,
|
|
|
- "animations" : generate_all_animations(option_animation_skeletal, option_frame_step, flipyz)
|
|
|
+ "animations" : generate_all_animations(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time)
|
|
|
}
|
|
|
|
|
|
text = TEMPLATE_FILE_ASCII % {
|
|
@@ -1483,6 +1611,10 @@ def extract_meshes(objects, scene, export_single_model, option_scale, flipyz):
|
|
|
if not mesh:
|
|
|
raise Exception("Error, could not get mesh data from object [%s]" % object.name)
|
|
|
|
|
|
+ # preserve original name
|
|
|
+
|
|
|
+ mesh.name = object.name
|
|
|
+
|
|
|
if export_single_model:
|
|
|
|
|
|
if flipyz:
|
|
@@ -1523,6 +1655,7 @@ def generate_mesh_string(objects, scene,
|
|
|
filepath,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
+ option_frame_index_as_time,
|
|
|
option_frame_step):
|
|
|
|
|
|
meshes = extract_meshes(objects, scene, export_single_model, option_scale, flipyz)
|
|
@@ -1587,6 +1720,7 @@ def generate_mesh_string(objects, scene,
|
|
|
filepath,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
+ option_frame_index_as_time,
|
|
|
option_frame_step)
|
|
|
|
|
|
# remove temp meshes
|
|
@@ -1614,7 +1748,8 @@ def export_mesh(objects,
|
|
|
option_copy_textures,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
- option_frame_step):
|
|
|
+ option_frame_step,
|
|
|
+ option_frame_index_as_time):
|
|
|
|
|
|
"""Export single mesh"""
|
|
|
|
|
@@ -1637,6 +1772,7 @@ def export_mesh(objects,
|
|
|
filepath,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
+ option_frame_index_as_time,
|
|
|
option_frame_step)
|
|
|
|
|
|
write_file(filepath, text)
|
|
@@ -2273,7 +2409,6 @@ def generate_lights(data):
|
|
|
|
|
|
return ",\n\n".join(chunks), len(chunks)
|
|
|
|
|
|
-
|
|
|
# #####################################################
|
|
|
# Scene exporter - embedded meshes
|
|
|
# #####################################################
|
|
@@ -2433,7 +2568,8 @@ def save(operator, context, filepath = "",
|
|
|
option_animation_morph = False,
|
|
|
option_animation_skeletal = False,
|
|
|
option_frame_step = 1,
|
|
|
- option_all_meshes = True):
|
|
|
+ option_all_meshes = True,
|
|
|
+ option_frame_index_as_time = False):
|
|
|
|
|
|
#print("URL TYPE", option_url_base_html)
|
|
|
|
|
@@ -2497,9 +2633,10 @@ def save(operator, context, filepath = "",
|
|
|
filepath,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
+ option_frame_index_as_time,
|
|
|
option_frame_step)
|
|
|
|
|
|
- embeds[name] = model_string
|
|
|
+ embeds[object.data.name] = model_string
|
|
|
|
|
|
else:
|
|
|
|
|
@@ -2522,7 +2659,8 @@ def save(operator, context, filepath = "",
|
|
|
option_copy_textures,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
- option_frame_step)
|
|
|
+ option_frame_step,
|
|
|
+ option_frame_index_as_time)
|
|
|
|
|
|
geo_set.add(name)
|
|
|
|
|
@@ -2555,6 +2693,7 @@ def save(operator, context, filepath = "",
|
|
|
option_copy_textures,
|
|
|
option_animation_morph,
|
|
|
option_animation_skeletal,
|
|
|
- option_frame_step)
|
|
|
+ option_frame_step,
|
|
|
+ option_frame_index_as_time)
|
|
|
|
|
|
return {'FINISHED'}
|