add separate button for painting in the grid map editor

This commit is contained in:
ItsVeryWindy 2024-09-29 17:14:28 +01:00
parent 44fa552343
commit a53dd9d464
5 changed files with 282 additions and 160 deletions

View file

@ -1274,7 +1274,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
Transform3D gt = spatial_editor->get_gizmo_transform();
if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
if (spatial_editor->is_select_tool_selected() || spatial_editor->is_move_tool_selected()) {
int col_axis = -1;
real_t col_d = 1e20;
@ -1340,7 +1340,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
}
}
if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
if (spatial_editor->is_select_tool_selected() || spatial_editor->is_rotate_tool_selected()) {
int col_axis = -1;
Vector3 hit_position;
@ -1394,7 +1394,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
}
}
if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
if (spatial_editor->is_scale_tool_selected()) {
int col_axis = -1;
float col_d = 1e20;
@ -1565,7 +1565,7 @@ bool Node3DEditorViewport::_is_node_locked(const Node *p_node) const {
void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
Vector<_RayResult> potential_selection_results;
_find_items_at_pos(b->get_position(), potential_selection_results, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
_find_items_at_pos(b->get_position(), potential_selection_results, spatial_editor->is_select_tool_selected());
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
@ -1596,7 +1596,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
selection_results.clear();
if (clicked.is_valid()) {
_select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
_select_clicked(spatial_editor->is_select_tool_selected());
}
} else if (!selection_results.is_empty()) {
NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
@ -1815,7 +1815,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
}
if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_LIST_SELECT) {
if (spatial_editor->is_list_select_tool_selected()) {
_list_select(b);
break;
}
@ -1920,17 +1920,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
bool node_selected = get_selected_count() > 0;
if (node_selected && ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)) {
if (node_selected && ((spatial_editor->is_select_tool_selected() && b->is_command_or_control_pressed()) || spatial_editor->is_rotate_tool_selected())) {
begin_transform(TRANSFORM_ROTATE, false);
break;
}
if (node_selected && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
if (node_selected && spatial_editor->is_move_tool_selected()) {
begin_transform(TRANSFORM_TRANSLATE, false);
break;
}
if (node_selected && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
if (node_selected && spatial_editor->is_scale_tool_selected()) {
begin_transform(TRANSFORM_SCALE, false);
break;
}
@ -3916,7 +3916,7 @@ void Node3DEditorViewport::_selection_result_pressed(int p_result) {
clicked = selection_results_menu[p_result]->get_instance_id();
if (clicked.is_valid()) {
_select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
_select_clicked(spatial_editor->is_select_tool_selected());
}
selection_results_menu.clear();
@ -4001,15 +4001,15 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
axis_angle.basis.scale(scale);
axis_angle.origin = xform.origin;
RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE));
RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], show_gizmo && (spatial_editor->is_select_tool_selected() || spatial_editor->is_move_tool_selected()));
RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE));
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], show_gizmo && (spatial_editor->is_select_tool_selected() || spatial_editor->is_move_tool_selected()));
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], show_gizmo && (spatial_editor->is_select_tool_selected() || spatial_editor->is_rotate_tool_selected()));
RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE));
RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], show_gizmo && (spatial_editor->is_scale_tool_selected()));
RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE));
RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], show_gizmo && (spatial_editor->is_scale_tool_selected()));
RenderingServer::get_singleton()->instance_set_transform(axis_gizmo_instance[i], xform);
}
@ -4023,7 +4023,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
xform.orthonormalize();
xform.basis.scale(scale);
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform);
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && !collision_reposition && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && !collision_reposition && (spatial_editor->is_select_tool_selected() || spatial_editor->is_rotate_tool_selected()));
}
void Node3DEditorViewport::set_state(const Dictionary &p_state) {
@ -6642,19 +6642,8 @@ void Node3DEditor::_update_camera_override_viewport(Object *p_viewport) {
void Node3DEditor::_menu_item_pressed(int p_option) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
switch (p_option) {
case MENU_TOOL_SELECT:
case MENU_TOOL_MOVE:
case MENU_TOOL_ROTATE:
case MENU_TOOL_SCALE:
case MENU_TOOL_LIST_SELECT: {
for (int i = 0; i < TOOL_MAX; i++) {
tool_button[i]->set_pressed(i == p_option);
}
tool_mode = (ToolMode)p_option;
update_transform_gizmo();
} break;
switch (p_option) {
case MENU_TRANSFORM_CONFIGURE_SNAP: {
snap_dialog->popup_centered(Size2(200, 180));
} break;
@ -7755,15 +7744,15 @@ void Node3DEditor::_refresh_menu_icons() {
all_locked = all_locked && has_node3d_item;
all_grouped = all_grouped && has_node3d_item;
tool_button[TOOL_LOCK_SELECTED]->set_visible(!all_locked);
tool_button[TOOL_LOCK_SELECTED]->set_disabled(!has_node3d_item);
tool_button[TOOL_UNLOCK_SELECTED]->set_visible(all_locked);
tool_button[TOOL_UNLOCK_SELECTED]->set_disabled(!has_node3d_item);
lock_selected_button->set_visible(!all_locked);
lock_selected_button->set_disabled(!has_node3d_item);
unlock_selected_button->set_visible(all_locked);
unlock_selected_button->set_disabled(!has_node3d_item);
tool_button[TOOL_GROUP_SELECTED]->set_visible(!all_grouped);
tool_button[TOOL_GROUP_SELECTED]->set_disabled(!has_node3d_item);
tool_button[TOOL_UNGROUP_SELECTED]->set_visible(all_grouped);
tool_button[TOOL_UNGROUP_SELECTED]->set_disabled(!has_node3d_item);
group_selected_button->set_visible(!all_grouped);
group_selected_button->set_disabled(!has_node3d_item);
ungroup_selected_button->set_visible(all_grouped);
ungroup_selected_button->set_disabled(!has_node3d_item);
}
template <typename T>
@ -8021,15 +8010,15 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) {
}
void Node3DEditor::_update_theme() {
tool_button[TOOL_MODE_SELECT]->set_icon(get_editor_theme_icon(SNAME("ToolSelect")));
tool_button[TOOL_MODE_MOVE]->set_icon(get_editor_theme_icon(SNAME("ToolMove")));
tool_button[TOOL_MODE_ROTATE]->set_icon(get_editor_theme_icon(SNAME("ToolRotate")));
tool_button[TOOL_MODE_SCALE]->set_icon(get_editor_theme_icon(SNAME("ToolScale")));
tool_button[TOOL_MODE_LIST_SELECT]->set_icon(get_editor_theme_icon(SNAME("ListSelect")));
tool_button[TOOL_LOCK_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Lock")));
tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Unlock")));
tool_button[TOOL_GROUP_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Group")));
tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_editor_theme_icon(SNAME("Ungroup")));
select_tool_button->set_icon(get_editor_theme_icon(SNAME("ToolSelect")));
move_tool_button->set_icon(get_editor_theme_icon(SNAME("ToolMove")));
rotate_tool_button->set_icon(get_editor_theme_icon(SNAME("ToolRotate")));
scale_tool_button->set_icon(get_editor_theme_icon(SNAME("ToolScale")));
list_select_tool_button->set_icon(get_editor_theme_icon(SNAME("ListSelect")));
lock_selected_button->set_icon(get_editor_theme_icon(SNAME("Lock")));
unlock_selected_button->set_icon(get_editor_theme_icon(SNAME("Unlock")));
group_selected_button->set_icon(get_editor_theme_icon(SNAME("Group")));
ungroup_selected_button->set_icon(get_editor_theme_icon(SNAME("Ungroup")));
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_editor_theme_icon(SNAME("Object")));
tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_editor_theme_icon(SNAME("Snap")));
@ -8682,7 +8671,6 @@ Node3DEditor::Node3DEditor() {
snap_enabled = false;
snap_key_enabled = false;
tool_mode = TOOL_MODE_SELECT;
camera_override_viewport_id = 0;
@ -8704,85 +8692,84 @@ Node3DEditor::Node3DEditor() {
String sct;
tool_button[TOOL_MODE_SELECT] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_MODE_SELECT]);
tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true);
tool_button[TOOL_MODE_SELECT]->set_theme_type_variation("FlatButton");
tool_button[TOOL_MODE_SELECT]->set_pressed(true);
tool_button[TOOL_MODE_SELECT]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT));
tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q));
tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this);
tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
main_menu_hbox->add_child(memnew(VSeparator));
tool_button_group.instantiate();
tool_button_group->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_tool_button_group_pressed));
tool_button[TOOL_MODE_MOVE] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_MODE_MOVE]);
tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true);
tool_button[TOOL_MODE_MOVE]->set_theme_type_variation("FlatButton");
tool_button[TOOL_MODE_MOVE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_MOVE));
tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), Key::W));
tool_button[TOOL_MODE_MOVE]->set_shortcut_context(this);
tool_button[TOOL_MODE_MOVE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
tool_button[TOOL_MODE_ROTATE] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_MODE_ROTATE]);
tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true);
tool_button[TOOL_MODE_ROTATE]->set_theme_type_variation("FlatButton");
tool_button[TOOL_MODE_ROTATE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_ROTATE));
tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), Key::E));
tool_button[TOOL_MODE_ROTATE]->set_shortcut_context(this);
tool_button[TOOL_MODE_ROTATE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
tool_button[TOOL_MODE_SCALE] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_MODE_SCALE]);
tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true);
tool_button[TOOL_MODE_SCALE]->set_theme_type_variation("FlatButton");
tool_button[TOOL_MODE_SCALE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SCALE));
tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), Key::R));
tool_button[TOOL_MODE_SCALE]->set_shortcut_context(this);
tool_button[TOOL_MODE_SCALE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
select_tool_button = memnew(Button);
main_menu_hbox->add_child(select_tool_button);
select_tool_button->set_toggle_mode(true);
select_tool_button->set_theme_type_variation("FlatButton");
select_tool_button->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q));
select_tool_button->set_shortcut_context(this);
select_tool_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
select_tool_button->set_pressed(true);
add_tool(select_tool_button);
main_menu_hbox->add_child(memnew(VSeparator));
tool_button[TOOL_MODE_LIST_SELECT] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_MODE_LIST_SELECT]);
tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true);
tool_button[TOOL_MODE_LIST_SELECT]->set_theme_type_variation("FlatButton");
tool_button[TOOL_MODE_LIST_SELECT]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_LIST_SELECT));
tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked."));
move_tool_button = memnew(Button);
main_menu_hbox->add_child(move_tool_button);
move_tool_button->set_theme_type_variation("FlatButton");
move_tool_button->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), Key::W));
move_tool_button->set_shortcut_context(this);
move_tool_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
add_tool(move_tool_button);
tool_button[TOOL_LOCK_SELECTED] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_LOCK_SELECTED]);
tool_button[TOOL_LOCK_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_LOCK_SELECTED]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED));
tool_button[TOOL_LOCK_SELECTED]->set_tooltip_text(TTR("Lock selected node, preventing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_GET_SHORTCUT("editor/lock_selected_nodes"));
rotate_tool_button = memnew(Button);
main_menu_hbox->add_child(rotate_tool_button);
rotate_tool_button->set_theme_type_variation("FlatButton");
rotate_tool_button->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), Key::E));
rotate_tool_button->set_shortcut_context(this);
rotate_tool_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
add_tool(rotate_tool_button);
tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]);
tool_button[TOOL_UNLOCK_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_UNLOCK_SELECTED]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED));
tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_GET_SHORTCUT("editor/unlock_selected_nodes"));
scale_tool_button = memnew(Button);
main_menu_hbox->add_child(scale_tool_button);
scale_tool_button->set_theme_type_variation("FlatButton");
scale_tool_button->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), Key::R));
scale_tool_button->set_shortcut_context(this);
scale_tool_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
add_tool(scale_tool_button);
tool_button[TOOL_GROUP_SELECTED] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]);
tool_button[TOOL_GROUP_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_GROUP_SELECTED]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED));
tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Groups the selected node with its children. This selects the parent when any child node is clicked in 2D and 3D view."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_GET_SHORTCUT("editor/group_selected_nodes"));
main_menu_hbox->add_child(memnew(VSeparator));
tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button);
main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]);
tool_button[TOOL_UNGROUP_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_UNGROUP_SELECTED]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED));
tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Ungroups the selected node from its children. Child nodes will be individual items in 2D and 3D view."));
list_select_tool_button = memnew(Button);
main_menu_hbox->add_child(list_select_tool_button);
list_select_tool_button->set_theme_type_variation("FlatButton");
list_select_tool_button->set_tooltip_text(TTR("Show list of selectable nodes at position clicked."));
add_tool(list_select_tool_button);
lock_selected_button = memnew(Button);
main_menu_hbox->add_child(lock_selected_button);
lock_selected_button->set_theme_type_variation("FlatButton");
lock_selected_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED));
lock_selected_button->set_tooltip_text(TTR("Lock selected node, preventing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_GET_SHORTCUT("editor/ungroup_selected_nodes"));
lock_selected_button->set_shortcut(ED_GET_SHORTCUT("editor/lock_selected_nodes"));
unlock_selected_button = memnew(Button);
main_menu_hbox->add_child(unlock_selected_button);
unlock_selected_button->set_theme_type_variation("FlatButton");
unlock_selected_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED));
unlock_selected_button->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
unlock_selected_button->set_shortcut(ED_GET_SHORTCUT("editor/unlock_selected_nodes"));
group_selected_button = memnew(Button);
main_menu_hbox->add_child(group_selected_button);
group_selected_button->set_theme_type_variation("FlatButton");
group_selected_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED));
group_selected_button->set_tooltip_text(TTR("Groups the selected node with its children. This selects the parent when any child node is clicked in 2D and 3D view."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
group_selected_button->set_shortcut(ED_GET_SHORTCUT("editor/group_selected_nodes"));
ungroup_selected_button = memnew(Button);
main_menu_hbox->add_child(ungroup_selected_button);
ungroup_selected_button->set_theme_type_variation("FlatButton");
ungroup_selected_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED));
ungroup_selected_button->set_tooltip_text(TTR("Ungroups the selected node from its children. Child nodes will be individual items in 2D and 3D view."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
ungroup_selected_button->set_shortcut(ED_GET_SHORTCUT("editor/ungroup_selected_nodes"));
main_menu_hbox->add_child(memnew(VSeparator));
@ -9330,6 +9317,49 @@ void Node3DEditorPlugin::make_visible(bool p_visible) {
}
}
void Node3DEditor::_tool_button_group_pressed(Button *p_button) {
update_transform_gizmo();
}
void Node3DEditor::add_tool(Button *p_button) const {
p_button->set_button_group(tool_button_group);
p_button->set_toggle_mode(true);
}
bool Node3DEditor::is_list_select_tool_selected() {
return is_tool_selected(list_select_tool_button);
}
bool Node3DEditor::is_move_tool_selected() {
return is_tool_selected(move_tool_button);
}
bool Node3DEditor::is_rotate_tool_selected() {
return is_tool_selected(rotate_tool_button);
}
bool Node3DEditor::is_scale_tool_selected() {
return is_tool_selected(scale_tool_button);
}
bool Node3DEditor::is_select_tool_selected() {
return is_tool_selected(select_tool_button);
}
bool Node3DEditor::is_tool_selected(Button *p_button) {
BaseButton *pressed_button = tool_button_group->get_pressed_button();
return pressed_button == p_button;
}
void Node3DEditor::remove_tool(Button *p_button) {
if (is_tool_selected(p_button)) {
select_tool_button->set_pressed(true);
}
p_button->set_button_group(NULL);
}
void Node3DEditorPlugin::edit(Object *p_object) {
spatial_editor->edit(Object::cast_to<Node3D>(p_object));
}

View file

@ -606,25 +606,11 @@ class Node3DEditor : public VBoxContainer {
public:
static const unsigned int VIEWPORTS_COUNT = 4;
enum ToolMode {
TOOL_MODE_SELECT,
TOOL_MODE_MOVE,
TOOL_MODE_ROTATE,
TOOL_MODE_SCALE,
TOOL_MODE_LIST_SELECT,
TOOL_LOCK_SELECTED,
TOOL_UNLOCK_SELECTED,
TOOL_GROUP_SELECTED,
TOOL_UNGROUP_SELECTED,
TOOL_MAX
};
enum ToolOptions {
TOOL_OPT_LOCAL_COORDS,
TOOL_OPT_USE_SNAP,
TOOL_OPT_OVERRIDE_CAMERA,
TOOL_OPT_MAX
};
private:
@ -638,8 +624,6 @@ private:
/////
ToolMode tool_mode;
RID origin_mesh;
RID origin_multimesh;
RID origin_instance;
@ -697,11 +681,6 @@ private:
} gizmo;
enum MenuOption {
MENU_TOOL_SELECT,
MENU_TOOL_MOVE,
MENU_TOOL_ROTATE,
MENU_TOOL_SCALE,
MENU_TOOL_LIST_SELECT,
MENU_TOOL_LOCAL_COORDS,
MENU_TOOL_USE_SNAP,
MENU_TOOL_OVERRIDE_CAMERA,
@ -724,7 +703,20 @@ private:
MENU_SNAP_TO_FLOOR
};
Button *tool_button[TOOL_MAX];
void _tool_button_group_pressed(Button *p_button);
Ref<ButtonGroup> tool_button_group;
Button *select_tool_button;
Button *move_tool_button;
Button *rotate_tool_button;
Button *scale_tool_button;
Button *list_select_tool_button;
Button *lock_selected_button;
Button *unlock_selected_button;
Button *group_selected_button;
Button *ungroup_selected_button;
Button *tool_option_button[TOOL_OPT_MAX];
MenuButton *transform_menu = nullptr;
@ -892,7 +884,6 @@ public:
Transform3D get_gizmo_transform() const { return gizmo.transform; }
bool is_gizmo_visible() const;
ToolMode get_tool_mode() const { return tool_mode; }
bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }
void set_local_coords_enabled(bool on) const { tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_pressed(on); }
bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }
@ -914,6 +905,15 @@ public:
void select_gizmo_highlight_axis(int p_axis);
void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }
void add_tool(Button *p_button) const;
bool is_tool_selected(Button *p_button);
void remove_tool(Button *p_button);
bool is_list_select_tool_selected();
bool is_move_tool_selected();
bool is_rotate_tool_selected();
bool is_scale_tool_selected();
bool is_select_tool_selected();
Dictionary get_state() const;
void set_state(const Dictionary &p_state);

