Init Repo

This commit is contained in:
indigo 2026-03-26 08:27:38 +08:00
commit 4eb266b623
12 changed files with 22763 additions and 0 deletions

225
.gitignore vendored Normal file
View File

@ -0,0 +1,225 @@
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
# Created by https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,python
# Edit at https://www.toptal.com/developers/gitignore?templates=windows,visualstudiocode,python
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
### Python Patch ###
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
poetry.toml
# ruff
.ruff_cache/
# LSP config files
pyrightconfig.json
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,python
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"python.analysis.extraPaths": [
"${workspaceFolder}/python",
"D:\\library\\stub\\mayaSDK"
]
}

2
MzTranslate.mod Normal file
View File

@ -0,0 +1,2 @@
+ MzTranslator 1.0 .
PYTHONPATH +:= python

111
README.md Normal file
View File

@ -0,0 +1,111 @@
# MzTranslator
Maya `.mz` 檔案格式 Translator 插件,使用 Maya Python API 開發。
## 檔案格式
`.mz` 檔案本質上是 ZIP 壓縮格式,內部包含 `data.ma` (Maya ASCII) 文件。
## 目錄結構
```
d:/workspace/MzTranslator/
├── mz_translator.py # 插件入口,包含 MPxFileTranslator 和插件註冊
├── mz_core/
│ ├── __init__.py # 模組初始化
│ ├── reader.py # 讀取模組
│ └── writer.py # 寫入模組
└── README.md # 使用說明
```
## 安裝方法
### 方法 1直接載入 Python 模組
在 Maya 的 Python 腳本編輯器中執行:
```python
import sys
import os
# 添加插件路徑
plugin_path = 'd:/workspace/MzTranslator'
if plugin_path not in sys.path:
sys.path.insert(0, plugin_path)
# 載入插件
import mz_translator
cmds.loadPlugin(mz_translator.__file__)
```
### 方法 2使用 pluginManager
1. 打開 Maya
2. 進入 `Window > Settings/Preferences > Plugin Manager`
3. 點擊 `Browse` 找到 `mz_translator.py`
4. 勾選 `Loaded` 載入插件
## 使用方法
### 存儲 (Save/Export)
1. 選擇 `File > Save As...``File > Export All...`
2. 在文件類型下拉選單中選擇 `Mz File (*.mz)`
3. 選擇保存位置並點擊 `Save`
### 開啟 (Open/Import)
1. 選擇 `File > Open...``File > Import...`
2. 在文件類型下拉選單中選擇 `Mz File (*.mz)`
3. 選擇 `.mz` 文件並點擊 `Open`
## 功能特性
- **讀取支援**:從 `.mz` 檔案解壓縮並讀取 `data.ma`
- **寫入支援**:將 Maya 場景導出為 `.mz` 檔案(壓縮格式)
- **Export Options**支援壓縮級別設定0-9
## 技術細節
### writer.py
- 使用 `tempfile` 建立臨時目錄
- 使用 Maya 的 `cmds.file()` 導出為 `.ma` 格式
- 使用 `zipfile``data.ma` 壓縮成 `.mz`
### reader.py
- 使用 `zipfile` 讀取 `.mz` 檔案
- 提取 `data.ma` 到臨時目錄
- 使用 Maya 的 `cmds.file()` 讀取場景
- 自動清理臨時檔案
### mz_translator.py
- 繼承 `maya.api.OpenMayaMPx.MPxFileTranslator`
- 實現 `writer()``reader()` 方法
- 包含 Maya 插件註冊函數 `initializePlugin()``uninitializePlugin()`
## 故障排除
### 問題:無法載入插件
確保插件路徑正確:
```python
import mz_translator
print(mz_translator.__file__) # 確認路徑正確
```
### 問題:無法識別 .mz 檔案
確認 `.mz` 檔案是有效的 ZIP 格式(包含 `data.ma`
### 問題:讀取後場景未更新
檢查臨時檔案是否有權限問題,或嘗試重新開啟 Maya
## 版本資訊
- Version: 1.0.0
- API: Maya Python API
- 支援 Maya 版本: 2017+

78
plans/plan.md Normal file
View File

@ -0,0 +1,78 @@
# MzTranslator 架構設計
## 概述
使用 Maya Python API 建立一個 `.mz` 檔案格式的 Maya Translator 插件。
## .mz 檔案格式
- 本質是 ZIP 壓縮格式
- 內部包含 `data.ma` 文件Maya ASCII 格式)
## 系統架構
```mermaid
graph TB
subgraph Maya
A[Maya GUI] -->|另存為/開啟| B[mz_translator.py]
end
subgraph Core
B --> D[mz_writer]
B --> E[mz_reader]
end
subgraph FileSystem
D --> F[.mz]
E --> F
end
```
## 實現步驟
### 1. 文件結構
```
d:/workspace/MzTranslator/
├── mz_translator.py # 插件入口,包含 MPxFileTranslator 和插件註冊
└── mz_core/
├── __init__.py # 模組初始化
├── reader.py # 讀取模組
└── writer.py # 寫入模組
```
### 2. mz_translator.py
- 繼承 `maya.api.MPxFileTranslator`
- 包含 `initializePlugin()``uninitializePlugin()` 函數
- `writer(fileObject, options)`: 調用 mz_writer
- `reader(fileObject, options)`: 調用 mz_reader
- `haveWriteSupport()` / `haveReadSupport()`: 返回 True
- `fileType()` / `defaultExtension()`: 返回 "mz"
- `optionsScript()`: Export Options UI
### 3. MzTranslator/mz/core/mz_writer.py
- `write_to_mz(filePath, options)`: 將 Maya 場景寫入 .mz
- 內部調用 Maya API 寫入 temp data.ma
- 使用 zipfile 壓縮成 .mz
### 4. MzTranslator/mz/core/mz_reader.py
- `read_from_mz(filePath, buffer)`: 從 .mz 讀取
- 使用 zipfile 解壓縮
- 讀取到內存緩衝區
### 5. Export Options 對話框
- 版本號
- 壓縮等級
## 技術要點
1. **MPxFileTranslator 繼承**: 使用 `maya.app.audio.MPxFileTranslator`
2. **Stream I/O**: reader 使用 buffer/stream 讀取
3. **臨時文件管理**: 使用 `tempfile` 模組
4. **Error Handling**: 處理各種異常情況
## 預期行為
- **保存**: Maya 另存為 → 選擇 .mz → 導出到 temp data.ma → 壓縮成 .mz
- **開啟**: 選擇 .mz 文件 → 解壓讀取 data.ma → 加載到 Maya

