1
0
mirror of https://github.com/DarklightGames/io_scene_psk_psa.git synced 2024-11-15 02:37:39 +01:00

Action selection now works in the PSA exporter, and actions that likely correspond to the selected armature are deselected by default (will save a bit of time!)

This commit is contained in:
Colin Basnett 2019-12-12 15:07:22 -08:00
parent d13cd881a4
commit 3001501006
3 changed files with 51 additions and 10 deletions

View File

@ -42,12 +42,15 @@ classes = [
psa_operator.ActionListItem psa_operator.ActionListItem
] ]
def psk_menu_func(self, context): def psk_menu_func(self, context):
self.layout.operator(psk_operator.PskExportOperator.bl_idname, text ='Unreal PSK (.psk)') self.layout.operator(psk_operator.PskExportOperator.bl_idname, text ='Unreal PSK (.psk)')
def psa_menu_func(self, context): def psa_menu_func(self, context):
self.layout.operator(psa_operator.PsaExportOperator.bl_idname, text='Unreal PSA (.psa)') self.layout.operator(psa_operator.PsaExportOperator.bl_idname, text='Unreal PSA (.psa)')
def register(): def register():
from bpy.utils import register_class from bpy.utils import register_class
for cls in classes: for cls in classes:
@ -57,6 +60,7 @@ def register():
bpy.types.Scene.psa_action_list = CollectionProperty(type=psa_operator.ActionListItem) bpy.types.Scene.psa_action_list = CollectionProperty(type=psa_operator.ActionListItem)
bpy.types.Scene.psa_action_list_index = IntProperty(name='index for list??', default=0) bpy.types.Scene.psa_action_list_index = IntProperty(name='index for list??', default=0)
def unregister(): def unregister():
del bpy.types.Scene.psa_action_list_index del bpy.types.Scene.psa_action_list_index
del bpy.types.Scene.psa_action_list del bpy.types.Scene.psa_action_list
@ -66,5 +70,6 @@ def unregister():
for cls in reversed(classes): for cls in reversed(classes):
unregister_class(cls) unregister_class(cls)
if __name__ == '__main__': if __name__ == '__main__':
register() register()

View File

@ -3,13 +3,18 @@ import mathutils
from .data import * from .data import *
class PsaBuilderOptions(object):
def __init__(self):
self.actions = []
# https://git.cth451.me/cth451/blender-addons/blob/master/io_export_unreal_psk_psa.py # https://git.cth451.me/cth451/blender-addons/blob/master/io_export_unreal_psk_psa.py
class PsaBuilder(object): class PsaBuilder(object):
def __init__(self): def __init__(self):
# TODO: add options in here (selected anims, eg.) # TODO: add options in here (selected anims, eg.)
pass pass
def build(self, context) -> Psa: def build(self, context, options) -> Psa:
object = context.view_layer.objects.active object = context.view_layer.objects.active
if object.type != 'ARMATURE': if object.type != 'ARMATURE':
@ -70,7 +75,7 @@ class PsaBuilder(object):
print('---- ACTIONS ----') print('---- ACTIONS ----')
frame_start_index = 0 frame_start_index = 0
for action in bpy.data.actions: for action in options.actions:
if len(action.fcurves) == 0: if len(action.fcurves) == 0:
continue continue

View File

@ -1,7 +1,7 @@
from bpy.types import Operator, Action, UIList, PropertyGroup from bpy.types import Operator, Action, UIList, PropertyGroup
from bpy_extras.io_utils import ExportHelper from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, FloatProperty, CollectionProperty, PointerProperty from bpy.props import StringProperty, BoolProperty, FloatProperty, CollectionProperty, PointerProperty
from .builder import PsaBuilder from .builder import PsaBuilder, PsaBuilderOptions
from .exporter import PsaExporter from .exporter import PsaExporter
import bpy import bpy
import re import re
@ -20,7 +20,7 @@ class PSA_UL_ActionList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.alignment = 'LEFT' layout.alignment = 'LEFT'
layout.prop(item, 'is_selected', icon_only=True) layout.prop(item, 'is_selected', icon_only=True)
layout.label(text=item.action.name, icon='ACTION') layout.label(text=item.action.name)
def filter_items(self, context, data, property): def filter_items(self, context, data, property):
# TODO: returns two lists, apparently # TODO: returns two lists, apparently
@ -44,30 +44,61 @@ class PsaExportOperator(Operator, ExportHelper):
maxlen=1024, maxlen=1024,
default='') default='')
def __init__(self):
self.armature = None
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
scene = context.scene scene = context.scene
row = layout.row() box = layout.box()
row.label(text='Actions') box.label(text='Actions', icon='ACTION')
row = layout.row() row = box.row()
row.template_list('PSA_UL_ActionList', 'asd', scene, 'psa_action_list', scene, 'psa_action_list_index', rows=len(context.scene.psa_action_list)) row.template_list('PSA_UL_ActionList', 'asd', scene, 'psa_action_list', scene, 'psa_action_list_index', rows=len(context.scene.psa_action_list))
def is_action_for_armature(self, action):
bone_names = [x.name for x in self.armature.data.bones]
print(bone_names)
for fcurve in action.fcurves:
match = re.match('pose\.bones\["(.+)"\].\w+', fcurve.data_path)
if not match:
continue
bone_name = match.group(1)
if bone_name not in bone_names:
return False
return True
def invoke(self, context, event): def invoke(self, context, event):
if context.view_layer.objects.active.type != 'ARMATURE': if context.view_layer.objects.active.type != 'ARMATURE':
self.report({'ERROR_INVALID_CONTEXT'}, 'The selected object must be an armature.') self.report({'ERROR_INVALID_CONTEXT'}, 'The selected object must be an armature.')
return {'CANCELLED'} return {'CANCELLED'}
self.armature = context.view_layer.objects.active
context.scene.psa_action_list.clear() context.scene.psa_action_list.clear()
for action in bpy.data.actions: for action in bpy.data.actions:
item = context.scene.psa_action_list.add() item = context.scene.psa_action_list.add()
item.action = action item.action = action
# TODO: add if self.is_action_for_armature(action):
item.is_selected = True item.is_selected = True
if len(context.scene.psa_action_list) == 0:
self.report({'ERROR_INVALID_CONTEXT'}, 'There are no actions to export.')
return {'CANCELLED'}
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def execute(self, context): def execute(self, context):
actions = [x.action for x in context.scene.psa_action_list if x.is_selected]
if len(actions) == 0:
self.report({'ERROR_INVALID_CONTEXT'}, 'No actions were selected for export.')
return {'CANCELLED'}
options = PsaBuilderOptions()
options.actions = actions
builder = PsaBuilder() builder = PsaBuilder()
psk = builder.build(context) psk = builder.build(context, options)
exporter = PsaExporter(psk) exporter = PsaExporter(psk)
exporter.export(self.filepath) exporter.export(self.filepath)
return {'FINISHED'} return {'FINISHED'}