Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dc3bc33
Add files via upload
mayloglog Feb 25, 2025
1c1e8e0
Update README.md
mayloglog Feb 25, 2025
48492d6
Add files via upload
mayloglog Feb 25, 2025
c2061cd
Merge pull request #1 from mayloglog/maylog-Blender4.4
mayloglog Feb 25, 2025
dbe1595
为5.0适配
mayloglog Nov 25, 2025
45e0fc7
适配blender5.0
mayloglog Nov 25, 2025
cc34bf6
Update README.md
mayloglog Nov 25, 2025
e11d8b4
适配blender5.0以及符合blender官方插件库规范
mayloglog Nov 25, 2025
243cf07
Update README.md
mayloglog Nov 25, 2025
9128b34
Delete addon_updater_ops.py
mayloglog Nov 26, 2025
2c055f9
Delete addon_updater.py
mayloglog Nov 26, 2025
607ca98
Update README.md
mayloglog Nov 27, 2025
0f3778b
Add files via upload
mayloglog Nov 28, 2025
07edba3
Add files via upload
mayloglog Nov 28, 2025
13c983f
Add files via upload
mayloglog Nov 28, 2025
075317a
Add files via upload
mayloglog Nov 28, 2025
364a35b
为适配官方插件平台清理注册/卸载逻辑
mayloglog Nov 29, 2025
a957f8f
Delete .gitignore
mayloglog Nov 29, 2025
58a1b08
Update README.md
mayloglog Nov 29, 2025
19b68b2
Update README.md
mayloglog Dec 1, 2025
10677c6
Performance Optimization/性能优化
mayloglog Dec 8, 2025
84b498f
Feature:
mayloglog Jan 7, 2026
f5242b1
Hide XPS Format Export
mayloglog Jan 14, 2026
9ae130f
Update README.md
mayloglog Jan 14, 2026
8fe8e6b
Update README.md
mayloglog Jan 15, 2026
648f704
2.2.5
mayloglog Feb 13, 2026
966b7c9
Update OBJ exporter
mayloglog Feb 27, 2026
8048451
Optimized XPS import speed
mayloglog Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 0 additions & 58 deletions .gitignore

This file was deleted.

26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
XPS Tools
=========
Blender an addon to Export/Import Haydee assets.

With Blender 2.80 released there where many changes.
Fork of XNALara Mesh import/export tool with Blender 5.0 compatibility.

From v2.0.0 of this addon will only work with Blender 2.80+ (and viceversa).
For Blender 2.79 download v1.8.7
Since the original author (johnzero7) has not updated the code for five years as of 2025, the old version of the plugin can no longer run on the new version of Blender. Therefore, I will maintain this version going forward.

- Blender 2.80 ==> v2.0.0
- Blender 2.79 ==> v1.8.7
Original addon by XNALara community.

With Blender 4.40 released there where many changes.

From v2.1.0 of this addon will only work with Blender 4.4.
From v2.2.0 of this addon will only work with Blender 5.0.

- Blender 5.00 ==> v2.2.0+
- Blender 4.40 ==> v2.1.0

Blender Toolshelf, an addon for Blender to:

Expand All @@ -21,6 +26,11 @@ Main Features:
- Creates Materials on import
- Easily set a new rest pose for the model

more info at:
http://johnzero7.github.io/XNALaraMesh/
### Known Issues

- Summary: Due to critical compatibility issues with the XPS binary format, I have disabled the native .xps binary export. The exporter now redirects to ASCII format by default, which ensures perfect compatibility and stability.

- Technical Details: The current mock_xps_data.py lacks the necessary file header logic. After I manually attempted to implement the header construction, it resulted in severe byte misalignment. While the file is generated, the scene appears empty upon re-import.
The XPS format requires strict alignment for the 1080-byte Settings Block. Due to changes in Blender 5.0's I/O handling, the logic that worked in older versions now causes offset shifts. As an individual developer, the binary structure of XPS remains a "black box" to me, and my current technical skills are insufficient to perform the precise byte-level adjustments required to fix this.

- Call for Help: I welcome any experienced developers to help fix this alignment issue. If you can resolve the binary header construction for Blender 5.0, please submit a Pull Request on GitHub. Thank you for your support!
222 changes: 64 additions & 158 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,167 +1,73 @@
# <pep8 compliant>

"""Blender Addon. XNALara/XPS importer/exporter."""

bl_info = {
"name": "XNALara/XPS Import/Export",
"author": "johnzero7",
"version": (2, 0, 2),
"blender": (2, 80, 0),
"location": "File > Import-Export > XNALara/XPS",
"description": "Import-Export XNALara/XPS",
"warning": "",
"wiki_url": "https://github.com/johnzero7/xps_tools",
"tracker_url": "https://github.com/johnzero7/xps_tools/issues",
"name": "XPS Import/Export",
"author": "maylog",
"version": (2, 2, 7),
"blender": (5, 0, 0),
"location": "File > Import-Export",
"description": "Community-maintained fork of the original XNALara/XPS Tools. Fully Blender 5.0+ compatible.",
"category": "Import-Export",
"support": "COMMUNITY",
"credits": "2025 johnzero7 (original author), 2025 Clothoid, 2025 XNALara/XPS community, 2025 maylog (Blender 5.0+ update & Extensions submission)",
}