370
plug-ins/mz_translator.py Normal file
View File

@ -0,0 +1,370 @@
# -*- coding: utf-8 -*-
"""
Mz Translator - Maya File Translator Plugin
Maya Python API implementation for .mz file format translator
.mz format is ZIP compressed, contains data.ma file
Usage:
Load plugin in Maya:
cmds.loadPlugin('mz_translator.py')
"""
import os
import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaUI as OpenMayaUI
import maya.cmds as cmds
from importlib import reload
# Import core modules
from mz_core import reader, writer
reload(reader)
reload(writer)
# Plugin name
kPluginName = "MzTranslator"
kPluginVersion = "1.0.0"
class MzFileTranslator(OpenMayaMPx.MPxFileTranslator):
"""
Maya .mz file format translator
Supports reading and writing .mz files (ZIP compressed, contains data.ma)
"""
_translator_name = "MayaZip"
_extension = "mz"
# Class variable
_temp_file_path = None
def __init__(self):
"""Initialize translator"""
super(MzFileTranslator, self).__init__()
self._options = {}
@staticmethod
def creator():
"""Factory method to create translator instance"""
return MzFileTranslator()
# =========================================================================
# MPxFileTranslator virtual functions
# =========================================================================
def canBeOpened(self):
"""
Return whether translator can be opened
Returns:
bool: Always returns True (can be opened)
"""
return True
def translatorName(self):
"""
Return translator name
Returns:
str: Translator name
"""
return self._translator_name
def haveWriteMethod(self):
"""
Return whether write is supported
Returns:
bool: Always returns True
"""
return True
def haveReferenceMethod(self):
"""
Return whether referencing is supported
Returns:
bool: Always returns False (not supported)
"""
return True
def haveReadMethod(self):
"""
Return whether read is supported
Returns:
bool: Always returns True
"""
return True
def fileType(self):
"""
Return file type name
Returns:
str: File type name
"""
return self._translator_name
def defaultExtension(self):
"""
Return default file extension
Returns:
str: Extension without dot
"""
return self._extension
def identifyFile(self, fileObject, buffer, size):
"""
Identify if file is .mz format
Args:
fileObject: MFileObject
buffer: File buffer
buffer_size: Buffer size
Returns:
int: kIsMyFileType if identified, kUnknown if failed
"""
import zipfile
file_name = fileObject.fullName()
# Check extension
if not file_name.lower().endswith('.mz'):
return OpenMayaMPx.MPxFileTranslator.kNotMyFileType
# Try to identify as ZIP file
try:
# Check if file is valid ZIP format
with open(file_name, 'rb') as f:
# Check ZIP file magic (PK\x03\x04)
magic = f.read(4)
if magic == b'PK\x03\x04' or magic == b'PK\x05\x06':
# Further check if contains data.ma
with zipfile.ZipFile(file_name, 'r') as zf:
if 'data.ma' in zf.namelist():
return OpenMayaMPx.MPxFileTranslator.kIsMyFileType
except Exception:
pass
return OpenMayaMPx.MPxFileTranslator.kNotMyFileType
def writer(self, fileObject, options, mode):
"""
Write Maya scene to .mz file
Args:
fileObject: MFileObject
options: Options dictionary
mode: File mode
Returns:
bool: True if successful
"""
try:
file_path = fileObject.fullName()
# Ensure extension is correct
if not file_path.lower().endswith('.mz'):
file_path += '.mz'
fileObject.setRawFullName(file_path)
# Parse options
writer_options = self._parse_options(options)
# Write .mz file
writer.write_scene_to_mz(file_path, writer_options)
return True
except Exception as e:
raise RuntimeError(f"Failed to write .mz file: {str(e)}")
def reader(self, fileObject, options, mode):
"""
Read Maya scene from .mz file
Args:
fileObject: MFileObject
options: Options dictionary
mode: File mode
Returns:
bool: True if successful
"""
try:
file_path = fileObject.fullName()
# Read .mz file to temp file
temp_ma_path = reader.read_to_temp_file(file_path)
# Save temp file path for cleanup
MzFileTranslator._temp_file_path = temp_ma_path
print(temp_ma_path)
print(options)
if mode == OpenMayaMPx.MPxFileTranslator.kOpenAccessMode:
OpenMaya.MFileIO.open(temp_ma_path, None, True)
if mode == OpenMayaMPx.MPxFileTranslator.kImportAccessMode:
OpenMaya.MFileIO.importFile(temp_ma_path, None, True)
# Use Maya's file command to read
# cmds.file(temp_ma_path, force=True, open=True, type='mayaAscii')
return True
except Exception as e:
raise RuntimeError(f"Failed to read .mz file: {str(e)}")
def optionsScript(self):
"""
Return Export Options UI script
Returns:
str: Python script string
"""
script = """
import maya.cmds as cmds
def MzTranslatorOptions():
# Create options dialog
if cmds.window('MzTranslatorOptions', exists=True):
cmds.deleteUI('MzTranslatorOptions')
cmds.window('MzTranslatorOptions', title='Mz Translator Options')
cmds.columnLayout(adjustableColumn=True)
# Compression level
cmds.text(label='Compression Level (0-9):')
cmds.intSliderGrp('compressionLevel',
label='Compression',
field=True,
minValue=0,
maxValue=9,
value=9,
step=1)
# Version info
cmds.text(label='Version: 1.0.0')
cmds.button(label='OK', command='cmds.layoutDialog(dismiss=\"ok\")')
cmds.button(label='Cancel', command='cmds.layoutDialog(dismiss=\"cancel\")')
cmds.showWindow()
return 'ok'
# Call options dialog
result = cmds.layoutDialog(ui=MzTranslatorOptions)
"""
return script
# =========================================================================
# Helper methods
# =========================================================================
def _parse_options(self, options):
"""
Parse options string to dictionary
Args:
options: Options string (format: key=value;key=value)
Returns:
dict: Options dictionary
"""
result = {}
if not options:
return result
# Parse options string
for pair in options.split(';'):
if '=' in pair:
key, value = pair.split('=', 1)
result[key.strip()] = value.strip()
return result
# =========================================================================
# Maya plugin registration functions
# =========================================================================
# creator
def translatorCreator():
return OpenMayaMPx.asMPxPtr( MzFileTranslator() )
def initializePlugin(mobject):
"""
Initialize plugin
Args:
mobject: MObject
"""
# Create plugin
pluginFn = OpenMayaMPx.MFnPlugin(mobject, "MzTranslator", "1.0.0", "Any")
# Register file translator
try:
pluginFn.registerFileTranslator(
MzFileTranslator._translator_name, # Translator name
"", # Options script (optional)
translatorCreator, # Factory function
"", # Default options
MzFileTranslator._extension # File extension
)
print(f"[{kPluginName}] Plugin initialized successfully (v{kPluginVersion})")
except Exception as e:
sys.stderr.write(f"Failed to register file translator: {str(e)}\n")
raise
def uninitializePlugin(mobject):
"""
Uninitialize plugin
Args:
mobject: MObject
"""
# Get plugin function
pluginFn = OpenMayaMPx.MFnPlugin(mobject)
# Deregister file translator
try:
pluginFn.deregisterFileTranslator(MzFileTranslator._translator_name)
print(f"[{kPluginName}] Plugin uninitialized successfully")
except Exception as e:
sys.stderr.write(f"Failed to deregister file translator: {str(e)}\n")
# =========================================================================
# Convenience functions
# =========================================================================
def cleanup_temp_file():
"""Cleanup temp file"""
if MzFileTranslator._temp_file_path:
import os
import shutil
try:
temp_dir = os.path.dirname(MzFileTranslator._temp_file_path)
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
except Exception:
pass
MzFileTranslator._temp_file_path = None
# =========================================================================
# Auto cleanup when plugin loads
# =========================================================================
# Register cleanup callback when Maya scene closes
try:
# This will cleanup temp files when Maya scene closes
cmds.scriptJob(event=['SceneClosed', cleanup_temp_file], permanent=True)
except Exception:
pass

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
"""
Mz Translator Core Module
.mz file format processing core module
"""
from .reader import (
read_scene_from_mz,
read_to_temp_file,
get_file_info
)
from .writer import (
write_scene_to_mz,
get_export_options
)
__all__ = [
'read_scene_from_mz',
'read_to_temp_file',
'get_file_info',
'write_scene_to_mz',
'get_export_options'
]
__version__ = '1.0.0'

