1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
485 lines
14 KiB
C++
485 lines
14 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include "ChannelControl.hxx"
|
|
#include <Source/Driller/moc_ChannelControl.cpp>
|
|
|
|
#include "Annotations/Annotations.hxx"
|
|
#include "ChannelDataView.hxx"
|
|
#include "ChannelProfilerWidget.hxx"
|
|
#include "DrillerAggregator.hxx"
|
|
#include "DrillerMainWindowMessages.h"
|
|
#include "Source/Driller/ChannelConfigurationDialog.hxx"
|
|
#include "Source/Driller/ChannelConfigurationWidget.hxx"
|
|
#include "Source/Driller/CollapsiblePanel.hxx"
|
|
#include "Source/Driller/CustomizeCSVExportWidget.hxx"
|
|
#include "Source/Driller/DrillerOperationTelemetryEvent.h"
|
|
|
|
namespace Driller
|
|
{
|
|
ChannelControl::ChannelControl(const char* channelName, AnnotationsProvider* ptrAnnotations, QWidget* parent, Qt::WindowFlags flags)
|
|
: QWidget(parent, flags)
|
|
, m_isSetup(false)
|
|
, m_captureMode(CaptureMode::Unknown)
|
|
, m_channelId(channelName)
|
|
, m_configurationDialog(nullptr)
|
|
{
|
|
setupUi(this);
|
|
|
|
m_State.m_EndFrame = -1;
|
|
m_State.m_FramesInView = 10; // magic numbers (this matches the default drop-down menu option)
|
|
m_State.m_ContractedHeight = false;
|
|
m_State.m_ScrubberFrame = 0;
|
|
m_State.m_FrameOffset = 0;
|
|
m_State.m_LoopBegin = 0;
|
|
m_State.m_LoopEnd = 0;
|
|
|
|
this->channelName->setText(channelName ? channelName : "Channel Name Here");
|
|
|
|
channelDataView->RegisterToChannel(this, ptrAnnotations);
|
|
channelDataView->setAutoFillBackground(true);
|
|
|
|
configChannel->setVisible(false);
|
|
|
|
connect(channelDataView, SIGNAL(InformOfMouseClick(Qt::MouseButton, FrameNumberType, FrameNumberType, int)), SIGNAL(InformOfMouseClick(Qt::MouseButton, FrameNumberType, FrameNumberType, int)));
|
|
connect(channelDataView, SIGNAL(InformOfMouseMove(FrameNumberType, FrameNumberType, int)), SIGNAL(InformOfMouseMove(FrameNumberType, FrameNumberType, int)));
|
|
connect(channelDataView, SIGNAL(InformOfMouseRelease(Qt::MouseButton, FrameNumberType, FrameNumberType, int)), SIGNAL(InformOfMouseRelease(Qt::MouseButton, FrameNumberType, FrameNumberType, int)));
|
|
connect(channelDataView, SIGNAL(InformOfMouseWheel(FrameNumberType, int, FrameNumberType, int)), SIGNAL(InformOfMouseWheel(FrameNumberType, int, FrameNumberType, int)));
|
|
connect(configChannel, SIGNAL(clicked()), SLOT(OnConfigureChannel()));
|
|
|
|
ConfigureUI();
|
|
}
|
|
|
|
ChannelControl::~ChannelControl()
|
|
{
|
|
if (m_configurationDialog)
|
|
{
|
|
m_configurationDialog->close();
|
|
}
|
|
m_configurationDialog = nullptr;
|
|
|
|
QList<QWidget*>::iterator iter = m_OpenDrills.begin();
|
|
while (iter != m_OpenDrills.end())
|
|
{
|
|
delete *iter;
|
|
++iter;
|
|
}
|
|
m_OpenDrills.clear();
|
|
}
|
|
|
|
bool ChannelControl::IsInCaptureMode(CaptureMode captureMode) const
|
|
{
|
|
return m_captureMode == captureMode;
|
|
}
|
|
|
|
void ChannelControl::SetCaptureMode(CaptureMode captureMode)
|
|
{
|
|
if (captureMode != m_captureMode)
|
|
{
|
|
m_captureMode = captureMode;
|
|
|
|
ConfigureUI();
|
|
|
|
emit OnCaptureModeChanged(m_captureMode);
|
|
}
|
|
}
|
|
|
|
void ChannelControl::OnContractedToggled(bool toggleState)
|
|
{
|
|
(void)toggleState;
|
|
|
|
// We're going to want to contract this eventually. So keeping the function
|
|
// to avoid unwiring all of the other methods, while we transition
|
|
/*
|
|
m_Contracted->setChecked(toggleState);
|
|
|
|
if (toggleState) // MINIMIZED
|
|
{
|
|
m_State.m_ContractedHeight = true;
|
|
m_Info->hide();
|
|
setFixedHeight(k_contractedSize);
|
|
QIcon eyecon(":/general/expand");
|
|
m_Contracted->setIcon(eyecon);
|
|
}
|
|
else // NORMAL
|
|
{
|
|
m_State.m_ContractedHeight = false;
|
|
m_Info->show();
|
|
this->setFixedHeight(k_expandedSize);
|
|
QIcon eyecon(":/general/contract");
|
|
m_Contracted->setIcon(eyecon);
|
|
}
|
|
emit ExpandedContracted();
|
|
*/
|
|
}
|
|
|
|
void ChannelControl::OnSuccessfulDrillDown(QWidget* drillerWidget)
|
|
{
|
|
if (drillerWidget)
|
|
{
|
|
connect(drillerWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnDrillDestroyed(QObject*)));
|
|
m_OpenDrills.push_back(drillerWidget);
|
|
}
|
|
}
|
|
|
|
void ChannelControl::OnDrillDestroyed(QObject* drill)
|
|
{
|
|
QWidget* qw = qobject_cast<QWidget*>(drill);
|
|
m_OpenDrills.removeOne(qw);
|
|
}
|
|
|
|
void ChannelControl::OnShowCommand()
|
|
{
|
|
//todo: phughes consider auto-hide toggle to control this behavior
|
|
|
|
//QList<QPoint>::iterator ptiter = m_OpenDrillsPositions.begin();
|
|
//QList<QWidget*>::iterator iter = m_OpenDrills.begin();
|
|
//while (iter != m_OpenDrills.end())
|
|
//{
|
|
// (*iter)->show();
|
|
// (*iter)->move(*ptiter);
|
|
// ++iter;
|
|
// ++ptiter;
|
|
//}
|
|
}
|
|
|
|
void ChannelControl::OnHideCommand()
|
|
{
|
|
//todo: phughes consider auto-hide toggle to control this behavior
|
|
|
|
//m_OpenDrillsPositions.clear();
|
|
//QList<QWidget*>::iterator iter = m_OpenDrills.begin();
|
|
//while (iter != m_OpenDrills.end())
|
|
//{
|
|
// if (*iter)
|
|
// {
|
|
// m_OpenDrillsPositions.push_back((*iter)->pos());
|
|
// (*iter)->hide();
|
|
// }
|
|
// ++iter;
|
|
//}
|
|
}
|
|
|
|
bool ChannelControl::IsSetup() const
|
|
{
|
|
return m_isSetup;
|
|
}
|
|
|
|
void ChannelControl::SignalSetup()
|
|
{
|
|
m_isSetup = true;
|
|
|
|
ConfigureUI();
|
|
}
|
|
|
|
bool ChannelControl::IsActive() const
|
|
{
|
|
bool isActive = false;
|
|
|
|
for (ChannelProfilerWidget* profiler : m_profilerWidgets)
|
|
{
|
|
if (profiler->IsActive())
|
|
{
|
|
isActive = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return isActive;
|
|
}
|
|
|
|
const AZStd::list< ChannelProfilerWidget* >& ChannelControl::GetProfilers() const
|
|
{
|
|
return m_profilerWidgets;
|
|
}
|
|
|
|
ChannelProfilerWidget* ChannelControl::GetMainProfiler() const
|
|
{
|
|
ChannelProfilerWidget* retVal = nullptr;
|
|
|
|
for (ChannelProfilerWidget* profiler : m_profilerWidgets)
|
|
{
|
|
if (profiler->IsActive())
|
|
{
|
|
retVal = profiler;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
ChannelProfilerWidget* ChannelControl::AddAggregator(Aggregator* aggregator)
|
|
{
|
|
ChannelProfilerWidget* retVal = nullptr;
|
|
|
|
for (ChannelProfilerWidget* profiler : m_profilerWidgets)
|
|
{
|
|
if (profiler->GetID() == aggregator->GetID())
|
|
{
|
|
AZ_Warning("ChannelControl", false, "Trying to register two aggregators with the same ID");
|
|
retVal = profiler;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (retVal == nullptr)
|
|
{
|
|
retVal = aznew ChannelProfilerWidget(this, aggregator);
|
|
|
|
if (retVal != nullptr)
|
|
{
|
|
ConnectProfilerWidget(retVal);
|
|
|
|
profilerLayout->addWidget(retVal);
|
|
m_profilerWidgets.push_back(retVal);
|
|
|
|
aggregator->AnnotateChannelView(channelDataView);
|
|
|
|
if (aggregator->HasConfigurations())
|
|
{
|
|
configChannel->setVisible(true);
|
|
}
|
|
|
|
connect(aggregator, SIGNAL(NormalizedRangeChanged()), SLOT(OnNormalizedRangeChanged()));
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
bool ChannelControl::RemoveAggregator(Aggregator* aggregator)
|
|
{
|
|
bool removed = false;
|
|
|
|
for (auto profilerIter = m_profilerWidgets.begin();
|
|
profilerIter != m_profilerWidgets.end();
|
|
++profilerIter)
|
|
{
|
|
if ((*profilerIter)->GetID() == aggregator->GetID())
|
|
{
|
|
removed = true;
|
|
m_profilerWidgets.erase(profilerIter);
|
|
break;
|
|
}
|
|
}
|
|
|
|
AZ_Warning("ChannelControl", removed, "Trying to remove aggregator from the wrong Channel Control");
|
|
return removed;
|
|
}
|
|
|
|
void ChannelControl::SetAllProfilersEnabled(bool enabled)
|
|
{
|
|
for (ChannelProfilerWidget* profiler : m_profilerWidgets)
|
|
{
|
|
profiler->SetIsActive(enabled);
|
|
}
|
|
}
|
|
|
|
AZ::Crc32 ChannelControl::GetChannelId() const
|
|
{
|
|
return m_channelId;
|
|
}
|
|
|
|
void ChannelControl::SetEndFrame(FrameNumberType endFrame)
|
|
{
|
|
channelDataView->DirtyGraphData();
|
|
m_State.m_EndFrame = endFrame;
|
|
channelDataView->update();
|
|
}
|
|
|
|
void ChannelControl::SetSliderOffset(FrameNumberType frameOffset)
|
|
{
|
|
channelDataView->DirtyGraphData();
|
|
m_State.m_FrameOffset = frameOffset;
|
|
//AZ_TracePrintf("Driller"," SetSliderOffset %d = %d - %d\n", m_State.m_FrameOffset, m_State.m_EndFrame, frame);
|
|
channelDataView->update();
|
|
}
|
|
|
|
void ChannelControl::SetLoopBegin(FrameNumberType frameNum)
|
|
{
|
|
if (m_State.m_LoopBegin != frameNum)
|
|
{
|
|
m_State.m_LoopBegin = frameNum;
|
|
|
|
FrameNumberType lastFrame = m_State.m_FrameOffset + m_State.m_FramesInView - 1;
|
|
|
|
if (frameNum < m_State.m_FrameOffset)
|
|
{
|
|
emit RequestScrollToFrame(frameNum);
|
|
}
|
|
else if (frameNum > lastFrame)
|
|
{
|
|
emit RequestScrollToFrame(m_State.m_FrameOffset + (frameNum - lastFrame));
|
|
}
|
|
|
|
channelDataView->update();
|
|
}
|
|
}
|
|
void ChannelControl::SetLoopEnd(FrameNumberType frameNum)
|
|
{
|
|
if (m_State.m_LoopEnd != frameNum)
|
|
{
|
|
m_State.m_LoopEnd = frameNum;
|
|
|
|
FrameNumberType lastFrame = m_State.m_FrameOffset + m_State.m_FramesInView - 1;
|
|
|
|
if (frameNum < m_State.m_FrameOffset)
|
|
{
|
|
emit RequestScrollToFrame(frameNum);
|
|
}
|
|
else if (frameNum > lastFrame)
|
|
{
|
|
emit RequestScrollToFrame(m_State.m_FrameOffset + (frameNum - lastFrame));
|
|
}
|
|
|
|
channelDataView->update();
|
|
}
|
|
}
|
|
|
|
void ChannelControl::SetScrubberFrame(FrameNumberType frameNum)
|
|
{
|
|
if (m_State.m_ScrubberFrame != frameNum)
|
|
{
|
|
m_State.m_ScrubberFrame = frameNum;
|
|
|
|
FrameNumberType lastFrame = m_State.m_FrameOffset + m_State.m_FramesInView - 1;
|
|
|
|
if (frameNum < m_State.m_FrameOffset)
|
|
{
|
|
emit RequestScrollToFrame(frameNum);
|
|
}
|
|
else if (frameNum > lastFrame)
|
|
{
|
|
emit RequestScrollToFrame(m_State.m_FrameOffset + (frameNum - lastFrame));
|
|
}
|
|
|
|
channelDataView->update();
|
|
}
|
|
}
|
|
|
|
void ChannelControl::SetDataPointsInView(FrameNumberType count)
|
|
{
|
|
m_State.m_FramesInView = count;
|
|
channelDataView->DirtyGraphData();
|
|
channelDataView->update();
|
|
}
|
|
|
|
void ChannelControl::OnRefreshView()
|
|
{
|
|
channelDataView->update();
|
|
}
|
|
|
|
void ChannelControl::OnActivationChanged(ChannelProfilerWidget* profilerWidget, bool activated)
|
|
{
|
|
if (activated)
|
|
{
|
|
profilerWidget->GetAggregator()->AnnotateChannelView(channelDataView);
|
|
}
|
|
else
|
|
{
|
|
profilerWidget->GetAggregator()->RemoveChannelAnnotation(channelDataView);
|
|
}
|
|
|
|
channelDataView->DirtyGraphData();
|
|
channelDataView->update();
|
|
}
|
|
|
|
void ChannelControl::OnConfigureChannel()
|
|
{
|
|
if (m_configurationDialog == nullptr)
|
|
{
|
|
m_configurationDialog = aznew ChannelConfigurationDialog();
|
|
QVBoxLayout* layout = new QVBoxLayout();
|
|
|
|
QMargins contentMargins(3,5,3,5);
|
|
layout->setContentsMargins(contentMargins);
|
|
layout->setSpacing(5);
|
|
|
|
for (ChannelProfilerWidget* profilerWidget : m_profilerWidgets)
|
|
{
|
|
if (profilerWidget->IsActive())
|
|
{
|
|
ChannelConfigurationWidget* configurationWidget = profilerWidget->CreateConfigurationWidget();
|
|
|
|
if (configurationWidget)
|
|
{
|
|
connect(configurationWidget, SIGNAL(ConfigurationChanged()), SLOT(OnConfigurationChanged()));
|
|
layout->addWidget(configurationWidget);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_configurationDialog->setLayout(layout);
|
|
m_configurationDialog->show();
|
|
m_configurationDialog->setFocus();
|
|
|
|
connect(m_configurationDialog, SIGNAL(DialogClosed(QDialog*)), SLOT(OnDialogClosed(QDialog*)));
|
|
|
|
m_configurationDialog->setWindowTitle(QString("%1's Channel Configurations.").arg(channelName->text()));
|
|
}
|
|
|
|
if (m_configurationDialog->isMinimized())
|
|
{
|
|
m_configurationDialog->showNormal();
|
|
}
|
|
|
|
m_configurationDialog->raise();
|
|
m_configurationDialog->activateWindow();
|
|
}
|
|
|
|
void ChannelControl::OnDialogClosed(QDialog* dialog)
|
|
{
|
|
if (m_configurationDialog == dialog)
|
|
{
|
|
m_configurationDialog = nullptr;
|
|
}
|
|
}
|
|
|
|
void ChannelControl::OnConfigurationChanged()
|
|
{
|
|
if (IsInCaptureMode(CaptureMode::Inspecting))
|
|
{
|
|
for (ChannelProfilerWidget* profilerWidget : m_profilerWidgets)
|
|
{
|
|
profilerWidget->GetAggregator()->OnConfigurationChanged();
|
|
}
|
|
|
|
// Force the channel data view to regrab all of the aggregator data.
|
|
channelDataView->RefreshGraphData();
|
|
}
|
|
}
|
|
|
|
void ChannelControl::OnNormalizedRangeChanged()
|
|
{
|
|
// Only want to allow this while we are inspecting.
|
|
// Otherwise just too much noise with the incoming data.
|
|
if (IsInCaptureMode(CaptureMode::Inspecting))
|
|
{
|
|
channelDataView->RefreshGraphData();
|
|
}
|
|
}
|
|
|
|
void ChannelControl::ConnectProfilerWidget(ChannelProfilerWidget* profilerWidget)
|
|
{
|
|
connect(this, SIGNAL(OnCaptureModeChanged(CaptureMode)), profilerWidget, SLOT(SetCaptureMode(CaptureMode)));
|
|
|
|
connect(profilerWidget, SIGNAL(OnActivationChanged(ChannelProfilerWidget*, bool)), this, SLOT(OnActivationChanged(ChannelProfilerWidget*, bool)));
|
|
|
|
profilerWidget->SetCaptureMode(m_captureMode);
|
|
}
|
|
|
|
void ChannelControl::ConfigureUI()
|
|
{
|
|
if (IsSetup())
|
|
{
|
|
configChannel->setEnabled(!IsInCaptureMode(CaptureMode::Capturing));
|
|
}
|
|
}
|
|
}
|