Repository: godotengine/godot
File: editor/plugins/node_3d_editor_plugin.cpp (C++)

Code before:
	_edit.instant = false;
	spatial_editor->update_transform_gizmo();
	surface->queue_redraw();
	set_process_input(false);
}

// Register a shortcut and also add it as an input action with the same events.
void Node3DEditorViewport::register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode, bool p_physical) {
	Ref<Shortcut> sc = ED_SHORTCUT(p_path, p_name, p_keycode, p_physical);
	shortcut_changed_callback(sc, p_path);
	// Connect to the change event on the shortcut so the input binding can be updated.
	sc->connect_changed(callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path));
}

// Update the action in the InputMap to the provided shortcut events.
void Node3DEditorViewport::shortcut_changed_callback(const Ref<Shortcut> p_shortcut, const String &p_shortcut_path) {
	InputMap *im = InputMap::get_singleton();
	if (im->has_action(p_shortcut_path)) {
		im->action_erase_events(p_shortcut_path);
	} else {
		im->add_action(p_shortcut_path);
	}

	for (int i = 0; i < p_shortcut->get_events().size(); i++) {
		im->action_add_event(p_shortcut_path, p_shortcut->get_events()[i]);
	}
}

void Node3DEditorViewport::_set_lock_view_rotation(bool p_lock_rotation) {
	lock_rotation = p_lock_rotation;
	int idx = view_menu->get_popup()->get_item_index(VIEW_LOCK_ROTATION);
	view_menu->get_popup()->set_item_checked(idx, p_lock_rotation);
	if (p_lock_rotation) {
		locked_label->show();
	} else {
		locked_label->hide();
	}
}

Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index) {
	cpu_time_history_index = 0;
	gpu_time_history_index = 0;

	_edit.mode = TRANSFORM_NONE;
	_edit.plane = TRANSFORM_VIEW;
	_edit.snap = true;
	_edit.show_rotation_line = true;
	_edit.instant = false;
	_edit.gizmo_handle = -1;
	_edit.gizmo_handle_secondary = false;


Review comment (bug):
```suggestion
			ERR_FAIL_MSG("_edit.mode cannot be TRANSFORM_NONE in update_transform_numeric.");
```

Code after:
			break;
		case TRANSFORM_YZ:
			motion = Vector3(0, 1, 1);
			break;
	}

	double value = _edit.numeric_input * (_edit.numeric_negate ? -1 : 1);
	double extra = 0.0;
	switch (_edit.mode) {
		case TRANSFORM_TRANSLATE:
			motion *= value;
			set_message(vformat(TTR("Translating %s."), motion));
			break;
		case TRANSFORM_ROTATE:
			extra = Math::deg_to_rad(value);
			set_message(vformat(TTR("Rotating %f degrees."), value));
			break;
		case TRANSFORM_SCALE:
			// To halve the size of an object in Blender, you scale it by 0.5.
			// Doing the same in Godot is considered scaling it by -0.5.
			motion *= (value - 1.0);
			set_message(vformat(TTR("Scaling %s."), motion));
			break;
		case TRANSFORM_NONE:
			ERR_FAIL_MSG("_edit.mode cannot be TRANSFORM_NONE in update_transform_numeric.");
	}

	apply_transform(motion, extra);
}

// Perform cleanup after a transform operation is committed or cancelled.
void Node3DEditorViewport::finish_transform() {
	_edit.mode = TRANSFORM_NONE;
	_edit.instant = false;
	_edit.numeric_input = 0;
	_edit.numeric_next_decimal = 0;
	_edit.numeric_negate = false;
	spatial_editor->set_local_coords_enabled(_edit.original_local);
	spatial_editor->update_transform_gizmo();
	surface->queue_redraw();
	set_process_input(false);
}

// Register a shortcut and also add it as an input action with the same events.
void Node3DEditorViewport::register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode, bool p_physical) {
	Ref<Shortcut> sc = ED_SHORTCUT(p_path, p_name, p_keycode, p_physical);
	shortcut_changed_callback(sc, p_path);
	// Connect to the change event on the shortcut so the input binding can be updated.
	sc->connect_changed(callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path));
}