自研插件:自动编组

This commit is contained in:
2026-10-04 19:46:30 +08:00
parent 8ebd331b20
commit b826bfb562
2 changed files with 30 additions and 2 deletions
+8
View File
@@ -40,6 +40,8 @@
一次拖入多个模型只弹**一个**弹窗,确认后整批处理。不想被问就把 `ask_before_adding` 关掉,改由 `auto_add_collision` 决定。
加完碰撞的模型会被自动**编组**:视图里点它的任何子节点,选中的都是模型本身(见下面「生成的节点结构」)。
菜单里还有四个手动操作:
| 菜单项 | 作用 |
@@ -59,6 +61,12 @@ Chair_PC_04 ← 模型实例,仍然引用 res://.../chair.
└─ Chair_PC_04Shape (CollisionShape3D)
```
加碰撞的同时,插件会给**模型实例**打上编辑器自己的「编组」标记(在场景面板点 Ctrl+G 是同一个东西,存成 `metadata/_edit_group_ = true`)。效果是:**在 2D / 3D 视图里点这个模型的任何子节点,选中的都是模型本身**,而不是 `CollisionBody` 或某个 `CollisionShape3D`。
- 这个标记会写进 `.tscn`,关掉编辑器再打开依然有效;
- 只在模型**还没有**这个标记时才打 —— 你自己手工编组过的不会被覆盖,撤销一次注入也不会把你自己编的组撤掉;
- 「移除选中模型的碰撞」**不会**取消编组(编组对模型本身是有益的,而且可能本来就是你加的)。
这个布局与 **Godot 自己**用 `-col` / `-convcol` 名字后缀导入时生成的完全一致。我实测过每种后缀的行为:
| 后缀 | Godot 生成的形状 |
+22 -2
View File
@@ -65,6 +65,16 @@ const MENU_ADD := "Mesh Collider: 给选中模型加碰撞 / Add collision to se
const MENU_REMOVE := "Mesh Collider: 移除选中模型的碰撞 / Remove collision"
const MENU_SETTINGS := "Mesh Collider: 打开项目设置 / Open project settings"
## The editor's own "group selected nodes" flag - the toggle next to the lock
## icon in the Scene dock, bound to Ctrl+G.
##
## A node carrying it is what gets selected when any of its children is clicked
## in the 2D/3D view, which is exactly what a model with a CollisionBody and a
## pile of CollisionShape3D under it needs. It is a plain node meta, and Godot
## serialises it into the scene as `metadata/_edit_group_ = true`, so setting it
## here is all it takes - no editor-only state, nothing to re-apply on load.
const META_GROUP := &"_edit_group_"
func _enter_tree() -> void:
Settings.install()
@@ -226,11 +236,21 @@ func _inject(model: Node, source: String = "") -> bool:
undo.add_do_method(Collider, "prepare_for_scene", body, scene_root)
undo.add_do_reference(body)
undo.add_undo_method(model, "remove_child", body)
# Group the model, so clicking it in the viewport selects the model rather
# than the body or a shape we just hung under it. Only when it is not already
# grouped, so a choice made by hand is never overwritten - and the undo entry
# is only added in that same case, so undoing an injection cannot un-group
# something the user had grouped themselves.
var grouping := not model.has_meta(META_GROUP)
if grouping:
undo.add_do_method(model, "set_meta", META_GROUP, true)
undo.add_undo_method(model, "remove_meta", META_GROUP)
undo.commit_action()
get_editor_interface().mark_scene_as_unsaved()
print("[MeshCollider] %s (%s): added %s with %d shape(s)"
% [model.name, source.get_file(), body.get_class(), Collider.count_shapes(body)])
print("[MeshCollider] %s (%s): added %s with %d shape(s)%s"
% [model.name, source.get_file(), body.get_class(), Collider.count_shapes(body),
" [已编组]" if grouping else ""])
return true