View file

@ -1412,7 +1412,7 @@ EditorPlugin::AfterGUIInput Skeleton3DEditorPlugin::forward_3d_gui_input(Camera3
if (se && se->is_edit_mode()) {
const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
if (ne->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) {
if (!ne->is_select_tool_selected()) {
if (!ne->is_gizmo_visible()) {
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
@ -1522,7 +1522,7 @@ int Skeleton3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gi
return -1;
}
if (Node3DEditor::get_singleton()->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) {
if (!Node3DEditor::get_singleton()->is_select_tool_selected()) {
return -1;
}
@ -1598,19 +1598,19 @@ void Skeleton3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, c
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Set Bone Transform"));
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
if (ne->is_select_tool_selected() || ne->is_move_tool_selected()) {
for (int i = 0; i < p_ids.size(); i++) {
ur->add_do_method(skeleton, "set_bone_pose_position", p_ids[i], skeleton->get_bone_pose_position(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_position", p_ids[i], se->get_bone_original_position());
}
}
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
if (ne->is_select_tool_selected() || ne->is_rotate_tool_selected()) {
for (int i = 0; i < p_ids.size(); i++) {
ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", p_ids[i], se->get_bone_original_rotation());
}
}
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
if (ne->is_scale_tool_selected()) {
for (int i = 0; i < p_ids.size(); i++) {
// If the axis is swapped by scaling, the rotation can be changed.
ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));

View file

@ -101,6 +101,9 @@ void GridMapEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CURSOR_ROTATE_Y: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -116,6 +119,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_ROTATE_X: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -131,6 +137,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_ROTATE_Z: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -146,6 +155,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_Y: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -161,6 +173,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_X: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -176,6 +191,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_Z: {
if (!_is_paint_tool_selected())
break;
Basis r;
if (input_action == INPUT_PASTE) {
r = node->get_basis_with_orthogonal_index(paste_indicator.orientation);
@ -191,6 +209,9 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_CLEAR_ROTATION: {
if (!_is_paint_tool_selected())
break;
if (input_action == INPUT_PASTE) {
paste_indicator.orientation = 0;
_update_paste_indicator();
@ -343,6 +364,56 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const
options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_FILL), !selection.active);
}
void GridMapEditor::_add_paint_tool() {
Node3DEditor::get_singleton()->add_tool(paint_tool_button);
paint_tool_button->connect("toggled", callable_mp(this, &GridMapEditor::_paint_tool_button_toggled));
if (selected_palette >= 0) {
_select_paint_tool();
}
}
void GridMapEditor::_remove_paint_tool() {
Node3DEditor::get_singleton()->remove_tool(paint_tool_button);
paint_tool_button->disconnect("toggled", callable_mp(this, &GridMapEditor::_paint_tool_button_toggled));
}
bool GridMapEditor::_cancel_actions() {
if (input_action == INPUT_PASTE) {
_clear_clipboard_data();
input_action = INPUT_NONE;
_update_paste_indicator();
return true;
} else if (selection.active) {
_set_selection(false);
return true;
} else if (selected_palette >= 0 || mesh_library_palette->is_anything_selected()) {
selected_palette = -1;
mesh_library_palette->deselect_all();
update_palette();
_update_cursor_instance();
return true;
}
return false;
}
void GridMapEditor::_paint_tool_button_toggled(bool p_toggled_on) {
if (!_is_paint_tool_selected()) {
_cancel_actions();
}
}
void GridMapEditor::_select_paint_tool() {
paint_tool_button->set_pressed(true);
}
bool GridMapEditor::_is_paint_tool_selected() const {
return Node3DEditor::get_singleton()->is_tool_selected(paint_tool_button);
}
bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click) {
if (!spatial_editor) {
return false;
@ -351,6 +422,9 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b
if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) {
return false;
}
if (!_is_paint_tool_selected()) {
return false;
}
if (mesh_library.is_null()) {
return false;
}
@ -653,6 +727,12 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
} else {
input_action = INPUT_PAINT;
set_items.clear();
if (selection.active) {
_set_selection(false);
if (selected_palette < 0) {
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
}
}
} else if (mb->get_button_index() == MouseButton::RIGHT) {
if (input_action == INPUT_PASTE) {
@ -735,22 +815,8 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
if (k.is_valid()) {
if (k->is_pressed()) {
if (k->get_keycode() == Key::ESCAPE) {
if (input_action == INPUT_PASTE) {
_clear_clipboard_data();
input_action = INPUT_NONE;
_update_paste_indicator();
return EditorPlugin::AFTER_GUI_INPUT_STOP;
} else if (selection.active) {
_set_selection(false);
return EditorPlugin::AFTER_GUI_INPUT_STOP;
} else {
selected_palette = -1;
mesh_library_palette->deselect_all();
update_palette();
_update_cursor_instance();
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
if (k->get_keycode() == Key::ESCAPE && _cancel_actions()) {
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
// Consume input to avoid conflicts with other plugins.
@ -1058,6 +1124,7 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) {
}
void GridMapEditor::_update_theme() {
paint_tool_button->set_icon(get_editor_theme_icon(SNAME("Paint")));
options->set_icon(get_theme_icon(SNAME("GridMap"), EditorStringName(EditorIcons)));
search_box->set_right_icon(get_theme_icon(SNAME("Search"), EditorStringName(EditorIcons)));
mode_thumbnail->set_icon(get_theme_icon(SNAME("FileThumbnail"), EditorStringName(EditorIcons)));
@ -1158,6 +1225,8 @@ void GridMapEditor::_update_cursor_instance() {
void GridMapEditor::_item_selected_cbk(int idx) {
selected_palette = mesh_library_palette->get_item_metadata(idx);
_select_paint_tool();
_update_cursor_instance();
}
@ -1210,6 +1279,13 @@ GridMapEditor::GridMapEditor() {
spatial_editor_hb->set_alignment(BoxContainer::ALIGNMENT_END);
Node3DEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb);
paint_tool_button = memnew(Button);
paint_tool_button->set_theme_type_variation("FlatButton");
paint_tool_button->set_tooltip_text(TTR("LMB: Place selected mesh on the grid.") + "\n" + TTR("RMB: Remove the mesh at position clicked.") + "\n" + TTR("Shift+Drag: Creates a selection box."));
spatial_editor_hb->add_child(paint_tool_button);
spatial_editor_hb->add_child(memnew(VSeparator));
spin_box_label = memnew(Label);
spin_box_label->set_text(TTR("Floor:"));
spatial_editor_hb->add_child(spin_box_label);
@ -1521,10 +1597,17 @@ bool GridMapEditorPlugin::handles(Object *p_object) const {
void GridMapEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
grid_map_editor->_add_paint_tool();
if (grid_map_editor->selected_palette >= 0) {
grid_map_editor->_select_paint_tool();
}
grid_map_editor->show();
grid_map_editor->spatial_editor_hb->show();
grid_map_editor->set_process(true);
} else {
grid_map_editor->_remove_paint_tool();
grid_map_editor->spatial_editor_hb->hide();
grid_map_editor->hide();
grid_map_editor->set_process(false);

View file

@ -80,6 +80,7 @@ class GridMapEditor : public VBoxContainer {
VBoxContainer *settings_vbc = nullptr;
SpinBox *settings_pick_distance = nullptr;
Label *spin_box_label = nullptr;
Button *paint_tool_button = nullptr;
struct SetItem {
Vector3i position;
@ -195,6 +196,7 @@ class GridMapEditor : public VBoxContainer {
void _set_display_mode(int p_mode);
void _item_selected_cbk(int idx);
void _update_cursor_transform();
void _hide_cursor_instance();
void _update_cursor_instance();
void _update_theme();
@ -218,6 +220,13 @@ class GridMapEditor : public VBoxContainer {
void _delete_selection();
void _fill_selection();
void _select_paint_tool();
bool _is_paint_tool_selected() const;
void _add_paint_tool();
void _remove_paint_tool();
void _paint_tool_button_toggled(bool p_toggled_on);
bool _cancel_actions();
bool do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click);
friend class GridMapEditorPlugin;