Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ Avoids Blender's automatic `.001` suffix by resolving conflicts using your patte
#### Extensibility
- Element registration via `ElementRegistry`
- Target registration via `RenameTargetRegistry`
- Currently supports: Objects, Bones (Edit/Pose)
- Planned: Outliner items, Nodes, Sequences, Materials
- Currently supports 19 target types: Objects, Bones (Bone / Pose / Edit),
Collections, Materials, Meshes, Armatures, Curves, Cameras, Lights, Images,
Textures, Actions, Scenes, Nodes, Sequence Strips, Shape Keys, and Files

### UI / Operators

Expand Down
38 changes: 24 additions & 14 deletions dev-note/plans/2026-06-12-milestone.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,32 @@
→ tests/blender/test_props_uniqueness.py(addon_utils.enable で実物
prefs.patterns を駆動。「Name.001.001 増殖」の反転テスト含む6件)

### 3. 負債返済(05章 A-3 / Phase 5)
- [ ] dead code 削除 約2,400行: class_diagram_generator / screen_utils /
collection_utils / Timeout / AlphabeticCounter / コメントアウト残骸。
conftest スタブの該当エントリも一緒に消す(スタブが縮む=結合が減った証明)
- [ ] ID 型ターゲットのパラメータ化(550行 → 60行)
- [ ] position_element.py の register_element 遅延 import 化
(要素層→target 層のモジュールレベル結合の解消。text_element と統一)
- [ ] ロガー修復(強制 WARNING 上書きの除去、preferences.py:267-272)
- [ ] バリデーション3系統の統合
- [ ] **配布物の整合**: README のサポート対象(2世代遅れ)・バージョン番号
(1.1.0 / 1.0.0 / 0.9.0 混在)・bl_info と manifest の二重管理。
### 3. 負債返済(05章 A-3 / Phase 5)— 2026-06-13 発注 #2 で大半完了
- [x] dead code 削除: class_diagram_generator / screen_utils /
collection_utils / Timeout / AlphabeticCounter / コメントアウト残骸
(schema/pattern.py の旧 JSON スキーマ、target/registry.py の
_initialize_defaults、conflict.py の実験ブロック)+ facade の到達不能
_remove_deleted_patterns。**製品コード -2,236 行**(facade 94%→98% /
counter_element 65%→85% / 全体 28%→31%)。conflict.py の
_find_unused_min_counter_value と FORCE 関連コメントは §3.5 の
設計判断用に意図的に残置。conftest スタブも 31 行縮小
(_Operator + _Object/_PoseBone/_EditBone/_Node = 結合が減った証明)
- [ ] ID 型ターゲットのパラメータ化(550行 → 60行)— 構造変更のため別 PR
- [x] position_element.py の register_element 遅延 import 化
(text_element と同方式に統一。要素層→target 層のモジュールレベル結合が解消)
- [x] ロガー修復(強制 WARNING 上書きの除去)。実機プローブで
prefs・実ロガーとも INFO で立ち上がることを確認
- [ ] バリデーション3系統の統合 — 設計判断が必要なため対象外のまま
- [x] **配布物の整合**: バージョンは manifest の 1.1.0 を正として docs を追従、
bl_info の blender 最小を (4,2,0) に(manifest と一致)。README のサポート
対象を実装済み 19 ターゲットに訂正、getting_started のプリセット名も実在の
ファイル名に。bl_info と manifest の**二重管理自体は残る**(値は揃えた)。
ライセンスは **2026-06-13 に GPLv3 へ統一済み**(発注者判断。LICENSE は
実は AGPL 全文だった — typo ではなく過去の選択の形跡だったため確認のうえ差し替え)
- [ ] **requirements.txt の刷新**: Dependabot 指摘 24 件(high 10)の発生源。
docs ツールチェーンの古いピンを更新するか、pyproject の dependency-groups
(例: `docs` グループ)へ移行して requirements.txt を廃止する
- [x] **requirements.txt の刷新**: 廃止し pyproject の `docs` dependency-group へ
移行(構成は conf.py の extensions が正 — 旧 requirements.txt は myst-parser /
furo 等を欠く不完全なピンだった)。black は dev グループへ。fake-bpy-module は
スタブ規律(00-policy 原則2)保護のため**どのグループにも入れない**

