mirror of
https://github.com/DarklightGames/io_scene_psk_psa.git
synced 2025-02-22 03:59:29 +01:00
Unified handling of translating bpy PSK options to the options passed into the build function
Also fixed a bug where the normal export operator was exporting duplicate objects
This commit is contained in:
parent
ff5ded004a
commit
c1d5a2229d
@ -1,24 +1,23 @@
|
||||
from typing import List, Optional, cast
|
||||
from typing import List, Optional, cast, Iterable
|
||||
|
||||
import bpy
|
||||
from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty, CollectionProperty, IntProperty
|
||||
from bpy.types import Operator, Context, Object, Collection, SpaceProperties
|
||||
from bpy.props import StringProperty
|
||||
from bpy.types import Operator, Context, Object, Collection, SpaceProperties, Depsgraph, Material
|
||||
from bpy_extras.io_utils import ExportHelper
|
||||
|
||||
from .properties import object_eval_state_items, export_space_items
|
||||
from .properties import add_psk_export_properties
|
||||
from ..builder import build_psk, PskBuildOptions, get_psk_input_objects_for_context, \
|
||||
get_psk_input_objects_for_collection
|
||||
from ..writer import write_psk
|
||||
from ...shared.data import bone_filter_mode_items
|
||||
from ...shared.helpers import populate_bone_collection_list
|
||||
from ...shared.types import PSX_PG_bone_collection_list_item
|
||||
from ...shared.ui import draw_bone_filter_mode
|
||||
|
||||
|
||||
def get_materials_for_mesh_objects(mesh_objects: List[Object]):
|
||||
def get_materials_for_mesh_objects(depsgraph: Depsgraph, mesh_objects: Iterable[Object]):
|
||||
materials = []
|
||||
for mesh_object in mesh_objects:
|
||||
for i, material_slot in enumerate(mesh_object.material_slots):
|
||||
evaluated_mesh_object = mesh_object.evaluated_get(depsgraph)
|
||||
for i, material_slot in enumerate(evaluated_mesh_object.material_slots):
|
||||
material = material_slot.material
|
||||
if material is None:
|
||||
raise RuntimeError('Material slot cannot be empty (index ' + str(i) + ')')
|
||||
@ -27,12 +26,12 @@ def get_materials_for_mesh_objects(mesh_objects: List[Object]):
|
||||
return materials
|
||||
|
||||
|
||||
def populate_material_list(mesh_objects, material_list):
|
||||
materials = get_materials_for_mesh_objects(mesh_objects)
|
||||
def populate_material_name_list(depsgraph: Depsgraph, mesh_objects, material_list):
|
||||
materials = get_materials_for_mesh_objects(depsgraph, mesh_objects)
|
||||
material_list.clear()
|
||||
for index, material in enumerate(materials):
|
||||
m = material_list.add()
|
||||
m.material = material
|
||||
m.material_name = material.name
|
||||
m.index = index
|
||||
|
||||
|
||||
@ -79,6 +78,27 @@ class PSK_OT_populate_bone_collection_list(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PSK_OT_populate_material_name_list(Operator):
|
||||
bl_idname = 'psk_export.populate_material_name_list'
|
||||
bl_label = 'Populate Material Name List'
|
||||
bl_description = 'Populate the material name list from the objects that will be used in this export'
|
||||
bl_options = {'INTERNAL'}
|
||||
|
||||
def execute(self, context):
|
||||
export_operator = get_collection_export_operator_from_context(context)
|
||||
if export_operator is None:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, 'No valid export operator found in context')
|
||||
return {'CANCELLED'}
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
input_objects = get_psk_input_objects_for_collection(context.collection)
|
||||
try:
|
||||
populate_material_name_list(depsgraph, [x.obj for x in input_objects.mesh_objects], export_operator.material_name_list)
|
||||
except RuntimeError as e:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, str(e))
|
||||
return {'CANCELLED'}
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PSK_OT_material_list_move_up(Operator):
|
||||
bl_idname = 'psk_export.material_list_item_move_up'
|
||||
bl_label = 'Move Up'
|
||||
@ -88,12 +108,12 @@ class PSK_OT_material_list_move_up(Operator):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
pg = getattr(context.scene, 'psk_export')
|
||||
return pg.material_list_index > 0
|
||||
return pg.material_name_list_index > 0
|
||||
|
||||
def execute(self, context):
|
||||
pg = getattr(context.scene, 'psk_export')
|
||||
pg.material_list.move(pg.material_list_index, pg.material_list_index - 1)
|
||||
pg.material_list_index -= 1
|
||||
pg.material_name_list.move(pg.material_name_list_index, pg.material_name_list_index - 1)
|
||||
pg.material_name_list_index -= 1
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@ -106,47 +126,97 @@ class PSK_OT_material_list_move_down(Operator):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
pg = getattr(context.scene, 'psk_export')
|
||||
return pg.material_list_index < len(pg.material_list) - 1
|
||||
return pg.material_name_list_index < len(pg.material_name_list) - 1
|
||||
|
||||
def execute(self, context):
|
||||
pg = getattr(context.scene, 'psk_export')
|
||||
pg.material_list.move(pg.material_list_index, pg.material_list_index + 1)
|
||||
pg.material_list_index += 1
|
||||
pg.material_name_list.move(pg.material_name_list_index, pg.material_name_list_index + 1)
|
||||
pg.material_name_list_index += 1
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PSK_OT_material_list_name_move_up(Operator):
|
||||
bl_idname = 'psk_export.material_name_list_item_move_up'
|
||||
bl_label = 'Move Up'
|
||||
bl_options = {'INTERNAL'}
|
||||
bl_description = 'Move the selected material name up one slot'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
export_operator = get_collection_export_operator_from_context(context)
|
||||
if export_operator is None:
|
||||
return False
|
||||
return export_operator.material_name_list_index > 0
|
||||
|
||||
def execute(self, context):
|
||||
export_operator = get_collection_export_operator_from_context(context)
|
||||
if export_operator is None:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, 'No valid export operator found in context')
|
||||
return {'CANCELLED'}
|
||||
export_operator.material_name_list.move(export_operator.material_name_list_index, export_operator.material_name_list_index - 1)
|
||||
export_operator.material_name_list_index -= 1
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PSK_OT_material_list_name_move_down(Operator):
|
||||
bl_idname = 'psk_export.material_name_list_item_move_down'
|
||||
bl_label = 'Move Down'
|
||||
bl_options = {'INTERNAL'}
|
||||
bl_description = 'Move the selected material name down one slot'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
export_operator = get_collection_export_operator_from_context(context)
|
||||
if export_operator is None:
|
||||
return False
|
||||
return export_operator.material_name_list_index < len(export_operator.material_name_list) - 1
|
||||
|
||||
def execute(self, context):
|
||||
export_operator = get_collection_export_operator_from_context(context)
|
||||
if export_operator is None:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, 'No valid export operator found in context')
|
||||
return {'CANCELLED'}
|
||||
export_operator.material_name_list.move(export_operator.material_name_list_index, export_operator.material_name_list_index + 1)
|
||||
export_operator.material_name_list_index += 1
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
empty_set = set()
|
||||
|
||||
axis_identifiers = ('X', 'Y', 'Z', '-X', '-Y', '-Z')
|
||||
|
||||
forward_items = (
|
||||
('X', 'X Forward', ''),
|
||||
('Y', 'Y Forward', ''),
|
||||
('Z', 'Z Forward', ''),
|
||||
('-X', '-X Forward', ''),
|
||||
('-Y', '-Y Forward', ''),
|
||||
('-Z', '-Z Forward', ''),
|
||||
)
|
||||
|
||||
up_items = (
|
||||
('X', 'X Up', ''),
|
||||
('Y', 'Y Up', ''),
|
||||
('Z', 'Z Up', ''),
|
||||
('-X', '-X Up', ''),
|
||||
('-Y', '-Y Up', ''),
|
||||
('-Z', '-Z Up', ''),
|
||||
)
|
||||
|
||||
def forward_axis_update(self, context):
|
||||
if self.forward_axis == self.up_axis:
|
||||
# Automatically set the up axis to the next available axis
|
||||
self.up_axis = next((axis for axis in axis_identifiers if axis != self.forward_axis), 'Z')
|
||||
def get_sorted_materials_by_names(materials: Iterable[Material], material_names: List[str]) -> List[Material]:
|
||||
"""
|
||||
Sorts the materials by the order of the material names list. Any materials not in the list will be appended to the
|
||||
end of the list in the order they are found.
|
||||
@param materials: A list of materials to sort
|
||||
@param material_names: A list of material names to sort by
|
||||
@return: A sorted list of materials
|
||||
"""
|
||||
materials_in_collection = [m for m in materials if m.name in material_names]
|
||||
materials_not_in_collection = [m for m in materials if m.name not in material_names]
|
||||
materials_in_collection = sorted(materials_in_collection, key=lambda x: material_names.index(x.name))
|
||||
return materials_in_collection + materials_not_in_collection
|
||||
|
||||
|
||||
def up_axis_update(self, context):
|
||||
if self.up_axis == self.forward_axis:
|
||||
# Automatically set the forward axis to the next available axis
|
||||
self.forward_axis = next((axis for axis in axis_identifiers if axis != self.up_axis), 'X')
|
||||
def get_psk_build_options_from_property_group(mesh_objects: Iterable[Object], pg: 'PSK_PG_export', depsgraph: Optional[Depsgraph] = None) -> PskBuildOptions:
|
||||
if depsgraph is None:
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
|
||||
options = PskBuildOptions()
|
||||
options.object_eval_state = pg.object_eval_state
|
||||
options.export_space = pg.export_space
|
||||
options.bone_filter_mode = pg.bone_filter_mode
|
||||
options.bone_collection_indices = [x.index for x in pg.bone_collection_list if x.is_selected]
|
||||
options.scale = pg.scale
|
||||
options.forward_axis = pg.forward_axis
|
||||
options.up_axis = pg.up_axis
|
||||
|
||||
# TODO: perhaps move this into the build function and replace the materials list with a material names list.
|
||||
materials = get_materials_for_mesh_objects(depsgraph, mesh_objects)
|
||||
options.materials = get_sorted_materials_by_names(materials, [m.material_name for m in pg.material_name_list])
|
||||
|
||||
return options
|
||||
|
||||
|
||||
class PSK_OT_export_collection(Operator, ExportHelper):
|
||||
bl_idname = 'export.psk_collection'
|
||||
@ -162,50 +232,6 @@ class PSK_OT_export_collection(Operator, ExportHelper):
|
||||
subtype='FILE_PATH')
|
||||
collection: StringProperty(options={'HIDDEN'})
|
||||
|
||||
object_eval_state: EnumProperty(
|
||||
items=object_eval_state_items,
|
||||
name='Object Evaluation State',
|
||||
default='EVALUATED'
|
||||
)
|
||||
should_exclude_hidden_meshes: BoolProperty(
|
||||
default=False,
|
||||
name='Visible Only',
|
||||
description='Export only visible meshes'
|
||||
)
|
||||
scale: FloatProperty(
|
||||
name='Scale',
|
||||
default=1.0,
|
||||
description='Scale factor to apply to the exported mesh and armature',
|
||||
min=0.0001,
|
||||
soft_max=100.0
|
||||
)
|
||||
export_space: EnumProperty(
|
||||
name='Export Space',
|
||||
description='Space to export the mesh in',
|
||||
items=export_space_items,
|
||||
default='WORLD'
|
||||
)
|
||||
bone_filter_mode: EnumProperty(
|
||||
name='Bone Filter',
|
||||
options=empty_set,
|
||||
description='',
|
||||
items=bone_filter_mode_items,
|
||||
)
|
||||
bone_collection_list: CollectionProperty(type=PSX_PG_bone_collection_list_item)
|
||||
bone_collection_list_index: IntProperty(default=0)
|
||||
forward_axis: EnumProperty(
|
||||
name='Forward',
|
||||
items=forward_items,
|
||||
default='X',
|
||||
update=forward_axis_update
|
||||
)
|
||||
up_axis: EnumProperty(
|
||||
name='Up',
|
||||
items=up_items,
|
||||
default='Z',
|
||||
update=up_axis_update
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
collection = bpy.data.collections.get(self.collection)
|
||||
|
||||
@ -215,15 +241,7 @@ class PSK_OT_export_collection(Operator, ExportHelper):
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, str(e))
|
||||
return {'CANCELLED'}
|
||||
|
||||
options = PskBuildOptions()
|
||||
options.object_eval_state = self.object_eval_state
|
||||
options.materials = get_materials_for_mesh_objects([x.obj for x in input_objects.mesh_objects])
|
||||
options.scale = self.scale
|
||||
options.export_space = self.export_space
|
||||
options.bone_filter_mode = self.bone_filter_mode
|
||||
options.bone_collection_indices = [x.index for x in self.bone_collection_list if x.is_selected]
|
||||
options.forward_axis = self.forward_axis
|
||||
options.up_axis = self.up_axis
|
||||
options = get_psk_build_options_from_property_group([x.obj for x in input_objects.mesh_objects], self)
|
||||
|
||||
try:
|
||||
result = build_psk(context, input_objects, options)
|
||||
@ -261,12 +279,25 @@ class PSK_OT_export_collection(Operator, ExportHelper):
|
||||
bones_header, bones_panel = layout.panel('Bones', default_closed=False)
|
||||
bones_header.label(text='Bones', icon='BONE_DATA')
|
||||
if bones_panel:
|
||||
bones_panel.operator(PSK_OT_populate_bone_collection_list.bl_idname, icon='FILE_REFRESH')
|
||||
draw_bone_filter_mode(bones_panel, self)
|
||||
if self.bone_filter_mode == 'BONE_COLLECTIONS':
|
||||
bones_panel.operator(PSK_OT_populate_bone_collection_list.bl_idname, icon='FILE_REFRESH')
|
||||
rows = max(3, min(len(self.bone_collection_list), 10))
|
||||
bones_panel.template_list('PSX_UL_bone_collection_list', '', self, 'bone_collection_list', self, 'bone_collection_list_index', rows=rows)
|
||||
|
||||
# MATERIALS
|
||||
materials_header, materials_panel = layout.panel('Materials', default_closed=False)
|
||||
materials_header.label(text='Materials', icon='MATERIAL')
|
||||
|
||||
if materials_panel:
|
||||
materials_panel.operator(PSK_OT_populate_material_name_list.bl_idname, icon='FILE_REFRESH')
|
||||
rows = max(3, min(len(self.material_name_list), 10))
|
||||
row = materials_panel.row()
|
||||
row.template_list('PSK_UL_material_names', '', self, 'material_name_list', self, 'material_name_list_index', rows=rows)
|
||||
col = row.column(align=True)
|
||||
col.operator(PSK_OT_material_list_name_move_up.bl_idname, text='', icon='TRIA_UP')
|
||||
col.operator(PSK_OT_material_list_name_move_down.bl_idname, text='', icon='TRIA_DOWN')
|
||||
|
||||
# TRANSFORM
|
||||
transform_header, transform_panel = layout.panel('Transform', default_closed=False)
|
||||
transform_header.label(text='Transform')
|
||||
@ -280,6 +311,11 @@ class PSK_OT_export_collection(Operator, ExportHelper):
|
||||
flow.prop(self, 'up_axis')
|
||||
|
||||
|
||||
|
||||
add_psk_export_properties(PSK_OT_export_collection)
|
||||
|
||||
|
||||
|
||||
class PSK_OT_export(Operator, ExportHelper):
|
||||
bl_idname = 'export.psk'
|
||||
bl_label = 'Export'
|
||||
@ -287,7 +323,6 @@ class PSK_OT_export(Operator, ExportHelper):
|
||||
bl_description = 'Export mesh and armature to PSK'
|
||||
filename_ext = '.psk'
|
||||
filter_glob: StringProperty(default='*.psk', options={'HIDDEN'})
|
||||
|
||||
filepath: StringProperty(
|
||||
name='File Path',
|
||||
description='File path used for exporting the PSK file',
|
||||
@ -309,8 +344,10 @@ class PSK_OT_export(Operator, ExportHelper):
|
||||
|
||||
populate_bone_collection_list(input_objects.armature_object, pg.bone_collection_list)
|
||||
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
|
||||
try:
|
||||
populate_material_list([x.obj for x in input_objects.mesh_objects], pg.material_list)
|
||||
populate_material_name_list(depsgraph, [x.obj for x in input_objects.mesh_objects], pg.material_name_list)
|
||||
except RuntimeError as e:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, str(e))
|
||||
return {'CANCELLED'}
|
||||
@ -349,7 +386,7 @@ class PSK_OT_export(Operator, ExportHelper):
|
||||
if materials_panel:
|
||||
row = materials_panel.row()
|
||||
rows = max(3, min(len(pg.bone_collection_list), 10))
|
||||
row.template_list('PSK_UL_materials', '', pg, 'material_list', pg, 'material_list_index', rows=rows)
|
||||
row.template_list('PSK_UL_material_names', '', pg, 'material_name_list', pg, 'material_name_list_index', rows=rows)
|
||||
col = row.column(align=True)
|
||||
col.operator(PSK_OT_material_list_move_up.bl_idname, text='', icon='TRIA_UP')
|
||||
col.operator(PSK_OT_material_list_move_down.bl_idname, text='', icon='TRIA_DOWN')
|
||||
@ -358,15 +395,8 @@ class PSK_OT_export(Operator, ExportHelper):
|
||||
pg = getattr(context.scene, 'psk_export')
|
||||
|
||||
input_objects = get_psk_input_objects_for_context(context)
|
||||
options = get_psk_build_options_from_property_group([x.obj for x in input_objects.mesh_objects], pg)
|
||||
|
||||
options = PskBuildOptions()
|
||||
options.bone_filter_mode = pg.bone_filter_mode
|
||||
options.bone_collection_indices = [x.index for x in pg.bone_collection_list if x.is_selected]
|
||||
options.object_eval_state = pg.object_eval_state
|
||||
options.materials = [m.material for m in pg.material_list]
|
||||
options.scale = pg.scale
|
||||
options.export_space = pg.export_space
|
||||
|
||||
try:
|
||||
result = build_psk(context, input_objects, options)
|
||||
for warning in result.warnings:
|
||||
@ -379,7 +409,7 @@ class PSK_OT_export(Operator, ExportHelper):
|
||||
except RuntimeError as e:
|
||||
self.report({'ERROR_INVALID_CONTEXT'}, str(e))
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@ -389,4 +419,7 @@ classes = (
|
||||
PSK_OT_export,
|
||||
PSK_OT_export_collection,
|
||||
PSK_OT_populate_bone_collection_list,
|
||||
PSK_OT_populate_material_name_list,
|
||||
PSK_OT_material_list_name_move_up,
|
||||
PSK_OT_material_list_name_move_down,
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
from bpy.props import EnumProperty, CollectionProperty, IntProperty, PointerProperty, FloatProperty
|
||||
from bpy.props import EnumProperty, CollectionProperty, IntProperty, PointerProperty, FloatProperty, StringProperty, \
|
||||
BoolProperty
|
||||
from bpy.types import PropertyGroup, Material
|
||||
|
||||
from ...shared.data import bone_filter_mode_items
|
||||
@ -6,7 +7,6 @@ from ...shared.types import PSX_PG_bone_collection_list_item
|
||||
|
||||
empty_set = set()
|
||||
|
||||
|
||||
object_eval_state_items = (
|
||||
('EVALUATED', 'Evaluated', 'Use data from fully evaluated object'),
|
||||
('ORIGINAL', 'Original', 'Use data from original object with no modifiers applied'),
|
||||
@ -17,44 +17,110 @@ export_space_items = [
|
||||
('ARMATURE', 'Armature', 'Export in armature space'),
|
||||
]
|
||||
|
||||
|
||||
axis_identifiers = ('X', 'Y', 'Z', '-X', '-Y', '-Z')
|
||||
forward_items = (
|
||||
('X', 'X Forward', ''),
|
||||
('Y', 'Y Forward', ''),
|
||||
('Z', 'Z Forward', ''),
|
||||
('-X', '-X Forward', ''),
|
||||
('-Y', '-Y Forward', ''),
|
||||
('-Z', '-Z Forward', ''),
|
||||
)
|
||||
|
||||
up_items = (
|
||||
('X', 'X Up', ''),
|
||||
('Y', 'Y Up', ''),
|
||||
('Z', 'Z Up', ''),
|
||||
('-X', '-X Up', ''),
|
||||
('-Y', '-Y Up', ''),
|
||||
('-Z', '-Z Up', ''),
|
||||
)
|
||||
|
||||
class PSK_PG_material_list_item(PropertyGroup):
|
||||
material: PointerProperty(type=Material)
|
||||
index: IntProperty()
|
||||
|
||||
class PSK_PG_material_name_list_item(PropertyGroup):
|
||||
material_name: StringProperty()
|
||||
index: IntProperty()
|
||||
|
||||
|
||||
|
||||
|
||||
def forward_axis_update(self, _context):
|
||||
if self.forward_axis == self.up_axis:
|
||||
# Automatically set the up axis to the next available axis
|
||||
self.up_axis = next((axis for axis in axis_identifiers if axis != self.forward_axis), 'Z')
|
||||
|
||||
|
||||
def up_axis_update(self, _context):
|
||||
if self.up_axis == self.forward_axis:
|
||||
# Automatically set the forward axis to the next available axis
|
||||
self.forward_axis = next((axis for axis in axis_identifiers if axis != self.up_axis), 'X')
|
||||
|
||||
|
||||
|
||||
# In order to share the same properties between the PSA and PSK export properties, we need to define the properties in a
|
||||
# separate function and then apply them to the classes. This is because the collection exporter cannot have
|
||||
# PointerProperties, so we must effectively duplicate the storage of the properties.
|
||||
def add_psk_export_properties(cls):
|
||||
cls.__annotations__['object_eval_state'] = EnumProperty(
|
||||
items=object_eval_state_items,
|
||||
name='Object Evaluation State',
|
||||
default='EVALUATED'
|
||||
)
|
||||
cls.__annotations__['should_exclude_hidden_meshes'] = BoolProperty(
|
||||
default=False,
|
||||
name='Visible Only',
|
||||
description='Export only visible meshes'
|
||||
)
|
||||
cls.__annotations__['scale'] = FloatProperty(
|
||||
name='Scale',
|
||||
default=1.0,
|
||||
description='Scale factor to apply to the exported mesh and armature',
|
||||
min=0.0001,
|
||||
soft_max=100.0
|
||||
)
|
||||
cls.__annotations__['export_space'] = EnumProperty(
|
||||
name='Export Space',
|
||||
description='Space to export the mesh in',
|
||||
items=export_space_items,
|
||||
default='WORLD'
|
||||
)
|
||||
cls.__annotations__['bone_filter_mode'] = EnumProperty(
|
||||
name='Bone Filter',
|
||||
options=empty_set,
|
||||
description='',
|
||||
items=bone_filter_mode_items,
|
||||
)
|
||||
cls.__annotations__['bone_collection_list'] = CollectionProperty(type=PSX_PG_bone_collection_list_item)
|
||||
cls.__annotations__['bone_collection_list_index'] = IntProperty(default=0)
|
||||
cls.__annotations__['forward_axis'] = EnumProperty(
|
||||
name='Forward',
|
||||
items=forward_items,
|
||||
default='X',
|
||||
update=forward_axis_update
|
||||
)
|
||||
cls.__annotations__['up_axis'] = EnumProperty(
|
||||
name='Up',
|
||||
items=up_items,
|
||||
default='Z',
|
||||
update=up_axis_update
|
||||
)
|
||||
cls.__annotations__['material_name_list'] = CollectionProperty(type=PSK_PG_material_name_list_item)
|
||||
cls.__annotations__['material_name_list_index'] = IntProperty(default=0)
|
||||
|
||||
|
||||
class PSK_PG_export(PropertyGroup):
|
||||
bone_filter_mode: EnumProperty(
|
||||
name='Bone Filter',
|
||||
options=empty_set,
|
||||
description='',
|
||||
items=bone_filter_mode_items
|
||||
)
|
||||
bone_collection_list: CollectionProperty(type=PSX_PG_bone_collection_list_item)
|
||||
bone_collection_list_index: IntProperty(default=0)
|
||||
object_eval_state: EnumProperty(
|
||||
items=object_eval_state_items,
|
||||
name='Object Evaluation State',
|
||||
default='EVALUATED'
|
||||
)
|
||||
material_list: CollectionProperty(type=PSK_PG_material_list_item)
|
||||
material_list_index: IntProperty(default=0)
|
||||
scale: FloatProperty(
|
||||
name='Scale',
|
||||
default=1.0,
|
||||
description='Scale factor to apply to the exported mesh',
|
||||
min=0.0001,
|
||||
soft_max=100.0
|
||||
)
|
||||
export_space: EnumProperty(
|
||||
name='Export Space',
|
||||
options=empty_set,
|
||||
description='Space to export the mesh in',
|
||||
items=export_space_items,
|
||||
default='WORLD'
|
||||
)
|
||||
pass
|
||||
|
||||
|
||||
add_psk_export_properties(PSK_PG_export)
|
||||
|
||||
|
||||
classes = (
|
||||
PSK_PG_material_list_item,
|
||||
PSK_PG_material_name_list_item,
|
||||
PSK_PG_export,
|
||||
)
|
||||
|
@ -1,12 +1,14 @@
|
||||
import bpy
|
||||
from bpy.types import UIList
|
||||
|
||||
|
||||
class PSK_UL_materials(UIList):
|
||||
class PSK_UL_material_names(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
row = layout.row()
|
||||
row.prop(item.material, 'name', text='', emboss=False, icon_value=layout.icon(item.material))
|
||||
material = bpy.data.materials.get(item.material_name, None)
|
||||
row.prop(item, 'material_name', text='', emboss=False, icon_value=layout.icon(material) if material else 0)
|
||||
|
||||
|
||||
classes = (
|
||||
PSK_UL_materials,
|
||||
PSK_UL_material_names,
|
||||
)
|
||||
|
@ -133,11 +133,12 @@ def dfs_view_layer_objects(view_layer: ViewLayer) -> Iterable[DfsObject]:
|
||||
@param view_layer: The view layer to inspect.
|
||||
@return: An iterable of tuples containing the object, the instance objects, and the world matrix.
|
||||
'''
|
||||
visited = set()
|
||||
def layer_collection_objects_recursive(layer_collection: LayerCollection):
|
||||
for child in layer_collection.children:
|
||||
yield from layer_collection_objects_recursive(child)
|
||||
# Iterate only the top-level objects in this collection first.
|
||||
yield from _dfs_collection_objects_recursive(layer_collection.collection)
|
||||
yield from _dfs_collection_objects_recursive(layer_collection.collection, visited=visited)
|
||||
|
||||
yield from layer_collection_objects_recursive(view_layer.layer_collection)
|
||||
|
||||
|
@ -4,12 +4,8 @@ from .data import bone_filter_mode_items
|
||||
|
||||
|
||||
def is_bone_filter_mode_item_available(pg, identifier):
|
||||
match identifier:
|
||||
case 'BONE_COLLECTIONS':
|
||||
if len(pg.bone_collection_list) == 0:
|
||||
return False
|
||||
case _:
|
||||
pass
|
||||
if identifier == 'BONE_COLLECTIONS' and len(pg.bone_collection_list) == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user