| … | … | @@ -39,15 +39,17 @@ Self-contained files import their embedded animations automatically. Models |
| 39 | 39 | that split clips into separate **skeleton-less** files (OctaForge does this — |
| 40 | 40 | see `iqm_src/animation/`) are applied onto an existing armature: |
| 41 | 41 | |
| 42 | - **One step:** in the import dialog, shift-select the base model **and** the | |
| 43 | clips together (e.g. `player.iqm` + everything in `animation/`). Models are | |
| 44 | imported first, then each clip is attached to the new armature as its own | |
| 45 | **action** (browse them in the Action Editor / NLA). | |
| 46 | - **Or sequentially:** import `player.iqm` first, then import the clip files — | |
| 47 | they attach to the armature already in the scene. | |
| 48 | ||
| 49 | The base model (the one with the skeleton) must be importable alongside the | |
| 50 | clips; the importer matches them by bone count. | |
| 42 | 1. Import the base model (`player.iqm`) first — this creates the armature. | |
| 43 | 2. Then **File ▸ Import** again and **shift-select all the clips** in the | |
| 44 | `animation/` folder. Each becomes its own **action** (browse them in the | |
| 45 | Action Editor / NLA). | |
| 46 | ||
| 47 | (If a model keeps its clips in the *same* folder as the base mesh, you can | |
| 48 | shift-select the model and the clips together in one go — models are always | |
| 49 | imported before clips.) | |
| 50 | ||
| 51 | The base model must already be imported (armature in the scene) and its `.iqm` | |
| 52 | must be reachable from the clips; the importer matches them by bone count. | |
| 51 | 53 | |
| 52 | 54 | > After editing the add-on file, restart Blender (or disable/re-enable it) so |
| 53 | 55 | > the new code is reloaded — Blender caches enabled add-ons. |
| … | … | @@ -1175,14 +1175,17 @@ class ImportIQM(bpy.types.Operator, ImportHelper): |
| 1175 | 1175 | bl_label = "Import IQM or IQE" |
| 1176 | 1176 | |
| 1177 | 1177 | filename_ext = ".iqe, .iqm" |
| 1178 | filter_glob = StringProperty(default="*.iq[em]", options={'HIDDEN'}) | |
| 1179 | filepath = StringProperty(name="File Path", maxlen=1024, default="") | |
| 1178 | # NOTE: properties MUST use annotation syntax (name: Property(...)). Since | |
| 1179 | # Blender 2.9x, assignment-style operator properties are silently ignored | |
| 1180 | # when a base class (here ImportHelper) already declares annotations. | |
| 1181 | filter_glob: StringProperty(default="*.iq[em]", options={'HIDDEN'}) | |
| 1180 | 1182 | # Allow selecting several files at once (e.g. a model + its animation clips); |
| 1181 | 1183 | # models are imported first so clips can attach to the new armature. |
| 1182 | files = CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement) | |
| 1183 | directory = StringProperty(subtype='DIR_PATH') | |
| 1184 | files: CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement, | |
| 1185 | options={'HIDDEN', 'SKIP_SAVE'}) | |
| 1186 | directory: StringProperty(subtype='DIR_PATH', options={'HIDDEN', 'SKIP_SAVE'}) | |
| 1184 | 1187 | |
| 1185 | bone_axis = EnumProperty(name="Bone Axis", | |
| 1188 | bone_axis: EnumProperty(name="Bone Axis", | |
| 1186 | 1189 | description="Flip bones to extend along the Y axis", |
| 1187 | 1190 | items=[ |
| 1188 | 1191 | ('Y', "Preserve", ""), |