Repository: godotengine/godot
File: editor/inspector/editor_inspector.cpp (C++)

Code before:
			clipboard["path"] = category_name;
			for (const String &property_name : properties) {
				clipboard[property_name] = object->get(property_name);
			}
			InspectorDock::get_inspector_singleton()->set_property_clipboard(clipboard);
		} break;

		case MENU_PASTE_VALUE: {
			Object *object = EditorInterface::get_singleton()->get_inspector()->get_edited_object();
			const Dictionary clipboard = InspectorDock::get_inspector_singleton()->get_property_clipboard();
			const String path = clipboard["path"];
			String category_name = info.name;
			if (!EditorNode::get_editor_data().is_type_recognized(info.name) && ResourceLoader::exists(info.hint_string, "Script")) {
				Ref<Script> scr = ResourceLoader::load(info.hint_string, "Script");
				if (scr.is_valid()) {
					category_name = scr->get_doc_class_name();
				}
			}

			if (path != category_name) {
				break;
			}

			EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();

			if (const MultiNodeEdit *multi_node_edit = cast_to<MultiNodeEdit>(object)) {
				const Node *es = EditorNode::get_singleton()->get_edited_scene();
				const String action_name = vformat(TTR("Set category %s on %d nodes"), category_name, multi_node_edit->get_node_count());
				ur->create_action(action_name);

				for (int i = 0; i < multi_node_edit->get_node_count(); i++) {
					const NodePath E = multi_node_edit->get_node(i);
					Node *n = es->get_node(E);
					if (!n) {
						continue;
					}

					for (const KeyValue<Variant, Variant> &pair : clipboard) {
						String property_name = pair.key;
						ur->add_do_property(n, property_name, pair.value);
						ur->add_undo_property(n, property_name, n->get(property_name));
					}
				}

				ur->commit_action();
			} else if (EditorDebuggerRemoteObjects *remote_objects = cast_to<EditorDebuggerRemoteObjects>(object)) {
				const int size = remote_objects->remote_object_ids.size();
				ur->create_action(size == 1 ? vformat(TTR("Set category %s"), category_name) : vformat(TTR("Set %s on %d objects"), category_name, size), UndoRedo::MERGE_ENDS);

				for (const KeyValue<Variant, Variant> &pair : clipboard) {
					const String property_name = pair.key;

Review comment (suggestion):
We usually call that static function from the class itself.
```suggestion
			if (const MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(object)) {
```
(there's multiple nude `cast_to` in your PR)

Code after:
}

Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const {
	// If it's not a doc tooltip, fallback to the default one.
	if (doc_class_name.is_empty()) {
		return nullptr;
	}

	return EditorHelpBitTooltip::make_tooltip(const_cast<EditorInspectorCategory *>(this), p_text);
}

void EditorInspectorCategory::set_as_favorite() {
	is_favorite = true;
	_update_icon();
}

void EditorInspectorCategory::set_property_info(const PropertyInfo &p_info) {
	info = p_info;

	Ref<Script> scr = _get_category_script(info);
	if (scr.is_valid()) {
		StringName script_name = EditorNode::get_editor_data().script_class_get_name(scr->get_path());
		if (script_name != StringName()) {
			label = script_name;
		}
	}
	if (label.is_empty()) {
		label = info.name;
	}
	_update_icon();
}

void EditorInspectorCategory::set_doc_class_name(const String &p_name) {
	doc_class_name = p_name;
}

Size2 EditorInspectorCategory::get_minimum_size() const {
	Size2 ms;
	if (theme_cache.bold_font.is_valid()) {
		ms.height = theme_cache.bold_font->get_height(theme_cache.bold_font_size);
	}
	if (icon.is_valid()) {
		ms.height = MAX(theme_cache.class_icon_size, ms.height);
	}
	ms.height += theme_cache.vertical_separation;

	if (theme_cache.background.is_valid()) {
		ms.height += theme_cache.background->get_content_margin(SIDE_TOP) + theme_cache.background->get_content_margin(SIDE_BOTTOM);
	}

	return ms;