blenderpython/suw_core/command_dispatcher.py

671 lines
24 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SUW Core - Command Dispatcher Module
拆分自: suw_impl.py (剩余所有命令方法)
用途: 命令分发器、选择管理、显示控制、辅助功能
版本: 1.0.0
作者: SUWood Team
"""
from .geometry_utils import MAT_TYPE_OBVERSE, MAT_TYPE_NORMAL, MAT_TYPE_NATURE
from .dimension_manager import dimension_manager
from .data_manager import data_manager, get_data_manager
from .door_drawer_manager import door_drawer_manager
from .hardware_manager import hardware_manager
from .deletion_manager import deletion_manager
from .selection_manager import selection_manager
from .machining_manager import machining_manager
from .part_creator import part_creator
from .material_manager import material_manager
from .memory_manager import memory_manager
import logging
from typing import Dict, Any, Optional
# 设置日志
logger = logging.getLogger(__name__)
# 检查Blender可用性
try:
import bpy
BLENDER_AVAILABLE = True
except ImportError:
BLENDER_AVAILABLE = False
# 导入依赖模块
# ==================== 命令分发器类 ====================
class CommandDispatcher:
"""命令分发器 - 负责所有命令分发和控制操作"""
def __init__(self):
"""
初始化命令分发器 - 完全独立不依赖suw_impl
"""
# 使用全局数据管理器
self.data_manager = get_data_manager()
self.selected_parts = set()
self.mat_type = MAT_TYPE_NORMAL
# 命令映射表
self.command_map = {
'c00': self.c00,
'c01': self.c01,
'c02': self.c02,
'c03': self.c03,
'c04': self.c04,
'c05': self.c05,
'c07': self.c07,
'c08': self.c08,
'c09': self.c09,
'c0a': self.c0a,
'c0c': self.c0c,
'c0d': self.c0d,
'c0e': self.c0e,
'c0f': self.c0f,
'c10': self.c10,
'c11': self.c11,
'c12': self.c12,
'c13': self.c13,
'c14': self.c14,
'c15': self.c15,
'c16': self.c16,
'c17': self.c17,
'c18': self.c18,
'c1a': self.c1a,
'c1b': self.c1b,
'c23': self.c23,
'c24': self.c24,
'c25': self.c25,
'c28': self.c28,
'c30': self.c30,
'set_config': self.set_config,
}
logger.info("CommandDispatcher 初始化完成")
# ==================== 材质控制命令 ====================
def c11(self, data: Dict[str, Any]):
"""part_obverse - 设置零件正面显示"""
try:
# 【修复】调用材质管理器的c11方法
from .material_manager import material_manager, init_material_manager
if not material_manager:
init_material_manager()
from .material_manager import material_manager
if material_manager:
return material_manager.c11(data)
else:
logger.warning("MaterialManager 初始化失败")
return None
except Exception as e:
logger.error(f"设置零件正面显示失败: {e}")
return None
def c30(self, data: Dict[str, Any]):
"""part_nature - 设置零件自然显示"""
try:
# 【修复】调用材质管理器的c30方法
from .material_manager import material_manager, init_material_manager
if not material_manager:
init_material_manager()
from .material_manager import material_manager
if material_manager:
return material_manager.c30(data)
else:
logger.warning("MaterialManager 初始化失败")
return None
except Exception as e:
logger.error(f"设置零件自然显示失败: {e}")
return None
def _is_selected_part(self, part):
"""检查零件是否被选中"""
return part in self.selected_parts
# ==================== 核心功能命令 ====================
def c02(self, data: Dict[str, Any]):
"""add_texture - 添加纹理"""
try:
# 【修复】直接检查全局变量如果为None就创建
from .material_manager import material_manager, init_material_manager
if not material_manager:
init_material_manager()
from .material_manager import material_manager
if material_manager:
return material_manager.c02(data)
else:
logger.warning("MaterialManager 初始化失败")
return None
except Exception as e:
logger.warning(f"MaterialManager 初始化失败: {e}")
return None
def c04(self, data: Dict[str, Any]):
"""add_part - 添加部件"""
try:
from .part_creator import part_creator, init_part_creator
if not part_creator:
init_part_creator()
from .part_creator import part_creator
if part_creator:
return part_creator.c04(data)
else:
logger.warning("PartCreator 初始化失败")
return None
except Exception as e:
logger.warning(f"PartCreator 初始化失败: {e}")
return None
def c05(self, data: Dict[str, Any]):
"""add_machining - 添加加工"""
try:
from .machining_manager import machining_manager, init_machining_manager
if not machining_manager:
init_machining_manager()
from .machining_manager import machining_manager
if machining_manager:
return machining_manager.c05(data)
else:
logger.warning("MachiningManager 初始化失败")
return None
except Exception as e:
logger.warning(f"MachiningManager 初始化失败: {e}")
return None
def c07(self, data: Dict[str, Any]):
"""add_dimension - 添加尺寸标注"""
try:
from .dimension_manager import dimension_manager, init_dimension_manager
if not dimension_manager:
init_dimension_manager()
from .dimension_manager import dimension_manager
if dimension_manager:
return dimension_manager.c07(data)
else:
logger.warning("DimensionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"DimensionManager 初始化失败: {e}")
return None
def c08(self, data: Dict[str, Any]):
"""add_hardware - 添加五金"""
try:
from .hardware_manager import hardware_manager, init_hardware_manager
if not hardware_manager:
init_hardware_manager()
from .hardware_manager import hardware_manager
if hardware_manager:
return hardware_manager.c08(data)
else:
logger.warning("HardwareManager 初始化失败")
return None
except Exception as e:
logger.warning(f"HardwareManager 初始化失败: {e}")
return None
def c09(self, data: Dict[str, Any]):
"""del_entity - 删除实体"""
try:
from .deletion_manager import deletion_manager, init_deletion_manager
if not deletion_manager:
init_deletion_manager()
from .deletion_manager import deletion_manager
if deletion_manager:
return deletion_manager.c09(data)
else:
logger.warning("DeletionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"DeletionManager 初始化失败: {e}")
return None
def c0a(self, data: Dict[str, Any]):
"""del_machining - 删除加工"""
try:
logger.info("删除加工")
from .machining_manager import machining_manager, init_machining_manager
if not machining_manager:
init_machining_manager()
from .machining_manager import machining_manager
if machining_manager:
return machining_manager.c0a(data)
else:
logger.warning("MachiningManager 初始化失败")
return None
except Exception as e:
logger.error(f"删除加工失败: {e}")
return None
def c0c(self, data: Dict[str, Any]):
"""del_dimension - 删除尺寸标注"""
try:
logger.info("删除尺寸标注")
# 【修复】应该路由到DimensionManager而不是DeletionManager
from .dimension_manager import dimension_manager, init_dimension_manager
if not dimension_manager:
init_dimension_manager()
from .dimension_manager import dimension_manager
if dimension_manager:
return dimension_manager.c0c(data)
else:
logger.warning("DimensionManager 初始化失败")
return None
except Exception as e:
logger.error(f"c0c命令执行失败: {e}")
return None
def c03(self, data: Dict[str, Any]):
"""add_zone - 添加区域"""
try:
from .deletion_manager import deletion_manager, init_deletion_manager
if not deletion_manager:
init_deletion_manager()
from .deletion_manager import deletion_manager
if deletion_manager:
return deletion_manager.c03(data)
else:
logger.warning("DeletionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"DeletionManager 初始化失败: {e}")
return None
# ==================== 选择和导航命令 ====================
def c15(self, data: Dict[str, Any]):
"""sel_unit - 显示框架 / 清除选择状态"""
try:
from .selection_manager import selection_manager, init_selection_manager
if not selection_manager:
init_selection_manager()
from .selection_manager import selection_manager
if selection_manager:
return selection_manager.c15(data)
else:
logger.warning("SelectionManager 初始化失败")
return None
except Exception as e:
logger.error(f"c15命令执行失败: {e}")
return None
def c16(self, data: Dict[str, Any]):
"""sel_zone - 选择区域"""
try:
from .selection_manager import selection_manager, init_selection_manager
if not selection_manager:
init_selection_manager()
from .selection_manager import selection_manager
if selection_manager:
return selection_manager.c16(data)
else:
logger.warning("SelectionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"SelectionManager 初始化失败: {e}")
return None
def c17(self, data: Dict[str, Any]):
"""sel_elem - 选择元素"""
try:
from .selection_manager import selection_manager, init_selection_manager
if not selection_manager:
init_selection_manager()
from .selection_manager import selection_manager
if selection_manager:
return selection_manager.c17(data)
else:
logger.warning("SelectionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"SelectionManager 初始化失败: {e}")
return None
# ==================== 模式切换命令 ====================
def c10(self, data: Dict[str, Any]):
"""set_doorinfo - 设置门信息"""
try:
logger.info("设置门信息")
from .door_drawer_manager import door_drawer_manager, init_door_drawer_manager
if not door_drawer_manager:
init_door_drawer_manager()
from .door_drawer_manager import door_drawer_manager
if door_drawer_manager:
return door_drawer_manager.c10(data)
else:
logger.warning("DoorDrawerManager 初始化失败")
return None
except Exception as e:
logger.error(f"设置门信息失败: {e}")
return None
def c1a(self, data: Dict[str, Any]):
"""open_doors - 打开门板"""
try:
logger.info("打开门板")
from .door_drawer_manager import door_drawer_manager, init_door_drawer_manager
if not door_drawer_manager:
init_door_drawer_manager()
from .door_drawer_manager import door_drawer_manager
if door_drawer_manager:
return door_drawer_manager.c1a(data)
else:
logger.warning("DoorDrawerManager 初始化失败")
return None
except Exception as e:
logger.error(f"打开门板失败: {e}")
return None
def c1b(self, data: Dict[str, Any]):
"""slide_drawers - 打开抽屉"""
try:
logger.info("打开抽屉")
from .door_drawer_manager import door_drawer_manager, init_door_drawer_manager
if not door_drawer_manager:
init_door_drawer_manager()
from .door_drawer_manager import door_drawer_manager
if door_drawer_manager:
return door_drawer_manager.c1b(data)
else:
logger.warning("DoorDrawerManager 初始化失败")
return None
except Exception as e:
logger.error(f"打开抽屉失败: {e}")
return None
# ==================== 控制命令 ====================
def c18(self, data: Dict[str, Any]):
"""hide_door - 隐藏门板"""
try:
logger.info("隐藏门板")
from .door_drawer_manager import door_drawer_manager, init_door_drawer_manager
if not door_drawer_manager:
init_door_drawer_manager()
from .door_drawer_manager import door_drawer_manager
if door_drawer_manager:
return door_drawer_manager.c18(data)
else:
logger.warning("DoorDrawerManager 初始化失败")
return None
except Exception as e:
logger.error(f"隐藏门板失败: {e}")
return None
def c28(self, data: Dict[str, Any]):
"""hide_drawer - 隐藏抽屉"""
try:
logger.info("隐藏抽屉")
from .door_drawer_manager import door_drawer_manager, init_door_drawer_manager
if not door_drawer_manager:
init_door_drawer_manager()
from .door_drawer_manager import door_drawer_manager
if door_drawer_manager:
return door_drawer_manager.c28(data)
else:
logger.warning("DoorDrawerManager 初始化失败")
return None
except Exception as e:
logger.error(f"隐藏抽屉失败: {e}")
return None
def c0f(self, data: Dict[str, Any]):
"""refresh_view - 刷新视图"""
try:
logger.info("刷新视图")
# 刷新Blender视图
from .selection_manager import get_selection_manager
sm = get_selection_manager()
if sm:
return sm.view_front_and_zoom_extents()
except Exception as e:
logger.error(f"刷新视图失败: {e}")
# ==================== 图层控制命令 ====================
def c23(self, data: Dict[str, Any]):
"""hide_layer - 隐藏图层"""
try:
layer_name = data.get("layer")
logger.info(f"隐藏图层: {layer_name}")
if BLENDER_AVAILABLE and layer_name:
# 隐藏指定图层
if hasattr(bpy.data, 'collections') and layer_name in bpy.data.collections:
collection = bpy.data.collections[layer_name]
collection.hide_viewport = True
except Exception as e:
logger.error(f"隐藏图层失败: {e}")
def c24(self, data: Dict[str, Any]):
"""show_layer - 显示图层"""
try:
layer_name = data.get("layer")
logger.info(f"显示图层: {layer_name}")
if BLENDER_AVAILABLE and layer_name:
# 显示指定图层
if hasattr(bpy.data, 'collections') and layer_name in bpy.data.collections:
collection = bpy.data.collections[layer_name]
collection.hide_viewport = False
except Exception as e:
logger.error(f"显示图层失败: {e}")
def c25(self, data: Dict[str, Any]):
"""toggle_layer - 切换图层"""
try:
layer_name = data.get("layer")
logger.info(f"切换图层: {layer_name}")
if BLENDER_AVAILABLE and layer_name:
# 切换指定图层显示状态
if hasattr(bpy.data, 'collections') and layer_name in bpy.data.collections:
collection = bpy.data.collections[layer_name]
collection.hide_viewport = not collection.hide_viewport
except Exception as e:
logger.error(f"切换图层失败: {e}")
# ==================== 视图控制命令 ====================
def c00(self, data: Dict[str, Any]):
"""zoom_extents - 缩放到全部"""
try:
logger.info("缩放到全部")
if BLENDER_AVAILABLE:
# 缩放到所有对象
bpy.ops.view3d.view_all()
except Exception as e:
logger.error(f"缩放到全部失败: {e}")
def c01(self, data: Dict[str, Any]):
"""zoom_selection - 缩放到选择"""
try:
logger.info("缩放到选择")
if BLENDER_AVAILABLE:
# 缩放到选中对象
bpy.ops.view3d.view_selected()
except Exception as e:
logger.error(f"缩放到选择失败: {e}")
# ==================== 保存和导出命令 ====================
def c12(self, data: Dict[str, Any]):
"""create_contour - 创建轮廓"""
try:
logger.info("创建轮廓")
from .dimension_manager import dimension_manager, init_dimension_manager
if not dimension_manager:
init_dimension_manager()
from .dimension_manager import dimension_manager
if dimension_manager:
return dimension_manager.c12(data)
else:
logger.warning("DimensionManager 初始化失败")
return None
except Exception as e:
logger.error(f"创建轮廓失败: {e}")
def c13(self, data: Dict[str, Any]):
"""save_pixmap - 保存图像"""
try:
logger.info("保存图像")
# 图像保存功能暂时简化
return True
except Exception as e:
logger.error(f"保存图像失败: {e}")
def c14(self, data: Dict[str, Any]):
"""pre_save_pixmap - 预保存图像"""
try:
logger.info("预保存图像")
# 预保存功能暂时简化
return True
except Exception as e:
logger.error(f"预保存图像失败: {e}")
# ==================== 标注和显示命令 ====================
def c0d(self, data: Dict[str, Any]):
"""parts_seqs - 设置零件序列信息"""
try:
from .explosion_manager import explosion_manager, init_explosion_manager
if not explosion_manager:
init_explosion_manager()
from .explosion_manager import explosion_manager
if explosion_manager:
return explosion_manager.c0d(data)
else:
logger.warning("ExplosionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"ExplosionManager 初始化失败: {e}")
return None
def c0e(self, data: Dict[str, Any]):
"""explode_zones - 炸开柜体"""
try:
from .explosion_manager import explosion_manager, init_explosion_manager
if not explosion_manager:
init_explosion_manager()
from .explosion_manager import explosion_manager
if explosion_manager:
return explosion_manager.c0e(data)
else:
logger.warning("ExplosionManager 初始化失败")
return None
except Exception as e:
logger.warning(f"ExplosionManager 初始化失败: {e}")
return None
# ==================== 分发器方法 ====================
def dispatch_command(self, command: str, data: Dict[str, Any]):
"""分发命令到相应的处理器"""
try:
if command in self.command_map:
handler = self.command_map[command]
return handler(data)
else:
logger.warning(f"未知命令: {command}")
return None
except Exception as e:
logger.error(f"命令分发失败 {command}: {e}")
return None
def get_dispatcher_stats(self) -> Dict[str, Any]:
"""获取分发器统计信息"""
try:
stats = {
"manager_type": "CommandDispatcher",
"available_commands": list(self.command_map.keys()),
"command_count": len(self.command_map),
"mat_type": getattr(self, 'mat_type', MAT_TYPE_NORMAL),
"selected_parts_count": len(self.selected_parts),
"blender_available": BLENDER_AVAILABLE
}
return stats
except Exception as e:
logger.error(f"获取分发器统计失败: {e}")
return {"error": str(e)}
def set_config(self, data: dict):
"""全局/单元配置命令"""
try:
from .selection_manager import selection_manager, init_selection_manager
if not selection_manager:
init_selection_manager()
from .selection_manager import selection_manager
if selection_manager:
return selection_manager.set_config(data)
else:
logger.warning("SelectionManager 初始化失败")
return None
except Exception as e:
logger.error(f"set_config命令执行失败: {e}")
return None
# ==================== 模块实例 ====================
# 全局实例将由SUWImpl初始化时设置
command_dispatcher = None
def init_command_dispatcher():
"""初始化命令分发器 - 不再需要suw_impl参数"""
global command_dispatcher
command_dispatcher = CommandDispatcher()
return command_dispatcher
def get_command_dispatcher():
"""获取命令分发器实例"""
global command_dispatcher
if command_dispatcher is None:
command_dispatcher = init_command_dispatcher()
return command_dispatcher
def get_dispatcher_stats():
"""获取命令分发器统计信息"""
if command_dispatcher:
return command_dispatcher.get_dispatcher_stats()
return {"error": "CommandDispatcher not initialized"}