/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "ComponentMimeData.h" #include #include #include #include #include #include #include #include #include namespace AzToolsFramework { QString ComponentTypeMimeData::GetMimeType() { return "application/x-amazon-o3de-editorcomponenttypes"; } AZStd::unique_ptr ComponentTypeMimeData::Create(const ClassDataContainer& container) { QByteArray dataArray; AZStd::unique_ptr mimeData = std::make_unique(); QDataStream stream(&dataArray, QIODevice::WriteOnly); // Count how many valid items we have so we don't stream out nullptrs quint64 numItems = 0; for (auto item : container) { AZ_Assert(item, "null class type provided as input to ComponentMimeData::Create"); if (item) { ++numItems; } } stream << numItems; for (auto item : container) { if (!item) { continue; } quint64 classDataPtr = reinterpret_cast(item); stream << classDataPtr; } mimeData->setData(GetMimeType(), dataArray); return mimeData; } bool ComponentTypeMimeData::Get(const QMimeData* mimeData, ClassDataContainer& container) { if (mimeData && mimeData->hasFormat(GetMimeType())) { container.clear(); QByteArray arrayData = mimeData->data(GetMimeType()); QDataStream stream(&arrayData, QIODevice::ReadOnly); quint64 numItems = 0; stream >> numItems; for (size_t i = 0; i < numItems; ++i) { quint64 ptrAddr; stream >> ptrAddr; auto classData = reinterpret_cast(ptrAddr); container.push_back(classData); } return !container.empty(); } return false; } void ComponentMimeData::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class() ->Field("Components", &ComponentMimeData::m_components); } } QString ComponentMimeData::GetMimeType() { return "application/x-amazon-o3de-editorcomponentdata"; } AZStd::unique_ptr ComponentMimeData::Create(const ComponentDataContainer& components) { AZ::SerializeContext* context; EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext); if (!context) { AZ_Assert(context, "No serialize context"); return nullptr; } // Extract the type data, put it in the mime data for early checking later ComponentTypeMimeData::ClassDataContainer componentClassTypes; for (AZ::Component* component : components) { AZ_Assert(component, "null component provided as input to ComponentMimeData::Create"); if (!component) { continue; } // Get the underlying component type if wrapped with a generic component wrapper auto classData = context->FindClassData(GetComponentTypeId(component)); if (classData) { componentClassTypes.push_back(classData); } } // Pack the components into a helper class for serialization ComponentMimeData componentMimeData; componentMimeData.m_components = components; // Save the helper class into a buffer to pack into mime data AZStd::vector buffer; AZ::IO::ByteContainerStream> byteStream(&buffer); if (!AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_XML, &componentMimeData)) { return nullptr; } QByteArray dataArray(buffer.data(), static_cast(sizeof(char) * buffer.size())); AZStd::unique_ptr mimeData = ComponentTypeMimeData::Create(componentClassTypes); if (mimeData) { mimeData->setData(GetMimeType(), dataArray); } return mimeData; } void ComponentMimeData::GetComponentDataFromMimeData(const QMimeData* mimeData, ComponentDataContainer& componentData) { if (!mimeData || !mimeData->hasFormat(GetMimeType())) { return; } QByteArray arrayData = mimeData->data(GetMimeType()); AZ::IO::MemoryStream memoryStream(arrayData.constData(), arrayData.size()); ComponentMimeData* componentMimeData = AZ::Utils::LoadObjectFromStream(memoryStream); if (!componentMimeData) { return; } componentData.clear(); componentData = AZStd::move(componentMimeData->m_components); delete componentMimeData; } const QMimeData* ComponentMimeData::GetComponentMimeDataFromClipboard() { // Do we have stuff on the clipboard? QClipboard* clipboard = QApplication::clipboard(); const QMimeData* mimeData = clipboard->mimeData(); if (mimeData && mimeData->hasFormat(GetMimeType())) { return mimeData; } return nullptr; } void ComponentMimeData::PutComponentMimeDataOnClipboard(AZStd::unique_ptr mimeData) { QClipboard* clipboard = QApplication::clipboard(); clipboard->setMimeData(mimeData.release()); } }