11515
python/mz_core/reader.c Normal file

File diff suppressed because it is too large Load Diff

161
python/mz_core/reader.py Normal file
View File

@ -0,0 +1,161 @@
# -*- coding: utf-8 -*-
"""
Mz Translator Reader Module
Read Maya scene from .mz file (ZIP compressed, contains data.ma)
"""
import os
import zipfile
import tempfile
import io
import maya.OpenMaya as OpenMaya
def read_scene_from_mz(file_path, buffer=None):
"""
Read Maya scene from .mz file
Args:
file_path: Input .mz file path
buffer: Optional buffer for direct data reading
Returns:
str: data.ma content (if using buffer), or temp file path
Raises:
Exception: Raised when read fails
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"MZ file not found: {file_path}")
try:
# Open ZIP file
with zipfile.ZipFile(file_path, 'r') as zf:
# Check if contains data.ma
if 'data.ma' not in zf.namelist():
raise ValueError("Invalid .mz file: no data.ma found")
# Read data.ma content
ma_content = zf.read('data.ma')
if buffer is not None:
# Write to provided buffer
if hasattr(buffer, 'write'):
buffer.write(ma_content)
else:
raise ValueError("buffer must be a writable file-like object")
return buffer
else:
# Return content string (for stream reading)
return ma_content
except zipfile.BadZipFile:
raise ValueError("Invalid .mz file: not a valid ZIP file")
except Exception as e:
raise RuntimeError(f"Failed to read .mz file: {str(e)}")
def read_to_temp_file(file_path):
"""
Read from .mz file and write to temp file
Args:
file_path: Input .mz file path
Returns:
str: Temp data.ma file path
Note:
Need to call cleanup_temp_file after use
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"MZ file not found: {file_path}")
# Create temp directory
temp_dir = tempfile.mkdtemp(prefix='mz_import_')
temp_ma_path = os.path.normpath(os.path.join(temp_dir, 'data.ma'))
try:
# Open ZIP file
with zipfile.ZipFile(file_path, 'r') as zf:
# Check if contains data.ma
if 'data.ma' not in zf.namelist():
raise ValueError("Invalid .mz file: no data.ma found")
# Read and write to temp file
ma_content = zf.read('data.ma')
with open(temp_ma_path, 'wb') as f:
f.write(ma_content)
return temp_ma_path
except Exception as e:
# Cleanup temp files
_cleanup_temp_dir(temp_dir)
raise RuntimeError(f"Failed to extract .mz file: {str(e)}")
def read_to_buffer(buffer):
"""
Read .mz file data.ma content to buffer
Args:
buffer: Writable file object (must have write method)
Returns:
int: Number of bytes read
Note:
buffer should be an IOBase or similar object for Maya's file command
"""
# This is a wrapper for supporting stream reading
# Will be called in MPxFileTranslator.reader()
pass
def _cleanup_temp_dir(temp_dir):
"""
Cleanup temp directory
Args:
temp_dir: Temp directory path to delete
"""
import shutil
try:
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
except Exception:
pass
def get_file_info(file_path):
"""
Get .mz file info
Args:
file_path: .mz file path
Returns:
dict: Dictionary containing file info
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"MZ file not found: {file_path}")
info = {
'file_size': os.path.getsize(file_path),
'files': []
}
try:
with zipfile.ZipFile(file_path, 'r') as zf:
for name in zf.namelist():
info['files'].append({
'name': name,
'size': zf.getinfo(name).file_size,
'compressed_size': zf.getinfo(name).compress_size
})
except Exception as e:
raise ValueError(f"Invalid .mz file: {str(e)}")
return info

10132
python/mz_core/writer.c Normal file

File diff suppressed because it is too large Load Diff

124
python/mz_core/writer.py Normal file
View File

@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
"""
Mz Translator Writer Module
Write Maya scene to .mz file format (ZIP compressed, contains data.ma)
"""
import os
import tempfile
import zipfile
import maya.OpenMaya as OpenMaya
# import maya.OpenMayaAnim as OpenMayaAnim
def write_scene_to_mz(file_path, options=None):
"""
Write current Maya scene to .mz file
Args:
file_path: Output .mz file path
options: Export options dictionary
Returns:
bool: True if successful
Raises:
Exception: Raised when write fails
"""
if options is None:
options = {}
# Get compression level (default is maximum compression)
compression_level = options.get('compression', 9)
# Create temp directory for data.ma
temp_dir = tempfile.mkdtemp(prefix='mz_export_')
try:
# Temp data.ma file path
temp_ma_path = os.path.join(temp_dir, 'data.ma')
# Use MFileIO to export as Maya ASCII format
if not _export_to_ma(temp_ma_path):
raise RuntimeError("Failed to export scene to .ma format")
# Create .mz (ZIP) file
with zipfile.ZipFile(file_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression_level) as zf:
# Add data.ma to ZIP
zf.write(temp_ma_path, 'data.ma')
return True
except Exception as e:
raise RuntimeError(f"Failed to write .mz file: {str(e)}")
finally:
# Cleanup temp files
_cleanup_temp_dir(temp_dir)
def _export_to_ma(file_path):
"""
Export current scene to Maya ASCII (.ma) format
Args:
file_path: Output .ma file path
Returns:
bool: True if successful
"""
try:
# Get current scene name
scene_name = OpenMaya.MFileIO.currentFile()
# Use MFileIO to export scene
# Note: Use file command to export as ASCII format
import maya.cmds as cmds
# Export current scene as MA format
cmds.file(file_path, exportAll=True, type='mayaAscii', force=True)
return True
except Exception as e:
print(f"Export to MA failed: {str(e)}")
return False
def _cleanup_temp_dir(temp_dir):
"""
Cleanup temp directory
Args:
temp_dir: Temp directory path to delete
"""
import shutil
try:
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
except Exception:
pass
def get_export_options():
"""
Get export options definition
Returns:
dict: Options dictionary
"""
return {
'compression': {
'type': 'int',
'default': 9,
'min': 0,
'max': 9,
'description': 'Compression level (0-9)'
},
'version': {
'type': 'string',
'default': '1.0',
'description': 'MZ format version'
}
}

12
setup.py Normal file
View File

@ -0,0 +1,12 @@
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(
["python/mz_core/reader.py", "python/mz_core/writer.py"]),
include_dirs=[
"C:/Program Files/Autodesk/Maya2023/include/Python39/Python"
],
library_dirs=[
"C:/Program Files/Autodesk/Maya2023/lib"
])