#############################################
# support reloading sub-modules
_modules = [
'xps_panels',
'xps_tools',
'xps_toolshelf',
'xps_const',
'xps_types',
'xps_material',
'write_ascii_xps',
'write_bin_xps',
'read_ascii_xps',
'read_bin_xps',
'mock_xps_data',
'export_xnalara_model',
'export_xnalara_pose',
'import_xnalara_model',
'import_xnalara_pose',
'import_obj',
'export_obj',
'ascii_ops',
'bin_ops',
'timing',
'material_creator',
'node_shader_utils',
'addon_updater_ops',
]

# Reload previously loaded modules
if "bpy" in locals():
from importlib import reload
_modules_loaded[:] = [reload(module) for module in _modules_loaded]
del reload


# First import the modules
__import__(name=__name__, fromlist=_modules)
_namespace = globals()
_modules_loaded = [_namespace[name] for name in _modules]
del _namespace
# support reloading sub-modules
#############################################

import bpy


class UpdaterPreferences(bpy.types.AddonPreferences):
"""Updater Class."""

bl_idname = __package__

# addon updater preferences from `__init__`, be sure to copy all of them
auto_check_update: bpy.props.BoolProperty(
name="Auto-check for Update",
description="If enabled, auto-check for updates using an interval",
default=False,
)
updater_interval_months: bpy.props.IntProperty(
name='Months',
description="Number of months between checking for updates",
default=0,
min=0
)
updater_interval_days: bpy.props.IntProperty(
name='Days',
description="Number of days between checking for updates",
default=7,
min=0,
)
updater_interval_hours: bpy.props.IntProperty(
name='Hours',
description="Number of hours between checking for updates",
default=0,
min=0,
max=23
)
updater_interval_minutes: bpy.props.IntProperty(
name='Minutes',
description="Number of minutes between checking for updates",
default=0,
min=0,
max=59
)

def draw(self, context):
"""Draw Method."""
addon_updater_ops.update_settings_ui(self, context)

#
# Registration
#


classesToRegister = [
UpdaterPreferences,
xps_panels.XPSToolsObjectPanel,
xps_panels.XPSToolsBonesPanel,
xps_panels.XPSToolsAnimPanel,

xps_toolshelf.ArmatureBonesHideByName_Op,
xps_toolshelf.ArmatureBonesHideByVertexGroup_Op,
xps_toolshelf.ArmatureBonesShowAll_Op,
xps_toolshelf.ArmatureBonesRenameToBlender_Op,
xps_toolshelf.ArmatureBonesRenameToXps_Op,
xps_toolshelf.ArmatureBonesConnect_Op,
xps_toolshelf.NewRestPose_Op,

xps_tools.Import_Xps_Model_Op,
xps_tools.Export_Xps_Model_Op,
xps_tools.Import_Xps_Pose_Op,
xps_tools.Export_Xps_Pose_Op,
xps_tools.Import_Poses_To_Keyframes_Op,
xps_tools.Export_Frames_To_Poses_Op,
xps_tools.ArmatureBoneDictGenerate_Op,
xps_tools.ArmatureBoneDictRename_Op,
xps_tools.ArmatureBoneDictRestore_Op,
xps_tools.ImportXpsNgff,
xps_tools.ExportXpsNgff,
xps_tools.XpsImportSubMenu,
xps_tools.XpsExportSubMenu,
]


# Use factory to create method to register and unregister the classes
registerClasses, unregisterClasses = bpy.utils.register_classes_factory(classesToRegister)

from . import (
xps_panels,
xps_tools,
xps_toolshelf,
xps_const,
xps_types,
xps_material,
write_ascii_xps,
write_bin_xps,
read_ascii_xps,
read_bin_xps,
mock_xps_data,
export_xnalara_model,
export_xnalara_pose,
import_xnalara_model,
import_xnalara_pose,
import_obj,
export_obj,
ascii_ops,
bin_ops,
timing,
material_creator,
node_shader_utils,
)


modules = (
xps_const,
xps_types,
xps_material,
read_ascii_xps,
read_bin_xps,
write_ascii_xps,
write_bin_xps,
mock_xps_data,
material_creator,
node_shader_utils,
timing,
ascii_ops,
bin_ops,
import_obj,
export_obj,
import_xnalara_model,
export_xnalara_model,
import_xnalara_pose,
export_xnalara_pose,
xps_tools,
xps_toolshelf,
xps_panels,
)

def register():
"""Register addon classes."""
registerClasses()
xps_tools.register()
addon_updater_ops.register(bl_info)

for mod in modules:
if hasattr(mod, "register"):
mod.register()

def unregister():
"""Unregister addon classes."""
addon_updater_ops.unregister()
xps_tools.unregister()
unregisterClasses()


if __name__ == "__main__":
register()

# call exporter
# bpy.ops.xps_tools.export_model('INVOKE_DEFAULT')

# call importer
# bpy.ops.xps_tools.import_model('INVOKE_DEFAULT')
for mod in reversed(modules):
if hasattr(mod, "unregister"):
mod.unregister()
Loading