#!/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__}")