blenderpython/suw_observer.py

317 lines
9.0 KiB
Python
Raw Normal View History

2025-08-01 17:13:30 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SUW Observer - Python翻译版本
原文件: SUWObserver.rb
用途: 观察者类监听Blender中的事件
"""
from typing import Optional, List, Any
try:
import bpy
from bpy.app.handlers import persistent
BLENDER_AVAILABLE = True
except ImportError:
BLENDER_AVAILABLE = False
# 定义一个假的persistent装饰器
def persistent(func):
return func
print("⚠️ Blender API 不可用,观察者功能将被禁用")
class SUWToolsObserver:
"""工具观察者类 - 监听工具变化"""
cloned_zone = None
def __init__(self):
self.current_tool = None
def on_active_tool_changed(self, context, tool_name: str, tool_id: int):
"""当活动工具改变时调用"""
try:
from .suw_core import get_selection_manager
# 工具ID常量对应SketchUp的工具ID
MOVE_TOOL_ID = 21048
ROTATE_TOOL_ID = 21129
SCALE_TOOL_ID = 21236
selection_manager = get_selection_manager()
if tool_id == SCALE_TOOL_ID:
# 注意:这里需要根据实际需求调用相应的方法
# 暂时使用sel_clear作为替代
selection_manager.sel_clear()
else:
# 暂时使用sel_clear作为替代
selection_manager.sel_clear()
except ImportError:
print(f"工具变化: {tool_name} (ID: {tool_id})")
class SUWSelectionObserver:
"""选择观察者类 - 监听选择变化"""
def __init__(self):
self.last_selection = []
def on_selection_bulk_change(self, selection: List[Any]):
"""当选择批量改变时调用"""
try:
from .suw_core import get_selection_manager
from .suw_client import set_cmd
selection_manager = get_selection_manager()
if len(selection) <= 0:
# 检查是否有订单ID且之前有选择
if self._has_order_id() and selection_manager.selected_uid():
set_cmd("r01", {}) # 切换到订单编辑界面
selection_manager.sel_clear() # 清除数据
return
# 过滤SUWood对象
suw_objs = self._filter_suw_objects(selection)
if not suw_objs:
if self._has_order_id() and selection_manager.selected_uid():
set_cmd("r01", {})
selection_manager.sel_clear()
elif len(suw_objs) == 1:
# 选择单个SUWood对象
self._clear_selection()
selection_manager.sel_local(suw_objs[0])
except ImportError:
print(f"选择变化: {len(selection)} 个对象")
def _filter_suw_objects(self, selection: List[Any]) -> List[Any]:
"""过滤SUWood对象"""
suw_objs = []
for obj in selection:
if self._is_suw_object(obj):
suw_objs.append(obj)
return suw_objs
def _is_suw_object(self, obj: Any) -> bool:
"""检查是否是SUWood对象"""
if not BLENDER_AVAILABLE:
return False
# 检查对象是否有SUWood属性
return (
obj and
hasattr(obj, 'get') and
obj.get("uid") is not None
)
def _has_order_id(self) -> bool:
"""检查是否有订单ID"""
if not BLENDER_AVAILABLE:
return False
scene = bpy.context.scene
return scene.get("order_id") is not None
def _clear_selection(self):
"""清除选择"""
if BLENDER_AVAILABLE:
bpy.ops.object.select_all(action='DESELECT')
class SUWModelObserver:
"""模型观察者类 - 监听模型事件"""
def on_save_model(self, context):
"""当模型保存时调用"""
try:
from .suw_client import set_cmd
from .suw_constants import SUWood
if not BLENDER_AVAILABLE:
return
scene = bpy.context.scene
order_id = scene.get("order_id")
if order_id is None:
return
params = {
"method": SUWood.SUSceneSave,
"order_id": order_id
}
set_cmd("r00", params)
except ImportError:
print("模型保存事件")
class SUWAppObserver:
"""应用观察者类 - 监听应用级事件"""
def __init__(self):
self.tools_observer = SUWToolsObserver()
self.selection_observer = SUWSelectionObserver()
self.model_observer = SUWModelObserver()
def on_new_model(self, context):
"""当新建模型时调用"""
try:
from .suw_core import init_all_managers
from .suw_client import set_cmd
from .suw_constants import SUWood
# 初始化所有管理器
init_all_managers()
# 注册观察者
self._register_observers()
params = {
"method": SUWood.SUSceneNew
}
set_cmd("r00", params)
except ImportError:
print("新建模型事件")
def on_open_model(self, context, filepath: str):
"""当打开模型时调用"""
try:
from .suw_core import init_all_managers
from .suw_client import set_cmd
from .suw_constants import SUWood
# 初始化所有管理器
init_all_managers()
# 注册观察者
self._register_observers()
if not BLENDER_AVAILABLE:
return
scene = bpy.context.scene
order_id = scene.get("order_id")
# 如果有订单ID清除相关实体
if order_id is not None:
self._clear_suw_entities()
params = {
"method": SUWood.SUSceneOpen
}
if order_id is not None:
params["order_id"] = order_id
set_cmd("r00", params)
except ImportError:
print(f"打开模型事件: {filepath}")
def _register_observers(self):
"""注册观察者"""
if BLENDER_AVAILABLE:
# 在Blender中注册相关的处理器
self._register_handlers()
def _register_handlers(self):
"""注册Blender处理器"""
if not BLENDER_AVAILABLE:
return
# 注册保存处理器
if self._save_handler not in bpy.app.handlers.save_pre:
bpy.app.handlers.save_pre.append(self._save_handler)
# 注册加载处理器
if self._load_handler not in bpy.app.handlers.load_post:
bpy.app.handlers.load_post.append(self._load_handler)
@persistent
def _save_handler(self, context):
"""保存处理器"""
self.model_observer.on_save_model(context)
@persistent
def _load_handler(self, context):
"""加载处理器"""
filepath = bpy.data.filepath
self.on_open_model(context, filepath)
def _clear_suw_entities(self):
"""清除SUWood实体"""
if not BLENDER_AVAILABLE:
return
scene = bpy.context.scene
objects_to_delete = []
for obj in scene.objects:
if obj.get("uid") is not None:
objects_to_delete.append(obj)
# 删除对象
for obj in objects_to_delete:
bpy.data.objects.remove(obj, do_unlink=True)
# 全局观察者实例
_app_observer = None
def get_app_observer():
"""获取应用观察者实例"""
global _app_observer
if _app_observer is None:
_app_observer = SUWAppObserver()
return _app_observer
def register_observers():
"""注册所有观察者"""
observer = get_app_observer()
observer._register_observers()
print("✅ SUWood 观察者已注册")
def unregister_observers():
"""注销所有观察者"""
if not BLENDER_AVAILABLE:
return
observer = get_app_observer()
# 移除处理器
try:
if observer._save_handler in bpy.app.handlers.save_pre:
bpy.app.handlers.save_pre.remove(observer._save_handler)
if observer._load_handler in bpy.app.handlers.load_post:
bpy.app.handlers.load_post.remove(observer._load_handler)
print("✅ SUWood 观察者已注销")
except Exception as e:
print(f"❌ 注销观察者时出错: {e}")
if __name__ == "__main__":
print("🚀 SUW观察者测试")
if BLENDER_AVAILABLE:
print("Blender API 可用,注册观察者...")
register_observers()
else:
print("Blender API 不可用,创建观察者实例进行测试...")
observer = get_app_observer()
print(f"观察者创建成功: {observer.__class__.__name__}")