- 桌面应用
- 3D建模
【免费下载链接】CAD_Sketcher
Constraint-based geometry sketcher for blender
本文围绕 Blender 约束草图扩展 CAD Sketcher 的用户界面文档展开,完整讲解 N 侧边栏(Sketch Selector、Tools、Entity/Constraint Browser)、约束 Gizmo 与上下文菜单的交互方式,并结合 base/preferences.py 等源码逐项补充偏好设置项的默认值、取值范围与底层实现,帮助开发者既会用 UI,也能理解每个开关背后的代码路径。
Sketcher 侧边栏总览
扩展在 N 侧边栏的 "Sketcher" 分类下挂接了若干面板:可以从中设置活动草图(active sketch)、访问草图属性、添加约束,并通过元素浏览器(browsers)与几何元素交互。
从 ui/init.py 的注册列表可以看到整个侧边栏的组成:
VIEW3D_PT_sketcher:Sketch Selector 面板(选择/进入草图),实现在 ui/panels/sketch_select.py;VIEW3D_PT_sketcher_tools:Tools 面板,实现在 ui/panels/tools.py;VIEW3D_PT_sketcher_entities:实体浏览器,实现在 ui/panels/entities_list.py;VIEW3D_PT_sketcher_constraints:约束浏览器,实现在 ui/panels/constraints_list.py;- 另外还注册了
VIEW3D_UL_features特征列表和若干菜单(VIEW3D_MT_selected_menu、VIEW3D_MT_slvs_part等)。
Sketch Selector:进入与离开草图
没有活动草图时,侧边栏会列出当前所选 part 范围内的全部草图,可以从那里把某个草图设为活动状态,或切换其可见性。由于草图本身是纯源数据(source),在视口中保持隐藏,眼睛图标切换的其实是它被实体化(realise)到的 body——那才是屏幕上代表它的东西。
一旦有草图处于活动状态,UI 会切换形态:出现一个醒目的(按下状态的)蓝色按钮用于退出草图,下方显示该草图及其所在 workplane 的属性。对照 ui/panels/sketch_select.py 的sketch_selector函数:
- 无活动草图时绘制
Add Sketch按钮(通过StatefulOps.InvokeTool调用AddSketch工作区工具),旁边还有一个下拉菜单,包含较不常用的自由 3D 草图模式(Add 3D Sketch算子,见 operators/add_sketch_3d.py); - 有活动草图时绘制
Leave: <name>按钮(depress=True的SetActiveSketch,sketch_name置空即离开草图),并在sketch.geometry_solved为假时把整行标红告警,旁边还有Update刷新按钮; - 进入草图后还会显示求解状态:若
solver_state != "OKAY"则显示状态名与图标,否则显示自由度(dof)——"Fully defined sketch" 或 "Degrees of freedom: n"。
_draw_workplane函数还会展示 workplane 及其 face anchor:锚定在网格面上时显示"<mesh>, face <index>"形式的锚点名称;当锚点与面脱离(KEY_DETACHED)时以红色 "Detached from face" 告警,并可通过下拉菜单执行 "Make Workplane Free" 解除锚定。
Tools Panel:作用于整个草图的工具
Tools 面板收纳的是"作用于整个草图而非单个元素"的工具:Merge Points、Project Geometry,以及添加约束的按钮组。不在草图内时,这里改为提供 Make Part 和 Add Assembly。
约束按钮有两种布局,通过 "Constraints" 标题行右侧的图标切换:紧凑的icon grid(默认)或带约束名称的列表。无论哪种布局,尺寸约束(dimensional)都与几何约束(geometric)分开排列,并且只显示适用于当前草图模式的约束。
ui/panels/tools.py 的实现印证了这些细节:
- 布局开关直接切换偏好项
constraint_grid_view(见base/preferences.py中该属性,默认True,即默认网格视图)。切换按钮使用wm.context_toggle算子而非普通的属性勾选框——源码注释解释得很直白:勾选框会把图标染成开/关状态色(白/黑),而算子图标始终跟随主题; - 网格视图下用
grid_flow(columns=5)排布纯图标按钮(约束名仍在 tooltip 中显示),尺寸约束单独成行一个网格,与几何约束网格同列数同缩放,保证按钮尺寸一致;列表视图下则按kind.title()显示名称; - 3D 草图(
sketch.is_3d)下会过滤按钮:只保留求解器实际派发的约束(declarations.Supported3DConstraintOperators与Supported3DDimensionKinds),采用"隐藏而非禁用"的策略,让可见按钮在网格中保持无缝的合并布局; - 面板底部还有
Drawing:区域,显示场景属性scene.sketcher.use_construction(构造线开关)。
不在草图内时,_draw_node_tools改为列出节点修改器工具:NodeExtrude、NodeRevolve、NodeArrayLinear、NodeArrayCircular、NodeBoolean。
Entity Browser 与 Constraint Browser
Entity Browser(bl_label = "Entities")列出当前全部 active entities,每种类型配一个图标,点击名称即可选中。从 ui/panels/entities_list.py 可以看到每行的完整结构:
- 数据直接读取草图 curve data 上的属性字段
curve_id、sketch_type、visible、construction、name——如果curve_id或sketch_type缺失整个面板就不渲染; - 行首是两个小开关:
Select算子(mode="TOGGLE",按 curve_id 切换选中,选中行整行标红提示)和SetCurveFlag算子(flag="visible"切换可见性); - 名称字段本身是
RenameCurve算子,点击即可重命名,行首图标由icon_manager.get_entity_icon(ctype, construction)给出,构造线显示虚线样式; - 行尾是
ContextMenu算子(打开该实体的上下文菜单,悬停时高亮实体)和DeleteEntity删除按钮。
Constraint Browser(bl_label = "Constraints")列出当前全部 active constraints,分为 Dimensional 与 Geometric 两组——这与sketch.constraints.dimensional/sketch.constraints.geometric两个集合一一对应(见 ui/panels/constraints_list.py 的draw方法)。每行包含:
visible开关(图标式勾选)与约束类型图标(icon_manager.get_constraint_icon_for_type);- 可编辑的约束名称字段;
- 可编辑的数值字段。源码注释指出一个实现细节:尺寸约束的数值实际存在场景自定义属性
scene["slvs:c:{uid}"]中,列表绘制的是这个端点(endpoint),以此保持数值可编辑、且方便挂驱动(driver); - 求解失败的约束(
constraint.failed)右侧显示ERROR图标; - 行尾
DeleteConstraint按钮,highlight_hover与highlight_members为真,悬停时同时高亮该约束及其作用的几何; - 顶部的Show All/Hide All按钮调用
SetAllConstraintsVisibility算子(visibility="SHOW"/"HIDE"),一次性切换整个草图的约束 gizmo 显隐。
Gizmos:约束的视口标注
Gizmo 用于在视口中显示约束:三种尺寸约束(angle、distance、diameter)各有专用 gizmo 类型,点击其 gizmo 可打开菜单来调整约束的设置。
其余约束使用通用 gizmo,显示在其依赖的实体旁边;点击这样的 gizmo 要么打开约束设置菜单,要么在约束没有可设置项时直接删除它。
源码层面(gizmos/constraint.py 与 gizmos/base.py)的分工是这样的:
VIEW3D_GGT_slvs_constraintgizmo group 为每个尺寸约束新建一个VIEW3D_GT_slvs_constraint_valuegizmo(gz.type/gz.index指向具体约束),并通过target_set_operator(Operators.TweakConstraintValuePos)绑定拖拽修改数值的算子。尺寸数值文本由_get_formatted_value格式化:LENGTH 单位走units.format_distance(diameter 约束若处于半径模式下前缀 "R"),ROTATION 单位走units.format_angle;- 所有几何约束共享一个
VIEW3D_GT_slvs_constraintgizmo。源码注释解释了动机:按约束逐个建 gizmo 意味着每次重绘/移动鼠标都要做每约束一次 Python 调用。这个单一 gizmo 的test_select直接根据 drawing/constraint_icons.py 中绘出的图标位置回答命中测试,每个图标是一个 part,绑定到对应约束的ContextMenu算子(delayed=True,等鼠标抬起再弹菜单,避免点击的 RELEASE 穿透触发菜单里的 "Delete"); - 尺寸 gizmo 的箭头/辅助线(helpline)几何只在
_shape_signature变化时重建——签名涵盖数值、draw offset、basis 矩阵和视图缩放,静态视口(包括 modal 拖拽期间的所有重绘)不会每帧重新上传 GPU batch。
图标分组:位于同一元素上、或在屏幕上会重叠的约束图标会被绘制成一个带计数(count)的图标,悬停展开分组即可触达单个约束。这一行为可以在偏好设置的 "Group Constraint Icons" 中关闭。对应实现在 drawing/constraint_icons.py:该模块头部注释说明所有几何约束图标现在用一次批量绘制从同一纹理图集(texture atlas)中完成——早期每个 gizmo 各自绘制一次带采样器的纹理,约束很多时会在 Vulkan 后端耗尽描述符池(VK_ERROR_OUT_OF_POOL_MEMORY)。分组的颜色优先级为 highlight > failed > reference,分组展开由光标悬停(constraint_icons.pick)驱动。
Context Menu:元素属性与操作
上下文菜单用来访问一个元素的属性和操作,有三种入口:
- 悬停某个实体后按鼠标右键;
- 点击支持该功能的约束 gizmo;
- 元素浏览器中对应的按钮。
INFO:上下文菜单只使用悬停的实体,忽略当前选中(selection)。
operators/context_menu.py 的View3D_OT_slvs_context_menu.execute印证了这一点:实体路径取selection.hover(或显式传入的curve_id),约束路径按type+index在get_active_constraints中定位。菜单内容:
- 实体:通过
seed_entity_editor把实体设置(名称、点坐标)载入内联编辑器,由element.draw_props绘制;随后是分隔线和红色警示行的Delete按钮,原点(is_origin)受保护,Delete 置灰; - 约束:绘制约束的
draw_props(即"设置"),再加DeleteConstraint按钮——这就是文档所说"没有设置可显示时点击直接删除"的来源; - 什么都没悬停到(
element为 None)时回退到 Blender 默认的VIEW3D_MT_selected_menu对象菜单; delayed=True时算子以 modal 方式运行,鼠标抬起(RELEASE)才执行,用于 gizmo 点击场景。
另外,ui/panels/entities_list.py 行尾的ContextMenu按钮把curve_id直接传给算子并设highlight_hover=True,这就是浏览器入口的实现。
Preferences:偏好设置逐项解析
在 Blender 中通过Edit > Preferences > Add-ons > CAD Sketcher展开已启用的扩展即可访问偏好设置。
Interface
一切关于扩展在视口中如何绘制与表现:淡出非绘制目标对象、将视图对齐到活动实体、实体大小、workplane、约束图标、文字与箭头的尺寸,以及是否把落在同一元素上的约束图标分组合并。
对照 base/preferences.pyPreferences.draw中 "Interface" 分组,各属性及其默认值/范围如下:
| 属性 | 含义 | 默认值 | 取值范围 |
|---|---|---|---|
auto_hide_objects | 草图模式下淡出曲线/网格 | True | — |
use_align_view | 激活草图时自动把视图对齐到 workplane | True | — |
entity_scale | 实体绘制缩放 | 1.0 | min 0.1,soft_max 3.0 |
workplane_size | workplane 显示大小 | 0.4 | soft 0.1–1.0 |
gizmo_scale | 约束图标缩放 | 18.0 | min 1.0,soft_max 25.0 |
group_constraint_icons | 同元素约束图标合并为一个带计数的图标 | True | — |
text_size | 数值文本字号 | 15 | min 5,soft_max 25 |
arrow_scale | 箭头缩放 | 1.0 | min 0.2,soft_max 3.0 |
其中entity_scale与gizmo_scale带有update=theme.update回调(base/theme.py),修改后立即对所有 VIEW_3D 区域执行tag_redraw。"淡出"的实际消费点在 operators/utilities.py:fade_objects = get_prefs().auto_hide_objects在进入草图时据此淡出场景对象;use_align_view则在 operators/utilities.py 与 operators/workplane_anchor.py 中被读取,决定是否调用view3d.view_axis对齐视图。
Geometry
- Curve Resolution— 圆弧与圆被网格化(mesh)时每边的最大夹角。它是新草图的默认值;每个草图在自己的 Convert modifier 上保留各自的数值,见 integration。对应属性
curve_angular_resolution,subtype="ANGLE",默认math.radians(7.5),范围 0.1°–90°,描述文本明确提示可在该草图的 "CAD Sketcher Convert modifier" 上按草图修改; - Boolean Solver— 新布尔运算使用的求解器,Exact 或更快的 Manifold,之后可逐布尔修改。属性
boolean_solver默认"Manifold",选项来自 utilities/boolean_nodes.py 的SOLVER_ITEMS:Exact 对不完美几何稳健但慢,Manifold 快得多但只处理干净的闭合网格(非流形输入会被丢弃)。偏好项描述提到 Manifold 约为另一求解器七倍快,且遇到处理不了的输入会自行回落到 Exact。
Units
决定数值显示所用的精度:公制小数位、英制分数、角度小数位。
实现集中在 units.py:
decimal_precision:IntProperty,默认 3,min 0,soft_max 7,控制_format_metric_length的小数位数(按场景length_unit输出 m / cm / mm / µm / km,ADAPTIVE 或use_separate时走 Blender 内置bpy.utils.units.to_string);imperial_precision:枚举1"/1/2"/1/4"/1/8"/1/16"/1/32"/1/64",由_inches_to_fraction把英寸值取整到对应分数并格式化为n-m⁄n″(英尺制再加′);angle_precision:IntProperty,min 0,max 5,默认 0;format_angle按场景旋转单位输出°或rad。
注意这些格式函数读取的是当前场景的单位制(unit_settings.system),所以公制/英制切换即时生效,偏好项只是控制精度。
Advanced
- "What's New" 对话框是否在扩展更新后显示(
show_whats_new,默认True,对应 base/whats_new.py); - 启用 "Show Debug Settings"(
show_debug_settings,默认False)会打开一些实验性功能,需谨慎使用。从 utilities/preferences.py 看,is_experimental()就是读这个开关,use_experimental(setting, fallback)在非实验模式下强制回退——这是实验功能进入各代码路径的统一门控; - 日志级别
logging_level:枚举CRITICAL / ERROR / WARNING / INFO / DEBUG / NOTSET,默认值2(Warning),update回调on_logging_level_update直接logger.setLevel。
偏好面板顶部还有一组快捷链接("What's New" 算子、Documentation、Source Code、Report a Bug、Request a Feature、Discord),方便从面板直接跳转。
Theme
扩展用到的颜色都在 theme 部分定义;扩展同时支持主题预设(theme presets),包括适配浅色视口的 light 预设。预设体系由 base/preferences.py 顶部的SKETCHER_PT_theme_presets(继承PresetPanel)实现:preset_subdir = "bgs/theme"、preset_operator = "script.execute_preset"、preset_add_operator = "bgs.theme_preset_add"——即预设以 Python 脚本形式保存在扩展资源目录下的bgs/theme子目录,通过 Blender 标准的 preset 机制执行。
展开偏好项里的 "Theme" 开关后,list_props_recursiv会递归遍历theme_settings(base/theme.py 的ThemeSettings)的 RNA 属性并全部渲染出来,结构上分两组:
ThemeSettingsEntity:default、highlight、selected、selected_highlight、inactive、inactive_selected、fixed七种实体颜色;ThemeSettingsConstraint:default、highlight、failed、failed_highlight、reference(引用测量)、text、text_highlight等约束颜色。
所有颜色项都带update=theme.update回调,改动即时重绘视口。约束的着色在 gizmos/utilities.py 的get_constraint_color_type与 gizmos/base.py 的_set_colors中被消费:失败约束用failed色、悬停高亮叠加*_highlight色,颜色按 gizmo 指针缓存(_gizmo_colors),只有真正变化时才写入,避免每帧无谓的属性设置。
主题预设脚本的存放路径可以在 Blender 的 Python 控制台执行以下语句获得:
bpy.utils.user_resource("SCRIPTS")小结
CAD Sketcher 的 UI 是一条从面板到算子再到绘制层的完整链路:侧边栏面板(ui/panels/)负责状态展示与算子入口,gizmo 层(gizmos/)负责视口内的标注与命中测试,偏好设置(base/preferences.py)提供全局行为开关并被绘制与算子代码直接读取。理解这三层各自的职责,再配合 ui/selected_menu.py、operators/context_menu.py 等入口,就能在修改界面行为或排查 UI 问题时快速定位到对应代码。
- 桌面应用
- 3D建模
【免费下载链接】CAD_Sketcher
Constraint-based geometry sketcher for blender
相关推荐
CAD_Sketcher用户界面详解:从侧边栏到偏好设置
CAD_Sketcher用户界面详解:从侧边栏到偏好设置 侧边栏功能解析 CAD_Sketcher扩展在Blender的"N"面板中添加了一个名为"Sketch
桌面应用3D建模炉石传说HsMod插件:55项功能全面解析与终极使用指南
炉石传说HsMod插件:55项功能全面解析与终极使用指南 HsMod是一款基于BepInEx框架开发的炉石传说多功能增强插件,为玩家提供55项实用功能,包括游戏
游戏开发paseo Explorer 侧边栏与 Side Pane:双宿主面板的契约设计、路由偏好与源码实现解析
paseo Explorer 侧边栏与 Side Pane:双宿主面板的契约设计、路由偏好与源码实现解析 Explorer 侧边栏(Explorer sideb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考