Initial SE Palette add-on

This commit is contained in:
2026-09-03 03:17:27 +09:00
commit 524d98f620
11 changed files with 877 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
"""Blenderに依存しないSEライブラリの走査・設定処理。"""
from __future__ import annotations
import json
import os
from pathlib import Path
AUDIO_EXTENSIONS = {".mp3", ".wav", ".flac", ".ogg", ".m4a", ".aac"}
CONFIG_FILENAME = ".se_palette.json"
def scan_audio_files(folder: str) -> list[Path]:
"""フォルダ直下の対応音声ファイルを名前順で返す。"""
root = Path(folder).expanduser()
if not root.is_dir():
return []
return sorted(
(
path
for path in root.iterdir()
if path.is_file() and path.suffix.lower() in AUDIO_EXTENSIONS
),
key=lambda path: path.name.casefold(),
)
def default_label(path: Path) -> str:
"""拡張子と管理用の先頭番号を除いた表示名を作る。"""
label = path.stem
if len(label) > 3 and label[:2].isdigit() and label[2] in {"_", "-", " "}:
label = label[3:]
return label.replace("_", " ")
def load_config(folder: str) -> dict:
config_path = Path(folder).expanduser() / CONFIG_FILENAME
if not config_path.is_file():
return {"items": {}}
try:
data = json.loads(config_path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return {"items": {}}
if not isinstance(data, dict) or not isinstance(data.get("items", {}), dict):
return {"items": {}}
return data
def save_config(folder: str, items: list[dict]) -> Path:
root = Path(folder).expanduser()
root.mkdir(parents=True, exist_ok=True)
config_path = root / CONFIG_FILENAME
payload = {
"version": 1,
"items": {
item["filename"]: {
"label": item.get("label", ""),
"icon": item.get("icon", "PLAY_SOUND"),
"icon_path": item.get("icon_path", ""),
}
for item in items
},
}
temporary_path = config_path.with_suffix(config_path.suffix + ".tmp")
temporary_path.write_text(
json.dumps(payload, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
os.replace(temporary_path, config_path)
return config_path