diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 860f3a43e..ab93150ef 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2450,6 +2450,8 @@ def __init__( self.global_data: FGlobalData = FGlobalData() self.texturesSavedLastExport: int = 0 # hacky + self.reference_to_extern: list[str] = [] + def processTexRefNonCITextures(self, fMaterial: FMaterial, material: bpy.types.Material, index: int): """ For non CI textures that use a texture reference, process additional textures that will possibly be loaded here. @@ -2849,6 +2851,16 @@ def save_textures(self, exportPath): def freePalettes(self): pass + def add_refs_externs(self, data: CData): + for ref in self.reference_to_extern: + extern = f"extern u64 {ref}[];\n" + + if extern not in data.source: + data.source += extern + + if len(self.reference_to_extern) > 0: + data.source += "\n" + class FTexRect(FModel): def __init__(self, name, matWriteMethod): diff --git a/fast64_internal/f3d/f3d_material.py b/fast64_internal/f3d/f3d_material.py index bf1a739b6..f08b0e151 100644 --- a/fast64_internal/f3d/f3d_material.py +++ b/fast64_internal/f3d/f3d_material.py @@ -780,17 +780,15 @@ def rendermode_presets_checks(material: "F3DMaterialProperty"): no_flags_2 = rdp.rendermode_preset_cycle_2 in f3d.rendermodePresetsWithoutFlags if no_flags_1 and no_flags_2: raise PluginError( - "Invalid combination of rendermode presets.\n" "Neither of these presets sets the rendermode flags." + "Invalid combination of rendermode presets.\nNeither of these presets sets the rendermode flags." ) elif not no_flags_1 and not no_flags_2: raise PluginError( - "Invalid combination of rendermode presets.\n" "Both of these presets set the rendermode flags." + "Invalid combination of rendermode presets.\nBoth of these presets set the rendermode flags." ) else: if no_flags_1: - raise PluginError( - "Invalid rendermode preset in 1-cycle.\n" "This preset does not set the rendermode flags." - ) + raise PluginError("Invalid rendermode preset in 1-cycle.\nThis preset does not set the rendermode flags.") # UI Assumptions: @@ -2986,6 +2984,10 @@ class TextureProperty(PropertyGroup): min=1, default=16, ) + extern_refs: bpy.props.BoolProperty( + name="Extern Texture Reference", + description="Adds externs to the exported source, useful if the texture or palette reference is a symbol.", + ) menu: bpy.props.BoolProperty() tex_set: bpy.props.BoolProperty( @@ -3146,13 +3148,19 @@ def ui_image( prop_input.prop(textureProp, "use_tex_reference") if textureProp.use_tex_reference: + flipbook = getattr(material.flipbookGroup, "flipbook" + texIndex) + + if (len(textureProp.tex_reference) > 0 and not textureProp.tex_reference.lower().startswith("0x")) or ( + not flipbook.enable and len(textureProp.pal_reference) > 0 and not textureProp.pal_reference.lower().startswith("0x") + ): + prop_input.prop(textureProp, "extern_refs") + prop_split(prop_input, textureProp, "tex_reference", "Texture Reference") prop_split(prop_input, textureProp, "tex_reference_size", "Texture Size") - if textureProp.tex_format[:2] == "CI": - flipbook = getattr(material.flipbookGroup, "flipbook" + texIndex) - if flipbook is None or not flipbook.enable: - prop_split(prop_input, textureProp, "pal_reference", "Palette Reference") - prop_split(prop_input, textureProp, "pal_reference_size", "Palette Size") + + if textureProp.tex_format[:2] == "CI" and not flipbook.enable: + prop_split(prop_input, textureProp, "pal_reference", "Palette Reference") + prop_split(prop_input, textureProp, "pal_reference_size", "Palette Size") else: prop_input.template_ID( @@ -3996,8 +4004,7 @@ def draw_rdp_world_defaults(layout: UILayout, scene: Scene): col.label(text="Saved to Repo Settings file", icon="PROPERTIES") multilineLabel( col, - text="If a material setting is the same as the default setting\n" - "it won't be set, otherwise a revert will be added.", + text="If a material setting is the same as the default setting\nit won't be set, otherwise a revert will be added.", ) if scene.gameEditorMode == "Homebrew": multilineLabel( diff --git a/fast64_internal/f3d/f3d_texture_writer.py b/fast64_internal/f3d/f3d_texture_writer.py index 2b22cd7da..4ba293d0f 100644 --- a/fast64_internal/f3d/f3d_texture_writer.py +++ b/fast64_internal/f3d/f3d_texture_writer.py @@ -131,7 +131,7 @@ def initWithFace(self, obj, face): raise PluginError( f"Large texture material {self.materialName} has a face that needs" + f" to cover texels {self.sl}-{self.sh} x {self.tl}-{self.th}" - + f" ({self.sh-self.sl+1} x {self.th-self.tl+1} texels) " + + f" ({self.sh - self.sl + 1} x {self.th - self.tl + 1} texels) " + f"in format {self.texFormat}, which can't fit in TMEM." ) self.faces.append(face) @@ -635,23 +635,34 @@ def __init__( if self.ti0.useTex and self.ti1.useTex: if self.ti0.isTexCI != self.ti1.isTexCI: raise PluginError("N64 does not support CI + non-CI texture. Must be both CI or neither CI.") - if ( - self.ti0.isTexRef - and self.ti1.isTexRef - and self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference - and self.ti0.texProp.tex_reference_size != self.ti1.texProp.tex_reference_size - ): - raise PluginError("Two textures with the same reference must have the same size.") + + def assert_size(is_pal: bool): + p_str = " palette " if is_pal else " " + + is_ref_enabled = ( + self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference + if is_pal + else self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference + ) + + data_1 = self.ti0.texProp.pal_reference_size if is_pal else self.ti0.texProp.tex_reference_size + size_1 = list(data_1) if not isinstance(data_1, int) else [data_1] + + data_2 = self.ti1.texProp.pal_reference_size if is_pal else self.ti1.texProp.tex_reference_size + size_2 = list(data_2) if not isinstance(data_2, int) else [data_2] + + is_same_size = size_1[0] == size_2[0] and size_1[0] == size_2[0] + + if self.ti0.isTexRef and self.ti1.isTexRef and is_ref_enabled and not is_same_size: + raise PluginError(f"Two textures with the same{p_str}reference must have the same{p_str}size.") + + assert_size(False) + if self.isCI: if self.ti0.palFormat != self.ti1.palFormat: raise PluginError("Both CI textures must use the same palette format (usually RGBA16).") - if ( - self.ti0.isTexRef - and self.ti1.isTexRef - and self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference - and self.ti0.texProp.pal_reference_size != self.ti1.texProp.pal_reference_size - ): - raise PluginError("Two textures with the same palette reference must have the same palette size.") + + assert_size(True) self.palFormat = self.ti0.palFormat if self.ti0.useTex else self.ti1.palFormat @@ -803,17 +814,18 @@ def writeAll( or ( # reference self.ti0.isTexRef and self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference - and self.ti0.texProp.tex_reference_size == self.ti1.texProp.tex_reference_size + and list(self.ti0.texProp.tex_reference_size) == list(self.ti1.texProp.tex_reference_size) and ( # ci format reference not self.isCI or ( self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference - and self.ti0.texProp.pal_reference_size == self.ti1.texProp.pal_reference_size + and list(self.ti0.texProp.pal_reference_size) == list(self.ti1.texProp.pal_reference_size) ) ) ) ) ) + useLargeTextures = material.mat_ver > 3 and f3dMat.use_large_textures tmemSize = 256 if self.isCI else 512 self.ti1.texAddr = None # must be set whenever tex 1 used (and loaded or tiled) diff --git a/fast64_internal/f3d/f3d_writer.py b/fast64_internal/f3d/f3d_writer.py index f6f2c5b1c..3161cac95 100644 --- a/fast64_internal/f3d/f3d_writer.py +++ b/fast64_internal/f3d/f3d_writer.py @@ -259,6 +259,13 @@ def fixLargeUVs(obj): " that are assigned to an empty material slot." ) + # ignore materials using texture references (avoids getTexDimensions throwing an error) + # TODO: find a better way + if (material.f3d_mat.tex0.tex_set and material.f3d_mat.tex0.use_tex_reference) or ( + material.f3d_mat.tex1.tex_set and material.f3d_mat.tex1.use_tex_reference + ): + continue + if material not in texSizeDict: texSizeDict[material] = getTexDimensions(material) if material.f3d_mat.use_large_textures: @@ -451,6 +458,18 @@ def saveStaticModel( for material_index, faces in faces_by_mat.items(): material = obj.material_slots[material_index].material + def try_append_refs(tex): + if tex.tex_set and tex.use_tex_reference and tex.extern_refs: + if len(tex.tex_reference) > 0 and not tex.tex_reference.lower().startswith("0x"): + fModel.reference_to_extern.append(tex.tex_reference) + + if len(tex.pal_reference) > 0 and not tex.pal_reference.lower().startswith("0x"): + fModel.reference_to_extern.append(tex.pal_reference) + + try_append_refs(material.f3d_mat.tex0) + try_append_refs(material.f3d_mat.tex1) + fModel.reference_to_extern = list(set(fModel.reference_to_extern)) # remove duplicates + if drawLayerField is not None and material.mat_ver > 3: drawLayer = getattr(material.f3d_mat.draw_layer, drawLayerField) drawLayerName = drawLayer diff --git a/fast64_internal/z64/exporter/__init__.py b/fast64_internal/z64/exporter/__init__.py index f88205c18..9edfc8b18 100644 --- a/fast64_internal/z64/exporter/__init__.py +++ b/fast64_internal/z64/exporter/__init__.py @@ -76,7 +76,7 @@ def create_scene(originalSceneObj: Object, transform: Matrix, exportInfo: Export sceneObj, transform, exportInfo, - OOTModel(f"{sceneName}_dl", DLFormat.Static, False), + OOTModel(f"{sceneName}_dl", DLFormat.Static, False, context="scene"), ) newScene.validateScene() diff --git a/fast64_internal/z64/exporter/room/__init__.py b/fast64_internal/z64/exporter/room/__init__.py index 38d297c2c..418e10ce2 100644 --- a/fast64_internal/z64/exporter/room/__init__.py +++ b/fast64_internal/z64/exporter/room/__init__.py @@ -203,6 +203,8 @@ def getRoomShapeModelC(self, textureSettings: TextureExportSettings): """Returns the C data of the room model""" roomModel = CData() + self.roomShape.model.add_refs_externs(roomModel) + for i, entry in enumerate(self.roomShape.dl_entries): if entry.opaque is not None: roomModel.append(entry.opaque.to_c(self.roomShape.model.f3d)) diff --git a/fast64_internal/z64/exporter/scene/rooms.py b/fast64_internal/z64/exporter/scene/rooms.py index 02a75d7f4..9b29b3a12 100644 --- a/fast64_internal/z64/exporter/scene/rooms.py +++ b/fast64_internal/z64/exporter/scene/rooms.py @@ -50,14 +50,7 @@ def new( original_room_obj, roomObj, roomHeader.roomShape, - model.addSubModel( - OOTModel( - f"{roomName}_dl", - model.DLFormat, - None, - model.draw_config, - ) - ), + model.addSubModel(OOTModel(f"{roomName}_dl", model.DLFormat, None, model.draw_config, context="scene")), roomIndex, sceneName, exportInfo, diff --git a/fast64_internal/z64/exporter/skeleton/functions.py b/fast64_internal/z64/exporter/skeleton/functions.py index 8c2e35724..895836eb2 100644 --- a/fast64_internal/z64/exporter/skeleton/functions.py +++ b/fast64_internal/z64/exporter/skeleton/functions.py @@ -264,7 +264,7 @@ def ootConvertArmatureToC( removeVanillaData = settings.removeVanillaData optimize = settings.optimize - fModel = OOTModel(skeletonName, DLFormat, drawLayer) + fModel = OOTModel(skeletonName, DLFormat, drawLayer, context="skeleton") skeleton, fModel = ootConvertArmatureToSkeletonWithMesh( originalArmatureObj, convertTransformMatrix, fModel, skeletonName, not savePNG, drawLayer, optimize ) @@ -326,6 +326,7 @@ def ootConvertArmatureToC( ) skeletonC = skeleton.toC() + fModel.add_refs_externs(data) data.append(exportData.all()) data.append(skeletonC) diff --git a/fast64_internal/z64/f3d/operators.py b/fast64_internal/z64/f3d/operators.py index fd25af0f5..6ccd19ac4 100644 --- a/fast64_internal/z64/f3d/operators.py +++ b/fast64_internal/z64/f3d/operators.py @@ -69,7 +69,7 @@ def ootConvertMeshToC( try: obj, allObjs = ootDuplicateHierarchy(originalObj, None, False, OOTObjectCategorizer()) - fModel = OOTModel(obj_name, DLFormat, None) + fModel = OOTModel(obj_name, DLFormat, None, context="dl") triConverterInfo = TriangleConverterInfo(obj, None, fModel.f3d, finalTransform, getInfoDict(obj)) fMeshes = saveStaticModel( triConverterInfo, fModel, obj, finalTransform, fModel.name, not saveTextures, False, "oot" @@ -108,6 +108,7 @@ def ootConvertMeshToC( OOTF3DGfxFormatter(ScrollMethod.Vertex, use_draw_layer_suffix=use_draw_layer_suffix), ) + fModel.add_refs_externs(data) data.append(exportData.all()) if isCustomExport: @@ -171,7 +172,7 @@ def execute(self, context): ] filedata = getImportData(paths) - f3dContext = OOTF3DContext(get_F3D_GBI(), [name], basePath) + f3dContext = OOTF3DContext(get_F3D_GBI(), [name], basePath, context="dl") # Test for "new" (post-ZAPD) assets system. is_2025_assets_system = "{\n#include" in filedata diff --git a/fast64_internal/z64/f3d/properties.py b/fast64_internal/z64/f3d/properties.py index e57fa50e3..d9fbdace7 100644 --- a/fast64_internal/z64/f3d/properties.py +++ b/fast64_internal/z64/f3d/properties.py @@ -27,6 +27,7 @@ class OOTDLExportSettings(PropertyGroup): default="assets/objects/gameplay_keep", description="Used in #include for including image files", ) + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) def draw_props(self, layout: UILayout): layout.label(text="Object name used for export.", icon="INFO") @@ -46,6 +47,7 @@ def draw_props(self, layout: UILayout): layout.prop(self, "isCustom") layout.prop(self, "removeVanillaData") + layout.prop(self, "ignore_segments") class OOTDLImportSettings(PropertyGroup): @@ -61,6 +63,7 @@ class OOTDLImportSettings(PropertyGroup): flipbookArrayIndex2D: IntProperty(name="Index if 2D Array", default=0, min=0) autoDetectActorScale: BoolProperty(name="Auto Detect Actor Scale", default=True) actorScale: FloatProperty(name="Actor Scale", min=0, default=10) + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) def draw_props(self, layout: UILayout): prop_split(layout, self, "name", "DL") @@ -82,6 +85,7 @@ def draw_props(self, layout: UILayout): layout.prop(self, "isCustom") layout.prop(self, "removeDoubles") layout.prop(self, "importNormals") + layout.prop(self, "ignore_segments") class OOTDynamicMaterialDrawLayerProperty(PropertyGroup): diff --git a/fast64_internal/z64/importer/scene.py b/fast64_internal/z64/importer/scene.py index f350dfcd4..bcb1b5601 100644 --- a/fast64_internal/z64/importer/scene.py +++ b/fast64_internal/z64/importer/scene.py @@ -175,7 +175,7 @@ def parseScene( ) # set scene default registers (see sDefaultDisplayList) - f3dContext = OOTF3DContext(get_F3D_GBI(), [], bpy.path.abspath(bpy.context.scene.ootDecompPath)) + f3dContext = OOTF3DContext(get_F3D_GBI(), [], bpy.path.abspath(bpy.context.scene.ootDecompPath), context="scene") f3dContext.mat().prim_color = (0.5, 0.5, 0.5, 0.5) f3dContext.mat().env_color = (0.5, 0.5, 0.5, 0.5) diff --git a/fast64_internal/z64/model_classes.py b/fast64_internal/z64/model_classes.py index dc1809383..97abf14cd 100644 --- a/fast64_internal/z64/model_classes.py +++ b/fast64_internal/z64/model_classes.py @@ -563,10 +563,13 @@ def getBufferVert(self, loop: MeshLoop, face: MeshLoopTriangle, groupIndex: int class OOTModel(FModel): - def __init__(self, name, DLFormat, drawLayerOverride, draw_config: Optional[str] = None): + def __init__( + self, name, DLFormat, drawLayerOverride, draw_config: Optional[str] = None, context: str = "undefined" + ): self.drawLayerOverride = drawLayerOverride self.flipbooks: list[TextureFlipbook] = [] self.draw_config = draw_config + self.context = context # ["skeleton", "scene", "dl"] FModel.__init__(self, name, DLFormat, GfxMatWriteMethod.WriteAll) @@ -754,18 +757,31 @@ def onMaterialCommandsBuilt(self, fMaterial, material, drawLayer): gfxList = fMaterial.material matDrawLayer = getattr(material.ootMaterial, drawLayer.lower()) - for i in range(8, 14): - if getattr(matDrawLayer, f"segment{i:X}"): - is_animated_material = False - - if self.draw_config is not None and "mat_anim" in self.draw_config: - is_animated_material = True - - gfxList.commands.append( - DynamicMaterialDL( - GfxList(f"0x0{i:X}000000", GfxListTag.Material, DLFormat.Static), is_animated_material + ignore_segments = False + + match self.context: + case "skeleton": + ignore_segments = bpy.context.scene.fast64.oot.skeletonExportSettings.ignore_segments + case "scene": + ignore_segments = bpy.context.scene.ootSceneExportSettings.ignore_segments + case "dl": + ignore_segments = bpy.context.scene.fast64.oot.DLExportSettings.ignore_segments + case _: + pass + + if not ignore_segments: + for i in range(8, 14): + if getattr(matDrawLayer, f"segment{i:X}"): + is_animated_material = False + + if self.draw_config is not None and "mat_anim" in self.draw_config: + is_animated_material = True + + gfxList.commands.append( + DynamicMaterialDL( + GfxList(f"0x0{i:X}000000", GfxListTag.Material, DLFormat.Static), is_animated_material + ) ) - ) for i in range(0, 2): p = f"customCall{i}" @@ -836,11 +852,12 @@ def __init__(self): class OOTF3DContext(F3DContext): - def __init__(self, f3d, limbList, basePath): + def __init__(self, f3d, limbList, basePath, context="undefined"): self.limbList = limbList self.dlList = [] # in the order they are rendered self.isBillboard = False self.flipbooks = {} # {(segment, draw layer) : TextureFlipbook} + self.context = context # ["skeleton", "scene", "dl"] # the new assets system extracts CI textures as PNGs with the TLUT already applied # so we need to avoid reading TLUTs as the files don't exist outside the build folder @@ -912,11 +929,24 @@ def processDLName(self, name): return None return name else: - segment = pointer >> 24 - if segment >= 0x08 and segment <= 0x0D: - setattr(self.materialContext.ootMaterial.opaque, "segment" + format(segment, "1X"), True) - setattr(self.materialContext.ootMaterial.transparent, "segment" + format(segment, "1X"), True) - self.materialChanged = True + ignore_segments = False + + match self.context: + case "skeleton": + ignore_segments = bpy.context.scene.fast64.oot.skeletonImportSettings.ignore_segments + case "scene": + ignore_segments = bpy.context.scene.ootSceneImportSettings.ignore_segments + case "dl": + ignore_segments = bpy.context.scene.fast64.oot.DLImportSettings.ignore_segments + case _: + pass + + if not ignore_segments: + segment = pointer >> 24 + if segment >= 0x08 and segment <= 0x0D: + setattr(self.materialContext.ootMaterial.opaque, "segment" + format(segment, "1X"), True) + setattr(self.materialContext.ootMaterial.transparent, "segment" + format(segment, "1X"), True) + self.materialChanged = True return None return name diff --git a/fast64_internal/z64/scene/properties.py b/fast64_internal/z64/scene/properties.py index 5338de3cb..7742a737f 100644 --- a/fast64_internal/z64/scene/properties.py +++ b/fast64_internal/z64/scene/properties.py @@ -608,6 +608,7 @@ class OOTExportSceneSettingsProperty(PropertyGroup): ) option: EnumProperty(items=ootEnumSceneID, default="SCENE_DEKU_TREE") auto_add_room_objects: BoolProperty(name="Auto-add Missing Room Objects", default=True) + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) # keeping this on purpose, will be removed once old code is cleaned-up useNewExporter: BoolProperty(name="Use New Exporter", default=True) @@ -627,6 +628,7 @@ def draw_props(self, layout: UILayout): layout.prop(self, "singleFile") layout.prop(self, "customExport") layout.prop(self, "auto_add_room_objects") + layout.prop(self, "ignore_segments") # layout.prop(self, "useNewExporter") @@ -646,6 +648,7 @@ class OOTImportSceneSettingsProperty(PropertyGroup): includeCutscenes: BoolProperty(name="Cutscenes", default=False) includeAnimatedMats: BoolProperty(name="Animated Materials", default=False) option: EnumProperty(items=ootEnumSceneID, default="SCENE_DEKU_TREE") + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) def draw_props(self, layout: UILayout, sceneOption: str): col = layout.column() @@ -669,6 +672,7 @@ def draw_props(self, layout: UILayout, sceneOption: str): includeButtons4.prop(self, "includeAnimatedMats", toggle=1) col.prop(self, "isCustomDest") + col.prop(self, "ignore_segments") if self.isCustomDest: prop_split(col, self, "destPath", "Directory") diff --git a/fast64_internal/z64/skeleton/importer/functions.py b/fast64_internal/z64/skeleton/importer/functions.py index c911f17a0..5c449fe0b 100644 --- a/fast64_internal/z64/skeleton/importer/functions.py +++ b/fast64_internal/z64/skeleton/importer/functions.py @@ -376,7 +376,7 @@ def ootImportSkeletonC(basePath: str, importSettings: OOTSkeletonImportSettings) limbs_info = ootGetLimbs(skeletonData, skel_info.limbs_name, False) - f3dContext = OOTF3DContext(get_F3D_GBI(), limbs_info.limb_list, basePath) + f3dContext = OOTF3DContext(get_F3D_GBI(), limbs_info.limb_list, basePath, context="skeleton") f3dContext.mat().draw_layer.oot = drawLayer f3dContext.ignore_tlut = ignore_tlut diff --git a/fast64_internal/z64/skeleton/properties.py b/fast64_internal/z64/skeleton/properties.py index 079dacfd7..37b633309 100644 --- a/fast64_internal/z64/skeleton/properties.py +++ b/fast64_internal/z64/skeleton/properties.py @@ -81,6 +81,7 @@ class OOTSkeletonExportSettings(PropertyGroup): + "If enabled, the skeleton limbs must be drawn in their normal order, " + "with nothing in between and no culling, otherwise the mesh will be corrupted.", ) + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) def draw_props(self, layout: UILayout): layout.prop(self, "removeVanillaData") @@ -91,6 +92,7 @@ def draw_props(self, layout: UILayout): b.label(text="callbacks or cull limbs, will be corrupted.") layout.prop(self, "isCustom") layout.label(text="Object name used for export.", icon="INFO") + layout.prop(self, "ignore_segments") layout.prop(self, "isCustomFilename") if self.isCustomFilename: prop_split(layout, self, "filename", "Filename") @@ -128,12 +130,14 @@ class OOTSkeletonImportSettings(PropertyGroup): flipbookArrayIndex2D: IntProperty(name="Index if 2D Array", default=0, min=0) autoDetectActorScale: BoolProperty(name="Auto Detect Actor Scale", default=True) actorScale: FloatProperty(name="Actor Scale", min=0, default=10) + ignore_segments: BoolProperty(name="Ignore DL Segments", default=False) def draw_props(self, layout: UILayout): prop_split(layout, self, "drawLayer", "Import Draw Layer") layout.prop(self, "removeDoubles") layout.prop(self, "importNormals") layout.prop(self, "import_animations") + layout.prop(self, "ignore_segments") layout.prop(self, "isCustom") if self.isCustom: prop_split(layout, self, "name", "Skeleton")