Skip to content
Snippets Groups Projects
io_export_unreal_psk_psa.py 58.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		final_parent_id = nbone
    		nbone = nbone + 1
    		#tail = tail-head
    		
    	my_id = nbone
    	
    	pb = make_vbone(blender_bone.name, final_parent_id, child_count, quat, set_position)
    	psk_file.AddBone(pb)
    	pbb = make_namedbonebinary(blender_bone.name, final_parent_id, child_count, quat, set_position, 1)
    	psa_file.StoreBone(pbb)
    
    	nbone = nbone + 1
    	
    	#RG - dump influences for this bone - use the data we collected in the mesh dump phase
    	# to map our bones to vertex groups
    	#print("///////////////////////")
    	#print("set influence")
    	if blender_bone.name in psk_file.VertexGroups:
    		vertex_list = psk_file.VertexGroups[blender_bone.name]
    		#print("vertex list:", len(vertex_list), " of >" ,blender_bone.name )
    		for vertex_data in vertex_list:
    			#print("set influence vettex")
    			point_index = vertex_data[0]
    			vertex_weight = vertex_data[1]
    			influence = VRawBoneInfluence()
    			influence.Weight = vertex_weight
    			influence.BoneIndex = my_id
    			influence.PointIndex = point_index
    			#print ('Adding Bone Influence for [%s] = Point Index=%i, Weight=%f' % (blender_bone.name, point_index, vertex_weight))
    			#print("adding influence")
    			psk_file.AddInfluence(influence)
    	
    	#blender_bone.matrix_local
    	#recursively dump child bones
    	mainparent = parent_matrix
    	#if len(blender_bone.children) > 0:
    	for current_child_bone in blender_bone.children:
    		parse_bone(current_child_bone, psk_file, psa_file, my_id, 0, mainparent, parent_root)
    
    
    def parse_armature(blender_armature, psk_file, psa_file):
    
    	print ("----- parsing armature -----")
    	print ('blender_armature length: %i' % (len(blender_armature)))
    	
    	#magic 0 sized root bone for UT - this is where all armature dummy bones will attach
    	#dont increment nbone here because we initialize it to 1 (hackity hackity hack)
    
    	#count top level bones first. NOT EFFICIENT.
    	child_count = 0
    	for current_obj in blender_armature: 
    		current_armature = current_obj.data
    		bones = [x for x in current_armature.bones if not x.parent is None]
    		child_count += len(bones)
    
    	for current_obj in blender_armature:
    		print ("Current Armature Name: " + current_obj.name)
    		current_armature = current_obj.data
    		#armature_id = make_armature_bone(current_obj, psk_file, psa_file)
    		
    		#we dont want children here - only the top level bones of the armature itself
    		#we will recursively dump the child bones as we dump these bones
    		"""
    		bones = [x for x in current_armature.bones if not x.parent is None]
    		#will ingore this part of the ocde
    		"""
    		for current_bone in current_armature.bones: #list the bone. #note this will list all the bones.
    			if(current_bone.parent is None):
    				parse_bone(current_bone, psk_file, psa_file, 0, 0, current_obj.matrix_local, None)
    				break
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    # get blender objects by type        
    
    	return [x for x in objects if x.type == intype]
    			
    
    #strips current extension (if any) from filename and replaces it with extension passed in
    def make_filename_ext(filename, extension):
    
    	new_filename = ''
    	extension_index = filename.find('.')
    	
    	if extension_index == -1:
    		new_filename = filename + extension
    	else:
    		new_filename = filename[0:extension_index] + extension
    		
    	return new_filename
    
    
    # returns the quaternion Grassman product a*b
    # this is the same as the rotation a(b(x)) 
    # (ie. the same as B*A if A and B are matrices representing 
    # the rotations described by quaternions a and b)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    def grassman(a, b):    
    
    	return mathutils.Quaternion(
    		a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z,
    		a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y,
    		a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x,
    		a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w)
    		
    
    def parse_animation(blender_scene, blender_armatures, psa_file):
    
    	#to do list:
    	#need to list the action sets
    	#need to check if there animation
    	#need to check if animation is has one frame then exit it
    	print ('\n----- parsing animation -----')
    	render_data = blender_scene.render
    	bHaveAction = True
    	
    	anim_rate = render_data.fps
    	
    	print("==== Blender Settings ====")
    	print ('Scene: %s Start Frame: %i, End Frame: %i' % (blender_scene.name, blender_scene.frame_start, blender_scene.frame_end))
    	print ('Frames Per Sec: %i' % anim_rate)
    	print ("Default FPS: 24" )
    	
    	cur_frame_index = 0
    	
    	if bpy.context.scene.unrealactionexportall :#if exporting all actions is ture then go do some work.
    		print("Exporting all action:",bpy.context.scene.unrealactionexportall)
    		print("[==== Action list Start====]")
    		
    		print("Number of Action set(s):",len(bpy.data.actions))
    		
    		for action in bpy.data.actions:#current number action sets
    			print("========>>>>>")
    			print("Action Name:",action.name)
    
    			#print("Groups:")
    			#for bone in action.groups:
    				#print("> Name: ",bone.name)
    
    				#print(dir(bone))
    			
    		print("[==== Action list End ====]")
    		
    		amatureobject = None #this is the armature set to none
    		bonenames = [] #bone name of the armature bones list
    		
    		for arm in blender_armatures:
    			amatureobject = arm
    			
    		print("\n[==== Armature Object ====]")
    		if amatureobject != None:
    			print("Name:",amatureobject.name)
    			print("Number of bones:", len(amatureobject.pose.bones))
    			for bone in amatureobject.pose.bones:
    				bonenames.append(bone.name)
    		print("[=========================]")
    		
    		for ActionNLA in bpy.data.actions:
    
    			print("\n==== Action Set ====")
    
    			#print("\nChecking actions matching groups with bone names...")
    
    			#Check if the bone names matches the action groups names
    			for group in ActionNLA.groups:
    				for abone in bonenames:
    					#print("name:>>",abone)
    					if abone == group.name:
    						nobone += 1
    						break
    			#if action groups matches the bones length and names matching the gourps do something
    			if (len(ActionNLA.groups) == len(bonenames)) and (nobone == len(ActionNLA.groups)):
    
    				print("Action Set match: Pass")
    
    				print("Action Set match: Fail")
    				print("Action Name:",ActionNLA.name)
    
    				baction = False
    			
    			if baction == True:
    				arm = amatureobject #set armature object
    				if not arm.animation_data:
    					print("======================================")
    					print("Check Animation Data: None")
    					print("Armature has no animation, skipping...")
    					print("======================================")
    					break
    					
    				if not arm.animation_data.action:
    					print("======================================")
    					print("Check Action: None")
    					print("Armature has no animation, skipping...")
    					print("======================================")
    					break
    				arm.animation_data.action = ActionNLA
    				act = arm.animation_data.action
    				action_name = act.name
    				
    				if not len(act.fcurves):
    					print("//===========================================================")
    					print("// None bone pose set keys for this action set... skipping...")
    					print("//===========================================================")
    					bHaveAction = False
    					
    				#this deal with action export control
    				if bHaveAction == True:
    
    					print("Action Name:",action_name)
    					#look for min and max frame that current set keys
    					framemin, framemax = act.frame_range
    					#print("max frame:",framemax)
    					start_frame = int(framemin)
    					end_frame = int(framemax)
    					scene_frames = range(start_frame, end_frame+1)
    					frame_count = len(scene_frames)
    					#===================================================
    					anim = AnimInfoBinary()
    					anim.Name = action_name
    					anim.Group = "" #what is group?
    					anim.NumRawFrames = frame_count
    					anim.AnimRate = anim_rate
    					anim.FirstRawFrame = cur_frame_index
    					#===================================================
    					count_previous_keys = len(psa_file.RawKeys.Data)
    					print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
    					#print("init action bones...")
    					unique_bone_indexes = {}
    					# bone lookup table
    					bones_lookup =  {}
    				
    					#build bone node for animation keys needed to be set
    					for bone in arm.data.bones:
    						bones_lookup[bone.name] = bone
    					#print("bone name:",bone.name)
    					frame_count = len(scene_frames)
    					#print ('Frame Count: %i' % frame_count)
    					pose_data = arm.pose
    				
    					#these must be ordered in the order the bones will show up in the PSA file!
    					ordered_bones = {}
    					ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
    					
    					#############################
    					# ORDERED FRAME, BONE
    					#for frame in scene_frames:
    					
    					for i in range(frame_count):
    						frame = scene_frames[i]
    						#LOUD
    						#print ("==== outputting frame %i ===" % frame)
    						
    						if frame_count > i+1:
    							next_frame = scene_frames[i+1]
    							#print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
    						else:
    							next_frame = -1
    							#print "This Frame: %i, Next Frame: NONE" % frame
    						
    						#frame start from 1 as number one from blender
    						blender_scene.frame_set(frame)
    						
    						cur_frame_index = cur_frame_index + 1
    						for bone_data in ordered_bones:
    							bone_index = bone_data[0]
    							pose_bone = bone_data[1]
    							#print("[=====POSE NAME:",pose_bone.name)
    							
    							#print("LENG >>.",len(bones_lookup))
    							blender_bone = bones_lookup[pose_bone.name]
    							
    							#just need the total unique bones used, later for this AnimInfoBinary
    							unique_bone_indexes[bone_index] = bone_index
    							#LOUD
    							#print ("-------------------", pose_bone.name)
    							head = pose_bone.head
    							
    							posebonemat = mathutils.Matrix(pose_bone.matrix)
    							parent_pose = pose_bone.parent
    							if parent_pose != None:
    								parentposemat = mathutils.Matrix(parent_pose.matrix)
    								#blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
    								posebonemat = parentposemat.invert() * posebonemat
    							head = posebonemat.translation_part()
    							quat = posebonemat.to_quat().normalize()
    							vkey = VQuatAnimKey()
    							vkey.Position.X = head.x
    							vkey.Position.Y = head.y
    							vkey.Position.Z = head.z
    							
    							if parent_pose != None:
    								quat = make_fquat(quat)
    							else:
    								quat = make_fquat_default(quat)
    							
    							vkey.Orientation = quat
    							#print("Head:",head)
    							#print("Orientation",quat)
    							
    							#time from now till next frame = diff / framesPerSec
    							if next_frame >= 0:
    								diff = next_frame - frame
    							else:
    								diff = 1.0
    							
    							#print ("Diff = ", diff)
    							vkey.Time = float(diff)/float(anim_rate)
    							
    							psa_file.AddRawKey(vkey)
    							
    					#done looping frames
    					#done looping armatures
    					#continue adding animInfoBinary counts here
    				
    					anim.TotalBones = len(unique_bone_indexes)
    					print("Bones Count:",anim.TotalBones)
    					anim.TrackTime = float(frame_count) / anim.AnimRate
    					print("Time Track Frame:",anim.TrackTime)
    					psa_file.AddAnimation(anim)
    		print("==== Finish Action Build(s) ====")
    	else:
    		print("Exporting one action:",bpy.context.scene.unrealactionexportall)
    		#list of armature objects
    		for arm in blender_armatures:
    			#check if there animation data from armature or something
    			
    			if not arm.animation_data:
    				print("======================================")
    				print("Check Animation Data: None")
    				print("Armature has no animation, skipping...")
    				print("======================================")
    				break
    				
    			if not arm.animation_data.action:
    				print("======================================")
    				print("Check Action: None")
    				print("Armature has no animation, skipping...")
    				print("======================================")
    				break
    			act = arm.animation_data.action
    			#print(dir(act))
    			action_name = act.name
    			
    			if not len(act.fcurves):
    				print("//===========================================================")
    				print("// None bone pose set keys for this action set... skipping...")
    				print("//===========================================================")
    				bHaveAction = False
    				
    			#this deal with action export control
    			if bHaveAction == True:
    				print("")
    				print("==== Action Set ====")
    				print("Action Name:",action_name)
    				#look for min and max frame that current set keys
    				framemin, framemax = act.frame_range
    				#print("max frame:",framemax)
    				start_frame = int(framemin)
    				end_frame = int(framemax)
    				scene_frames = range(start_frame, end_frame+1)
    				frame_count = len(scene_frames)
    				#===================================================
    				anim = AnimInfoBinary()
    				anim.Name = action_name
    				anim.Group = "" #what is group?
    				anim.NumRawFrames = frame_count
    				anim.AnimRate = anim_rate
    				anim.FirstRawFrame = cur_frame_index
    				#===================================================
    				count_previous_keys = len(psa_file.RawKeys.Data)
    				print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
    				#print("init action bones...")
    				unique_bone_indexes = {}
    				# bone lookup table
    				bones_lookup =  {}
    			
    				#build bone node for animation keys needed to be set
    				for bone in arm.data.bones:
    					bones_lookup[bone.name] = bone
    				#print("bone name:",bone.name)
    				frame_count = len(scene_frames)
    				#print ('Frame Count: %i' % frame_count)
    				pose_data = arm.pose
    			
    				#these must be ordered in the order the bones will show up in the PSA file!
    				ordered_bones = {}
    				ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
    				
    				#############################
    				# ORDERED FRAME, BONE
    				#for frame in scene_frames:
    				
    				for i in range(frame_count):
    					frame = scene_frames[i]
    					#LOUD
    					#print ("==== outputting frame %i ===" % frame)
    					
    					if frame_count > i+1:
    						next_frame = scene_frames[i+1]
    						#print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
    					else:
    						next_frame = -1
    						#print "This Frame: %i, Next Frame: NONE" % frame
    					
    					#frame start from 1 as number one from blender
    					blender_scene.frame_set(frame)
    					
    					cur_frame_index = cur_frame_index + 1
    					for bone_data in ordered_bones:
    						bone_index = bone_data[0]
    						pose_bone = bone_data[1]
    						#print("[=====POSE NAME:",pose_bone.name)
    						
    						#print("LENG >>.",len(bones_lookup))
    						blender_bone = bones_lookup[pose_bone.name]
    						
    						#just need the total unique bones used, later for this AnimInfoBinary
    						unique_bone_indexes[bone_index] = bone_index
    						#LOUD
    						#print ("-------------------", pose_bone.name)
    						head = pose_bone.head
    						
    						posebonemat = mathutils.Matrix(pose_bone.matrix)
    						parent_pose = pose_bone.parent
    						if parent_pose != None:
    							parentposemat = mathutils.Matrix(parent_pose.matrix)
    							#blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
    							posebonemat = parentposemat.invert() * posebonemat
    						head = posebonemat.translation_part()
    						quat = posebonemat.to_quat().normalize()
    						vkey = VQuatAnimKey()
    						vkey.Position.X = head.x
    						vkey.Position.Y = head.y
    						vkey.Position.Z = head.z
    						
    						if parent_pose != None:
    							quat = make_fquat(quat)
    						else:
    							quat = make_fquat_default(quat)
    						
    						vkey.Orientation = quat
    						#print("Head:",head)
    						#print("Orientation",quat)
    						
    						#time from now till next frame = diff / framesPerSec
    						if next_frame >= 0:
    							diff = next_frame - frame
    						else:
    							diff = 1.0
    						
    						#print ("Diff = ", diff)
    						vkey.Time = float(diff)/float(anim_rate)
    						
    						psa_file.AddRawKey(vkey)
    						
    				#done looping frames
    				#done looping armatures
    				#continue adding animInfoBinary counts here
    			
    				anim.TotalBones = len(unique_bone_indexes)
    				print("Bones Count:",anim.TotalBones)
    				anim.TrackTime = float(frame_count) / anim.AnimRate
    				print("Time Track Frame:",anim.TrackTime)
    				psa_file.AddAnimation(anim)
    				print("==== Finish Action Build(s) ====")
    	
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    exportmessage = "Export Finish"        
    
    def fs_callback(filename, context):
    
    	#this deal with repeat export and the reset settings
    	global bonedata, BBCount, nbone, exportmessage
    	bonedata = []#clear array
    	BBCount = 0
    	nbone = 0
    	
    	start_time = time.clock()
    	
    	print ("========EXPORTING TO UNREAL SKELETAL MESH FORMATS========\r\n")
    	print("Blender Version:", bpy.app.version_string)
    	
    	psk = PSKFile()
    	psa = PSAFile()
    	
    	#sanity check - this should already have the extension, but just in case, we'll give it one if it doesn't
    	psk_filename = make_filename_ext(filename, '.psk')
    	
    	#make the psa filename
    	psa_filename = make_filename_ext(filename, '.psa')
    	
    	print ('PSK File: ' +  psk_filename)
    	print ('PSA File: ' +  psa_filename)
    	
    	barmature = True
    	bmesh = True
    	blender_meshes = []
    	blender_armature = []
    	selectmesh = []
    	selectarmature = []
    	
    	current_scene = context.scene
    	cur_frame = current_scene.frame_current #store current frame before we start walking them during animation parse
    	objects = current_scene.objects
    	
    	print("Checking object count...")
    	for next_obj in objects:
    		if next_obj.type == 'MESH':
    			blender_meshes.append(next_obj)
    			if (next_obj.select):
    				#print("mesh object select")
    				selectmesh.append(next_obj)
    		if next_obj.type == 'ARMATURE':
    			blender_armature.append(next_obj)
    			if (next_obj.select):
    				#print("armature object select")
    				selectarmature.append(next_obj)
    	
    	print("Mesh Count:",len(blender_meshes)," Armature Count:",len(blender_armature))
    	print("====================================")
    	print("Checking Mesh Condtion(s):")
    	if len(blender_meshes) == 1:
    		print(" - One Mesh Scene")
    	elif (len(blender_meshes) > 1) and (len(selectmesh) == 1):
    		print(" - One Mesh [Select]")
    	else:
    		print(" - Too Many Meshes!")
    		print(" - Select One Mesh Object!")
    		bmesh = False
    	print("====================================")
    	print("Checking Armature Condtion(s):")
    	if len(blender_armature) == 1:
    		print(" - One Armature Scene")
    	elif (len(blender_armature) > 1) and (len(selectarmature) == 1):
    		print(" - One Armature [Select]")
    	else:
    		print(" - Too Armature Meshes!")
    		print(" - Select One Armature Object Only!")
    		barmature = False
    	
    	if     (bmesh == False) or (barmature == False):
    		exportmessage = "Export Fail! Check Log."
    		print("=================================")
    		print("= Export Fail!                  =")
    		print("=================================")
    	else:
    		exportmessage = "Export Finish!"
    		#need to build a temp bone index for mesh group vertex
    		BoneIndexArmature(blender_armature)
    
    		try:
    			#######################
    			# STEP 1: MESH DUMP
    			# we build the vertexes, wedges, and faces in here, as well as a vertexgroup lookup table
    			# for the armature parse
    			print("//===============================")
    			print("// STEP 1")
    			print("//===============================")
    			parse_meshes(blender_meshes, psk)
    		except:
    			context.scene.frame_set(cur_frame) #set frame back to original frame
    			print ("Exception during Mesh Parse")
    			raise
    		
    		try:
    			#######################
    			# STEP 2: ARMATURE DUMP
    			# IMPORTANT: do this AFTER parsing meshes - we need to use the vertex group data from 
    			# the mesh parse in here to generate bone influences
    			print("//===============================")
    			print("// STEP 2")
    			print("//===============================")
    			parse_armature(blender_armature, psk, psa) 
    			
    		except:
    			context.scene.frame_set(cur_frame) #set frame back to original frame
    			print ("Exception during Armature Parse")
    			raise
    
    		try:
    			#######################
    			# STEP 3: ANIMATION DUMP
    			# IMPORTANT: do AFTER parsing bones - we need to do bone lookups in here during animation frames
    			print("//===============================")
    			print("// STEP 3")
    			print("//===============================")
    			parse_animation(current_scene, blender_armature, psa) 
    			
    		except:
    			context.scene.frame_set(cur_frame) #set frame back to original frame
    			print ("Exception during Animation Parse")
    			raise
    
    		# reset current frame
    		
    		context.scene.frame_set(cur_frame) #set frame back to original frame
    		
    		##########################
    		# FILE WRITE
    		print("//===========================================")
    		print("// bExportPsk:",bpy.context.scene.unrealexportpsk," bExportPsa:",bpy.context.scene.unrealexportpsa)
    		print("//===========================================")
    		if bpy.context.scene.unrealexportpsk == True:
    			print("Writing Skeleton Mesh Data...")
    			#RG - dump psk file
    			psk.PrintOut()
    			file = open(psk_filename, "wb") 
    			file.write(psk.dump())
    			file.close() 
    			print ("Successfully Exported File: " + psk_filename)
    		if bpy.context.scene.unrealexportpsa == True:
    			print("Writing Animaiton Data...")
    			#RG - dump psa file
    			if not psa.IsEmpty():
    				psa.PrintOut()
    				file = open(psa_filename, "wb") 
    				file.write(psa.dump())
    				file.close() 
    				print ("Successfully Exported File: " + psa_filename)
    			else:
    				print ("No Animations (.psa file) to Export")
    
    		print ('PSK/PSA Export Script finished in %.2f seconds' % (time.clock() - start_time))
    		print( "Current Script version: ",bl_addon_info['version'])
    		#MSG BOX EXPORT COMPLETE
    		#...
    
    		#DONE
    		print ("PSK/PSA Export Complete")
    
    	print("//============================")
    	print("// running psk/psa export...")
    	print("//============================")
    
    
    from bpy.props import *
    
    exporttypedata = []
    
    # [index,text field,0] #or something like that
    exporttypedata.append(("0","PSK","Export PSK"))
    exporttypedata.append(("1","PSA","Export PSA"))
    exporttypedata.append(("2","ALL","Export ALL"))
    
    
    bpy.types.Scene.unrealfpsrate = IntProperty(
    
    	name="fps rate",
    	description="Set the frame per second (fps) for unreal.",
    	default=24,min=1,max=100)
    	
    
    bpy.types.Scene.unrealexport_settings = EnumProperty(
    
    	name="Export:",
    	description="Select a export settings (psk/psa/all)...",
    	items = exporttypedata, default = '0')
    		
    
    bpy.types.Scene.unrealtriangulatebool = BoolProperty(
    
    	name="Triangulate Mesh",
    	description="Convert Quad to Tri Mesh Boolean...",
    	default=False)
    	
    
    bpy.types.Scene.unrealactionexportall = BoolProperty(
    
    	name="All Actions",
    	description="This let you export all the actions from current armature that matches bone name in action groups names.",
    	default=False)    
    	
    
    bpy.types.Scene.unrealexportpsk = BoolProperty(
    
    	name="bool export psa",
    	description="bool for exporting this psk format",
    	default=False)
    	
    
    bpy.types.Scene.unrealexportpsa = BoolProperty(
    
    	name="bool export psa",
    	description="bool for exporting this psa format",
    	default=False)
    
    	global exportmessage
    	'''Export Skeleton Mesh / Animation Data file(s)'''
    	bl_idname = "export.udk_anim_data" # this is important since its how bpy.ops.export.udk_anim_data is constructed
    	bl_label = "Export PSK/PSA"
    	__doc__ = "One mesh and one armature else select one mesh or armature to be exported."
    
    	# List of operator properties, the attributes will be assigned
    	# to the class instance from the operator settings before calling.
    
    
    	filepath = StringProperty(name="File Path", description="Filepath used for exporting the PSA file", maxlen= 1024, default= "", subtype='FILE_PATH')
    
    	pskexportbool = BoolProperty(name="Export PSK", description="Export Skeletal Mesh", default= True)
    	psaexportbool = BoolProperty(name="Export PSA", description="Export Action Set (Animation Data)", default= True)
    	actionexportall = BoolProperty(name="All Actions", description="This will export all the actions that matches the current armature.", default=False)
    
    	@classmethod
    	def poll(cls, context):
    		return context.active_object != None
    
    	def execute(self, context):
    		#check if  skeleton mesh is needed to be exported
    		if (self.pskexportbool):
    			bpy.context.scene.unrealexportpsk = True
    		else:
    			bpy.context.scene.unrealexportpsk = False
    		#check if  animation data is needed to be exported
    		if (self.psaexportbool):
    			bpy.context.scene.unrealexportpsa = True
    		else:
    			bpy.context.scene.unrealexportpsa = False
    			
    
    		if (self.actionexportall):
    			bpy.context.scene.unrealactionexportall = True
    		else:
    			bpy.context.scene.unrealactionexportall = False
    		
    		write_data(self.filepath, context)
    
    		
    		self.report({'WARNING', 'INFO'}, exportmessage)
    		return {'FINISHED'}
    		
    	def invoke(self, context, event):
    		wm = context.window_manager
    		wm.add_fileselect(self)
    		return {'RUNNING_MODAL'}
    
    class VIEW3D_PT_unrealtools_objectmode(bpy.types.Panel):
    
    	bl_space_type = "VIEW_3D"
    	bl_region_type = "TOOLS"
    	bl_label = "Unreal Tools"
    	
    	@classmethod
    	def poll(cls, context):
    		return context.active_object
    
    	def draw(self, context):
    		layout = self.layout
    		rd = context.scene
    
    		layout.prop(rd, "unrealexport_settings",expand=True)		
    		layout.operator("object.UnrealExport")#button
    
    		#FPS #it use the real data from your scene
    		layout.prop(rd.render, "fps")
    		
    		layout.prop(rd, "unrealactionexportall")
    		#row = layout.row()
    		#row.label(text="Action Set(s)(not build)")
    		#for action in  bpy.data.actions:
    			#print(dir( action))
    			#print(action.frame_range)
    			#row = layout.row()
    			#row.prop(action, "name")
    			
    			#print(dir(action.groups[0]))
    			#for g in action.groups:#those are bones
    				#print("group...")
    				#print(dir(g))
    				#print("////////////")
    				#print((g.name))
    				#print("////////////")
    			
    			#row.label(text="Active:" + action.select)
    		btrimesh = False
    		
    
    class OBJECT_OT_UnrealExport(bpy.types.Operator):
    
    	global exportmessage
    	bl_idname = "OBJECT_OT_UnrealExport"
    	bl_label = "Unreal Export"
    	__doc__ = "Select export setting for .psk/.psa or both."
    	
    	def invoke(self, context, event):
    		print("Init Export Script:")
    		if(int(bpy.context.scene.unrealexport_settings) == 0):
    			bpy.context.scene.unrealexportpsk = True
    			bpy.context.scene.unrealexportpsa = False
    			print("Exporting PSK...")
    		if(int(bpy.context.scene.unrealexport_settings) == 1):
    			bpy.context.scene.unrealexportpsk = False
    			bpy.context.scene.unrealexportpsa = True
    			print("Exporting PSA...")
    		if(int(bpy.context.scene.unrealexport_settings) == 2):
    			bpy.context.scene.unrealexportpsk = True
    			bpy.context.scene.unrealexportpsa = True
    			print("Exporting ALL...")
    
    		default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
    
    		fs_callback(default_path, bpy.context)
    
    		
    		#self.report({'WARNING', 'INFO'}, exportmessage)
    		self.report({'INFO'}, exportmessage)
    		return{'FINISHED'}    
    
    	bpy.context.scene.unrealexportpsk = True
    	bpy.context.scene.unrealexportpsa = True
    	default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
    	self.layout.operator("export.udk_anim_data", text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
    
    	bpy.types.INFO_MT_file_export.append(menu_func)
    
    	bpy.types.INFO_MT_file_export.remove(menu_func)