### 3.5 設計判断: 非選択オブジェクトが占有するカウンターの扱い(2026-06-13 浮上)

Expand Down
2 changes: 1 addition & 1 deletion docs/source/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ The add-on includes various presets for different purposes (rigging, characters,

1. Click the import button ({material-regular}`download`) in the **Naming Patterns** section at the top of the panel.
2. When the file browser opens, navigate to the `resources/presets` folder in the add-on directory. (Usually opens automatically)
3. Select and import preset files you want to try, such as `vrm.json`, `hardsurface.json`, `archviz.json`, etc.
3. Select and import preset files you want to try, such as `vrm.json`, `hard surface.json`, `architecture.json`, etc.
4. The imported patterns will be added to the **Naming Patterns** dropdown.

For details: {ref}`Import/Export`
Expand Down
4 changes: 2 additions & 2 deletions docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Author
: Pluglug

Version
: 1.0.0
: 1.1.0

Compatibility
: Blender 4.4 - 3.6
: Blender 4.2 - 6.1

License
: GPLv3
Expand Down
2 changes: 1 addition & 1 deletion docs/source/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ If you want to edit the JSON file in an external editor, please refer to this JS
{
"type": "object",
"properties": {
// Specify the current version 1.0.0.
// Specify the current version 1.1.0.
"version": {
"type": "array",
"description": "Addon version when the file was exported.",
Expand Down
16 changes: 16 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ dev = [
"pytest>=8",
"hypothesis>=6",
"pytest-cov>=7.1.0",
"black>=25",
]
# docs ツールチェーン (旧 requirements.txt から移行)。構成は docs/source/conf.py の
# extensions リストが正。ビルド: `uv run --group docs sphinx-build docs/source <出力>`
# NOTE: fake-bpy-module はどのグループにも入れないこと — uv sync が入れる環境で
# `import bpy` が成功すると conftest の bpy スタブ規律 (00-policy 原則2) が壊れる
docs = [
"sphinx>=8",
"myst-parser",
"furo",
"sphinx-automodapi",
"sphinxcontrib-mermaid",
"sphinx-design",
"sphinx-copybutton",
"sphinx-togglebutton",
"atsphinx-color-text",
]

# このリポジトリは pip インストール可能なパッケージではない(アドオン本体は
Expand Down
38 changes: 0 additions & 38 deletions requirements.txt

This file was deleted.

5 changes: 1 addition & 4 deletions src/structured_renamer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Structured Renamer",
"author": "Pluglug",
"version": (1, 1, 0),
"blender": (3, 6, 5),
"blender": (4, 2, 0), # blender_manifest.toml の blender_version_min と一致させる
"location": "View3D > Sidebar > Tool Tab",
"description": "Deconstruct and reconstruct names with semantic elements.",
"doc_url": "https://pluglug.github.io/structured-renamer-docs",
Expand Down Expand Up @@ -50,9 +50,6 @@
"ui.pie_menu_props",
"targets",
"ui.operators",
"utils.class_diagram_generator",
"utils.collection_utils",
"utils.screen_utils",
"core.blender.outliner_struct",
"core.pattern.cache",
"utils.property_utils",
Expand Down
73 changes: 0 additions & 73 deletions src/structured_renamer/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -1058,76 +1058,3 @@ def _validate_class(cls: bpy.types.bpy_struct) -> None:
raise ValueError(f"Class {cls.__name__} has no bl_rna attribute")
if not issubclass(cls, bpy.types.bpy_struct):
raise TypeError(f"Invalid class type: {cls.__name__}")


# ======================================================
# タイムアウト管理
# ======================================================


class Timeout:
"""
遅延実行用オペレータ

Blenderのイベントシステムを利用して、指定された関数を
一定時間後に実行します。UIスレッドのブロックを回避する
ために使用します。
"""

bl_idname = f"{ADDON_PREFIX_PY}.timeout"
bl_label = ""
bl_options = {"INTERNAL"}

idx: bpy.props.IntProperty(options={"SKIP_SAVE", "HIDDEN"})
delay: bpy.props.FloatProperty(default=0.0001, options={"SKIP_SAVE", "HIDDEN"})

_data: Dict[int, tuple] = dict() # タイムアウト関数のデータ保持用
_timer = None
_finished = False

def modal(self, context, event):
if event.type == "TIMER":
if self._finished:
context.window_manager.event_timer_remove(self._timer)
del self._data[self.idx]
return {"FINISHED"}

if self._timer.time_duration >= self.delay:
self._finished = True
try:
func, args = self._data[self.idx]
func(*args)
except Exception as e:
print(f"Timeout error: {str(e)}")
return {"PASS_THROUGH"}

def execute(self, context):
self._finished = False
context.window_manager.modal_handler_add(self)
self._timer = context.window_manager.event_timer_add(
self.delay, window=context.window
)
return {"RUNNING_MODAL"}


TimeoutOperator = type(
"%s_OT_timeout" % ADDON_PREFIX, (Timeout, bpy.types.Operator), {}
)


def timeout(func: callable, *args) -> None:
"""
関数を遅延実行

Blenderのモーダルイベントを利用して関数を非同期で実行します。
UI更新や時間のかかる処理の分散に役立ちます。

Args:
func: 実行する関数
*args: 関数に渡す引数
"""
idx = len(Timeout._data)
while idx in Timeout._data:
idx += 1
Timeout._data[idx] = (func, args)
getattr(bpy.ops, ADDON_PREFIX_PY).timeout(idx=idx)
5 changes: 0 additions & 5 deletions src/structured_renamer/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@
ic("EVENT_NDOF_BUTTON_1"),
2,
), # BLANK1 SNAP_VERTEX ONIONSKIN_ON
# (
# "alphabetic_counter",
# "Alphabetic Counter",
# "Alphabetic counter with formatting options",
# ),
# ("date", "Date", "Date in various formats"),
# ("regex", "RegEx", "Custom regular expression pattern"),
]
Expand Down
19 changes: 0 additions & 19 deletions src/structured_renamer/core/namespace/conflict.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,24 +192,6 @@ def _resolve_with_counter(
if e.element_type == "numeric_counter" and e.enabled and e.count_up
]
numeric_counter = counters[-1] if counters else None
# blender_counter = [
# e for e in pattern.elements if isinstance(e, BlenderCounter)
# ][-1]

# log.info(f"numeric_counter: {numeric_counter.value}")
# log.info(f"blender_counter: {blender_counter.value}")

# # BlenderCounterの値を優先的に使用
# if blender_counter.value is not None:
# # BlenderCounterの値を直接設定
# counter_value = int(blender_counter.value.lstrip("."))
# numeric_counter.set_value(str(counter_value))
# log.info(f"set counter value: {counter_value}")
# else:
# # BlenderCounterの値がない場合は、現在のNumericCounterの値を使用
# current_value = numeric_counter.value_int or 1
# numeric_counter.set_value(str(current_value))
# log.info(f"using current counter: {current_value}")

if not numeric_counter:
# カウンター要素がない場合は単純にサフィックスを追加
Expand All @@ -236,7 +218,6 @@ def _resolve_with_counter(
# TODO: Patternがincrementすべき
numeric_counter.increment()
proposed_name = pattern.render_name()
# proposed_name = numeric_counter.gen_proposed_name(idx)
log.debug(f"Conflict Resolver: render_name() -> {proposed_name}")

if proposed_name == current_name or not namespace.contains(proposed_name):
Expand Down
16 changes: 0 additions & 16 deletions src/structured_renamer/core/pattern/facade.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ def synchronize_patterns(self) -> None:
return

self._synchronize_modified_patterns()
self._remove_deleted_patterns()

def _synchronize_modified_patterns(self) -> None:
"""Synchronize new or modified patterns"""
Expand Down Expand Up @@ -145,21 +144,6 @@ def _should_update_pattern(
is_new = pattern.id not in cached_ids
return is_new or pattern.modified

def _remove_deleted_patterns(self) -> None:
"""Remove deleted patterns from cache"""
patterns = get_prefs(self._context).patterns
prefs_pattern_ids = set(p.id for p in patterns)
cached_pattern_ids = set(self._pattern_cache.keys())
removed_count = 0

for pattern_id in cached_pattern_ids - prefs_pattern_ids:
del self._pattern_cache[pattern_id]
removed_count += 1
log.debug(f"Pattern '{pattern_id}' removed from cache")

if removed_count > 0:
log.info(f"{removed_count} patterns removed from cache")

# キャッシュ管理
def clear_cache(self) -> None:
"""Clear the cache"""
Expand Down
Loading
Loading