Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--io_export_unreal_psk_psa.py2114
1 files changed, 1206 insertions, 908 deletions
diff --git a/io_export_unreal_psk_psa.py b/io_export_unreal_psk_psa.py
index 7ecef29b..ca22ca46 100644
--- a/io_export_unreal_psk_psa.py
+++ b/io_export_unreal_psk_psa.py
@@ -1,4 +1,4 @@
-#====================== BEGIN GPL LICENSE BLOCK ============================
+# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,17 +14,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# All rights reserved.
#
-#======================= END GPL LICENSE BLOCK =============================
+# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Export Unreal Engine Format(.psk/.psa)",
"author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft/VendorX/Spoof",
- "version": (2, 7),
+ "version": (2, 7, 1),
"blender": (2, 65, 4),
"location": "File > Export > Skeletal Mesh/Animation Data (.psk/.psa)",
"description": "Export Skeleletal Mesh/Animation Data",
"warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
+ "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Import-Export/Unreal_psk_psa",
"category": "Import-Export",
}
@@ -47,7 +47,8 @@ bl_info = {
- This will work on UT3 and it is a stable version that work with vehicle for testing.
- Main Bone fix no dummy needed to be there.
- Just bone issues position, rotation, and offset for psk.
-- The armature bone position, rotation, and the offset of the bone is fix. It was to deal with skeleton mesh export for psk.
+- The armature bone position, rotation, and the offset of the bone is fix.
+ It was to deal with skeleton mesh export for psk.
- Animation is fix for position, offset, rotation bone support one rotation direction when armature build.
- It will convert your mesh into triangular when exporting to psk file.
- Did not work with psa export yet.
@@ -78,7 +79,7 @@ Credit to:
"""
-#===========================================================================
+# ===========================================================================
"""
NOTES for Jan 2012 refactor (Spoof)
@@ -135,7 +136,7 @@ deformer bones (bad for optimising a game character). I had partial success
writing a parser for the structure, but it was taking too much time and,
considering the other issues with Rigify, it was abandoned.
"""
-#===========================================================================
+# ===========================================================================
import bmesh
import os
@@ -143,12 +144,26 @@ import time
import bpy
import mathutils
import math
-import random
import operator
import sys
-from bpy.props import *
+from bpy.props import (
+ BoolProperty,
+ CollectionProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ StringProperty,
+ )
+from bpy.types import (
+ Operator,
+ Panel,
+ UIList,
+ PropertyGroup,
+ AddonPreferences,
+ )
from struct import pack
+
# REFERENCE MATERIAL JUST IN CASE:
#
# U = x / sqrt(x^2 + y^2 + z^2)
@@ -157,36 +172,43 @@ from struct import pack
# Triangles specifed counter clockwise for front face
#
# defines for sizeofs
-SIZE_FQUAT = 16
-SIZE_FVECTOR = 12
-SIZE_VJOINTPOS = 44
-SIZE_ANIMINFOBINARY = 168
-SIZE_VCHUNKHEADER = 32
-SIZE_VMATERIAL = 88
-SIZE_VBONE = 120
-SIZE_FNAMEDBONEBINARY = 120
-SIZE_VRAWBONEINFLUENCE = 12
-SIZE_VQUATANIMKEY = 32
-SIZE_VVERTEX = 16
-SIZE_VPOINT = 12
-SIZE_VTRIANGLE = 12
-
-MaterialName = []
-
-#===========================================================================
+SIZE_FQUAT = 16
+SIZE_FVECTOR = 12
+SIZE_VJOINTPOS = 44
+SIZE_ANIMINFOBINARY = 168
+SIZE_VCHUNKHEADER = 32
+SIZE_VMATERIAL = 88
+SIZE_VBONE = 120
+SIZE_FNAMEDBONEBINARY = 120
+SIZE_VRAWBONEINFLUENCE = 12
+SIZE_VQUATANIMKEY = 32
+SIZE_VVERTEX = 16
+SIZE_VPOINT = 12
+SIZE_VTRIANGLE = 12
+
+MaterialName = []
+
+
+# Python 3 doesn't have cmp anymore
+def cmp(a, b):
+ return (a > b) - (a < b)
+
+
+# ===========================================================================
# Custom exception class
-#===========================================================================
-class Error( Exception ):
+# ===========================================================================
+class Error(Exception):
def __init__(self, message):
self.message = message
-#===========================================================================
+
+# ===========================================================================
# Verbose logging with loop truncation
-#===========================================================================
-def verbose( msg, iteration=-1, max_iterations=4, msg_truncated="..." ):
+# ===========================================================================
+def verbose(msg, iteration=-1, max_iterations=4, msg_truncated="..."):
- if bpy.context.scene.udk_option_verbose == True:
+ if bpy.context.scene.udk_option_verbose is True:
# limit the number of times a loop can output messages
if iteration > max_iterations:
return
@@ -196,26 +218,28 @@ def verbose( msg, iteration=-1, max_iterations=4, msg_truncated="..." ):
print(msg)
-#===========================================================================
+
+# ===========================================================================
# Log header/separator
-#===========================================================================
-def header( msg, justify='LEFT', spacer='_', cols=78 ):
+# ===========================================================================
+def header(msg, justify='LEFT', spacer='_', cols=78):
if justify == 'LEFT':
- s = '{:{spacer}<{cols}}'.format(msg+" ", spacer=spacer, cols=cols)
+ s = '{:{spacer}<{cols}}'.format(msg + " ", spacer=spacer, cols=cols)
elif justify == 'RIGHT':
- s = '{:{spacer}>{cols}}'.format(" "+msg, spacer=spacer, cols=cols)
+ s = '{:{spacer}>{cols}}'.format(" " + msg, spacer=spacer, cols=cols)
else:
- s = '{:{spacer}^{cols}}'.format(" "+msg+" ", spacer=spacer, cols=cols)
+ s = '{:{spacer}^{cols}}'.format(" " + msg + " ", spacer=spacer, cols=cols)
return "\n" + s + "\n"
-#===========================================================================
+
+# ===========================================================================
# Generic Object->Integer mapping
# the object must be usable as a dictionary key
-#===========================================================================
+# ===========================================================================
class ObjMap:
def __init__(self):
@@ -236,11 +260,12 @@ class ObjMap:
getkey = operator.itemgetter(1)
return map(getval, sorted(self.dict.items(), key=getkey))
-#===========================================================================
+
+# ===========================================================================
# RG - UNREAL DATA STRUCTS - CONVERTED FROM C STRUCTS GIVEN ON UDN SITE
# provided here: http://udn.epicgames.com/Two/BinaryFormatSpecifications.html
# updated UDK (Unreal Engine 3): http://udn.epicgames.com/Three/BinaryFormatSpecifications.html
-#===========================================================================
+# ===========================================================================
class FQuat:
def __init__(self):
@@ -253,10 +278,10 @@ class FQuat:
return pack('ffff', self.X, self.Y, self.Z, self.W)
def __cmp__(self, other):
- return cmp(self.X, other.X) \
- or cmp(self.Y, other.Y) \
- or cmp(self.Z, other.Z) \
- or cmp(self.W, other.W)
+ return cmp(self.X, other.X) or \
+ cmp(self.Y, other.Y) or \
+ cmp(self.Z, other.Z) or \
+ cmp(self.W, other.W)
def __hash__(self):
return hash(self.X) ^ hash(self.Y) ^ hash(self.Z) ^ hash(self.W)
@@ -264,6 +289,7 @@ class FQuat:
def __str__(self):
return "[%f,%f,%f,%f](FQuat)" % (self.X, self.Y, self.Z, self.W)
+
class FVector(object):
def __init__(self, X=0.0, Y=0.0, Z=0.0):
@@ -275,9 +301,9 @@ class FVector(object):
return pack('fff', self.X, self.Y, self.Z)
def __cmp__(self, other):
- return cmp(self.X, other.X) \
- or cmp(self.Y, other.Y) \
- or cmp(self.Z, other.Z)
+ return cmp(self.X, other.X) or \
+ cmp(self.Y, other.Y) or \
+ cmp(self.Z, other.Z)
def _key(self):
return (type(self).__name__, self.X, self.Y, self.Z)
@@ -303,130 +329,146 @@ class FVector(object):
self.Y - other.Y,
self.Z - other.Z)
+
class VJointPos:
def __init__(self):
- self.Orientation = FQuat()
- self.Position = FVector()
- self.Length = 0.0
- self.XSize = 0.0
- self.YSize = 0.0
- self.ZSize = 0.0
+ self.Orientation = FQuat()
+ self.Position = FVector()
+ self.Length = 0.0
+ self.XSize = 0.0
+ self.YSize = 0.0
+ self.ZSize = 0.0
def dump(self):
- return self.Orientation.dump() + self.Position.dump() + pack('4f', self.Length, self.XSize, self.YSize, self.ZSize)
+ return self.Orientation.dump() + self.Position.dump() + \
+ pack('4f', self.Length, self.XSize, self.YSize, self.ZSize)
+
class AnimInfoBinary:
def __init__(self):
- self.Name = "" # length=64
- self.Group = "" # length=64
- self.TotalBones = 0
- self.RootInclude = 0
+ self.Name = "" # length=64
+ self.Group = "" # length=64
+ self.TotalBones = 0
+ self.RootInclude = 0
self.KeyCompressionStyle = 0
- self.KeyQuotum = 0
- self.KeyPrediction = 0.0
- self.TrackTime = 0.0
- self.AnimRate = 0.0
- self.StartBone = 0
- self.FirstRawFrame = 0
- self.NumRawFrames = 0
+ self.KeyQuotum = 0
+ self.KeyPrediction = 0.0
+ self.TrackTime = 0.0
+ self.AnimRate = 0.0
+ self.StartBone = 0
+ self.FirstRawFrame = 0
+ self.NumRawFrames = 0
def dump(self):
- return pack('64s64siiiifffiii', str.encode(self.Name), str.encode(self.Group), self.TotalBones, self.RootInclude, self.KeyCompressionStyle, self.KeyQuotum, self.KeyPrediction, self.TrackTime, self.AnimRate, self.StartBone, self.FirstRawFrame, self.NumRawFrames)
+ return pack('64s64siiiifffiii', str.encode(self.Name), str.encode(self.Group),
+ self.TotalBones, self.RootInclude, self.KeyCompressionStyle, self.KeyQuotum,
+ self.KeyPrediction, self.TrackTime, self.AnimRate, self.StartBone,
+ self.FirstRawFrame, self.NumRawFrames)
+
class VChunkHeader:
def __init__(self, name, type_size):
- self.ChunkID = str.encode(name) # length=20
- self.TypeFlag = 1999801 # special value
- self.DataSize = type_size
- self.DataCount = 0
+ self.ChunkID = str.encode(name) # length=20
+ self.TypeFlag = 1999801 # special value
+ self.DataSize = type_size
+ self.DataCount = 0
def dump(self):
return pack('20siii', self.ChunkID, self.TypeFlag, self.DataSize, self.DataCount)
+
class VMaterial:
def __init__(self):
- self.MaterialName = "" # length=64
- self.TextureIndex = 0
- self.PolyFlags = 0 # DWORD
- self.AuxMaterial = 0
- self.AuxFlags = 0 # DWORD
- self.LodBias = 0
- self.LodStyle = 0
+ self.MaterialName = "" # length=64
+ self.TextureIndex = 0
+ self.PolyFlags = 0 # DWORD
+ self.AuxMaterial = 0
+ self.AuxFlags = 0 # DWORD
+ self.LodBias = 0
+ self.LodStyle = 0
def dump(self):
- #print("DATA MATERIAL:",self.MaterialName)
- return pack('64siLiLii', str.encode(self.MaterialName), self.TextureIndex, self.PolyFlags, self.AuxMaterial, self.AuxFlags, self.LodBias, self.LodStyle)
+ # print("DATA MATERIAL:",self.MaterialName)
+ return pack('64siLiLii', str.encode(self.MaterialName), self.TextureIndex,
+ self.PolyFlags, self.AuxMaterial, self.AuxFlags, self.LodBias, self.LodStyle)
+
class VBone:
def __init__(self):
- self.Name = "" # length = 64
- self.Flags = 0 # DWORD
- self.NumChildren = 0
- self.ParentIndex = 0
- self.BonePos = VJointPos()
+ self.Name = "" # length = 64
+ self.Flags = 0 # DWORD
+ self.NumChildren = 0
+ self.ParentIndex = 0
+ self.BonePos = VJointPos()
def dump(self):
- return pack('64sLii', str.encode(self.Name), self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
+ return pack('64sLii', str.encode(self.Name), self.Flags,
+ self.NumChildren, self.ParentIndex) + self.BonePos.dump()
-#same as above - whatever - this is how Epic does it...
+
+# same as above - whatever - this is how Epic does it...
class FNamedBoneBinary:
def __init__(self):
- self.Name = "" # length = 64
- self.Flags = 0 # DWORD
- self.NumChildren = 0
- self.ParentIndex = 0
- self.BonePos = VJointPos()
- self.IsRealBone = 0 # this is set to 1 when the bone is actually a bone in the mesh and not a dummy
+ self.Name = "" # length = 64
+ self.Flags = 0 # DWORD
+ self.NumChildren = 0
+ self.ParentIndex = 0
+ self.BonePos = VJointPos()
+ self.IsRealBone = 0 # this is set to 1 when the bone is actually a bone in the mesh and not a dummy
def dump(self):
- return pack('64sLii', str.encode(self.Name), self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
+ return pack('64sLii', str.encode(self.Name), self.Flags,
+ self.NumChildren, self.ParentIndex) + self.BonePos.dump()
+
class VRawBoneInfluence:
def __init__(self):
- self.Weight = 0.0
- self.PointIndex = 0
- self.BoneIndex = 0
+ self.Weight = 0.0
+ self.PointIndex = 0
+ self.BoneIndex = 0
def dump(self):
return pack('fii', self.Weight, self.PointIndex, self.BoneIndex)
+
class VQuatAnimKey:
def __init__(self):
- self.Position = FVector()
- self.Orientation = FQuat()
- self.Time = 0.0
+ self.Position = FVector()
+ self.Orientation = FQuat()
+ self.Time = 0.0
def dump(self):
return self.Position.dump() + self.Orientation.dump() + pack('f', self.Time)
+
class VVertex(object):
def __init__(self):
- self.PointIndex = 0 # WORD
- self.U = 0.0
- self.V = 0.0
- self.MatIndex = 0 # BYTE
- self.Reserved = 0 # BYTE
- self.SmoothGroup = 0
+ self.PointIndex = 0 # WORD
+ self.U = 0.0
+ self.V = 0.0
+ self.MatIndex = 0 # BYTE
+ self.Reserved = 0 # BYTE
+ self.SmoothGroup = 0
def dump(self):
return pack('HHffBBH', self.PointIndex, 0, self.U, self.V, self.MatIndex, self.Reserved, 0)
def __cmp__(self, other):
- return cmp(self.PointIndex, other.PointIndex) \
- or cmp(self.U, other.U) \
- or cmp(self.V, other.V) \
- or cmp(self.MatIndex, other.MatIndex) \
- or cmp(self.Reserved, other.Reserved) \
- or cmp(self.SmoothGroup, other.SmoothGroup )
+ return cmp(self.PointIndex, other.PointIndex) or\
+ cmp(self.U, other.U) or \
+ cmp(self.V, other.V) or \
+ cmp(self.MatIndex, other.MatIndex) or \
+ cmp(self.Reserved, other.Reserved) or \
+ cmp(self.SmoothGroup, other.SmoothGroup)
def _key(self):
return (type(self).__name__, self.PointIndex, self.U, self.V, self.MatIndex, self.Reserved)
@@ -439,6 +481,7 @@ class VVertex(object):
return False
return self._key() == other._key()
+
class VPointSimple:
def __init__(self):
@@ -458,6 +501,7 @@ class VPointSimple:
return False
return self._key() == other._key()
+
class VPoint(object):
def __init__(self):
@@ -483,33 +527,38 @@ class VPoint(object):
return False
return self._key() == other._key()
+
class VTriangle:
def __init__(self):
- self.WedgeIndex0 = 0 # WORD
- self.WedgeIndex1 = 0 # WORD
- self.WedgeIndex2 = 0 # WORD
- self.MatIndex = 0 # BYTE
- self.AuxMatIndex = 0 # BYTE
+ self.WedgeIndex0 = 0 # WORD
+ self.WedgeIndex1 = 0 # WORD
+ self.WedgeIndex2 = 0 # WORD
+ self.MatIndex = 0 # BYTE
+ self.AuxMatIndex = 0 # BYTE
self.SmoothingGroups = 0 # DWORD
def dump(self):
- return pack('HHHBBL', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2, self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
- #print("smooth",self.SmoothingGroups)
- #return pack('HHHBBI', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2, self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
-
+ return pack('HHHBBL', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2,
+ self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
+ """
+ print("smooth",self.SmoothingGroups)
+ return pack('HHHBBI', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2,
+ self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
+ """
# END UNREAL DATA STRUCTS
-#===========================================================================
+# ===========================================================================
+
-#===========================================================================
+# ===========================================================================
# RG - helper class to handle the normal way the UT files are stored
# as sections consisting of a header and then a list of data structures
-#===========================================================================
+# ===========================================================================
class FileSection:
def __init__(self, name, type_size):
self.Header = VChunkHeader(name, type_size)
- self.Data = [] # list of datatypes
+ self.Data = [] # list of datatypes
def dump(self):
data = self.Header.dump()
@@ -520,21 +569,22 @@ class FileSection:
def UpdateHeader(self):
self.Header.DataCount = len(self.Data)
-#===========================================================================
+
+# ===========================================================================
# PSK
-#===========================================================================
+# ===========================================================================
class PSKFile:
def __init__(self):
- self.GeneralHeader = VChunkHeader("ACTRHEAD", 0)
- self.Points = FileSection("PNTS0000", SIZE_VPOINT) # VPoint
- self.Wedges = FileSection("VTXW0000", SIZE_VVERTEX) # VVertex
- self.Faces = FileSection("FACE0000", SIZE_VTRIANGLE) # VTriangle
- self.Materials = FileSection("MATT0000", SIZE_VMATERIAL) # VMaterial
- self.Bones = FileSection("REFSKELT", SIZE_VBONE) # VBone
- self.Influences = FileSection("RAWWEIGHTS", SIZE_VRAWBONEINFLUENCE) # VRawBoneInfluence
-
- #RG - this mapping is not dumped, but is used internally to store the new point indices
+ self.GeneralHeader = VChunkHeader("ACTRHEAD", 0)
+ self.Points = FileSection("PNTS0000", SIZE_VPOINT) # VPoint
+ self.Wedges = FileSection("VTXW0000", SIZE_VVERTEX) # VVertex
+ self.Faces = FileSection("FACE0000", SIZE_VTRIANGLE) # VTriangle
+ self.Materials = FileSection("MATT0000", SIZE_VMATERIAL) # VMaterial
+ self.Bones = FileSection("REFSKELT", SIZE_VBONE) # VBone
+ self.Influences = FileSection("RAWWEIGHTS", SIZE_VRAWBONEINFLUENCE) # VRawBoneInfluence
+
+ # RG - this mapping is not dumped, but is used internally to store the new point indices
# for vertex groups calculated during the mesh dump, so they can be used again
# to dump bone influences during the armature dump
#
@@ -545,7 +595,7 @@ class PSKFile:
# { groupname : [ (index, weight), ... ], ... }
#
# example:
- # { 'MyVertexGroup' : [ (0, 1.0), (5, 1.0), (3, 0.5) ] , 'OtherGroup' : [(2, 1.0)] }
+ # {'MyVertexGroup' : [ (0, 1.0), (5, 1.0), (3, 0.5) ] , 'OtherGroup' : [(2, 1.0)]}
self.VertexGroups = {}
@@ -577,7 +627,8 @@ class PSKFile:
def dump(self):
self.UpdateHeaders()
- data = self.GeneralHeader.dump() + self.Points.dump() + self.Wedges.dump() + self.Faces.dump() + self.Materials.dump() + self.Bones.dump() + self.Influences.dump()
+ data = self.GeneralHeader.dump() + self.Points.dump() + self.Wedges.dump() + \
+ self.Faces.dump() + self.Materials.dump() + self.Bones.dump() + self.Influences.dump()
return data
def GetMatByIndex(self, mat_index):
@@ -591,14 +642,15 @@ class PSKFile:
return m
def PrintOut(self):
- print( "{:>16} {:}".format( "Points", len(self.Points.Data) ) )
- print( "{:>16} {:}".format( "Wedges", len(self.Wedges.Data) ) )
- print( "{:>16} {:}".format( "Faces", len(self.Faces.Data) ) )
- print( "{:>16} {:}".format( "Materials", len(self.Materials.Data) ) )
- print( "{:>16} {:}".format( "Bones", len(self.Bones.Data) ) )
- print( "{:>16} {:}".format( "Influences", len(self.Influences.Data) ) )
-
-#===========================================================================
+ print("{:>16} {:}".format("Points", len(self.Points.Data)))
+ print("{:>16} {:}".format("Wedges", len(self.Wedges.Data)))
+ print("{:>16} {:}".format("Faces", len(self.Faces.Data)))
+ print("{:>16} {:}".format("Materials", len(self.Materials.Data)))
+ print("{:>16} {:}".format("Bones", len(self.Bones.Data)))
+ print("{:>16} {:}".format("Influences", len(self.Influences.Data)))
+
+
+# ===========================================================================
# PSA
#
# Notes from UDN:
@@ -613,14 +665,14 @@ class PSKFile:
# bones are linked up by name. Any bone in a skeleton (from the PSK) that finds no partner in
# the animation sequence (from the PSA) will assume its reference pose stance ( as defined in
# the offsets & rotations that are in the VBones making up the reference skeleton from the PSK)
-#===========================================================================
+# ===========================================================================
class PSAFile:
def __init__(self):
- self.GeneralHeader = VChunkHeader("ANIMHEAD", 0)
- self.Bones = FileSection("BONENAMES", SIZE_FNAMEDBONEBINARY) #FNamedBoneBinary
- self.Animations = FileSection("ANIMINFO", SIZE_ANIMINFOBINARY) #AnimInfoBinary
- self.RawKeys = FileSection("ANIMKEYS", SIZE_VQUATANIMKEY) #VQuatAnimKey
+ self.GeneralHeader = VChunkHeader("ANIMHEAD", 0)
+ self.Bones = FileSection("BONENAMES", SIZE_FNAMEDBONEBINARY) # FNamedBoneBinary
+ self.Animations = FileSection("ANIMINFO", SIZE_ANIMINFOBINARY) # AnimInfoBinary
+ self.RawKeys = FileSection("ANIMKEYS", SIZE_VQUATANIMKEY) # VQuatAnimKey
# this will take the format of key=Bone Name, value = (BoneIndex, Bone Object)
# THIS IS NOT DUMPED
self.BoneLookup = {}
@@ -656,7 +708,7 @@ class PSAFile:
if bone_data[0] == -1:
bone_data[0] = len(self.Bones.Data)
self.AddBone(bone_data[1])
- #self.Bones.Data.append(bone_data[1])
+ # self.Bones.Data.append(bone_data[1])
return bone_data[0]
@@ -675,92 +727,100 @@ class PSAFile:
return self.GeneralHeader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
def PrintOut(self):
- print( "{:>16} {:}".format( "Bones", len(self.Bones.Data) ) )
- print( "{:>16} {:}".format( "Animations", len(self.Animations.Data) ) )
- print( "{:>16} {:}".format( "Raw keys", len(self.RawKeys.Data) ) )
-
-#===========================================================================
-# Helpers to create bone structs
-#===========================================================================
-def make_vbone( name, parent_index, child_count, orientation_quat, position_vect ):
- bone = VBone()
- bone.Name = name
- bone.ParentIndex = parent_index
- bone.NumChildren = child_count
- bone.BonePos.Orientation = orientation_quat
- bone.BonePos.Position.X = position_vect.x
- bone.BonePos.Position.Y = position_vect.y
- bone.BonePos.Position.Z = position_vect.z
- #these values seem to be ignored?
- #bone.BonePos.Length = tail.length
- #bone.BonePos.XSize = tail.x
- #bone.BonePos.YSize = tail.y
- #bone.BonePos.ZSize = tail.z
+ print("{:>16} {:}".format("Bones", len(self.Bones.Data)))
+ print("{:>16} {:}".format("Animations", len(self.Animations.Data)))
+ print("{:>16} {:}".format("Raw keys", len(self.RawKeys.Data)))
+
+
+# ===========================================================================
+# Helpers to create bone structs
+# ===========================================================================
+def make_vbone(name, parent_index, child_count, orientation_quat, position_vect):
+ bone = VBone()
+ bone.Name = name
+ bone.ParentIndex = parent_index
+ bone.NumChildren = child_count
+ bone.BonePos.Orientation = orientation_quat
+ bone.BonePos.Position.X = position_vect.x
+ bone.BonePos.Position.Y = position_vect.y
+ bone.BonePos.Position.Z = position_vect.z
+ # these values seem to be ignored?
+ # bone.BonePos.Length = tail.length
+ # bone.BonePos.XSize = tail.x
+ # bone.BonePos.YSize = tail.y
+ # bone.BonePos.ZSize = tail.z
return bone
-def make_namedbonebinary( name, parent_index, child_count, orientation_quat, position_vect, is_real ):
- bone = FNamedBoneBinary()
- bone.Name = name
- bone.ParentIndex = parent_index
- bone.NumChildren = child_count
- bone.BonePos.Orientation = orientation_quat
- bone.BonePos.Position.X = position_vect.x
- bone.BonePos.Position.Y = position_vect.y
- bone.BonePos.Position.Z = position_vect.z
- bone.IsRealBone = is_real
+
+def make_namedbonebinary(name, parent_index, child_count, orientation_quat, position_vect, is_real):
+ bone = FNamedBoneBinary()
+ bone.Name = name
+ bone.ParentIndex = parent_index
+ bone.NumChildren = child_count
+ bone.BonePos.Orientation = orientation_quat
+ bone.BonePos.Position.X = position_vect.x
+ bone.BonePos.Position.Y = position_vect.y
+ bone.BonePos.Position.Z = position_vect.z
+ bone.IsRealBone = is_real
return bone
-def make_fquat( bquat ):
- quat = FQuat()
- #flip handedness for UT = set x,y,z to negative (rotate in other direction)
- quat.X = -bquat.x
- quat.Y = -bquat.y
- quat.Z = -bquat.z
- quat.W = bquat.w
+
+def make_fquat(bquat):
+ quat = FQuat()
+ # flip handedness for UT = set x,y,z to negative (rotate in other direction)
+ quat.X = -bquat.x
+ quat.Y = -bquat.y
+ quat.Z = -bquat.z
+ quat.W = bquat.w
+
return quat
-def make_fquat_default( bquat ):
- quat = FQuat()
- #print(dir(bquat))
- quat.X = bquat.x
- quat.Y = bquat.y
- quat.Z = bquat.z
- quat.W = bquat.w
+
+def make_fquat_default(bquat):
+ quat = FQuat()
+ # print(dir(bquat))
+ quat.X = bquat.x
+ quat.Y = bquat.y
+ quat.Z = bquat.z
+ quat.W = bquat.w
+
return quat
-#===========================================================================
-#RG - check to make sure face isnt a line
-#===========================================================================
-def is_1d_face( face, mesh ):
- #ID Vertex of id point
+
+# ===========================================================================
+# RG - check to make sure face isnt a line
+# ===========================================================================
+def is_1d_face(face, mesh):
+ # ID Vertex of id point
v0 = face.vertices[0]
v1 = face.vertices[1]
v2 = face.vertices[2]
- return (mesh.vertices[v0].co == mesh.vertices[v1].co \
- or mesh.vertices[v1].co == mesh.vertices[v2].co \
- or mesh.vertices[v2].co == mesh.vertices[v0].co)
+ return (mesh.vertices[v0].co == mesh.vertices[v1].co or
+ mesh.vertices[v1].co == mesh.vertices[v2].co or
+ mesh.vertices[v2].co == mesh.vertices[v0].co)
return False
-#===========================================================================
+
+# ===========================================================================
# Smoothing group
# (renamed to seperate it from VVertex.SmoothGroup)
-#===========================================================================
+# ===========================================================================
class SmoothingGroup:
static_id = 1
def __init__(self):
- self.faces = []
- self.neighboring_faces = []
+ self.faces = []
+ self.neighboring_faces = []
self.neighboring_groups = []
- self.id = -1
- self.local_id = SmoothingGroup.static_id
+ self.id = -1
+ self.local_id = SmoothingGroup.static_id
SmoothingGroup.static_id += 1
def __cmp__(self, other):
if isinstance(other, SmoothingGroup):
- return cmp( self.local_id, other.local_id )
+ return cmp(self.local_id, other.local_id)
return -1
def __hash__(self):
@@ -774,27 +834,29 @@ class SmoothingGroup:
if temp_id < 0x80000000:
temp_id = temp_id << 1
else:
- raise Error("Smoothing Group ID Overflowed, Smoothing Group evidently has more than 31 neighboring groups")
+ raise Error("Smoothing Group ID Overflowed, "
+ "Smoothing Group evidently has more than 31 neighboring groups")
self.id = temp_id
return self.id
def make_neighbor(self, new_neighbor):
if new_neighbor not in self.neighboring_groups:
- self.neighboring_groups.append( new_neighbor )
+ self.neighboring_groups.append(new_neighbor)
def contains_face(self, face):
return (face in self.faces)
def add_neighbor_face(self, face):
- if not face in self.neighboring_faces:
- self.neighboring_faces.append( face )
+ if face not in self.neighboring_faces:
+ self.neighboring_faces.append(face)
def add_face(self, face):
- if not face in self.faces:
- self.faces.append( face )
+ if face not in self.faces:
+ self.faces.append(face)
-def determine_edge_sharing( mesh ):
+
+def determine_edge_sharing(mesh):
edge_sharing_list = dict()
@@ -803,12 +865,13 @@ def determine_edge_sharing( mesh ):
for face in mesh.tessfaces:
for key in face.edge_keys:
- if not face in edge_sharing_list[key]:
- edge_sharing_list[key].append(face) # mark this face as sharing this edge
+ if face not in edge_sharing_list[key]:
+ edge_sharing_list[key].append(face) # mark this face as sharing this edge
return edge_sharing_list
-def find_edges( mesh, key ):
+
+def find_edges(mesh, key):
""" Temp replacement for mesh.findEdges().
This is painfully slow.
"""
@@ -817,7 +880,8 @@ def find_edges( mesh, key ):
if key[0] == v[0] and key[1] == v[1]:
return edge.index
-def add_face_to_smoothgroup( mesh, face, edge_sharing_list, smoothgroup ):
+
+def add_face_to_smoothgroup(mesh, face, edge_sharing_list, smoothgroup):
if face in smoothgroup.faces:
return
@@ -831,62 +895,68 @@ def add_face_to_smoothgroup( mesh, face, edge_sharing_list, smoothgroup ):
if edge_id is not None:
# not sharp
- if not( mesh.edges[edge_id].use_edge_sharp):
+ if not (mesh.edges[edge_id].use_edge_sharp):
for shared_face in edge_sharing_list[key]:
if shared_face != face:
# recursive
- add_face_to_smoothgroup( mesh, shared_face, edge_sharing_list, smoothgroup )
+ add_face_to_smoothgroup(mesh, shared_face, edge_sharing_list, smoothgroup)
# sharp
else:
for shared_face in edge_sharing_list[key]:
if shared_face != face:
- smoothgroup.add_neighbor_face( shared_face )
+ smoothgroup.add_neighbor_face(shared_face)
+
-def determine_smoothgroup_for_face( mesh, face, edge_sharing_list, smoothgroup_list ):
+def determine_smoothgroup_for_face(mesh, face, edge_sharing_list, smoothgroup_list):
for group in smoothgroup_list:
if (face in group.faces):
return
- smoothgroup = SmoothingGroup();
- add_face_to_smoothgroup( mesh, face, edge_sharing_list, smoothgroup )
+ smoothgroup = SmoothingGroup()
+ add_face_to_smoothgroup(mesh, face, edge_sharing_list, smoothgroup)
+
+ if smoothgroup not in smoothgroup_list:
+ smoothgroup_list.append(smoothgroup)
- if not smoothgroup in smoothgroup_list:
- smoothgroup_list.append( smoothgroup )
-def build_neighbors_tree( smoothgroup_list ):
+def build_neighbors_tree(smoothgroup_list):
for group in smoothgroup_list:
for face in group.neighboring_faces:
for neighbor_group in smoothgroup_list:
- if neighbor_group.contains_face( face ) and neighbor_group not in group.neighboring_groups:
- group.make_neighbor( neighbor_group )
- neighbor_group.make_neighbor( group )
+ if neighbor_group.contains_face(face) and neighbor_group not in group.neighboring_groups:
+ group.make_neighbor(neighbor_group)
+ neighbor_group.make_neighbor(group)
-#===========================================================================
+
+# ===========================================================================
# parse_smooth_groups
-#===========================================================================
-def parse_smooth_groups( mesh ):
+# ===========================================================================
+def parse_smooth_groups(mesh):
print("Parsing smooth groups...")
- t = time.clock()
- smoothgroup_list = []
- edge_sharing_list = determine_edge_sharing(mesh)
- #print("faces:",len(mesh.tessfaces))
- interval = math.floor(len(mesh.tessfaces) / 100)
- if interval == 0: #if the faces are few do this
- interval = math.floor(len(mesh.tessfaces) / 10)
- #print("FACES:",len(mesh.tessfaces),"//100 =" "interval:",interval)
+ t = time.clock()
+ smoothgroup_list = []
+ edge_sharing_list = determine_edge_sharing(mesh)
+
+ # print("faces:",len(mesh.tessfaces))
+ interval = math.floor(len(mesh.tessfaces) / 100)
+
+ if interval == 0: # if the faces are few do this
+ interval = math.floor(len(mesh.tessfaces) / 10)
+ # print("FACES:",len(mesh.tessfaces),"//100 =" "interval:",interval)
+
for face in mesh.tessfaces:
- #print(dir(face))
+ # print(dir(face))
determine_smoothgroup_for_face(mesh, face, edge_sharing_list, smoothgroup_list)
# progress indicator, writes to console without scrolling
if face.index > 0 and (face.index % interval) == 0:
- print("Processing... {}%\r".format( int(face.index / len(mesh.tessfaces) * 100) ), end='')
+ print("Processing... {}%\r".format(int(face.index / len(mesh.tessfaces) * 100)), end='')
sys.stdout.flush()
- print("Completed" , ' '*20)
+ print("Completed", ' ' * 20)
verbose("len(smoothgroup_list)={}".format(len(smoothgroup_list)))
@@ -898,31 +968,33 @@ def parse_smooth_groups( mesh ):
print("Smooth group parsing completed in {:.2f}s".format(time.clock() - t))
return smoothgroup_list
-#===========================================================================
+
+# ===========================================================================
# http://en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python/Cookbook#Triangulate_NMesh
# blender 2.50 format using the Operators/command convert the mesh to tri mesh
-#===========================================================================
-def triangulate_mesh( object ):
+# ===========================================================================
+def triangulate_mesh(object):
verbose(header("triangulateNMesh"))
- #print(type(object))
+ # print(type(object))
scene = bpy.context.scene
- me_ob = object.copy()
- me_ob.data = object.to_mesh(bpy.context.scene, True, 'PREVIEW') #write data object
+ me_ob = object.copy()
+ me_ob.data = object.to_mesh(bpy.context.scene, True, 'PREVIEW') # write data object
bpy.context.scene.objects.link(me_ob)
bpy.context.scene.update()
bpy.ops.object.mode_set(mode='OBJECT')
+
for i in scene.objects:
- i.select = False # deselect all objects
+ i.select = False # deselect all objects
- me_ob.select = True
- scene.objects.active = me_ob
+ me_ob.select = True
+ scene.objects.active = me_ob
print("Copy and Convert mesh just incase any way...")
bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')# select all the face/vertex/edge
+ bpy.ops.mesh.select_all(action='SELECT') # select all the face/vertex/edge
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.quads_convert_to_tris()
bpy.context.scene.update()
@@ -933,81 +1005,99 @@ def triangulate_mesh( object ):
verbose("Triangulated mesh")
- me_ob.data = me_ob.to_mesh(bpy.context.scene, True, 'PREVIEW') #write data object
+ me_ob.data = me_ob.to_mesh(bpy.context.scene, True, 'PREVIEW') # write data object
bpy.context.scene.update()
return me_ob
-#copy mesh data and then merge them into one object
+
+# copy mesh data and then merge them into one object
def meshmerge(selectedobjects):
- bpy.ops.object.mode_set(mode='OBJECT') #object mode and not edit mode
- cloneobjects = [] #object holder for copying object data
+ bpy.ops.object.mode_set(mode='OBJECT') # object mode and not edit mode
+ cloneobjects = [] # object holder for copying object data
+
if len(selectedobjects) > 1:
- print("selectedobjects:",len(selectedobjects)) #print select object
- count = 0 #reset count
- for count in range(len( selectedobjects)):
- #print("Index:",count)
+ print("selectedobjects:", len(selectedobjects)) # print select object
+ count = 0 # reset count
+
+ for count in range(len(selectedobjects)):
+ # print("Index:",count)
if selectedobjects[count] is not None:
- me_da = selectedobjects[count].data.copy() #copy data
- me_ob = selectedobjects[count].copy() #copy object
- #note two copy two types else it will use the current data or mesh
- me_ob.data = me_da #assign the data
- bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
- print("Index:",count,"clone object",me_ob.name) #print clone object
- cloneobjects.append(me_ob) #add object to the array
- for i in bpy.data.objects: i.select = False #deselect all objects
- count = 0 #reset count
- #begin merging the mesh together as one
- for count in range(len( cloneobjects)):
+ me_da = selectedobjects[count].data.copy() # copy data
+ me_ob = selectedobjects[count].copy() # copy object
+ # note two copy two types else it will use the current data or mesh
+ me_ob.data = me_da # assign the data
+ bpy.context.scene.objects.link(me_ob) # link the object to the scene #current object location
+ print("Index:", count, "clone object", me_ob.name) # print clone object
+ cloneobjects.append(me_ob) # add object to the array
+
+ for i in bpy.data.objects:
+ i.select = False # deselect all objects
+ count = 0 # reset count
+ # begin merging the mesh together as one
+ for count in range(len(cloneobjects)):
if count == 0:
bpy.context.scene.objects.active = cloneobjects[count]
- print("Set Active Object:",cloneobjects[count].name)
+ print("Set Active Object:", cloneobjects[count].name)
cloneobjects[count].select = True
- bpy.ops.object.join() #join object together
+ bpy.ops.object.join() # join object together
if len(cloneobjects) > 1:
bpy.types.Scene.udk_copy_merge = True
return cloneobjects[0]
-#sort the mesh center top list and not center at the last array. Base on order while select to merge mesh to make them center.
+
+# sort the mesh center top list and not center at the last array.
+# Base on order while select to merge mesh to make them center.
def sortmesh(selectmesh):
print("MESH SORTING...")
centermesh = []
notcentermesh = []
for countm in range(len(selectmesh)):
- #if object are center add here
- if selectmesh[countm].location.x == 0 and selectmesh[countm].location.y == 0 and selectmesh[countm].location.z == 0:
+ # if object are center add here
+ if selectmesh[countm].location.x == 0 and \
+ selectmesh[countm].location.y == 0 and \
+ selectmesh[countm].location.z == 0:
centermesh.append(selectmesh[countm])
- else:#if not add here for not center
+ else: # if not add here for not center
notcentermesh.append(selectmesh[countm])
selectmesh = []
- #add mesh object in order for merge object
+ # add mesh object in order for merge object
for countm in range(len(centermesh)):
selectmesh.append(centermesh[countm])
for countm in range(len(notcentermesh)):
selectmesh.append(notcentermesh[countm])
- if len(selectmesh) == 1: #if there one mesh just do some here
- return selectmesh[0] #return object mesh
+ if len(selectmesh) == 1: # if there one mesh just do some here
+ return selectmesh[0] # return object mesh
else:
- return meshmerge(selectmesh) #return merge object mesh
+ return meshmerge(selectmesh) # return merge object mesh
+
+
import binascii
-#===========================================================================
+
+
+# ===========================================================================
# parse_mesh
-#===========================================================================
-def parse_mesh( mesh, psk ):
- #bpy.ops.object.mode_set(mode='OBJECT')
- #error ? on commands for select object?
+# ===========================================================================
+def parse_mesh(mesh, psk):
+ # bpy.ops.object.mode_set(mode='OBJECT')
+ # error ? on commands for select object?
print(header("MESH", 'RIGHT'))
print("Mesh object:", mesh.name)
scene = bpy.context.scene
- for i in scene.objects: i.select = False # deselect all objects
- scene.objects.active = mesh
+
+ for i in scene.objects:
+ i.select = False # deselect all objects
+
+ scene.objects.active = mesh
setmesh = mesh
mesh = triangulate_mesh(mesh)
- if bpy.types.Scene.udk_copy_merge == True:
+
+ if bpy.types.Scene.udk_copy_merge is True:
bpy.context.scene.objects.unlink(setmesh)
- #print("FACES----:",len(mesh.data.tessfaces))
+
+ # print("FACES----:",len(mesh.data.tessfaces))
verbose("Working mesh object: {}".format(mesh.name))
- #collect a list of the material names
+ # collect a list of the material names
print("Materials...")
mat_slot_index = 0
@@ -1016,26 +1106,30 @@ def parse_mesh( mesh, psk ):
print(" Material {} '{}'".format(mat_slot_index, slot.name))
MaterialName.append(slot.name)
- #if slot.material.texture_slots[0] is not None:
- #if slot.material.texture_slots[0].texture.image.filepath is not None:
- #print(" Texture path {}".format(slot.material.texture_slots[0].texture.image.filepath))
- #create the current material
- v_material = psk.GetMatByIndex(mat_slot_index)
+
+ """
+ if slot.material.texture_slots[0] is not None:
+ if slot.material.texture_slots[0].texture.image.filepath is not None:
+ print(" Texture path {}".format(slot.material.texture_slots[0].texture.image.filepath))
+ """
+
+ # create the current material
+ v_material = psk.GetMatByIndex(mat_slot_index)
v_material.MaterialName = slot.name
v_material.TextureIndex = mat_slot_index
- v_material.AuxMaterial = mat_slot_index
+ v_material.AuxMaterial = mat_slot_index
mat_slot_index += 1
verbose(" PSK index {}".format(v_material.TextureIndex))
- #END slot in mesh.material_slots
+ # END slot in mesh.material_slots
# object_mat = mesh.materials[0]
- #object_material_index = mesh.active_material_index
- #FIXME ^ this is redundant due to "= face.material_index" in face loop
+ # object_material_index = mesh.active_material_index
+ # FIXME ^ this is redundant due to "= face.material_index" in face loop
- wedges = ObjMap()
- points = ObjMap() #vertex
- points_linked = {}
+ wedges = ObjMap()
+ points = ObjMap() # vertex
+ points_linked = {}
discarded_face_count = 0
sys.setrecursionlimit(1000000)
@@ -1054,15 +1148,13 @@ def parse_mesh( mesh, psk ):
smoothgroup_id = smooth_group.id
break
- #print ' -- Dumping UVs -- '
- #print current_face.uv_textures
# modified by VendorX
object_material_index = face.material_index
if len(face.vertices) != 3:
raise Error("Non-triangular face (%i)" % len(face.vertices))
- #RG - apparently blender sometimes has problems when you do quad to triangle
+ # RG - apparently blender sometimes has problems when you do quad to triangle
# conversion, and ends up creating faces that have only TWO points -
# one of the points is simply in the vertex list for the face twice.
# This is bad, since we can't get a real face normal for a LINE, we need
@@ -1073,40 +1165,40 @@ def parse_mesh( mesh, psk ):
if not is_1d_face(face, mesh.data):
- wedge_list = []
- vect_list = []
+ wedge_list = []
+ vect_list = []
- #get or create the current material
+ # get or create the current material
psk.GetMatByIndex(object_material_index)
- face_index = face.index
- has_uv = False
- face_uv = None
+ face_index = face.index
+ has_uv = False
+ face_uv = None
if len(mesh.data.uv_textures) > 0:
- has_uv = True
- uv_layer = mesh.data.tessface_uv_textures.active
- face_uv = uv_layer.data[face_index]
- #size(data) is number of texture faces. Each face has UVs
- #print("DATA face uv: ",len(faceUV.uv), " >> ",(faceUV.uv[0][0]))
+ has_uv = True
+ uv_layer = mesh.data.tessface_uv_textures.active
+ face_uv = uv_layer.data[face_index]
+ # size(data) is number of texture faces. Each face has UVs
+ # print("DATA face uv: ",len(faceUV.uv), " >> ",(faceUV.uv[0][0]))
for i in range(3):
- vert_index = face.vertices[i]
- vert = mesh.data.vertices[vert_index]
- uv = []
- #assumes 3 UVs Per face (for now)
+ vert_index = face.vertices[i]
+ vert = mesh.data.vertices[vert_index]
+ uv = []
+ # assumes 3 UVs Per face (for now)
if (has_uv):
if len(face_uv.uv) != 3:
print("WARNING: face has more or less than 3 UV coordinates - writing 0,0...")
uv = [0.0, 0.0]
else:
- uv = [face_uv.uv[i][0],face_uv.uv[i][1]] #OR bottom works better # 24 for cube
+ uv = [face_uv.uv[i][0], face_uv.uv[i][1]] # OR bottom works better # 24 for cube
else:
- #print ("No UVs?")
+ # print ("No UVs?")
uv = [0.0, 0.0]
- #flip V coordinate because UEd requires it and DOESN'T flip it on its own like it
- #does with the mesh Y coordinates. this is otherwise known as MAGIC-2
+ # flip V coordinate because UEd requires it and DOESN'T flip it on its own like it
+ # does with the mesh Y coordinates. this is otherwise known as MAGIC-2
uv[1] = 1.0 - uv[1]
# clamp UV coords if udk_option_clamp_uv is True
@@ -1122,31 +1214,32 @@ def parse_mesh( mesh, psk ):
# RE - Append untransformed vector (for normal calc below)
# TODO: convert to Blender.Mathutils
- vect_list.append( FVector(vert.co.x, vert.co.y, vert.co.z) )
+ vect_list.append(FVector(vert.co.x, vert.co.y, vert.co.z))
# Transform position for export
- #vpos = vert.co * object_material_index
+ # vpos = vert.co * object_material_index
- #should fixed this!!
+ # should fixed this!!
vpos = mesh.matrix_local * vert.co
if bpy.context.scene.udk_option_scale < 0 or bpy.context.scene.udk_option_scale > 1:
- #print("OK!")
+ # print("OK!")
vpos.x = vpos.x * bpy.context.scene.udk_option_scale
vpos.y = vpos.y * bpy.context.scene.udk_option_scale
vpos.z = vpos.z * bpy.context.scene.udk_option_scale
- #print("scale pos:", vpos)
+
+ # print("scale pos:", vpos)
# Create the point
- p = VPoint()
- p.Point.X = vpos.x
- p.Point.Y = vpos.y
- p.Point.Z = vpos.z
- if bpy.context.scene.udk_option_smoothing_groups:#is this necessary?
+ p = VPoint()
+ p.Point.X = vpos.x
+ p.Point.Y = vpos.y
+ p.Point.Z = vpos.z
+ if bpy.context.scene.udk_option_smoothing_groups: # is this necessary?
p.SmoothGroup = smoothgroup_id
- lPoint = VPointSimple()
- lPoint.Point.X = vpos.x
- lPoint.Point.Y = vpos.y
- lPoint.Point.Z = vpos.z
+ lPoint = VPointSimple()
+ lPoint.Point.X = vpos.x
+ lPoint.Point.Y = vpos.y
+ lPoint.Point.Z = vpos.z
if lPoint in points_linked:
if not(p in points_linked[lPoint]):
@@ -1155,24 +1248,24 @@ def parse_mesh( mesh, psk ):
points_linked[lPoint] = [p]
# Create the wedge
- w = VVertex()
- w.MatIndex = object_material_index
- w.PointIndex = points.get(p) # store keys
- w.U = uv[0]
- w.V = uv[1]
- if bpy.context.scene.udk_option_smoothing_groups:#is this necessary?
+ w = VVertex()
+ w.MatIndex = object_material_index
+ w.PointIndex = points.get(p) # store keys
+ w.U = uv[0]
+ w.V = uv[1]
+ if bpy.context.scene.udk_option_smoothing_groups: # is this necessary?
w.SmoothGroup = smoothgroup_id
index_wedge = wedges.get(w)
wedge_list.append(index_wedge)
- #print results
- #print("result PointIndex={}, U={:.6f}, V={:.6f}, wedge_index={}".format(
+ # print results
+ # print("result PointIndex={}, U={:.6f}, V={:.6f}, wedge_index={}".format(
# w.PointIndex,
# w.U,
# w.V,
# index_wedge))
- #END for i in range(3)
+ # END for i in range(3)
# Determine face vertex order
@@ -1198,9 +1291,9 @@ def parse_mesh( mesh, psk ):
elif dot < 0:
(tri.WedgeIndex0, tri.WedgeIndex1, tri.WedgeIndex2) = wedge_list
else:
- dindex0 = face.vertices[0];
- dindex1 = face.vertices[1];
- dindex2 = face.vertices[2];
+ dindex0 = face.vertices[0]
+ dindex1 = face.vertices[1]
+ dindex2 = face.vertices[2]
mesh.data.vertices[dindex0].select = True
mesh.data.vertices[dindex1].select = True
@@ -1211,7 +1304,7 @@ def parse_mesh( mesh, psk ):
str(mesh.data.vertices[dindex2].co)))
face.select = True
- if face.use_smooth == True:
+ if face.use_smooth is True:
tri.SmoothingGroups = 1
else:
tri.SmoothingGroups = 0
@@ -1223,12 +1316,12 @@ def parse_mesh( mesh, psk ):
psk.AddFace(tri)
- #END if not is_1d_face(current_face, mesh.data)
+ # END if not is_1d_face(current_face, mesh.data)
else:
discarded_face_count += 1
- #END face in mesh.data.faces
+ # END face in mesh.data.faces
print("{} points".format(len(points.dict)))
@@ -1236,7 +1329,7 @@ def parse_mesh( mesh, psk ):
psk.AddPoint(point)
if len(points.dict) > 32767:
- raise Error("Mesh vertex limit exceeded! {} > 32767".format(len(points.dict)))
+ raise Error("Mesh vertex limit exceeded! {} > 32767".format(len(points.dict)))
print("{} wedges".format(len(wedges.dict)))
@@ -1248,73 +1341,75 @@ def parse_mesh( mesh, psk ):
print("WARNING: Mesh contained degenerate faces (non-planar)")
print(" Discarded {} faces".format(discarded_face_count))
- #RG - walk through the vertex groups and find the indexes into the PSK points array
- #for them, then store that index and the weight as a tuple in a new list of
- #verts for the group that we can look up later by bone name, since Blender matches
- #verts to bones for influences by having the VertexGroup named the same thing as
- #the bone
+ # RG - walk through the vertex groups and find the indexes into the PSK points array
+ # for them, then store that index and the weight as a tuple in a new list of
+ # verts for the group that we can look up later by bone name, since Blender matches
+ # verts to bones for influences by having the VertexGroup named the same thing as
+ # the bone
- #[print(x, len(points_linked[x])) for x in points_linked]
- #print("pointsindex length ",len(points_linked))
- #vertex group
+ # [print(x, len(points_linked[x])) for x in points_linked]
+ # print("pointsindex length ",len(points_linked))
+ # vertex group
# all vertex groups of the mesh (obj)...
for obj_vertex_group in mesh.vertex_groups:
- #print(" bone group build:",obj_vertex_group.name)#print bone name
- #print(dir(obj_vertex_group))
+ # print(" bone group build:",obj_vertex_group.name)#print bone name
+ # print(dir(obj_vertex_group))
verbose("obj_vertex_group.name={}".format(obj_vertex_group.name))
vertex_list = []
# all vertices in the mesh...
for vertex in mesh.data.vertices:
- #print(dir(vertex))
+ # print(dir(vertex))
# all groups this vertex is a member of...
for vgroup in vertex.groups:
if vgroup.group == obj_vertex_group.index:
- vertex_weight = vgroup.weight
- p = VPointSimple()
- vpos = mesh.matrix_local * vertex.co
+ vertex_weight = vgroup.weight
+ p = VPointSimple()
+ vpos = mesh.matrix_local * vertex.co
+
if bpy.context.scene.udk_option_scale < 0 or bpy.context.scene.udk_option_scale > 1:
vpos.x = vpos.x * bpy.context.scene.udk_option_scale
vpos.y = vpos.y * bpy.context.scene.udk_option_scale
vpos.z = vpos.z * bpy.context.scene.udk_option_scale
- p.Point.X = vpos.x
- p.Point.Y = vpos.y
- p.Point.Z = vpos.z
- #print(p)
- #print(len(points_linked[p]))
- try: #check if point doesn't give error
+ p.Point.X = vpos.x
+ p.Point.Y = vpos.y
+ p.Point.Z = vpos.z
+ # print(p)
+ # print(len(points_linked[p]))
+ try: # check if point doesn't give error
for point in points_linked[p]:
- point_index = points.get(point) #point index
- v_item = (point_index, vertex_weight)
+ point_index = points.get(point) # point index
+ v_item = (point_index, vertex_weight)
vertex_list.append(v_item)
- except Exception:#if get error ignore them #not safe I think
+ except Exception: # if get error ignore them # not safe I think
print("Error link points!")
pass
- #bone name, [point id and wieght]
- #print("Add Vertex Group:",obj_vertex_group.name, " No. Points:",len(vertex_list))
+ # bone name, [point id and wieght]
+ # print("Add Vertex Group:",obj_vertex_group.name, " No. Points:",len(vertex_list))
psk.VertexGroups[obj_vertex_group.name] = vertex_list
# remove the temporary triangulated mesh
- if bpy.context.scene.udk_option_triangulate == True:
+ if bpy.context.scene.udk_option_triangulate is True:
verbose("Removing temporary triangle mesh: {}".format(mesh.name))
bpy.ops.object.mode_set(mode='OBJECT') # OBJECT mode
mesh.parent = None # unparent to avoid phantom links
bpy.context.scene.objects.unlink(mesh) # unlink
-#===========================================================================
+
+# ===========================================================================
# Collate bones that belong to the UDK skeletal mesh
-#===========================================================================
-def parse_armature( armature, psk, psa ):
+# ===========================================================================
+def parse_armature(armature, psk, psa):
print(header("ARMATURE", 'RIGHT'))
verbose("Armature object: {} Armature data: {}".format(armature.name, armature.data.name))
# generate a list of root bone candidates
- root_candidates = [b for b in armature.data.bones if b.parent is None and b.use_deform == True]
+ root_candidates = [b for b in armature.data.bones if b.parent is None and b.use_deform is True]
# should be a single, unambiguous result
if len(root_candidates) == 0:
@@ -1324,9 +1419,9 @@ def parse_armature( armature, psk, psa ):
raise Error("Ambiguous root for UDK. More than one root bone is using deform.")
# prep for bone collection
- udk_root_bone = root_candidates[0]
- udk_bones = []
- BoneUtil.static_bone_id = 0 # replaces global
+ udk_root_bone = root_candidates[0]
+ udk_bones = []
+ BoneUtil.static_bone_id = 0 # replaces global
# traverse bone chain
print("{: <3} {: <48} {: <20}".format("ID", "Bone", "Status"))
@@ -1341,7 +1436,8 @@ def parse_armature( armature, psk, psa ):
# this is passed to parse_animation instead of working from keyed bones in the action
return udk_bones
-#===========================================================================
+
+# ===========================================================================
# bone current bone
# bones bone list
# psk the PSK file object
@@ -1349,19 +1445,18 @@ def parse_armature( armature, psk, psa ):
# parent_id
# parent_matrix
# indent text indent for recursive log
-#===========================================================================
-def recurse_bone( bone, bones, psk, psa, parent_id, parent_matrix, indent="" ):
+# ===========================================================================
+def recurse_bone(bone, bones, psk, psa, parent_id, parent_matrix, indent=""):
status = "Ok"
-
- bones.append(bone);
+ bones.append(bone)
if not bone.use_deform:
status = "No effect"
# calc parented bone transform
if bone.parent is not None:
- quat = make_fquat(bone.matrix.to_quaternion())
+ quat = make_fquat(bone.matrix.to_quaternion())
quat_parent = bone.parent.matrix.to_quaternion().inverted()
parent_head = quat_parent * bone.parent.head
parent_tail = quat_parent * bone.parent.tail
@@ -1370,73 +1465,81 @@ def recurse_bone( bone, bones, psk, psa, parent_id, parent_matrix, indent="" ):
# calc root bone transform
else:
translation = parent_matrix * bone.head # ARMATURE OBJECT Location
- rot_matrix = bone.matrix * parent_matrix.to_3x3() # ARMATURE OBJECT Rotation
- quat = make_fquat_default(rot_matrix.to_quaternion())
- #udk_option_scale bones here?
+ rot_matrix = bone.matrix * parent_matrix.to_3x3() # ARMATURE OBJECT Rotation
+ quat = make_fquat_default(rot_matrix.to_quaternion())
+
+ # udk_option_scale bones here?
if bpy.context.scene.udk_option_scale < 0 or bpy.context.scene.udk_option_scale > 1:
translation.x = translation.x * bpy.context.scene.udk_option_scale
translation.y = translation.y * bpy.context.scene.udk_option_scale
translation.z = translation.z * bpy.context.scene.udk_option_scale
- bone_id = BoneUtil.static_bone_id # ALT VERS
+ bone_id = BoneUtil.static_bone_id # ALT VERS
BoneUtil.static_bone_id += 1 # ALT VERS
child_count = len(bone.children)
- psk.AddBone( make_vbone(bone.name, parent_id, child_count, quat, translation) )
- psa.StoreBone( make_namedbonebinary(bone.name, parent_id, child_count, quat, translation, 1) )
+ psk.AddBone(make_vbone(bone.name, parent_id, child_count, quat, translation))
+ psa.StoreBone(make_namedbonebinary(bone.name, parent_id, child_count, quat, translation, 1))
- #RG - dump influences for this bone - use the data we collected in the mesh dump phase to map our bones to vertex groups
+ # RG - dump influences for this bone - use the data we collected
+ # in the mesh dump phase to map our bones to vertex groups
if bone.name in psk.VertexGroups:
vertex_list = psk.VertexGroups[bone.name]
- #print("vertex list:", len(vertex_list), " of >" ,bone.name )
+ # print("vertex list:", len(vertex_list), " of >" ,bone.name)
+
for vertex_data in vertex_list:
- point_index = vertex_data[0]
- vertex_weight = vertex_data[1]
- influence = VRawBoneInfluence()
- influence.Weight = vertex_weight
- influence.BoneIndex = bone_id
- influence.PointIndex = point_index
- #print (" AddInfluence to vertex {}, weight={},".format(point_index, vertex_weight))
+ point_index = vertex_data[0]
+ vertex_weight = vertex_data[1]
+ influence = VRawBoneInfluence()
+ influence.Weight = vertex_weight
+ influence.BoneIndex = bone_id
+ influence.PointIndex = point_index
+ # print (" AddInfluence to vertex {}, weight={},".format(point_index, vertex_weight))
psk.AddInfluence(influence)
else:
status = "No vertex group"
- #FIXME overwriting previous status error?
+ # FIXME overwriting previous status error?
- print("{:<3} {:<48} {:<20}".format(bone_id, indent+bone.name, status))
+ print("{:<3} {:<48} {:<20}".format(bone_id, indent + bone.name, status))
- #bone.matrix_local
- #recursively dump child bones
+ # bone.matrix_local
+ # recursively dump child bones
for child_bone in bone.children:
- recurse_bone(child_bone, bones, psk, psa, bone_id, parent_matrix, " "+indent)
+ recurse_bone(child_bone, bones, psk, psa, bone_id, parent_matrix, " " + indent)
+
# FIXME rename? remove?
class BoneUtil:
- static_bone_id = 0 # static property to replace global
+ static_bone_id = 0 # static property to replace global
-#===========================================================================
+
+# ===========================================================================
# armature the armature
# udk_bones list of bones to be exported
# actions_to_export list of actions to process for export
# psa the PSA file object
-#===========================================================================
-def parse_animation( armature, udk_bones, actions_to_export, psa ):
+# ===========================================================================
+def parse_animation(armature, udk_bones, actions_to_export, psa):
print(header("ANIMATION", 'RIGHT'))
- context = bpy.context
- anim_rate = context.scene.render.fps
+ context = bpy.context
+ anim_rate = context.scene.render.fps
verbose("Armature object: {}".format(armature.name))
- print("Scene: {} FPS: {} Frames: {} to {}".format(context.scene.name, anim_rate, context.scene.frame_start, context.scene.frame_end))
- print("Processing {} action(s)".format(len(actions_to_export)))
- print()
- if armature.animation_data is None: #if animation data was not create for the armature it will skip the exporting action set(s)
+ print("Scene: {} FPS: {} Frames: {} to {}".format(context.scene.name, anim_rate,
+ context.scene.frame_start, context.scene.frame_end)
+ )
+ print("Processing {} action(s)\n".format(len(actions_to_export)))
+
+ # if animation data was not create for the armature it will skip the exporting action set(s)
+ if armature.animation_data is None:
print("None Actions Set! skipping...")
return
- restoreAction = armature.animation_data.action # Q: is animation_data always valid?
-
- restoreFrame = context.scene.frame_current # we already do this in export_proxy, but we'll do it here too for now
+ restoreAction = armature.animation_data.action # Q: is animation_data always valid?
+ # we already do this in export_proxy, but we'll do it here too for now
+ restoreFrame = context.scene.frame_current
raw_frame_index = 0 # used to set FirstRawFrame, seperating actions in the raw keyframe array
# action loop...
@@ -1449,24 +1552,24 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
continue
# apply action to armature and update scene
- # note if loop all actions that is not armature it will override and will break armature animation.
+ # note if loop all actions that is not armature it will override and will break armature animation
armature.animation_data.action = action
context.scene.update()
# min/max frames define range
- framemin, framemax = action.frame_range
- start_frame = int(framemin)
- end_frame = int(framemax)
- scene_range = range(start_frame, end_frame + 1)
- frame_count = len(scene_range)
+ framemin, framemax = action.frame_range
+ start_frame = int(framemin)
+ end_frame = int(framemax)
+ scene_range = range(start_frame, end_frame + 1)
+ frame_count = len(scene_range)
# create the AnimInfoBinary
- anim = AnimInfoBinary()
- anim.Name = action.name
- anim.Group = "" # unused?
- anim.NumRawFrames = frame_count
- anim.AnimRate = anim_rate
- anim.FirstRawFrame = raw_frame_index
+ anim = AnimInfoBinary()
+ anim.Name = action.name
+ anim.Group = "" # unused?
+ anim.NumRawFrames = frame_count
+ anim.AnimRate = anim_rate
+ anim.FirstRawFrame = raw_frame_index
print("{}, frames {} to {} ({} frames)".format(action.name, start_frame, end_frame, frame_count))
@@ -1479,7 +1582,7 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
for pb in armature.pose.bones:
if b.name == pb.name:
udk_pose_bones.append(pb)
- break;
+ break
# sort in the order the bones appear in the PSA file
ordered_bones = {}
@@ -1493,7 +1596,7 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
frame = scene_range[i]
- #verbose("FRAME {}".format(i), i) # test loop sampling
+ # verbose("FRAME {}".format(i), i) # test loop sampling
# advance to frame (automatically updates the pose)
context.scene.frame_set(frame)
@@ -1501,36 +1604,36 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
# compute the key for each bone
for bone_data in ordered_bones:
- bone_index = bone_data[0]
- pose_bone = bone_data[1]
- pose_bone_matrix = mathutils.Matrix(pose_bone.matrix)
+ bone_index = bone_data[0]
+ pose_bone = bone_data[1]
+ pose_bone_matrix = mathutils.Matrix(pose_bone.matrix)
if pose_bone.parent is not None:
pose_bone_parent_matrix = mathutils.Matrix(pose_bone.parent.matrix)
- pose_bone_matrix = pose_bone_parent_matrix.inverted() * pose_bone_matrix
+ pose_bone_matrix = pose_bone_parent_matrix.inverted() * pose_bone_matrix
- head = pose_bone_matrix.to_translation()
- quat = pose_bone_matrix.to_quaternion().normalized()
+ head = pose_bone_matrix.to_translation()
+ quat = pose_bone_matrix.to_quaternion().normalized()
if pose_bone.parent is not None:
quat = make_fquat(quat)
else:
quat = make_fquat_default(quat)
- #scale animation position here?
+ # scale animation position here?
if bpy.context.scene.udk_option_scale < 0 or bpy.context.scene.udk_option_scale > 1:
head.x = head.x * bpy.context.scene.udk_option_scale
head.y = head.y * bpy.context.scene.udk_option_scale
head.z = head.z * bpy.context.scene.udk_option_scale
- vkey = VQuatAnimKey()
- vkey.Position.X = head.x
- vkey.Position.Y = head.y
- vkey.Position.Z = head.z
- vkey.Orientation = quat
+ vkey = VQuatAnimKey()
+ vkey.Position.X = head.x
+ vkey.Position.Y = head.y
+ vkey.Position.Z = head.z
+ vkey.Orientation = quat
# frame delta = 1.0 / fps
- vkey.Time = 1.0 / anim_rate # according to C++ header this is "disregarded"
+ vkey.Time = 1.0 / anim_rate # according to C++ header this is "disregarded"
psa.AddRawKey(vkey)
@@ -1540,8 +1643,10 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
# END for i in range(frame_count)
- anim.TotalBones = len(ordered_bones) # REMOVED len(unique_bone_indexes)
- anim.TrackTime = float(frame_count) # frame_count/anim.AnimRate makes more sense, but this is what actually works in UDK
+ # REMOVED len(unique_bone_indexes)
+ anim.TotalBones = len(ordered_bones)
+ # frame_count/anim.AnimRate makes more sense, but this is what actually works in UDK
+ anim.TrackTime = float(frame_count)
verbose("anim.TotalBones={}, anim.TrackTime={}".format(anim.TotalBones, anim.TrackTime))
@@ -1553,52 +1658,54 @@ def parse_animation( armature, udk_bones, actions_to_export, psa ):
armature.animation_data.action = restoreAction
context.scene.frame_set(restoreFrame)
-#===========================================================================
+
+# ===========================================================================
# Collate actions to be exported
# Modify this to filter for one, some or all actions. For now use all.
# RETURNS list of actions
-#===========================================================================
+# ===========================================================================
def collate_actions():
verbose(header("collate_actions"))
actions_to_export = []
for action in bpy.data.actions:
- if bpy.context.scene.udk_option_selectanimations: # check if needed to select actions set for exporting it
+ if bpy.context.scene.udk_option_selectanimations: # check if needed to select actions set for exporting it
print("Action Set is selected!")
bready = False
- for actionlist in bpy.context.scene.udkas_list: #list the action set from the list
- if actionlist.name == action.name and actionlist.bmatch == True and actionlist.bexport == True:
+ for actionlist in bpy.context.scene.udkas_list: # list the action set from the list
+ if actionlist.name == action.name and actionlist.bmatch is True and actionlist.bexport is True:
bready = True
- print("Added Action Set:",action.name)
+ print("Added Action Set:", action.name)
break
- if bready == False:#don't export it
- print("Skipping Action Set:",action.name)
+ if bready is False: # don't export it
+ print("Skipping Action Set:", action.name)
continue
- verbose(" + {}".format(action.name)) #action set name
- actions_to_export.append(action) #add to the action array
+ verbose(" + {}".format(action.name)) # action set name
+ actions_to_export.append(action) # add to the action array
return actions_to_export
-#===========================================================================
+
+# ===========================================================================
# Locate the target armature and mesh for export
# RETURNS armature, mesh
-#===========================================================================
+# ===========================================================================
def find_armature_and_mesh():
verbose(header("find_armature_and_mesh", 'LEFT', '<', 60))
- context = bpy.context
- active_object = context.active_object
- armature = None
- mesh = None
+ context = bpy.context
+ active_object = context.active_object
+ armature = None
+ mesh = None
# TODO:
# this could be more intuitive
- #bpy.ops.object.mode_set(mode='OBJECT')
+ # bpy.ops.object.mode_set(mode='OBJECT')
- if bpy.context.scene.udk_option_selectobjects: #if checked select object true do list object on export
+ if bpy.context.scene.udk_option_selectobjects: # if checked select object true do list object on export
print("select mode:")
if len(bpy.context.scene.udkArm_list) > 0:
- print("Armature Name:",bpy.context.scene.udkArm_list[bpy.context.scene.udkArm_list_idx].name)
+ print("Armature Name:", bpy.context.scene.udkArm_list[bpy.context.scene.udkArm_list_idx].name)
for obj in bpy.context.scene.objects:
if obj.name == bpy.context.scene.udkArm_list[bpy.context.scene.udkArm_list_idx].name:
armature = obj
@@ -1606,21 +1713,22 @@ def find_armature_and_mesh():
else:
raise Error("There is no Armature in the list!")
meshselected = []
- #parented_meshes = [obj for obj in armature.children if obj.type == 'MESH']
+ # parented_meshes = [obj for obj in armature.children if obj.type == 'MESH']
meshes = [obj for obj in bpy.context.scene.objects if obj.type == 'MESH']
for obj in meshes:
- #print(dir(obj))
+ # print(dir(obj))
if obj.type == 'MESH':
bexportmesh = False
- #print("PARENT MESH:",obj.name)
+ # print("PARENT MESH:",obj.name)
for udkmeshlist in bpy.context.scene.udkmesh_list:
- if obj.name == udkmeshlist.name and udkmeshlist.bexport == True:
+ if obj.name == udkmeshlist.name and udkmeshlist.bexport is True:
bexportmesh = True
break
- if bexportmesh == True:
- print("Mesh Name:",obj.name," < SELECT TO EXPORT!")
+ if bexportmesh is True:
+ print("Mesh Name:", obj.name, " < SELECT TO EXPORT!")
meshselected.append(obj)
- print("MESH COUNT:",len(meshselected))
+
+ print("MESH COUNT:", len(meshselected))
# try the active object
if active_object and active_object.type == 'MESH' and len(meshselected) == 0:
if active_object.parent == armature:
@@ -1630,8 +1738,8 @@ def find_armature_and_mesh():
# otherwise, expect a single mesh parented to the armature (other object types are ignored)
else:
- print("Number of meshes:",len(meshes))
- print("Number of meshes (selected):",len(meshes))
+ print("Number of meshes:", len(meshes))
+ print("Number of meshes (selected):", len(meshes))
if len(meshes) == 1:
mesh = meshes[0]
@@ -1642,7 +1750,7 @@ def find_armature_and_mesh():
raise Error("More than one mesh(s) parented to armature. Select object(s)!")
else:
raise Error("No mesh parented to armature")
- else: #if not check for select function from the list work the code here
+ else: # if not check for select function from the list work the code here
print("normal mode:")
# try the active object
if active_object and active_object.type == 'ARMATURE':
@@ -1650,19 +1758,19 @@ def find_armature_and_mesh():
bpy.ops.object.mode_set(mode='OBJECT')
# otherwise, try for a single armature in the scene
else:
- #bpy.ops.object.mode_set(mode='OBJECT')
+ # bpy.ops.object.mode_set(mode='OBJECT')
all_armatures = [obj for obj in bpy.context.scene.objects if obj.type == 'ARMATURE']
- if len(all_armatures) == 1:#if armature has one scene just assign it
+ if len(all_armatures) == 1: # if armature has one scene just assign it
armature = all_armatures[0]
- elif len(all_armatures) > 1:#if there more armature then find the select armature
+ elif len(all_armatures) > 1: # if there more armature then find the select armature
barmselect = False
for _armobj in all_armatures:
if _armobj.select:
armature = _armobj
barmselect = True
break
- if barmselect == False:
+ if barmselect is False:
raise Error("Please select an armatures in the scene")
else:
raise Error("No armatures in scene")
@@ -1676,8 +1784,8 @@ def find_armature_and_mesh():
raise Error("The selected Armature has no mesh parented to the Armature Object!")
for obj in armature.children:
- #print(dir(obj))
- if obj.type == 'MESH' and obj.select == True:
+ # print(dir(obj))
+ if obj.type == 'MESH' and obj.select is True:
meshselected.append(obj)
# try the active object
if active_object and active_object.type == 'MESH' and len(meshselected) == 0:
@@ -1688,8 +1796,8 @@ def find_armature_and_mesh():
# otherwise, expect a single mesh parented to the armature (other object types are ignored)
else:
- print("Number of meshes:",len(parented_meshes))
- print("Number of meshes (selected):",len(meshselected))
+ print("Number of meshes:", len(parented_meshes))
+ print("Number of meshes (selected):", len(meshselected))
if len(parented_meshes) == 1:
mesh = parented_meshes[0]
@@ -1704,28 +1812,33 @@ def find_armature_and_mesh():
verbose("Found mesh: {}".format(mesh.name))
if mesh is None or armature is None:
raise Error("Check Mesh and Armature are list!")
- #if len(armature.pose.bones) == len(mesh.vertex_groups):
- #print("Armature and Mesh Vertex Groups matches Ok!")
- #else:
- #raise Error("Armature bones:" + str(len(armature.pose.bones)) + " Mesh Vertex Groups:" + str(len(mesh.vertex_groups)) +" doesn't match!")
- #this will check if object need to be rebuild.
+ """
+ if len(armature.pose.bones) == len(mesh.vertex_groups):
+ print("Armature and Mesh Vertex Groups matches Ok!")
+ else:
+ raise Error("Armature bones:" + str(len(armature.pose.bones)) +
+ " Mesh Vertex Groups:" + str(len(mesh.vertex_groups)) +" doesn't match!")
+ """
+ # this will check if object need to be rebuild
if bpy.context.scene.udk_option_rebuildobjects:
- #print("INIT... REBUILDING...")
+ # print("INIT... REBUILDING...")
print("REBUILDING ARMATURE...")
- #if deform mesh
- armature = rebuildarmature(armature) #rebuild the armature to raw . If there IK constraint it will ignore it.
+ # if deform mesh
+ # rebuild the armature to raw. If there IK constraint it will ignore it
+ armature = rebuildarmature(armature)
print("REBUILDING MESH...")
- mesh = rebuildmesh(mesh) #rebuild the mesh to raw data format.
+ mesh = rebuildmesh(mesh) # rebuild the mesh to raw data format.
return armature, mesh
-#===========================================================================
+
+# ===========================================================================
# Returns a list of vertex groups in the mesh. Can be modified to filter
# groups as necessary.
# UNUSED
-#===========================================================================
-def collate_vertex_groups( mesh ):
+# ===========================================================================
+def collate_vertex_groups(mesh):
verbose("collate_vertex_groups")
groups = []
@@ -1736,13 +1849,14 @@ def collate_vertex_groups( mesh ):
return groups
-#===========================================================================
+
+# ===========================================================================
# Main
-#===========================================================================
+# ===========================================================================
def export(filepath):
print(header("Export", 'RIGHT'))
- bpy.types.Scene.udk_copy_merge = False #in case fail to export set this to default
- t = time.clock()
+ bpy.types.Scene.udk_copy_merge = False # in case fail to export set this to default
+ t = time.clock()
context = bpy.context
print("Blender Version {}.{}.{}".format(bpy.app.version[0], bpy.app.version[1], bpy.app.version[2]))
@@ -1778,7 +1892,7 @@ def export(filepath):
udk_bones = parse_armature(udk_armature, psk, psa)
# step 3
- if context.scene.udk_option_export_psa == True:
+ if context.scene.udk_option_export_psa is True:
actions = collate_actions()
parse_animation(udk_armature, udk_bones, actions, psa)
@@ -1788,7 +1902,7 @@ def export(filepath):
psk_filename = filepath + '.psk'
psa_filename = filepath + '.psa'
- if context.scene.udk_option_export_psk == True:
+ if context.scene.udk_option_export_psk is True:
print("Skeletal mesh data...")
psk.PrintOut()
file = open(psk_filename, "wb")
@@ -1797,7 +1911,7 @@ def export(filepath):
print("Exported: " + psk_filename)
print()
- if context.scene.udk_option_export_psa == True:
+ if context.scene.udk_option_export_psa is True:
print("Animation data...")
if not psa.IsEmpty():
psa.PrintOut()
@@ -1810,27 +1924,27 @@ def export(filepath):
print()
- #if objects are rebuild do the unlink
+ # if objects are rebuild do the unlink
if bpy.context.scene.udk_option_rebuildobjects:
print("Unlinking Objects")
- print("Armature Object Name:",udk_armature.name) #display object name
- bpy.context.scene.objects.unlink(udk_armature) #remove armature from the scene
- print("Mesh Object Name:",udk_mesh.name) #display object name
- bpy.context.scene.objects.unlink(udk_mesh) #remove mesh from the scene
+ print("Armature Object Name:", udk_armature.name) # display object name
+ bpy.context.scene.objects.unlink(udk_armature) # remove armature from the scene
+ print("Mesh Object Name:", udk_mesh.name) # display object name
+ bpy.context.scene.objects.unlink(udk_mesh) # remove mesh from the scene
print("Export completed in {:.2f} seconds".format((time.clock() - t)))
-#===========================================================================
+
+# ===========================================================================
# Operator
-#===========================================================================
-class Operator_UDKExport( bpy.types.Operator ):
+# ===========================================================================
+class Operator_UDKExport(Operator):
"""Export to UDK"""
- bl_idname = "object.udk_export"
- bl_label = "Export now"
+ bl_idname = "object.udk_export"
+ bl_label = "Export now"
def execute(self, context):
- print( "\n"*8 )
-
+ print("\n" * 8)
scene = bpy.context.scene
scene.udk_option_export_psk = (scene.udk_option_export == '0' or scene.udk_option_export == '2')
@@ -1840,8 +1954,7 @@ class Operator_UDKExport( bpy.types.Operator ):
# cache settings
restore_frame = scene.frame_current
-
- message = "Finish Export!"
+ message = "Object(s) exported to: {}".format(filepath)
try:
export(filepath)
@@ -1852,144 +1965,80 @@ class Operator_UDKExport( bpy.types.Operator ):
# restore settings
scene.frame_set(restore_frame)
- self.report({'ERROR'}, message)
+ def draw(self, context):
+ self.layout.label(text="Export Finished")
+ try:
+ context.window_manager.popup_menu(draw, title=message, icon="INFO")
+ except:
+ pass
+
+ self.report({'INFO'}, message)
# restore settings
scene.frame_set(restore_frame)
return {'FINISHED'}
-#===========================================================================
+
+# ===========================================================================
# Operator
-#===========================================================================
-class Operator_ToggleConsole( bpy.types.Operator ):
+# ===========================================================================
+class Operator_ToggleConsole(Operator):
"""Show or hide the console"""
- bl_idname = "object.toggle_console"
- bl_label = "Toggle console"
+ bl_idname = "object.toggle_console"
+ bl_label = "Toggle console"
- #def invoke(self, context, event):
- # bpy.ops.wm.console_toggle()
- # return{'FINISHED'}
def execute(self, context):
bpy.ops.wm.console_toggle()
return {'FINISHED'}
-#===========================================================================
+
+# ===========================================================================
# Get filepath for export
-#===========================================================================
+# ===========================================================================
def get_dst_path():
if bpy.context.scene.udk_option_filename_src == '0':
if bpy.context.active_object:
- path = os.path.split(bpy.data.filepath)[0] + "\\" + bpy.context.active_object.name# + ".psk"
+ path = os.path.split(bpy.data.filepath)[0] + "\\" + bpy.context.active_object.name # + ".psk"
else:
- #path = os.path.split(bpy.data.filepath)[0] + "\\" + "Unknown";
- path = os.path.splitext(bpy.data.filepath)[0]# + ".psk"
+ # path = os.path.split(bpy.data.filepath)[0] + "\\" + "Unknown";
+ path = os.path.splitext(bpy.data.filepath)[0] # + ".psk"
else:
- path = os.path.splitext(bpy.data.filepath)[0]# + ".psk"
+ path = os.path.splitext(bpy.data.filepath)[0] # + ".psk"
return path
-#Added by [MGVS]
-bpy.types.Scene.udk_option_filename_src = EnumProperty(
- name = "Filename",
- description = "Sets the name for the files",
- items = [ ('0', "From object", "Name will be taken from object name"),
- ('1', "From Blend", "Name will be taken from .blend file name") ],
- default = '0')
-
-bpy.types.Scene.udk_option_export_psk = BoolProperty(
- name = "bool export psa",
- description = "Boolean for exporting psk format (Skeleton Mesh)",
- default = True)
-
-bpy.types.Scene.udk_option_export_psa = BoolProperty(
- name = "bool export psa",
- description = "Boolean for exporting psa format (Animation Data)",
- default = True)
-
-bpy.types.Scene.udk_option_clamp_uv = BoolProperty(
- name = "Clamp UV",
- description = "True is to limit Clamp UV co-ordinates to [0-1]. False is unrestricted (x,y). ",
- default = False)
-
-bpy.types.Scene.udk_copy_merge = BoolProperty(
- name = "Merge Mesh",
- description = "This will copy the mesh(s) and merge the object together and unlink the mesh to be remove while exporting the object",
- default = False)
-
-bpy.types.Scene.udk_option_export = EnumProperty(
- name = "Export",
- description = "What to export",
- items = [ ('0', "Mesh only", "Exports the PSK file for the Skeletal Mesh"),
- ('1', "Animation only", "Export the PSA file for Action Set(s)(Animations Data)"),
- ('2', "Mesh & Animation", "Export both PSK and PSA files(Skeletal Mesh/Animation(s) Data)") ],
- default = '2')
-
-bpy.types.Scene.udk_option_verbose = BoolProperty(
- name = "Verbose",
- description = "Verbose console output",
- default = False)
-
-bpy.types.Scene.udk_option_smoothing_groups = BoolProperty(
- name = "Smooth Groups",
- description = "Activate hard edges as smooth groups",
- default = True)
-
-bpy.types.Scene.udk_option_triangulate = BoolProperty(
- name = "Triangulate Mesh",
- description = "Convert Quads to Triangles",
- default = False)
-
-bpy.types.Scene.udk_option_selectanimations = BoolProperty(
- name = "Select Animation(s)",
- description = "Select animation(s) for export to psa file",
- default = False)
-
-bpy.types.Scene.udk_option_selectobjects = BoolProperty(
- name = "Select Object(s)",
- description = "Select Armature and Mesh(s). Just make sure mesh(s) is parent to armature",
- default = False)
-
-bpy.types.Scene.udk_option_rebuildobjects = BoolProperty(
- name = "Rebuild Objects",
- description = "In case of deform skeleton mesh and animations data - This will rebuild objects from raw format on export when checked",
- default = False)
-
-bpy.types.Scene.udk_option_ignoreactiongroupnames = BoolProperty(
- name = "Ignore Action Group Names",
- description = "This will Ignore Action Set Group Names Check With Armature Bones. It will override armature to set action set",
- default = False)
-
-bpy.types.Scene.udk_option_scale = FloatProperty(
- name = "UDK Scale",
- description = "In case you don't want to scale objects manually - This will just scale position when on export for the skeleton mesh and animation data",
- default = 1)
-
-#===========================================================================
+
+# ===========================================================================
# User interface
-#===========================================================================
-class OBJECT_OT_UTSelectedFaceSmooth(bpy.types.Operator):
+# ===========================================================================
+class OBJECT_OT_UTSelectedFaceSmooth(Operator):
"""It will only select smooth faces that is select mesh"""
bl_idname = "object.utselectfacesmooth" # XXX, name???
- bl_label = "Select Smooth Faces"#"Select Smooth faces"
+ bl_label = "Select Smooth Faces" # "Select Smooth faces"
def invoke(self, context, event):
print("----------------------------------------")
print("Init Select Face(s):")
bselected = False
for obj in bpy.data.objects:
- if obj.type == 'MESH' and obj.select == True:
+ if obj.type == 'MESH' and obj.select is True:
smoothcount = 0
flatcount = 0
- bpy.ops.object.mode_set(mode='OBJECT')#it need to go into object mode to able to select the faces
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
- obj.select = True #set current object select
- bpy.context.scene.objects.active = obj #set active object
- mesh = bmesh.new();
+ bpy.ops.object.mode_set(mode='OBJECT') # it need to go into object mode to able to select the faces
+
+ for i in bpy.context.scene.objects:
+ i.select = False # deselect all objects
+
+ obj.select = True # set current object select
+ bpy.context.scene.objects.active = obj # set active object
+ mesh = bmesh.new()
mesh.from_mesh(obj.data)
+
for face in mesh.faces:
face.select = False
+
for face in mesh.faces:
- if face.smooth == True:
+ if face.smooth is True:
face.select = True
smoothcount += 1
else:
@@ -1998,173 +2047,195 @@ class OBJECT_OT_UTSelectedFaceSmooth(bpy.types.Operator):
mesh.to_mesh(obj.data)
bpy.context.scene.update()
bpy.ops.object.mode_set(mode='EDIT')
- print("Select Smooth Count(s):",smoothcount," Flat Count(s):",flatcount)
+ print("Select Smooth Count(s):", smoothcount, " Flat Count(s):", flatcount)
bselected = True
break
if bselected:
- print("Selected Face(s) Exectue!")
- self.report({'INFO'}, "Selected Face(s) Exectue!")
+ self.report({'INFO'}, "Selected Face(s) Executed")
else:
- print("Didn't select Mesh Object!")
- self.report({'INFO'}, "Didn't Select Mesh Object!")
+ self.report({'INFO'}, "Mesh Object is not selected")
print("----------------------------------------")
+
return{'FINISHED'}
-class OBJECT_OT_MeshClearWeights(bpy.types.Operator):
+
+class OBJECT_OT_MeshClearWeights(Operator):
"""Remove all mesh vertex groups weights for the bones"""
bl_idname = "object.meshclearweights" # XXX, name???
- bl_label = "Remove Vertex Weights"#"Remove Mesh vertex weights"
+ bl_label = "Remove Vertex Weights" # "Remove Mesh vertex weights"
def invoke(self, context, event):
for obj in bpy.data.objects:
- if obj.type == 'MESH' and obj.select == True:
+ if obj.type == 'MESH' and obj.select is True:
for vg in obj.vertex_groups:
obj.vertex_groups.remove(vg)
- self.report({'INFO'}, "Mesh Vertex Groups Remove!")
+ self.report({'INFO'}, "Mesh Vertex Groups Removed")
break
return{'FINISHED'}
+
def unpack_list(list_of_tuples):
l = []
for t in list_of_tuples:
l.extend(t)
return l
+
def rebuildmesh(obj):
- #make sure it in object mode
- print("Mesh Object Name:",obj.name)
+ # make sure it in object mode
+ print("Mesh Object Name:", obj.name)
bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
+
+ for i in bpy.context.scene.objects:
+ i.select = False # deselect all objects
obj.select = True
bpy.context.scene.objects.active = obj
- me_ob = bpy.data.meshes.new(("Re_"+obj.name))
+ me_ob = bpy.data.meshes.new(("Re_" + obj.name))
mesh = obj.data
faces = []
verts = []
smoothings = []
uvfaces = []
- #print("creating array build mesh...")
- mmesh = obj.to_mesh(bpy.context.scene,True,'PREVIEW')
+ # print("creating array build mesh...")
+ mmesh = obj.to_mesh(bpy.context.scene, True, 'PREVIEW')
uv_layer = mmesh.tessface_uv_textures.active
+
for face in mmesh.tessfaces:
- smoothings.append(face.use_smooth)#smooth or flat in boolean
- if uv_layer is not None:#check if there texture data exist
+ smoothings.append(face.use_smooth) # smooth or flat in boolean
+ if uv_layer is not None: # check if there texture data exist
faceUV = uv_layer.data[face.index]
uvs = []
for uv in faceUV.uv:
- uvs.append((uv[0],uv[1]))
+ uvs.append((uv[0], uv[1]))
uvfaces.append(uvs)
- #print((face.vertices[:]))
+ # print((face.vertices[:]))
if len(face.vertices) == 3:
- faces.extend([(face.vertices[0],face.vertices[1],face.vertices[2],0)])
+ faces.extend([(face.vertices[0], face.vertices[1], face.vertices[2], 0)])
else:
- faces.extend([(face.vertices[0],face.vertices[1],face.vertices[2],face.vertices[3])])
- #vertex positions
+ faces.extend([(face.vertices[0], face.vertices[1], face.vertices[2], face.vertices[3])])
+
+ # vertex positions
for vertex in mesh.vertices:
verts.append(vertex.co.to_tuple())
- #vertices weight groups into array
- vertGroups = {} #array in strings
+ # vertices weight groups into array
+ vertGroups = {} # array in strings
+
for vgroup in obj.vertex_groups:
vlist = []
for v in mesh.vertices:
for vg in v.groups:
if vg.group == vgroup.index:
- vlist.append((v.index,vg.weight))
- #print((v.index,vg.weight))
+ vlist.append((v.index, vg.weight))
+ # print((v.index,vg.weight))
vertGroups[vgroup.name] = vlist
- #print("creating mesh object...")
- #me_ob.from_pydata(verts, [], faces)
+ # print("creating mesh object...")
+ # me_ob.from_pydata(verts, [], faces)
me_ob.vertices.add(len(verts))
me_ob.tessfaces.add(len(faces))
me_ob.vertices.foreach_set("co", unpack_list(verts))
- me_ob.tessfaces.foreach_set("vertices_raw",unpack_list( faces))
- me_ob.tessfaces.foreach_set("use_smooth", smoothings)#smooth array from face
+ me_ob.tessfaces.foreach_set("vertices_raw", unpack_list(faces))
+ me_ob.tessfaces.foreach_set("use_smooth", smoothings) # smooth array from face
- #check if there is uv faces
+ # check if there is uv faces
if len(uvfaces) > 0:
uvtex = me_ob.tessface_uv_textures.new(name="retex")
for i, face in enumerate(me_ob.tessfaces):
- blender_tface = uvtex.data[i] #face
+ blender_tface = uvtex.data[i] # face
mfaceuv = uvfaces[i]
if len(mfaceuv) == 3:
- blender_tface.uv1 = mfaceuv[0];
- blender_tface.uv2 = mfaceuv[1];
- blender_tface.uv3 = mfaceuv[2];
+ blender_tface.uv1 = mfaceuv[0]
+ blender_tface.uv2 = mfaceuv[1]
+ blender_tface.uv3 = mfaceuv[2]
if len(mfaceuv) == 4:
- blender_tface.uv1 = mfaceuv[0];
- blender_tface.uv2 = mfaceuv[1];
- blender_tface.uv3 = mfaceuv[2];
- blender_tface.uv4 = mfaceuv[3];
+ blender_tface.uv1 = mfaceuv[0]
+ blender_tface.uv2 = mfaceuv[1]
+ blender_tface.uv3 = mfaceuv[2]
+ blender_tface.uv4 = mfaceuv[3]
- me_ob.update()#need to update the information to able to see into the secne
- obmesh = bpy.data.objects.new(("Re_"+obj.name),me_ob)
+ me_ob.update() # need to update the information to able to see into the secne
+ obmesh = bpy.data.objects.new(("Re_" + obj.name), me_ob)
bpy.context.scene.update()
- #Build tmp materials
+
+ # Build tmp materials
materialname = "ReMaterial"
for matcount in mesh.materials:
matdata = bpy.data.materials.new(materialname)
me_ob.materials.append(matdata)
- #assign face to material id
+
+ # assign face to material id
for face in mesh.tessfaces:
me_ob.faces[face.index].material_index = face.material_index
- #vertices weight groups
+
+ # vertices weight groups
for vgroup in vertGroups:
group = obmesh.vertex_groups.new(vgroup)
for v in vertGroups[vgroup]:
- group.add([v[0]], v[1], 'ADD')# group.add(array[vertex id],weight,add)
+ group.add([v[0]], v[1], 'ADD') # group.add(array[vertex id],weight,add)
bpy.context.scene.objects.link(obmesh)
- #print("Mesh Material Count:",len(me_ob.materials))
+ # print("Mesh Material Count:",len(me_ob.materials))
matcount = 0
- #print("MATERIAL ID OREDER:")
+ # print("MATERIAL ID OREDER:")
for mat in me_ob.materials:
- #print("-Material:",mat.name,"INDEX:",matcount)
+ # print("-Material:",mat.name,"INDEX:",matcount)
matcount += 1
- print("Mesh Object Name:",obmesh.name)
+
+ print("Mesh Object Name:", obmesh.name)
bpy.context.scene.update()
+
return obmesh
-class OBJECT_OT_UTRebuildMesh(bpy.types.Operator):
+
+class OBJECT_OT_UTRebuildMesh(Operator):
"""It rebuild the mesh from scrape from the selected mesh object. """ \
"""Note the scale will be 1:1 for object mode. To keep from deforming"""
bl_idname = "object.utrebuildmesh" # XXX, name???
- bl_label = "Rebuild Mesh"#"Rebuild Mesh"
+ bl_label = "Rebuild Mesh" # "Rebuild Mesh"
def invoke(self, context, event):
print("----------------------------------------")
print("Init Mesh Bebuild...")
bselected = False
bpy.ops.object.mode_set(mode='OBJECT')
+
for obj in bpy.data.objects:
- if obj.type == 'MESH' and obj.select == True:
+ if obj.type == 'MESH' and obj.select is True:
rebuildmesh(obj)
- self.report({'INFO'}, "Rebuild Mesh Finish!")
+
+ self.report({'INFO'}, "Rebuild Mesh Finished!")
print("Finish Mesh Build...")
print("----------------------------------------")
return{'FINISHED'}
+
def rebuildarmature(obj):
- currentbone = [] #select armature for roll copy
- print("Armature Name:",obj.name)
+ currentbone = [] # select armature for roll copy
+ print("Armature Name:", obj.name)
objectname = "ArmatureDataPSK"
- meshname ="ArmatureObjectPSK"
+ meshname = "ArmatureObjectPSK"
armdata = bpy.data.armatures.new(objectname)
ob_new = bpy.data.objects.new(meshname, armdata)
bpy.context.scene.objects.link(ob_new)
- #bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
+ # bpy.ops.object.mode_set(mode='OBJECT')
+
+ for i in bpy.context.scene.objects:
+ i.select = False # deselect all objects
+
ob_new.select = True
bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
for bone in obj.data.edit_bones:
if bone.parent is not None:
- currentbone.append([bone.name,bone.roll])
+ currentbone.append([bone.name, bone.roll])
else:
- currentbone.append([bone.name,bone.roll])
+ currentbone.append([bone.name, bone.roll])
bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
+
+ for i in bpy.context.scene.objects:
+ i.select = False # deselect all objects
+
bpy.context.scene.objects.active = ob_new
bpy.ops.object.mode_set(mode='EDIT')
@@ -2181,135 +2252,185 @@ def rebuildarmature(obj):
parentbone = ob_new.data.edit_bones[bone.parent.name]
newbone.parent = parentbone
- ob_new.animation_data_create()#create animation data
- if obj.animation_data is not None:#check for animation
- ob_new.animation_data.action = obj.animation_data.action #just make sure it here to do the animations if exist
- print("Armature Object Name:",ob_new.name)
+ ob_new.animation_data_create() # create animation data
+ if obj.animation_data is not None: # check for animation
+ # just make sure it here to do the animations if exist
+ ob_new.animation_data.action = obj.animation_data.action
+
+ print("Armature Object Name:", ob_new.name)
return ob_new
-class OBJECT_OT_UTRebuildArmature(bpy.types.Operator):
+
+class OBJECT_OT_UTRebuildArmature(Operator):
"""If mesh is deform when importing to unreal engine try this. """ \
"""It rebuild the bones one at the time by select one armature object scrape to raw setup build. """ \
"""Note the scale will be 1:1 for object mode. To keep from deforming"""
bl_idname = "object.utrebuildarmature" # XXX, name???
- bl_label = "Rebuild Armature" #Rebuild Armature
+ bl_label = "Rebuild Armature" # Rebuild Armature
def invoke(self, context, event):
print("----------------------------------------")
print("Init Rebuild Armature...")
bselected = False
for obj in bpy.data.objects:
- if obj.type == 'ARMATURE' and obj.select == True:
+ if obj.type == 'ARMATURE' and obj.select is True:
rebuildarmature(obj)
self.report({'INFO'}, "Rebuild Armature Finish!")
print("End of Rebuild Armature.")
print("----------------------------------------")
return{'FINISHED'}
-class UDKActionSetListPG(bpy.types.PropertyGroup):
- bool = BoolProperty(default=False)
- string = StringProperty()
- actionname = StringProperty()
- bmatch = BoolProperty(default=False,name="Match", options={"HIDDEN"},description = "This check against bone names and action group names matches and override boolean if true")
- bexport = BoolProperty(default=False,name="Export",description = "Check this to export the animation")
-bpy.utils.register_class(UDKActionSetListPG)
-bpy.types.Scene.udkas_list = CollectionProperty(type=UDKActionSetListPG)
-bpy.types.Scene.udkas_list_idx = IntProperty()
+class UDKActionSetListPG(PropertyGroup):
+ bool = BoolProperty(default=False)
+ string = StringProperty()
+ actionname = StringProperty()
+ bmatch = BoolProperty(
+ default=False,
+ name="Match",
+ options={"HIDDEN"},
+ description="This check against bone names and action group "
+ "names matches and override boolean if true"
+ )
+ bexport = BoolProperty(
+ default=False,
+ name="Export",
+ description="Check this to export the animation"
+ )
+
-class UL_UDKActionSetList(bpy.types.UIList):
+class UL_UDKActionSetList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.label(item.name)
layout.prop(item, "bmatch", text="Match")
layout.prop(item, "bexport", text="Export")
-class UDKObjListPG(bpy.types.PropertyGroup):
- bool = BoolProperty(default=False)
- string = StringProperty()
- bexport = BoolProperty(default=False,name="Export", options={"HIDDEN"},description = "This will be ignore when exported")
- bselect = BoolProperty(default=False,name="Select", options={"HIDDEN"},description = "This will be ignore when exported")
- otype = StringProperty(name="Type",description = "This will be ignore when exported")
-bpy.utils.register_class(UDKObjListPG)
-bpy.types.Scene.udkobj_list = CollectionProperty(type=UDKObjListPG)
-bpy.types.Scene.udkobj_list_idx = IntProperty()
+class UDKObjListPG(PropertyGroup):
+ bool = BoolProperty(default=False)
+ string = StringProperty()
+ bexport = BoolProperty(
+ default=False,
+ name="Export",
+ options={"HIDDEN"},
+ description="This will be ignore when exported"
+ )
+ bselect = BoolProperty(
+ default=False,
+ name="Select",
+ options={"HIDDEN"},
+ description="This will be ignore when exported"
+ )
+ otype = StringProperty(
+ name="Type",
+ description="This will be ignore when exported"
+ )
-class UL_UDKObjList(bpy.types.UIList):
+
+class UL_UDKObjList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.label(item.name)
layout.prop(item, "otype", text="")
layout.prop(item, "bselect", text="")
-class UDKMeshListPG(bpy.types.PropertyGroup):
- bool = BoolProperty(default=False)
- string = StringProperty()
- bexport = BoolProperty(default=False,name="Export", options={"HIDDEN"},description = "This object will be export when true")
- bselect = BoolProperty(default=False,name="Select", options={"HIDDEN"},description = "Make sure you have Mesh is parent to Armature")
- otype = StringProperty(name="Type",description = "This will be ignore when exported")
-bpy.utils.register_class(UDKMeshListPG)
-bpy.types.Scene.udkmesh_list = CollectionProperty(type=UDKMeshListPG)
-bpy.types.Scene.udkmesh_list_idx = IntProperty()
+class UDKMeshListPG(PropertyGroup):
+ bool = BoolProperty(
+ default=False
+ )
+ string = StringProperty()
+ bexport = BoolProperty(
+ default=False,
+ name="Export",
+ options={"HIDDEN"},
+ description="This object will be export when true"
+ )
+ bselect = BoolProperty(
+ default=False,
+ name="Select",
+ options={"HIDDEN"},
+ description="Make sure you have Mesh is parent to Armature"
+ )
+ otype = StringProperty(
+ name="Type",
+ description="This will be ignore when exported"
+ )
+
-class UL_UDKMeshList(bpy.types.UIList):
+class UL_UDKMeshList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.label(item.name)
- #layout.prop(item, "bselect", text="Select")
+ # layout.prop(item, "bselect", text="Select")
layout.prop(item, "bexport", text="Export")
-class UDKArmListPG(bpy.types.PropertyGroup):
- bool = BoolProperty(default=False)
- string = StringProperty()
- bexport = BoolProperty(default=False,name="Export", options={"HIDDEN"},description = "This will be ignore when exported")
- bselect = BoolProperty(default=False,name="Select", options={"HIDDEN"},description = "This will be ignore when exported")
- otype = StringProperty(name="Type",description = "This will be ignore when exported")
-bpy.utils.register_class(UDKArmListPG)
-bpy.types.Scene.udkArm_list = CollectionProperty(type=UDKArmListPG)
-bpy.types.Scene.udkArm_list_idx = IntProperty()
+class UDKArmListPG(PropertyGroup):
+ bool = BoolProperty(default=False)
+ string = StringProperty()
+ bexport = BoolProperty(
+ default=False,
+ name="Export",
+ options={"HIDDEN"},
+ description="This will be ignore when exported"
+ )
+ bselect = BoolProperty(
+ default=False,
+ name="Select",
+ options={"HIDDEN"},
+ description="This will be ignore when exported"
+ )
+ otype = StringProperty(
+ name="Type",
+ description="This will be ignore when exported"
+ )
+
-class UL_UDKArmList(bpy.types.UIList):
+class UL_UDKArmList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.label(item.name)
-class Panel_UDKExport( bpy.types.Panel ):
- bl_label = "UDK Export"
- bl_idname = "OBJECT_PT_udk_tools"
- bl_category = "File I/O"
- bl_space_type = "VIEW_3D"
- bl_region_type = "TOOLS"
+class Panel_UDKExport(Panel):
+ bl_label = "UDK Export"
+ bl_idname = "OBJECT_PT_udk_tools"
+ bl_category = "File I/O"
+ bl_space_type = "VIEW_3D"
+ bl_region_type = "TOOLS"
bl_context = "objectmode"
- #def draw_header(self, context):
- # layout = self.layout
- #obj = context.object
- #layout.prop(obj, "select", text="")
+ """
+ def draw_header(self, context):
+ layout = self.layout
+ obj = context.object
+ layout.prop(obj, "select", text="")
- #@classmethod
- #def poll(cls, context):
- # return context.active_object
+ @classmethod
+ def poll(cls, context):
+ return context.active_object
+ """
def draw(self, context):
layout = self.layout
path = get_dst_path()
object_name = ""
- #if context.object:
- # object_name = context.object.name
+ """
+ if context.object:
+ object_name = context.object.name
+ """
if context.active_object:
object_name = context.active_object.name
row10 = layout.row()
row10.prop(context.scene, "udk_option_smoothing_groups")
row10.prop(context.scene, "udk_option_clamp_uv")
row10.prop(context.scene, "udk_option_verbose")
+
row = layout.row()
row.label(text="Active object: " + object_name)
- #layout.separator()
layout.prop(context.scene, "udk_option_filename_src")
row = layout.row()
row.label(text=path)
- #layout.separator()
+
layout.prop(context.scene, "udk_option_export")
layout.prop(context.scene, "udk_option_selectobjects")
@@ -2322,15 +2443,17 @@ class Panel_UDKExport( bpy.types.Panel ):
layout.template_list("UL_UDKMeshList", "", context.scene, "udkmesh_list",
context.scene, "udkmesh_list_idx", rows=5)
layout.prop(context.scene, "udk_option_selectanimations")
+
if context.scene.udk_option_selectanimations:
layout.operator("action.setanimupdate")
layout.label(text="Action Set(s) - Match / Export")
layout.template_list("UL_UDKActionSetList", "", context.scene, "udkas_list",
context.scene, "udkas_list_idx", rows=5)
- test = layout.separator()
+ layout.separator()
layout.prop(context.scene, "udk_option_scale")
layout.prop(context.scene, "udk_option_rebuildobjects")
- #layout.prop(context.scene, "udk_option_ignoreactiongroupnames")
+ # layout.prop(context.scene, "udk_option_ignoreactiongroupnames")
+
row11 = layout.row()
row11.operator("object.udk_export")
row11.operator("object.toggle_console")
@@ -2341,79 +2464,85 @@ class Panel_UDKExport( bpy.types.Panel ):
layout.operator(OBJECT_OT_UTRebuildMesh.bl_idname)
layout.operator(OBJECT_OT_UDKCheckMeshLines.bl_idname)
+
def udkupdateobjects():
- my_objlist = bpy.context.scene.udkArm_list
- objectl = []
- for objarm in bpy.context.scene.objects:#list and filter only mesh and armature
- if objarm.type == 'ARMATURE':
- objectl.append(objarm)
- for _objd in objectl:#check if list has in udk list
- bfound_obj = False
- for _obj in my_objlist:
- if _obj.name == _objd.name and _obj.otype == _objd.type:
- _obj.bselect = _objd.select
- bfound_obj = True
- break
- if bfound_obj == False:
- #print("ADD ARMATURE...")
- my_item = my_objlist.add()
- my_item.name = _objd.name
- my_item.bselect = _objd.select
- my_item.otype = _objd.type
- removeobject = []
- for _udkobj in my_objlist:
- bfound_objv = False
- for _objd in bpy.context.scene.objects: #check if there no existing object from sense to remove it
- if _udkobj.name == _objd.name and _udkobj.otype == _objd.type:
- bfound_objv = True
- break
- if bfound_objv == False:
- removeobject.append(_udkobj)
- #print("remove check...")
- for _item in removeobject: #loop remove object from udk list object
- count = 0
- for _obj in my_objlist:
- if _obj.name == _item.name and _obj.otype == _item.otype:
- my_objlist.remove(count)
- break
- count += 1
-
- my_objlist = bpy.context.scene.udkmesh_list
- objectl = []
- for objarm in bpy.context.scene.objects:#list and filter only mesh and armature
- if objarm.type == 'MESH':
- objectl.append(objarm)
- for _objd in objectl:#check if list has in udk list
- bfound_obj = False
- for _obj in my_objlist:
- if _obj.name == _objd.name and _obj.otype == _objd.type:
- _obj.bselect = _objd.select
- bfound_obj = True
- break
- if bfound_obj == False:
- my_item = my_objlist.add()
- my_item.name = _objd.name
- my_item.bselect = _objd.select
- my_item.otype = _objd.type
- removeobject = []
- for _udkobj in my_objlist:
- bfound_objv = False
- for _objd in bpy.context.scene.objects: #check if there no existing object from sense to remove it
- if _udkobj.name == _objd.name and _udkobj.otype == _objd.type:
- bfound_objv = True
- break
- if bfound_objv == False:
- removeobject.append(_udkobj)
- #print("remove check...")
- for _item in removeobject: #loop remove object from udk list object
- count = 0
- for _obj in my_objlist:
- if _obj.name == _item.name and _obj.otype == _item.otype:
- my_objlist.remove(count)
- break
- count += 1
+ my_objlist = bpy.context.scene.udkArm_list
+ objectl = []
+ for objarm in bpy.context.scene.objects: # list and filter only mesh and armature
+ if objarm.type == 'ARMATURE':
+ objectl.append(objarm)
+
+ for _objd in objectl: # check if list has in udk list
+ bfound_obj = False
+ for _obj in my_objlist:
+ if _obj.name == _objd.name and _obj.otype == _objd.type:
+ _obj.bselect = _objd.select
+ bfound_obj = True
+ break
+
+ if bfound_obj is False:
+ # print("ADD ARMATURE...")
+ my_item = my_objlist.add()
+ my_item.name = _objd.name
+ my_item.bselect = _objd.select
+ my_item.otype = _objd.type
+ removeobject = []
+ for _udkobj in my_objlist:
+ bfound_objv = False
+
+ for _objd in bpy.context.scene.objects: # check if there no existing object from sense to remove it
+ if _udkobj.name == _objd.name and _udkobj.otype == _objd.type:
+ bfound_objv = True
+ break
-class OBJECT_OT_UDKObjUpdate(bpy.types.Operator):
+ if bfound_objv is False:
+ removeobject.append(_udkobj)
+ # print("remove check...")
+ for _item in removeobject: # loop remove object from udk list object
+ count = 0
+ for _obj in my_objlist:
+ if _obj.name == _item.name and _obj.otype == _item.otype:
+ my_objlist.remove(count)
+ break
+ count += 1
+
+ my_objlist = bpy.context.scene.udkmesh_list
+ objectl = []
+ for objarm in bpy.context.scene.objects: # list and filter only mesh and armature
+ if objarm.type == 'MESH':
+ objectl.append(objarm)
+ for _objd in objectl: # check if list has in udk list
+ bfound_obj = False
+ for _obj in my_objlist:
+ if _obj.name == _objd.name and _obj.otype == _objd.type:
+ _obj.bselect = _objd.select
+ bfound_obj = True
+ break
+ if bfound_obj is False:
+ my_item = my_objlist.add()
+ my_item.name = _objd.name
+ my_item.bselect = _objd.select
+ my_item.otype = _objd.type
+ removeobject = []
+ for _udkobj in my_objlist:
+ bfound_objv = False
+ for _objd in bpy.context.scene.objects: # check if there no existing object from sense to remove it
+ if _udkobj.name == _objd.name and _udkobj.otype == _objd.type:
+ bfound_objv = True
+ break
+ if bfound_objv is False:
+ removeobject.append(_udkobj)
+ # print("remove check...")
+ for _item in removeobject: # loop remove object from udk list object
+ count = 0
+ for _obj in my_objlist:
+ if _obj.name == _item.name and _obj.otype == _item.otype:
+ my_objlist.remove(count)
+ break
+ count += 1
+
+
+class OBJECT_OT_UDKObjUpdate(Operator):
"""This will update the filter of the mesh and armature"""
bl_idname = "object.selobjectpdate"
bl_label = "Update Object(s)"
@@ -2424,21 +2553,26 @@ class OBJECT_OT_UDKObjUpdate(bpy.types.Operator):
udkupdateobjects()
return{'FINISHED'}
+
def udkcheckmeshline():
objmesh = None
for obj in bpy.context.scene.objects:
- if obj.type == 'MESH' and obj.select == True:
+ if obj.type == 'MESH' and obj.select is True:
objmesh = obj
- objmesh = triangulate_mesh(objmesh) #create a copy of the mesh
+
+ objmesh = triangulate_mesh(objmesh) # create a copy of the mesh
bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False # deselect all objects
+
+ for i in bpy.context.scene.objects:
+ i.select = False # deselect all objects
+
objmesh.select = True
- bpy.context.scene.objects.active = objmesh #set active mesh
- wedges = ObjMap()
- points = ObjMap()
- bpy.ops.object.mode_set(mode='EDIT') #set in edit mode
+ bpy.context.scene.objects.active = objmesh # set active mesh
+ wedges = ObjMap()
+ points = ObjMap()
+ bpy.ops.object.mode_set(mode='EDIT') # set in edit mode
bpy.ops.mesh.select_all(action='DESELECT')
- bpy.context.tool_settings.mesh_select_mode = (True, False, False) #select vertices
+ bpy.context.tool_settings.mesh_select_mode = (True, False, False) # select vertices
if objmesh is not None:
print("found mesh")
@@ -2446,19 +2580,19 @@ def udkcheckmeshline():
print(objmesh.data.tessfaces)
vertex_list = []
for face in objmesh.data.tessfaces:
- wedge_list = []
- vect_list = []
+ wedge_list = []
+ vect_list = []
for i in range(3):
- vert_index = face.vertices[i]
- vert = objmesh.data.vertices[vert_index]
- vect_list.append( FVector(vert.co.x, vert.co.y, vert.co.z) )
+ vert_index = face.vertices[i]
+ vert = objmesh.data.vertices[vert_index]
+ vect_list.append(FVector(vert.co.x, vert.co.y, vert.co.z))
vpos = objmesh.matrix_local * vert.co
- p = VPoint()
- p.Point.X = vpos.x
- p.Point.Y = vpos.y
- p.Point.Z = vpos.z
- w = VVertex()
- w.PointIndex = points.get(p) # store keys
+ p = VPoint()
+ p.Point.X = vpos.x
+ p.Point.Y = vpos.y
+ p.Point.Z = vpos.z
+ w = VVertex()
+ w.PointIndex = points.get(p) # store keys
index_wedge = wedges.get(w)
wedge_list.append(index_wedge)
no = face.normal
@@ -2472,28 +2606,29 @@ def udkcheckmeshline():
elif dot < 0:
(tri.WedgeIndex0, tri.WedgeIndex1, tri.WedgeIndex2) = wedge_list
else:
- dindex0 = face.vertices[0];
- dindex1 = face.vertices[1];
- dindex2 = face.vertices[2];
+ dindex0 = face.vertices[0]
+ dindex1 = face.vertices[1]
+ dindex2 = face.vertices[2]
vertex_list.append(dindex0)
vertex_list.append(dindex1)
vertex_list.append(dindex2)
bpy.ops.object.mode_set(mode='OBJECT')
- for vertex in objmesh.data.vertices: #loop all vertex in the mesh list
- for vl in vertex_list: #loop for error vertex
- if vertex.index == vl: #if match set to select
+ for vertex in objmesh.data.vertices: # loop all vertex in the mesh list
+ for vl in vertex_list: # loop for error vertex
+ if vertex.index == vl: # if match set to select
vertex.select = True
break
- bpy.ops.object.mode_set(mode='EDIT') #set in edit mode to see the select vertex
- objmesh.data.update() # update object
- bpy.context.scene.update() #update scene
+ bpy.ops.object.mode_set(mode='EDIT') # set in edit mode to see the select vertex
+ objmesh.data.update() # update object
+ bpy.context.scene.update() # update scene
message = "MESH PASS"
if len(vertex_list) > 0:
message = "MESH FAIL"
return message
-class OBJECT_OT_UDKCheckMeshLines(bpy.types.Operator):
+
+class OBJECT_OT_UDKCheckMeshLines(Operator):
"""Select the mesh for export test. This will create dummy mesh to see which area are broken. """ \
"""If the vertices share the same position it will cause a bug"""
bl_idname = "object.udkcheckmeshline"
@@ -2504,7 +2639,8 @@ class OBJECT_OT_UDKCheckMeshLines(bpy.types.Operator):
self.report({'ERROR'}, message)
return{'FINISHED'}
-class OBJECT_OT_ActionSetAnimUpdate(bpy.types.Operator):
+
+class OBJECT_OT_ActionSetAnimUpdate(Operator):
"""Select Armture to match the action set groups. """ \
"""All bones keys must be set to match with number of bones"""
bl_idname = "action.setanimupdate"
@@ -2521,9 +2657,9 @@ class OBJECT_OT_ActionSetAnimUpdate(bpy.types.Operator):
armatureselected = []
for objarm in bpy.context.scene.objects:
if objarm.type == 'ARMATURE':
- #print("ADDED ARMATURE...")
+ # print("ADDED ARMATURE...")
armatures.append(objarm)
- if objarm.select == True:
+ if objarm.select is True:
armatureselected.append(objarm)
if len(armatureselected) == len(armatures) == 1:
@@ -2537,15 +2673,15 @@ class OBJECT_OT_ActionSetAnimUpdate(bpy.types.Operator):
for bone in armature.pose.bones:
bones.append(bone.name)
- for action in bpy.data.actions:#action list
+ for action in bpy.data.actions: # action list
bfound = False
count = 0
for actionbone in action.groups:
- #print("Pose bone name: ",actionbone.name)
+ # print("Pose bone name: ",actionbone.name)
for b in bones:
if b == actionbone.name:
count += 1
- #print(b," : ",actionbone.name)
+ # print(b," : ",actionbone.name)
break
for actionlist in my_sett:
if action.name == actionlist.name:
@@ -2556,17 +2692,17 @@ class OBJECT_OT_ActionSetAnimUpdate(bpy.types.Operator):
actionlist.bmatch = False
bfound = True
break
- if bfound != True:
+ if bfound is not True:
my_item = my_sett.add()
- #print(dir(my_item.bmatch))
+ # print(dir(my_item.bmatch))
my_item.name = action.name
- #my_item.template_list_controls = "bmatch:bexport"
+ # my_item.template_list_controls = "bmatch:bexport"
if len(bones) == len(action.groups) == count:
my_item.bmatch = True
else:
my_item.bmatch = False
removeactions = []
- #check action list and data actions
+ # check action list and data actions
for actionlist in bpy.context.scene.udkas_list:
bfind = False
notfound = 0
@@ -2575,26 +2711,27 @@ class OBJECT_OT_ActionSetAnimUpdate(bpy.types.Operator):
bfind = True
else:
notfound += 1
- #print("ACT NAME:",actionlist.name," COUNT",notfound)
+ # print("ACT NAME:",actionlist.name," COUNT",notfound)
if notfound == len(bpy.data.actions):
- #print("remove :",actionlist.name)
+ # print("remove :",actionlist.name)
removeactions.append(actionlist.name)
- #print("Not in the action data list:",len(removeactions))
- #remove list or chnages in the name the template list
+ # print("Not in the action data list:",len(removeactions))
+ # remove list or chnages in the name the template list
for actname in removeactions:
actioncount = 0
for actionlist in my_sett:
- #print("action name:",actionlist.name)
+ # print("action name:",actionlist.name)
if actionlist.name == actname:
- my_sett.remove(actioncount);
+ my_sett.remove(actioncount)
break
actioncount += 1
return{'FINISHED'}
-class ExportUDKAnimData(bpy.types.Operator):
+
+class ExportUDKAnimData(Operator):
"""Export Skeleton Mesh / Animation Data file(s). """ \
"""One mesh and one armature else select one mesh or armature to be exported"""
- bl_idname = "export_anim.udk" # this is important since its how bpy.ops.export.udk_anim_data is constructed
+ bl_idname = "export_anim.udk" # this is important since its how bpy.ops.export.udk_anim_data is constructed
bl_label = "Export PSK/PSA"
# List of operator properties, the attributes will be assigned
@@ -2607,13 +2744,18 @@ class ExportUDKAnimData(bpy.types.Operator):
default="*.psk;*.psa",
options={'HIDDEN'},
)
- udk_option_smoothing_groups = bpy.types.Scene.udk_option_smoothing_groups
- udk_option_clamp_uv = bpy.types.Scene.udk_option_clamp_uv
- udk_option_verbose = bpy.types.Scene.udk_option_verbose
- udk_option_filename_src = bpy.types.Scene.udk_option_filename_src
- udk_option_export = bpy.types.Scene.udk_option_export
- udk_option_scale = bpy.types.Scene.udk_option_scale
- udk_option_rebuildobjects = bpy.types.Scene.udk_option_rebuildobjects
+ udk_option_scale = FloatProperty(
+ name="UDK Scale",
+ description="In case you don't want to scale objects manually - "
+ "This will just scale position when on export for the skeleton mesh and animation data",
+ default=1
+ )
+ udk_option_rebuildobjects = BoolProperty(
+ name="Rebuild Objects",
+ description="In case of deform skeleton mesh and animations data - "
+ "This will rebuild objects from raw format on export when checked",
+ default=False
+ )
@classmethod
def poll(cls, context):
@@ -2645,61 +2787,217 @@ class ExportUDKAnimData(bpy.types.Operator):
self.report({'WARNING', 'INFO'}, message)
return {'FINISHED'}
+ def draw(self, context):
+ layout = self.layout
+ scene = context.scene
+
+ layout.prop(scene, "udk_option_smoothing_groups")
+ layout.prop(scene, "udk_option_clamp_uv")
+ layout.prop(scene, "udk_option_verbose")
+ layout.prop(scene, "udk_option_filename_src")
+ layout.prop(scene, "udk_option_export")
+ layout.prop(self, "udk_option_scale")
+ layout.prop(self, "udk_option_rebuildobjects")
+
def invoke(self, context, event):
+ self.udk_option_scale = bpy.context.scene.udk_option_scale
+ self.udk_option_rebuildobjects = bpy.context.scene.udk_option_rebuildobjects
+
wm = context.window_manager
wm.fileselect_add(self)
return {'RUNNING_MODAL'}
+
def menu_func(self, context):
default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
- self.layout.operator(ExportUDKAnimData.bl_idname, text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
+ self.layout.operator(ExportUDKAnimData.bl_idname,
+ text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
+
+
+# Add-ons Preferences Update Panel
+
+# Define Panel classes for updating
+panels = (
+ Panel_UDKExport,
+ )
+
-## Addons Preferences Update Panel
def update_panel(self, context):
+ message = "Export Unreal Engine Format(.psk/.psa): Updating Panel locations has failed"
try:
- bpy.utils.unregister_class(Panel_UDKExport)
- except:
+ for panel in panels:
+ if "bl_rna" in panel.__dict__:
+ bpy.utils.unregister_class(panel)
+
+ for panel in panels:
+ panel.bl_category = context.user_preferences.addons[__name__].preferences.category
+ bpy.utils.register_class(panel)
+
+ except Exception as e:
+ print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
pass
- Panel_UDKExport.bl_category = context.user_preferences.addons[__name__].preferences.category
- bpy.utils.register_class(Panel_UDKExport)
-class PskAddonPreferences(bpy.types.AddonPreferences):
+
+class PskAddonPreferences(AddonPreferences):
# this must match the addon name, use '__package__'
# when defining this in a submodule of a python package.
bl_idname = __name__
- category = bpy.props.StringProperty(
+ category = StringProperty(
name="Tab Category",
description="Choose a name for the category of the panel",
default="File I/O",
- update=update_panel)
+ update=update_panel
+ )
def draw(self, context):
-
layout = self.layout
+
row = layout.row()
col = row.column()
col.label(text="Tab Category:")
col.prop(self, "category", text="")
-#===========================================================================
+
+
+# ===========================================================================
# Entry
-#===========================================================================
+# ===========================================================================
def register():
- #print("REGISTER")
+
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_export.append(menu_func)
update_panel(None, bpy.context)
+ # Added by [MGVS]
+ bpy.types.Scene.udk_option_filename_src = EnumProperty(
+ name="Filename",
+ description="Sets the name for the files",
+ items=[
+ ('0', "From object", "Name will be taken from object name"),
+ ('1', "From Blend", "Name will be taken from .blend file name")
+ ],
+ default='0'
+ )
+ bpy.types.Scene.udk_option_export_psk = BoolProperty(
+ name="bool export psa",
+ description="Boolean for exporting psk format (Skeleton Mesh)",
+ default=True
+ )
+ bpy.types.Scene.udk_option_export_psa = BoolProperty(
+ name="bool export psa",
+ description="Boolean for exporting psa format (Animation Data)",
+ default=True
+ )
+ bpy.types.Scene.udk_option_clamp_uv = BoolProperty(
+ name="Clamp UV",
+ description="True is to limit Clamp UV co-ordinates to [0-1]. False is unrestricted (x,y)",
+ default=False
+ )
+ bpy.types.Scene.udk_copy_merge = BoolProperty(
+ name="Merge Mesh",
+ description="This will copy the mesh(s) and merge the object together "
+ "and unlink the mesh to be remove while exporting the object",
+ default=False
+ )
+ bpy.types.Scene.udk_option_export = EnumProperty(
+ name="Export",
+ description="What to export",
+ items=[
+ ('0', "Mesh only", "Exports the PSK file for the Skeletal Mesh"),
+ ('1', "Animation only", "Export the PSA file for Action Set(s)(Animations Data)"),
+ ('2', "Mesh & Animation", "Export both PSK and PSA files(Skeletal Mesh/Animation(s) Data)")
+ ],
+ default='2'
+ )
+ bpy.types.Scene.udk_option_verbose = BoolProperty(
+ name="Verbose",
+ description="Verbose console output",
+ default=False
+ )
+ bpy.types.Scene.udk_option_smoothing_groups = BoolProperty(
+ name="Smooth Groups",
+ description="Activate hard edges as smooth groups",
+ default=True
+ )
+ bpy.types.Scene.udk_option_triangulate = BoolProperty(
+ name="Triangulate Mesh",
+ description="Convert Quads to Triangles",
+ default=False
+ )
+ bpy.types.Scene.udk_option_selectanimations = BoolProperty(
+ name="Select Animation(s)",
+ description="Select animation(s) for export to psa file",
+ default=False
+ )
+ bpy.types.Scene.udk_option_selectobjects = BoolProperty(
+ name="Select Object(s)",
+ description="Select Armature and Mesh(s). Just make sure mesh(s) is parent to armature",
+ default=False
+ )
+ bpy.types.Scene.udk_option_rebuildobjects = BoolProperty(
+ name="Rebuild Objects",
+ description="In case of deform skeleton mesh and animations data - "
+ "This will rebuild objects from raw format on export when checked",
+ default=False
+ )
+ bpy.types.Scene.udk_option_ignoreactiongroupnames = BoolProperty(
+ name="Ignore Action Group Names",
+ description="This will Ignore Action Set Group Names Check With Armature Bones. "
+ "It will override armature to set action set",
+ default=False
+ )
+ bpy.types.Scene.udk_option_scale = FloatProperty(
+ name="UDK Scale",
+ description="In case you don't want to scale objects manually - "
+ "This will just scale position when on export for the skeleton mesh and animation data",
+ default=1
+ )
+ bpy.types.Scene.udkas_list = CollectionProperty(
+ type=UDKActionSetListPG
+ )
+ bpy.types.Scene.udkas_list_idx = IntProperty()
+ bpy.types.Scene.udkobj_list = CollectionProperty(
+ type=UDKObjListPG
+ )
+ bpy.types.Scene.udkobj_list_idx = IntProperty()
+ bpy.types.Scene.udkmesh_list = CollectionProperty(
+ type=UDKMeshListPG
+ )
+ bpy.types.Scene.udkmesh_list_idx = IntProperty()
+ bpy.types.Scene.udkArm_list = CollectionProperty(
+ type=UDKArmListPG
+ )
+ bpy.types.Scene.udkArm_list_idx = IntProperty()
+
+
def unregister():
- #print("UNREGISTER")
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_export.remove(menu_func)
+ del bpy.types.Scene.udk_option_filename_src
+ del bpy.types.Scene.udk_option_export_psk
+ del bpy.types.Scene.udk_option_export_psa
+ del bpy.types.Scene.udk_option_clamp_uv
+ del bpy.types.Scene.udk_copy_merge
+ del bpy.types.Scene.udk_option_export
+ del bpy.types.Scene.udk_option_verbose
+ del bpy.types.Scene.udk_option_smoothing_groups
+ del bpy.types.Scene.udk_option_triangulate
+ del bpy.types.Scene.udk_option_selectanimations
+ del bpy.types.Scene.udk_option_selectobjects
+ del bpy.types.Scene.udk_option_rebuildobjects
+ del bpy.types.Scene.udk_option_ignoreactiongroupnames
+ del bpy.types.Scene.udk_option_scale
+ del bpy.types.Scene.udkas_list
+ del bpy.types.Scene.udkas_list_idx
+ del bpy.types.Scene.udkobj_list
+ del bpy.types.Scene.udkobj_list_idx
+ del bpy.types.Scene.udkmesh_list
+ del bpy.types.Scene.udkmesh_list_idx
+ del bpy.types.Scene.udkArm_list
+ del bpy.types.Scene.udkArm_list_idx
+
+
if __name__ == "__main__":
- #print("\n"*4)
print(header("UDK Export PSK/PSA 2.6", 'CENTER'))
register()
-
-#loader
-#filename = "D:/Projects/BlenderScripts/io_export_udk_psa_psk_alpha.py"
-#exec(compile(open(filename).read(), filename, 'exec'))