Merge branch 'development' into cmake/linux_fix_warn_unused
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Legacy/CrySystem/Log.cpp # Code/Tools/Standalone/Source/Driller/Annotations/AnnotationHeaderView.cpp # Code/Tools/Standalone/Source/Driller/AreaChart.cpp # Code/Tools/Standalone/Source/Driller/AreaChart.hxx # Code/Tools/Standalone/Source/Driller/ChannelDataView.cpp # Code/Tools/Standalone/Source/Driller/DrillerCaptureWindow.cpp # Code/Tools/Standalone/Source/Driller/Profiler/ProfilerDataView.cpp
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetCatalogComponent.h>
|
||||
#include <AzFramework/Driller/RemoteDrillerInterface.h>
|
||||
#include <AzFramework/Entity/GameEntityContextComponent.h>
|
||||
#include <AzFramework/FileTag/FileTagComponent.h>
|
||||
#include <AzFramework/Input/System/InputSystemComponent.h>
|
||||
@@ -169,7 +168,6 @@ namespace AssetBundler
|
||||
if (*iter == azrtti_typeid<AzFramework::GameEntityContextComponent>() ||
|
||||
*iter == azrtti_typeid<AzFramework::AzFrameworkConfigurationSystemComponent>() ||
|
||||
*iter == azrtti_typeid<AzFramework::InputSystemComponent>() ||
|
||||
*iter == azrtti_typeid<AzFramework::DrillerNetworkAgentComponent>() ||
|
||||
*iter == azrtti_typeid<AZ::SliceSystemComponent>())
|
||||
{
|
||||
// Asset Bundler does not require the above components to be active
|
||||
|
||||
@@ -74,6 +74,10 @@ namespace AssetBuilderSDK
|
||||
{
|
||||
return AssetBuilderSDK::Platform_PC;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "linux") == 0)
|
||||
{
|
||||
return AssetBuilderSDK::Platform_LINUX;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "android") == 0)
|
||||
{
|
||||
return AssetBuilderSDK::Platform_ANDROID;
|
||||
|
||||
@@ -144,15 +144,16 @@ namespace AssetBuilderSDK
|
||||
{
|
||||
Platform_NONE = 0x00,
|
||||
Platform_PC = 0x01,
|
||||
Platform_ANDROID = 0x02,
|
||||
Platform_IOS = 0x04,
|
||||
Platform_MAC = 0x08,
|
||||
Platform_LINUX = 0x02,
|
||||
Platform_ANDROID = 0x04,
|
||||
Platform_IOS = 0x08,
|
||||
Platform_MAC = 0x10,
|
||||
Platform_PROVO = 0x20,
|
||||
Platform_SALEM = 0x40,
|
||||
Platform_JASPER = 0x80,
|
||||
|
||||
//! if you add a new platform entry to this enum, you must add it to allplatforms as well otherwise that platform would not be considered valid.
|
||||
AllPlatforms = Platform_PC | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER
|
||||
AllPlatforms = Platform_PC | Platform_LINUX | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER
|
||||
};
|
||||
#endif // defined(ENABLE_LEGACY_PLATFORMFLAGS_SUPPORT)
|
||||
//! Map data structure to holder parameters that are passed into a job for ProcessJob requests.
|
||||
|
||||
+3
@@ -14,6 +14,9 @@
|
||||
"Platform server": {
|
||||
"tags": "server"
|
||||
},
|
||||
"Platform linux": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platforms": {
|
||||
"android": "enabled",
|
||||
"server": "enabled"
|
||||
|
||||
+4
-1
@@ -14,6 +14,9 @@
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform linux": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform server": {
|
||||
"tags": "server"
|
||||
},
|
||||
@@ -110,4 +113,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,6 @@ namespace AZ::SceneAPI::Containers
|
||||
MOCK_CONST_METHOD0(GetAppRoot, const char*());
|
||||
MOCK_CONST_METHOD0(GetEngineRoot, const char*());
|
||||
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
|
||||
MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
|
||||
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
|
||||
};
|
||||
|
||||
|
||||
@@ -38,34 +38,3 @@ ly_add_target(
|
||||
PRIVATE
|
||||
STANDALONETOOLS_ENABLE_LUA_IDE
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME Profiler APPLICATION
|
||||
NAMESPACE AZ
|
||||
AUTOMOC
|
||||
AUTOUIC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
standalone_tools_files.cmake
|
||||
profiler_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/profiler_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
.
|
||||
Source/Editor
|
||||
Source/Driller
|
||||
Source/Driller/Carrier
|
||||
Source/Driller/Profiler
|
||||
Source/Driller/IO
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Legacy::CryCommon
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzToolsFramework
|
||||
AZ::GridMate
|
||||
${additional_dependencies}
|
||||
COMPILE_DEFINITIONS
|
||||
PRIVATE
|
||||
STANDALONETOOLS_ENABLE_PROFILER
|
||||
)
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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 "AnnotationHeaderView.hxx"
|
||||
#include "AnnotationsDataView.hxx"
|
||||
#include "Annotations.hxx"
|
||||
#include <QtWidgets/QGridLayout>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const int k_contractedSize = 20;
|
||||
|
||||
AnnotationHeaderView::AnnotationHeaderView(AnnotationsProvider* ptrAnnotations, QWidget* parent, Qt::WindowFlags flags)
|
||||
: QWidget(parent, flags)
|
||||
, m_ptrAnnotations(ptrAnnotations)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
m_State.m_EndFrame = -1;
|
||||
m_State.m_FramesInView = 10;
|
||||
m_State.m_FrameOffset = 0;
|
||||
|
||||
annotationDataView->RegisterAnnotationHeaderView(this, m_ptrAnnotations);
|
||||
annotationDataView->setAutoFillBackground(true);
|
||||
|
||||
connect(configureAnnotations, SIGNAL(pressed()), this, SIGNAL(OnOptionsClick()));
|
||||
connect(annotationDataView, SIGNAL(InformOfMouseOverAnnotation(const Annotation&)), this, SIGNAL(InformOfMouseOverAnnotation(const Annotation&)));
|
||||
connect(annotationDataView, SIGNAL(InformOfClickAnnotation(const Annotation&)), this, SIGNAL(InformOfClickAnnotation(const Annotation&)));
|
||||
connect(m_ptrAnnotations, SIGNAL(AnnotationDataInvalidated()), this, SLOT(RefreshView()));
|
||||
|
||||
annotationDataView->update();
|
||||
|
||||
QSize size = annotationDataView->size();
|
||||
int nextHeight = size.height();
|
||||
|
||||
(void)nextHeight;
|
||||
}
|
||||
|
||||
QSize AnnotationHeaderView::sizeHint() const
|
||||
{
|
||||
return QSize(0, k_contractedSize);
|
||||
}
|
||||
|
||||
|
||||
AnnotationHeaderView::~AnnotationHeaderView()
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationHeaderView::RefreshView()
|
||||
{
|
||||
annotationDataView->update();
|
||||
}
|
||||
|
||||
void AnnotationHeaderView::SetEndFrame(FrameNumberType frameNum)
|
||||
{
|
||||
QSize size = annotationDataView->size();
|
||||
int nextHeight = size.height();
|
||||
|
||||
(void)nextHeight;
|
||||
|
||||
m_State.m_EndFrame = frameNum;
|
||||
annotationDataView->update();
|
||||
}
|
||||
|
||||
void AnnotationHeaderView::SetSliderOffset(FrameNumberType frameNum)
|
||||
{
|
||||
m_State.m_FrameOffset = frameNum;
|
||||
annotationDataView->update();
|
||||
}
|
||||
|
||||
void AnnotationHeaderView::SetDataPointsInView(int count)
|
||||
{
|
||||
m_State.m_FramesInView = count;
|
||||
annotationDataView->update();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_AnnotationHeaderView.cpp>
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANNOTATION_HEADER_VIEW_HXX
|
||||
#define ANNOTATION_HEADER_VIEW_HXX
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include <Source/Driller/Annotations/ui_AnnotationHeaderView.h>
|
||||
#include <Source/Driller/DrillerNetworkMessages.h>
|
||||
#include <Source/Driller/DrillerDataTypes.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class AnnotationsDataView;
|
||||
class Annotation;
|
||||
|
||||
/** The annotation header view runs along the top of the channels, and shows annotation blips that can be hovered over.
|
||||
* this gives nice hit boxes for clicking that are not a sliver thick.
|
||||
*/
|
||||
|
||||
class AnnotationHeaderView : public QWidget, private Ui::AnnotationHeaderView
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnnotationHeaderView,AZ::SystemAllocator,0);
|
||||
AnnotationHeaderView(AnnotationsProvider* ptrAnnotations, QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~AnnotationHeaderView(void);
|
||||
|
||||
struct HeaderViewState
|
||||
{
|
||||
int m_EndFrame;
|
||||
int m_FramesInView;
|
||||
int m_FrameOffset;
|
||||
};
|
||||
|
||||
const HeaderViewState& GetState() { return m_State; }
|
||||
|
||||
void SetDataPointsInView( int count );
|
||||
void SetEndFrame( FrameNumberType frame );
|
||||
void SetSliderOffset( FrameNumberType frame );
|
||||
|
||||
signals:
|
||||
void OnOptionsClick();
|
||||
void InformOfMouseOverAnnotation(const Annotation& annotation);
|
||||
void InformOfClickAnnotation(const Annotation& annotation);
|
||||
public slots:
|
||||
void RefreshView();
|
||||
|
||||
private:
|
||||
HeaderViewState m_State;
|
||||
|
||||
AnnotationsProvider *m_ptrAnnotations;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // ANNOTATION_HEADER_VIEW_HXX
|
||||
@@ -1,178 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AnnotationHeaderView</class>
|
||||
<widget class="QWidget" name="AnnotationHeaderView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1023</width>
|
||||
<height>38</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="annotationBackground">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="configureAnnotations">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Configure which messages are annotated on the display</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure Annotations</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/driller/settings_icon</normaloff>:/driller/settings_icon</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Driller::AnnotationsDataView" name="annotationDataView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::AnnotationsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Source/Driller/Annotations/AnnotationsDataView.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,405 +0,0 @@
|
||||
/*
|
||||
* 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 "Annotations.hxx"
|
||||
#include <Source/Driller/Workspaces/Workspace.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/IO/GenericStreams.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QRgb>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// stores the settings that are saved into the file and transported from user to user to accompany drill files.
|
||||
// as always, this is just a dumb container and does not need encapsulation
|
||||
class AnnotationWorkspaceSettings
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AnnotationWorkspaceSettings, "{431EFFCF-C3C5-4BB3-8246-E452E11D4FF8}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(AnnotationWorkspaceSettings, AZ::SystemAllocator, 0);
|
||||
|
||||
ChannelContainer m_ActiveAnnotationChannels;
|
||||
ChannelCRCContainer m_ActiveAnnotationChannelCRCs;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<AnnotationWorkspaceSettings>()
|
||||
->Version(2)
|
||||
->Field("m_ActiveAnnotationChannels", &AnnotationWorkspaceSettings::m_ActiveAnnotationChannels)
|
||||
->Field("m_ActiveAnnotationChannelCRCs", &AnnotationWorkspaceSettings::m_ActiveAnnotationChannelCRCs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// stores the data that goes with the user preferences, even without a workspace file
|
||||
// mainly gui stuff...
|
||||
// as always, this is just a dumb container and does not need encapsulation
|
||||
class AnnotationUserSettings
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AnnotationUserSettings, "{D3584846-0574-4B63-9693-4F3265CDE16D}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(AnnotationUserSettings, AZ::SystemAllocator, 0);
|
||||
|
||||
ChannelContainer m_KnownAnnotationChannels; // keeps track of all annotation channels ever seen
|
||||
AZStd::unordered_map<AZ::u32, AZ::u32> m_customizedColors;
|
||||
|
||||
AZ::u32 GetRGBAColorForChannel(AZ::u32 channelNameCRC)
|
||||
{
|
||||
auto found = m_customizedColors.find(channelNameCRC);
|
||||
if (found != m_customizedColors.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
AZ::u32 num_different_colors = 7;
|
||||
QColor col;
|
||||
float sat = .9f;
|
||||
float val = .9f;
|
||||
col.setHsvF((float)(channelNameCRC % num_different_colors) / (float(num_different_colors)), sat, val);
|
||||
QRgb rgbColor = col.rgba();
|
||||
return rgbColor;
|
||||
}
|
||||
|
||||
void SetRGBAColorForChannel(AZ::u32 channelNameCRC, AZ::u32 rgbaColor)
|
||||
{
|
||||
m_customizedColors[channelNameCRC] = rgbaColor;
|
||||
}
|
||||
|
||||
void ResetColorForChannel(AZ::u32 channelNameCRC)
|
||||
{
|
||||
m_customizedColors.erase(channelNameCRC);
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<AnnotationUserSettings>()
|
||||
->Version(1)
|
||||
->Field("m_KnownAnnotationChannels", &AnnotationUserSettings::m_KnownAnnotationChannels)
|
||||
->Field("m_customizedColors", &AnnotationUserSettings::m_customizedColors);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AnnotationsProvider::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AnnotationWorkspaceSettings::Reflect(context);
|
||||
AnnotationUserSettings::Reflect(context);
|
||||
}
|
||||
|
||||
Annotation::Annotation()
|
||||
{
|
||||
m_ChannelCRC = 0;
|
||||
m_eventIndex = 0;
|
||||
m_frameIndex = 0;
|
||||
}
|
||||
|
||||
Annotation::Annotation(AZ::s64 eventID, FrameNumberType frame, const char* text, const char* channel)
|
||||
{
|
||||
m_eventIndex = eventID;
|
||||
m_frameIndex = frame;
|
||||
m_text = text;
|
||||
m_channel = channel;
|
||||
m_ChannelCRC = AZ::Crc32(m_channel.c_str());
|
||||
}
|
||||
|
||||
Annotation::Annotation(const Annotation& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Annotation::Annotation(Annotation&& other)
|
||||
{
|
||||
*this = AZStd::move(other);
|
||||
}
|
||||
|
||||
Annotation& Annotation::operator=(Annotation&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_eventIndex = other.m_eventIndex;
|
||||
m_frameIndex = other.m_frameIndex;
|
||||
m_text = AZStd::move(other.m_text);
|
||||
m_channel = AZStd::move(other.m_channel);
|
||||
m_ChannelCRC = other.m_ChannelCRC;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Annotation& Annotation::operator=(const Annotation& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_eventIndex = other.m_eventIndex;
|
||||
m_frameIndex = other.m_frameIndex;
|
||||
m_text = other.m_text;
|
||||
m_channel = other.m_channel;
|
||||
m_ChannelCRC = other.m_ChannelCRC;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AnnotationsProvider::AnnotationsProvider(QObject* pParent)
|
||||
: QObject(pParent)
|
||||
{
|
||||
m_bVectorDirty = false;
|
||||
|
||||
/// load user settings and workspace settings from usersettings component to persist state
|
||||
|
||||
m_ptrUserSettings = AZ::UserSettings::CreateFind<AnnotationUserSettings>(AZ_CRC("ANNOT_USERSETTINGS", 0x3ddaa4f1), AZ::UserSettings::CT_GLOBAL);
|
||||
m_ptrWorkspaceSettings = AZ::UserSettings::CreateFind<AnnotationWorkspaceSettings>(AZ_CRC("ANNOT_WORKSPACESETTINGS", 0xf7ca8dd3), AZ::UserSettings::CT_GLOBAL);
|
||||
}
|
||||
|
||||
AnnotationsProvider::~AnnotationsProvider()
|
||||
{
|
||||
AZ::UserSettings::Release(m_ptrUserSettings);
|
||||
AZ::UserSettings::Release(m_ptrWorkspaceSettings);
|
||||
}
|
||||
|
||||
|
||||
void AnnotationsProvider::LoadSettingsFromWorkspace(WorkspaceSettingsProvider* ptrProvider)
|
||||
{
|
||||
AnnotationWorkspaceSettings* rawPtr = ptrProvider->FindSetting<AnnotationWorkspaceSettings>(AZ_CRC("ANNOTATIONWORKSPACE", 0x28319f66));
|
||||
if (rawPtr)
|
||||
{
|
||||
m_ptrWorkspaceSettings->m_ActiveAnnotationChannels = rawPtr->m_ActiveAnnotationChannels;
|
||||
m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs = rawPtr->m_ActiveAnnotationChannelCRCs;
|
||||
|
||||
// aggregate missing channels:
|
||||
for (auto it = m_ptrWorkspaceSettings->m_ActiveAnnotationChannels.begin(); it != m_ptrWorkspaceSettings->m_ActiveAnnotationChannels.end(); ++it)
|
||||
{
|
||||
NotifyOfChannelExistence(it->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsProvider::SaveSettingsToWorkspace(WorkspaceSettingsProvider* ptrProvider)
|
||||
{
|
||||
AnnotationWorkspaceSettings* rawPtr = ptrProvider->CreateSetting<AnnotationWorkspaceSettings>(AZ_CRC("ANNOTATIONWORKSPACE", 0x28319f66));
|
||||
rawPtr->m_ActiveAnnotationChannels = m_ptrWorkspaceSettings->m_ActiveAnnotationChannels;
|
||||
rawPtr->m_ActiveAnnotationChannelCRCs = m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs;
|
||||
}
|
||||
|
||||
// returns the end of the vector (ie, the invalid iterator)
|
||||
AnnotationsProvider::ConstAnnotationIterator AnnotationsProvider::GetEnd() const
|
||||
{
|
||||
AZ_Assert(!m_bVectorDirty, "You may not interrogate the annotations provider before it is finalized");
|
||||
|
||||
return m_currentAnnotations.end();
|
||||
}
|
||||
|
||||
// returns iterator to the first annotation thats on the frame given (or the end iterator)
|
||||
AnnotationsProvider::ConstAnnotationIterator AnnotationsProvider::GetFirstAnnotationForFrame(FrameNumberType frameIndex) const
|
||||
{
|
||||
AZ_Assert(!m_bVectorDirty, "You may not interrogate the annotations provider before it is finalized");
|
||||
|
||||
// do we have annotations for that framE?
|
||||
FrameIndexToCurrentMap::const_iterator it = m_frameToIndex.find(frameIndex);
|
||||
if (it == m_frameToIndex.end())
|
||||
{
|
||||
return GetEnd();
|
||||
}
|
||||
|
||||
return m_currentAnnotations.begin() + it->second;
|
||||
}
|
||||
|
||||
// returns iterator to the first annotation that is foer that event # (or the end iterator)
|
||||
AnnotationsProvider::ConstAnnotationIterator AnnotationsProvider::GetAnnotationForEvent(EventNumberType eventIndex) const
|
||||
{
|
||||
AZ_Assert(!m_bVectorDirty, "You may not interrogate the annotations provider before it is finalized");
|
||||
|
||||
// do we have annotations for that event index?
|
||||
EventIndexToCurrentMap::const_iterator it = m_eventToIndex.find(eventIndex);
|
||||
if (it == m_eventToIndex.end())
|
||||
{
|
||||
return GetEnd();
|
||||
}
|
||||
|
||||
return m_currentAnnotations.begin() + it->second;
|
||||
}
|
||||
|
||||
// note:: claims ownership of the data in annotation.
|
||||
void AnnotationsProvider::AddAnnotation(Annotation&& target)
|
||||
{
|
||||
if (m_eventToIndex.find(target.GetEventIndex()) != m_eventToIndex.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// can we do this quickly and easily?
|
||||
if (
|
||||
(!m_bVectorDirty) && // if we're not already going to need to sort, and...
|
||||
(
|
||||
(m_currentAnnotations.empty()) || // we either have no annotations or...
|
||||
(m_currentAnnotations.back().GetEventIndex() < target.GetEventIndex()) // the fresh annotation belongs at the end anyway and we will not need to re-sort.
|
||||
)
|
||||
)
|
||||
{
|
||||
// we're adding annotations onto the end, so we will not have to sort, we can just accumulate the data.
|
||||
|
||||
m_eventToIndex[target.GetEventIndex()] = m_currentAnnotations.size();
|
||||
|
||||
// if its the first annotation for this frame, we can also add it:
|
||||
if (m_frameToIndex.find(target.GetFrameIndex()) == m_frameToIndex.end())
|
||||
{
|
||||
m_frameToIndex[target.GetFrameIndex()] = m_currentAnnotations.size();
|
||||
}
|
||||
|
||||
m_currentAnnotations.push_back(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're adding annotations out of order, we have to re-sort:
|
||||
m_currentAnnotations.push_back(target);
|
||||
m_bVectorDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// called by the main controller to sort and build the map cache.
|
||||
void AnnotationsProvider::Finalize()
|
||||
{
|
||||
/*
|
||||
// temp: add some fake annots
|
||||
AddAnnotation(Annotation(5, 10, "Test annotation", "tracker"));
|
||||
AddAnnotation(Annotation(15, 110, "Test annotation2", "tracker1"));
|
||||
AddAnnotation(Annotation(25, 210, "Test annotatio3n", "tracker2"));
|
||||
AddAnnotation(Annotation(35, 310, "Test annotation4", "tracker3"));
|
||||
*/
|
||||
|
||||
if (!m_bVectorDirty)
|
||||
{
|
||||
emit AnnotationDataInvalidated();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_frameToIndex.clear();
|
||||
m_eventToIndex.clear();
|
||||
|
||||
// sort them so they are in order from beginning to end:
|
||||
AZStd::sort(
|
||||
m_currentAnnotations.begin(),
|
||||
m_currentAnnotations.end(),
|
||||
[](const Annotation& a, const Annotation& b) -> bool
|
||||
{
|
||||
return a.GetEventIndex() < b.GetEventIndex();
|
||||
}
|
||||
);
|
||||
|
||||
// now build the lookup tables:
|
||||
FrameNumberType lastFrameIndex = -1;
|
||||
for (AZStd::size_t idx = 0, endIdx = m_currentAnnotations.size(); idx < endIdx; ++idx)
|
||||
{
|
||||
const Annotation& current = m_currentAnnotations[idx];
|
||||
m_eventToIndex[current.GetEventIndex()] = idx;
|
||||
if (lastFrameIndex != current.GetFrameIndex())
|
||||
{
|
||||
m_frameToIndex[current.GetFrameIndex()] = idx;
|
||||
lastFrameIndex = current.GetFrameIndex();
|
||||
}
|
||||
}
|
||||
|
||||
emit AnnotationDataInvalidated();
|
||||
|
||||
m_bVectorDirty = false;
|
||||
}
|
||||
|
||||
const ChannelContainer& AnnotationsProvider::GetAllKnownChannels() const
|
||||
{
|
||||
return m_ptrUserSettings->m_KnownAnnotationChannels;
|
||||
}
|
||||
|
||||
void AnnotationsProvider::GetCurrentlyEnabledChannelCRCs(ChannelCRCContainer& target) const
|
||||
{
|
||||
target.insert(m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.begin(), m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.end());
|
||||
}
|
||||
|
||||
// let us know that a channel exists:
|
||||
void AnnotationsProvider::NotifyOfChannelExistence(const char* name)
|
||||
{
|
||||
if (m_ptrUserSettings->m_KnownAnnotationChannels.insert(name).second)
|
||||
{
|
||||
emit KnownAnnotationsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsProvider::SetChannelEnabled(const char* channelName, bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if (m_ptrWorkspaceSettings->m_ActiveAnnotationChannels.insert(channelName).second)
|
||||
{
|
||||
m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.insert(AZ::Crc32(channelName));
|
||||
NotifyOfChannelExistence(channelName);
|
||||
emit SelectedAnnotationsChanged();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::u32 channelCRC = AZ::Crc32(channelName);
|
||||
if (IsChannelEnabled(channelCRC))
|
||||
{
|
||||
m_ptrWorkspaceSettings->m_ActiveAnnotationChannels.erase(channelName);
|
||||
m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.erase(channelCRC);
|
||||
emit SelectedAnnotationsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QColor AnnotationsProvider::GetColorForChannel(AZ::u32 channelNameCRC) const
|
||||
{
|
||||
QRgb rgbaValue = m_ptrUserSettings->GetRGBAColorForChannel(channelNameCRC);
|
||||
return QColor(rgbaValue);
|
||||
}
|
||||
|
||||
void AnnotationsProvider::SetColorForChannel(AZ::u32 channelNameCRC, QColor newColor)
|
||||
{
|
||||
QRgb rgbaValue = newColor.rgba();
|
||||
m_ptrUserSettings->SetRGBAColorForChannel(channelNameCRC, rgbaValue);
|
||||
|
||||
if (IsChannelEnabled(channelNameCRC))
|
||||
{
|
||||
// update displays
|
||||
emit SelectedAnnotationsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsProvider::ResetColorForChannel(AZ::u32 channelNameCRC)
|
||||
{
|
||||
m_ptrUserSettings->ResetColorForChannel(channelNameCRC);
|
||||
}
|
||||
|
||||
bool AnnotationsProvider::IsChannelEnabled(AZ::u32 channelNameCRC) const
|
||||
{
|
||||
return (m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.find(channelNameCRC) != m_ptrWorkspaceSettings->m_ActiveAnnotationChannelCRCs.end());
|
||||
}
|
||||
|
||||
void AnnotationsProvider::Clear()
|
||||
{
|
||||
m_frameToIndex.clear();
|
||||
m_eventToIndex.clear();
|
||||
m_currentAnnotations.clear();
|
||||
m_bVectorDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_Annotations.cpp>
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_ANNOTATIONS_H
|
||||
#define DRILLER_ANNOTATIONS_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_ptr.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <QObject>
|
||||
|
||||
#include <Source/Driller/DrillerDataTypes.h>
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace AZ { class ReflectContext; }
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// Annotation
|
||||
// represents one annotation returned or fed into the annotations interface.
|
||||
class Annotation
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Annotation, AZ::SystemAllocator, 0);
|
||||
Annotation();
|
||||
Annotation(AZ::s64 eventID, FrameNumberType frame, const char* text, const char* channel);
|
||||
Annotation(const Annotation& other);
|
||||
Annotation(Annotation&& other);
|
||||
Annotation& operator=(Annotation&& other);
|
||||
Annotation& operator=(const Annotation& other);
|
||||
|
||||
AZ::s64 GetEventIndex() const { return m_eventIndex; }
|
||||
FrameNumberType GetFrameIndex() const { return m_frameIndex; }
|
||||
const AZStd::string& GetText() const { return m_text; }
|
||||
const AZStd::string& GetChannel() const { return m_channel; }
|
||||
const AZ::u32 GetChannelCRC() const { return m_ChannelCRC; }
|
||||
|
||||
private:
|
||||
AZ::s64 m_eventIndex;
|
||||
FrameNumberType m_frameIndex;
|
||||
AZStd::string m_text;
|
||||
AZStd::string m_channel;
|
||||
AZ::u32 m_ChannelCRC;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// AnnotationsProviderInterface
|
||||
// a class which provides annotation information to the parts of the system that care about annotations.
|
||||
// other parts of the system that want to know what annotations occur where will be given a pointer to this guy
|
||||
// and they will ask him what they need to know.
|
||||
// PLEASE NOTE: This is essentially a live cache of what's currently in the view range and is for rendering only.
|
||||
// its essentially destroyed and recreated every frame.
|
||||
|
||||
class AnnotationWorkspaceSettings;
|
||||
class AnnotationUserSettings;
|
||||
class WorkspaceSettingsProvider;
|
||||
|
||||
// contains a set of channel names
|
||||
typedef AZStd::unordered_set<AZStd::string> ChannelContainer;
|
||||
typedef AZStd::unordered_set<AZ::u32> ChannelCRCContainer;
|
||||
|
||||
class AnnotationsProvider
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnnotationsProvider, AZ::SystemAllocator, 0);
|
||||
|
||||
typedef AZStd::vector<Annotation> AnnotationContainer;
|
||||
typedef AnnotationContainer::const_iterator ConstAnnotationIterator;
|
||||
|
||||
// graph renderers need to know what color to draw annotations, and what annotations exist given a particular event or frame:
|
||||
ConstAnnotationIterator GetEnd() const; // returns the end of the vector (ie, the invalid iterator)
|
||||
ConstAnnotationIterator GetFirstAnnotationForFrame(FrameNumberType frameIndex) const; // returns iterator to the first annotation thats on the frame given (or the end iterator)
|
||||
ConstAnnotationIterator GetAnnotationForEvent(EventNumberType eventIndex) const; // returns iterator to the first annotation that is for that event # (or the end iterator)
|
||||
|
||||
// claims ownership of the given annotation, via r-value ref. This is used during populate.
|
||||
void AddAnnotation(Annotation&& target);
|
||||
|
||||
// configure a channel
|
||||
void ConfigureChannel(const char* channel, QColor color);
|
||||
|
||||
AnnotationsProvider(QObject* pParent = NULL);
|
||||
~AnnotationsProvider();
|
||||
|
||||
// called by the main controller to sort and build the map cache.
|
||||
void Finalize();
|
||||
void Clear();
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
// --- channel management ---
|
||||
const ChannelContainer& GetAllKnownChannels() const;
|
||||
void GetCurrentlyEnabledChannelCRCs(ChannelCRCContainer& target) const;
|
||||
void NotifyOfChannelExistence(const char* name);
|
||||
void SetChannelEnabled(const char* channelName, bool enabled);
|
||||
bool IsChannelEnabled(AZ::u32 channelNameCRC) const;
|
||||
QColor GetColorForChannel(AZ::u32 channelNameCRC) const; // each channel has a color, this is configured externally.
|
||||
void SetColorForChannel(AZ::u32 channelNameCRC, QColor newColor); // each channel has a color, this is configured externally.
|
||||
void ResetColorForChannel(AZ::u32 channelNameCRC); // each channel has a color, this is configured externally.
|
||||
|
||||
void LoadSettingsFromWorkspace(WorkspaceSettingsProvider* ptrProvider);
|
||||
void SaveSettingsToWorkspace(WorkspaceSettingsProvider* ptrProvider);
|
||||
signals:
|
||||
void KnownAnnotationsChanged();
|
||||
void SelectedAnnotationsChanged();
|
||||
void AnnotationDataInvalidated();
|
||||
|
||||
protected:
|
||||
AnnotationContainer m_currentAnnotations;
|
||||
typedef AZStd::unordered_map<EventNumberType, AZStd::size_t> EventIndexToCurrentMap; // maps from event index to index in our vector.
|
||||
typedef AZStd::unordered_map<FrameNumberType, AZStd::size_t> FrameIndexToCurrentMap; // maps from frame index to index in our vector.
|
||||
EventIndexToCurrentMap m_eventToIndex;
|
||||
FrameIndexToCurrentMap m_frameToIndex;
|
||||
|
||||
// housekeeping
|
||||
bool m_bVectorDirty;
|
||||
|
||||
AZStd::intrusive_ptr<AnnotationWorkspaceSettings> m_ptrWorkspaceSettings; // loaded from workspace and user settings. // crc(somethingelse)
|
||||
AZStd::intrusive_ptr<AnnotationUserSettings> m_ptrUserSettings; // loaded only from user settings / CRC(whatever)
|
||||
};
|
||||
}
|
||||
|
||||
#endif//DRILLER_ANNOTATIONS_H
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* 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 "AnnotationsDataView.hxx"
|
||||
#include "AnnotationHeaderView.hxx"
|
||||
#include "Annotations.hxx"
|
||||
|
||||
#include <QPen>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QMouseEvent>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const float adv_arrow_width = 8.0f;
|
||||
|
||||
AnnotationsDataView::AnnotationsDataView(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_ptrHeaderView(nullptr)
|
||||
, m_ptrAnnotations(nullptr)
|
||||
{
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
AnnotationsDataView::~AnnotationsDataView()
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationsDataView::RegisterAnnotationHeaderView(AnnotationHeaderView* header, AnnotationsProvider* annotations)
|
||||
{
|
||||
m_ptrHeaderView = header;
|
||||
m_ptrAnnotations = annotations;
|
||||
}
|
||||
|
||||
int AnnotationsDataView::PositionToFrame(const QPoint& pt)
|
||||
{
|
||||
QRect wrect = rect();
|
||||
|
||||
int frame = m_ptrHeaderView->GetState().m_FrameOffset + m_ptrHeaderView->GetState().m_FramesInView - 1;
|
||||
frame = frame <= m_ptrHeaderView->GetState().m_EndFrame ? frame : m_ptrHeaderView->GetState().m_EndFrame;
|
||||
|
||||
int rOffset = wrect.width() - pt.x();
|
||||
int rCell = (int)((float)rOffset / GetBarWidth());
|
||||
int retFrame = frame - rCell;
|
||||
|
||||
//AZ_TracePrintf("Driller","Click Frame Raw Input = %d\n", retFrame);
|
||||
|
||||
return retFrame;
|
||||
}
|
||||
|
||||
float AnnotationsDataView::GetBarWidth()
|
||||
{
|
||||
return ((float)(rect().width()) / (float)(m_ptrHeaderView->GetState().m_FramesInView));
|
||||
}
|
||||
|
||||
void AnnotationsDataView::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
|
||||
m_ClickableAreas.clear();
|
||||
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
pen.setBrush(brush);
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||
|
||||
painter.setPen(pen);
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
|
||||
int frame = m_ptrHeaderView->GetState().m_FrameOffset + m_ptrHeaderView->GetState().m_FramesInView - 1;
|
||||
frame = frame <= m_ptrHeaderView->GetState().m_EndFrame ? frame : m_ptrHeaderView->GetState().m_EndFrame;
|
||||
|
||||
QRect wrect = rect();
|
||||
|
||||
float barWidth = GetBarWidth();
|
||||
int barWidthHalf = (int)(barWidth / 2.0f);
|
||||
|
||||
QPen fatPen(QColor(255, 255, 255, 255));
|
||||
fatPen.setWidth(2);
|
||||
fatPen.setCapStyle(Qt::FlatCap);
|
||||
|
||||
if (m_ptrHeaderView->GetState().m_EndFrame)
|
||||
{
|
||||
float rightEdgeOfBar = (float)wrect.right();
|
||||
float leftEdgeOfBar = rightEdgeOfBar - barWidth;
|
||||
|
||||
while (frame >= 0 && rightEdgeOfBar >= wrect.left())
|
||||
{
|
||||
int actualLeftEdge = (int)floorf(leftEdgeOfBar);
|
||||
|
||||
float center = (float)(actualLeftEdge + barWidthHalf) + 0.5f;
|
||||
|
||||
// annotations?
|
||||
AnnotationsProvider::ConstAnnotationIterator it = m_ptrAnnotations->GetFirstAnnotationForFrame(frame);
|
||||
AnnotationsProvider::ConstAnnotationIterator endIt = m_ptrAnnotations->GetEnd();
|
||||
|
||||
while ((it != endIt) && (it->GetFrameIndex() == frame))
|
||||
{
|
||||
QPainterPath newPath;
|
||||
QPolygonF newPolygon;
|
||||
newPolygon << QPointF(center - adv_arrow_width, 1.0f) << QPointF(center, wrect.height() - 1.0f) << QPointF(center + adv_arrow_width, 1.0f);
|
||||
newPath.addPolygon(newPolygon);
|
||||
newPath.closeSubpath();
|
||||
|
||||
if (m_eventsToHighlight.find(it->GetEventIndex()) != m_eventsToHighlight.end())
|
||||
{
|
||||
painter.setPen(fatPen);
|
||||
painter.setBrush(m_ptrAnnotations->GetColorForChannel(it->GetChannelCRC()));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.setPen(QColor(0, 0, 0, 0));
|
||||
painter.setBrush(m_ptrAnnotations->GetColorForChannel(it->GetChannelCRC()));
|
||||
}
|
||||
painter.drawPath(newPath);
|
||||
m_ClickableAreas[it->GetEventIndex()] = newPath;
|
||||
++it;
|
||||
}
|
||||
|
||||
--frame;
|
||||
rightEdgeOfBar -= barWidth;
|
||||
leftEdgeOfBar -= barWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsDataView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
AZStd::unordered_set<AZ::s64> newEventsToHighlight;
|
||||
|
||||
for (auto it = m_ClickableAreas.begin(); it != m_ClickableAreas.end(); ++it)
|
||||
{
|
||||
if (it->second.contains(event->pos()))
|
||||
{
|
||||
auto annot = m_ptrAnnotations->GetAnnotationForEvent(it->first);
|
||||
if (annot != m_ptrAnnotations->GetEnd())
|
||||
{
|
||||
newEventsToHighlight.insert(annot->GetEventIndex());
|
||||
emit InformOfMouseOverAnnotation(*annot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool doUpdate = false;
|
||||
// did our highlight change?
|
||||
for (auto it = newEventsToHighlight.begin(); it != newEventsToHighlight.end(); ++it)
|
||||
{
|
||||
if (m_eventsToHighlight.find(*it) == m_eventsToHighlight.end())
|
||||
{
|
||||
doUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// did our highlight change?
|
||||
if (!doUpdate)
|
||||
{
|
||||
for (auto it = m_eventsToHighlight.begin(); it != m_eventsToHighlight.end(); ++it)
|
||||
{
|
||||
if (newEventsToHighlight.find(*it) == newEventsToHighlight.end())
|
||||
{
|
||||
doUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doUpdate)
|
||||
{
|
||||
newEventsToHighlight.swap(m_eventsToHighlight);
|
||||
update();
|
||||
}
|
||||
|
||||
// find the first annotation within a margin:
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void AnnotationsDataView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
for (auto it = m_ClickableAreas.begin(); it != m_ClickableAreas.end(); ++it)
|
||||
{
|
||||
if (it->second.contains(event->pos()))
|
||||
{
|
||||
auto annot = m_ptrAnnotations->GetAnnotationForEvent(it->first);
|
||||
if (annot != m_ptrAnnotations->GetEnd())
|
||||
{
|
||||
emit InformOfClickAnnotation(*annot);
|
||||
}
|
||||
}
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void AnnotationsDataView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_AnnotationsDataView.cpp>
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANNOTATIONS_DATA_VIEW
|
||||
#define ANNOTATIONS_DATA_VIEW
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class Annotation;
|
||||
class AnnotationHeaderView;
|
||||
/** Annotations Data View just shows the annotations that are available in a horizontal strip with indicators for easy clickability.
|
||||
*/
|
||||
|
||||
class AnnotationsDataView : public QWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnnotationsDataView, AZ::SystemAllocator, 0);
|
||||
AnnotationsDataView(QWidget* parent = nullptr);
|
||||
virtual ~AnnotationsDataView();
|
||||
|
||||
void RegisterAnnotationHeaderView(AnnotationHeaderView* header, AnnotationsProvider* annotations);
|
||||
|
||||
int PositionToFrame( const QPoint &pt );
|
||||
|
||||
float GetBarWidth();
|
||||
|
||||
virtual void paintEvent( QPaintEvent *event );
|
||||
virtual void mouseMoveEvent( QMouseEvent *event );
|
||||
virtual void mousePressEvent( QMouseEvent *event );
|
||||
virtual void mouseReleaseEvent( QMouseEvent *event );
|
||||
|
||||
signals:
|
||||
void InformOfMouseOverAnnotation(const Annotation& annotation);
|
||||
void InformOfClickAnnotation(const Annotation& annotation);
|
||||
private:
|
||||
typedef AZStd::unordered_map<AZ::s64, QPainterPath> EventIndexToClickablePath;
|
||||
EventIndexToClickablePath m_ClickableAreas;
|
||||
AZStd::unordered_set<AZ::s64> m_eventsToHighlight;
|
||||
|
||||
AnnotationsProvider *m_ptrAnnotations;
|
||||
AnnotationHeaderView *m_ptrHeaderView;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ANNOTATIONS_DATA_VIEW
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* 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 "AnnotationsDataView_Events.hxx"
|
||||
#include "AnnotationsHeaderView_Events.hxx"
|
||||
#include "Annotations.hxx"
|
||||
#include <Source/Driller/Axis.hxx>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPen>
|
||||
#include <QMouseEvent>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const float adv_events_arrow_width = 8.0f;
|
||||
|
||||
AnnotationsDataView_Events::AnnotationsDataView_Events(AnnotationHeaderView_Events* header, AnnotationsProvider* annotations)
|
||||
: QWidget(header)
|
||||
, m_ptrHeaderView(header)
|
||||
, m_ptrAnnotations(annotations)
|
||||
, m_ptrAxis(NULL)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
setFixedHeight(18);
|
||||
setAutoFillBackground(false);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
setMouseTracking(true);
|
||||
m_CurrentFrameNumber = 0;
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::AttachToAxis(Charts::Axis* pAxis)
|
||||
{
|
||||
if (m_ptrAxis)
|
||||
{
|
||||
disconnect(m_ptrAxis, SIGNAL(destroyed(QObject*)), this, SLOT(OnAxisDestroyed()));
|
||||
disconnect(m_ptrAxis, SIGNAL(Invalidated()), this, SLOT(OnAxisInvalidated()));
|
||||
}
|
||||
|
||||
m_ptrAxis = pAxis;
|
||||
if (pAxis)
|
||||
{
|
||||
connect(m_ptrAxis, SIGNAL(destroyed(QObject*)), this, SLOT(OnAxisDestroyed()));
|
||||
connect(m_ptrAxis, SIGNAL(Invalidated()), this, SLOT(OnAxisInvalidated()));
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::OnAxisDestroyed()
|
||||
{
|
||||
m_ptrAxis = NULL;
|
||||
update();
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::OnAxisInvalidated()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
AnnotationsDataView_Events::~AnnotationsDataView_Events()
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
|
||||
m_ClickableAreas.clear();
|
||||
|
||||
// scan for annotations
|
||||
|
||||
|
||||
|
||||
// fill with black
|
||||
QPainter painter(this);
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
|
||||
if (!m_ptrAxis)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_ptrAxis->GetValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QRectF drawRange = rect();
|
||||
// adjust for inset:
|
||||
|
||||
drawRange.adjust(2.0f, 0.0f, -4.0f, 0.0f);
|
||||
float leftEdge = (float)drawRange.left();
|
||||
float drawRangeWidth = (float)drawRange.width();
|
||||
|
||||
AZ::s64 eventIndexStart = (AZ::s64)m_ptrAxis->GetWindowMin();
|
||||
AZ::s64 eventIndexEnd = (AZ::s64)m_ptrAxis->GetWindowMax() + 1;
|
||||
float eventIndexRange = ((float)m_ptrAxis->GetWindowMax() - (float)m_ptrAxis->GetWindowMin()); // this is the domain range
|
||||
|
||||
|
||||
if (eventIndexRange <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float oneEventWidthInPixels = drawRangeWidth / eventIndexRange;
|
||||
float halfEventWidth = oneEventWidthInPixels * 0.5f;
|
||||
|
||||
// find the first event within that range:
|
||||
QPen fatPen(QColor(255, 255, 255, 255));
|
||||
fatPen.setWidth(2);
|
||||
fatPen.setCapStyle(Qt::FlatCap);
|
||||
|
||||
AnnotationsProvider::ConstAnnotationIterator it = m_ptrAnnotations->GetFirstAnnotationForFrame(m_CurrentFrameNumber);
|
||||
AnnotationsProvider::ConstAnnotationIterator endIt = m_ptrAnnotations->GetEnd();
|
||||
|
||||
// now keep going until we hit the end of the range:
|
||||
while (it != endIt)
|
||||
{
|
||||
if (it->GetEventIndex() >= eventIndexEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (it->GetEventIndex() < eventIndexStart)
|
||||
{
|
||||
++it;
|
||||
continue; // we're within the zoom
|
||||
}
|
||||
|
||||
// transform that event ID into the window domain:
|
||||
|
||||
|
||||
float eventRatio = ((float)it->GetEventIndex() - m_ptrAxis->GetWindowMin()) / eventIndexRange;
|
||||
|
||||
float center = floorf(leftEdge + (drawRangeWidth * eventRatio));
|
||||
|
||||
center += (float)drawRange.left();
|
||||
center += halfEventWidth;
|
||||
|
||||
QPainterPath newPath;
|
||||
QPolygonF newPolygon;
|
||||
newPolygon << QPointF(center - adv_events_arrow_width, 1.0f) << QPointF(center, drawRange.height() - 1.0f) << QPointF(center + adv_events_arrow_width, 1.0f);
|
||||
newPath.addPolygon(newPolygon);
|
||||
newPath.closeSubpath();
|
||||
|
||||
if (m_eventsToHighlight.find(it->GetEventIndex()) != m_eventsToHighlight.end())
|
||||
{
|
||||
painter.setPen(fatPen);
|
||||
painter.setBrush(m_ptrAnnotations->GetColorForChannel(it->GetChannelCRC()));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.setPen(QColor(0, 0, 0, 0));
|
||||
painter.setBrush(m_ptrAnnotations->GetColorForChannel(it->GetChannelCRC()));
|
||||
}
|
||||
painter.drawPath(newPath);
|
||||
m_ClickableAreas[it->GetEventIndex()] = newPath;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
AZStd::unordered_set<AZ::s64> newEventsToHighlight;
|
||||
|
||||
for (auto it = m_ClickableAreas.begin(); it != m_ClickableAreas.end(); ++it)
|
||||
{
|
||||
if (it->second.contains(event->pos()))
|
||||
{
|
||||
auto annot = m_ptrAnnotations->GetAnnotationForEvent(it->first);
|
||||
if (annot != m_ptrAnnotations->GetEnd())
|
||||
{
|
||||
newEventsToHighlight.insert(annot->GetEventIndex());
|
||||
emit InformOfMouseOverAnnotation(*annot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool doUpdate = false;
|
||||
// did our highlight change?
|
||||
for (auto it = newEventsToHighlight.begin(); it != newEventsToHighlight.end(); ++it)
|
||||
{
|
||||
if (m_eventsToHighlight.find(*it) == m_eventsToHighlight.end())
|
||||
{
|
||||
doUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// did our highlight change?
|
||||
if (!doUpdate)
|
||||
{
|
||||
for (auto it = m_eventsToHighlight.begin(); it != m_eventsToHighlight.end(); ++it)
|
||||
{
|
||||
if (newEventsToHighlight.find(*it) == newEventsToHighlight.end())
|
||||
{
|
||||
doUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doUpdate)
|
||||
{
|
||||
newEventsToHighlight.swap(m_eventsToHighlight);
|
||||
update();
|
||||
}
|
||||
|
||||
// find the first annotation within a margin:
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
for (auto it = m_ClickableAreas.begin(); it != m_ClickableAreas.end(); ++it)
|
||||
{
|
||||
if (it->second.contains(event->pos()))
|
||||
{
|
||||
auto annot = m_ptrAnnotations->GetAnnotationForEvent(it->first);
|
||||
if (annot != m_ptrAnnotations->GetEnd())
|
||||
{
|
||||
emit InformOfClickAnnotation(*annot);
|
||||
}
|
||||
}
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
|
||||
void AnnotationsDataView_Events::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void AnnotationsDataView_Events::OnScrubberFrameUpdate(FrameNumberType newFramenumber)
|
||||
{
|
||||
if (newFramenumber != m_CurrentFrameNumber)
|
||||
{
|
||||
m_CurrentFrameNumber = newFramenumber;
|
||||
// we don't update here because we wait for the new range to be set
|
||||
//update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_AnnotationsDataView_Events.cpp>
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANNOTATIONS_DATA_VIEW_EVENTS_HXX
|
||||
#define ANNOTATIONS_DATA_VIEW_EVENTS_HXX
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
#endif
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
class Axis;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class Annotation;
|
||||
class AnnotationHeaderView_Events;
|
||||
/** Annotations Data View just shows the annotations that are available in a horizontal strip with indicators for easy clickability.
|
||||
* This flavor of the view is supposed to operate on individual events instead of individual frames and is supposed to sit above the event driller track
|
||||
* But it can actually work on any track thats willing to provide it with an axis.
|
||||
*/
|
||||
|
||||
class AnnotationsDataView_Events : public QWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnnotationsDataView_Events, AZ::SystemAllocator, 0);
|
||||
AnnotationsDataView_Events( AnnotationHeaderView_Events* header, AnnotationsProvider *annotations );
|
||||
virtual ~AnnotationsDataView_Events();
|
||||
|
||||
void AttachToAxis(Charts::Axis *pAxis);
|
||||
|
||||
virtual void paintEvent( QPaintEvent *event );
|
||||
virtual void mouseMoveEvent( QMouseEvent *event );
|
||||
virtual void mousePressEvent( QMouseEvent *event );
|
||||
virtual void mouseReleaseEvent( QMouseEvent *event );
|
||||
|
||||
signals:
|
||||
void InformOfMouseOverAnnotation(const Annotation& annotation);
|
||||
void InformOfClickAnnotation(const Annotation& annotation);
|
||||
private:
|
||||
typedef AZStd::unordered_map<AZ::s64, QPainterPath> EventIndexToClickablePath;
|
||||
|
||||
EventIndexToClickablePath m_ClickableAreas;
|
||||
AZStd::unordered_set<AZ::s64> m_eventsToHighlight;
|
||||
QPainter *m_Painter;
|
||||
Charts::Axis *m_ptrAxis;
|
||||
|
||||
AnnotationsProvider *m_ptrAnnotations;
|
||||
AnnotationHeaderView_Events *m_ptrHeaderView;
|
||||
FrameNumberType m_CurrentFrameNumber;
|
||||
|
||||
const Annotation* GetNearestAnnotationToMousePoint(QPoint pos) const;
|
||||
|
||||
public slots:
|
||||
void OnAxisInvalidated();
|
||||
void OnAxisDestroyed();
|
||||
void OnScrubberFrameUpdate(FrameNumberType newFrameNumber);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ANNOTATIONS_DATA_VIEW
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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 "AnnotationsHeaderView_Events.hxx"
|
||||
#include "AnnotationsDataView_Events.hxx"
|
||||
#include "Annotations.hxx"
|
||||
#include <QtWidgets/QGridLayout>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const int k_eventContractedSize = 18;
|
||||
|
||||
AnnotationHeaderView_Events::AnnotationHeaderView_Events(QWidget* parent, Qt::WindowFlags flags)
|
||||
: QWidget(parent, flags)
|
||||
, m_ptrAnnotations(NULL)
|
||||
{
|
||||
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
this->setFixedHeight(k_eventContractedSize);
|
||||
this->setAutoFillBackground(true);
|
||||
|
||||
QHBoxLayout* mainLayout = new QHBoxLayout(this);
|
||||
this->setLayout(mainLayout);
|
||||
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
}
|
||||
|
||||
void AnnotationHeaderView_Events::OnScrubberFrameUpdate(FrameNumberType newFrame)
|
||||
{
|
||||
if (m_ptrDataView)
|
||||
{
|
||||
m_ptrDataView->OnScrubberFrameUpdate(newFrame);
|
||||
}
|
||||
}
|
||||
|
||||
QSize AnnotationHeaderView_Events::sizeHint() const
|
||||
{
|
||||
return QSize(0, k_eventContractedSize);
|
||||
}
|
||||
|
||||
void AnnotationHeaderView_Events::ControllerSizeChanged(QSize newSize)
|
||||
{
|
||||
(void)newSize;
|
||||
}
|
||||
|
||||
AnnotationHeaderView_Events::~AnnotationHeaderView_Events()
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationHeaderView_Events::AttachToAxis(AnnotationsProvider* ptrAnnotations, Charts::Axis* target)
|
||||
{
|
||||
m_ptrAnnotations = ptrAnnotations;
|
||||
m_ptrDataView = aznew AnnotationsDataView_Events(this, ptrAnnotations);
|
||||
|
||||
connect(m_ptrDataView, SIGNAL(InformOfMouseOverAnnotation(const Annotation&)), this, SIGNAL(InformOfMouseOverAnnotation(const Annotation&)));
|
||||
connect(m_ptrDataView, SIGNAL(InformOfClickAnnotation(const Annotation&)), this, SIGNAL(InformOfClickAnnotation(const Annotation&)));
|
||||
connect(m_ptrAnnotations, SIGNAL(AnnotationDataInvalidated()), this, SLOT(RefreshView()));
|
||||
|
||||
layout()->addWidget(m_ptrDataView);
|
||||
m_ptrDataView->AttachToAxis(target);
|
||||
}
|
||||
|
||||
void AnnotationHeaderView_Events::RefreshView()
|
||||
{
|
||||
m_ptrDataView->update();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_AnnotationsHeaderView_Events.cpp>
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANNOTATION_HEADER_VIEW_EVENTS_HXX
|
||||
#define ANNOTATION_HEADER_VIEW_EVENTS_HXX
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <Source/Driller/DrillerNetworkMessages.h>
|
||||
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
#endif
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
class Axis;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class AnnotationsDataView_Events;
|
||||
class Annotation;
|
||||
|
||||
/** This version of the annotations header view sits above the per-frame events widget (near the bottom of hte main view).
|
||||
* Its job is to show annotations that happen within a single frame (on an event-by-event basis!)
|
||||
* It can actually work on any track thats willing to provide it with an axis.
|
||||
*/
|
||||
|
||||
class AnnotationHeaderView_Events : public QWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnnotationHeaderView_Events,AZ::SystemAllocator,0);
|
||||
AnnotationHeaderView_Events(QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~AnnotationHeaderView_Events(void);
|
||||
|
||||
void AttachToAxis(AnnotationsProvider* ptrAnnotations, Charts::Axis *target);
|
||||
signals:
|
||||
void InformOfMouseOverAnnotation(const Annotation& annotation);
|
||||
void InformOfClickAnnotation(const Annotation& annotation);
|
||||
|
||||
public slots:
|
||||
void RefreshView();
|
||||
void ControllerSizeChanged(QSize newSize);
|
||||
void OnScrubberFrameUpdate(FrameNumberType newFrame);
|
||||
private:
|
||||
AnnotationsProvider *m_ptrAnnotations;
|
||||
AnnotationsDataView_Events *m_ptrDataView;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // ANNOTATION_HEADER_VIEW_HXX
|
||||
@@ -1,151 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>configureAnnotationsDialog</class>
|
||||
<widget class="QDialog" name="configureAnnotationsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>168</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Annotations</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Display Annotations From the Selected Features</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchField">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Search Annotations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="statusTable">
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>60</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>30</number>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* 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 <QtCore/QAbstractTableModel>
|
||||
#include "ConfigureAnnotationsWindow.hxx"
|
||||
#include <Source/Driller/Annotations/ui_ConfigureAnnotationsDialog.h>
|
||||
#include <Source/Driller/Annotations/Annotations.hxx>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
|
||||
#include <AzToolsFramework/UI/UICore/ColorPickerDelegate.hxx>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QCloseEvent>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
//////////////////////////////
|
||||
// ConfigureAnnotationsModel
|
||||
//////////////////////////////
|
||||
int ConfigureAnnotationsModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
if (index == QModelIndex())
|
||||
{
|
||||
return (int)m_cache.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConfigureAnnotationsModel::columnCount(const QModelIndex& index) const
|
||||
{
|
||||
(void)index;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Qt::ItemFlags ConfigureAnnotationsModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
if (index == QModelIndex())
|
||||
{
|
||||
return Qt::ItemFlags();
|
||||
}
|
||||
|
||||
if (index.column() == 0)
|
||||
{
|
||||
return Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
bool ConfigureAnnotationsModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
Qt::CheckState newState = (Qt::CheckState)value.toInt();
|
||||
if (index.column() == 0)
|
||||
{
|
||||
if (index.row() < (int)m_cache.size())
|
||||
{
|
||||
Qt::CheckState oldEnabled = m_ptrProvider->IsChannelEnabled(AZ::Crc32(m_cache[index.row()].toUtf8().data())) ? Qt::Checked : Qt::Unchecked;
|
||||
|
||||
if (newState != oldEnabled)
|
||||
{
|
||||
m_ptrProvider->SetChannelEnabled(m_cache[index.row()].toUtf8().data(), newState == Qt::Checked ? true : false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == AzToolsFramework::ColorPickerDelegate::COLOR_PICKER_ROLE)
|
||||
{
|
||||
QColor newColor = qvariant_cast<QColor>(value);
|
||||
AZ::u32 crcOfChannel = AZ::Crc32(m_cache[index.row()].toUtf8().data());
|
||||
m_ptrProvider->SetColorForChannel(crcOfChannel, newColor);
|
||||
m_cachedColorIcons[index.row()] = CreatePixmapForColor(newColor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant ConfigureAnnotationsModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (index == QModelIndex())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (index.column() == 0)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
AZ::u32 crcvalue = AZ::Crc32(m_cache[index.row()].toUtf8().data());
|
||||
return QVariant(m_ptrProvider->IsChannelEnabled(crcvalue) ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked));
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
return m_cachedColorIcons[index.row()];
|
||||
}
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
return m_cache[index.row()];
|
||||
}
|
||||
case AzToolsFramework::ColorPickerDelegate::COLOR_PICKER_ROLE:
|
||||
{
|
||||
AZ::u32 crcvalue = AZ::Crc32(m_cache[index.row()].toUtf8().data());
|
||||
QColor channelColor = m_ptrProvider->GetColorForChannel(crcvalue);
|
||||
return QVariant(channelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ConfigureAnnotationsModel::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
(void)orientation;
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return QVariant(tr("Annotation Type"));
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole)
|
||||
{
|
||||
if (section == 0)
|
||||
{
|
||||
return QVariant(Qt::AlignVCenter | Qt::AlignLeft);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QPixmap ConfigureAnnotationsModel::CreatePixmapForColor(QColor color)
|
||||
{
|
||||
QPixmap pixmap(16, 16);
|
||||
{
|
||||
QPainter painter(&pixmap);
|
||||
painter.fillRect(0, 0, 16, 16, Qt::black);
|
||||
painter.fillRect(1, 1, 15, 15, color);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
void ConfigureAnnotationsModel::Recache()
|
||||
{
|
||||
beginResetModel();
|
||||
m_cache.clear();
|
||||
m_cachedColorIcons.clear();
|
||||
AZStd::for_each(m_ptrProvider->GetAllKnownChannels().begin(), m_ptrProvider->GetAllKnownChannels().end(),
|
||||
[this](const AZStd::string& value)
|
||||
{
|
||||
m_cache.push_back(QString::fromUtf8(value.c_str()));
|
||||
QColor channelColor = m_ptrProvider->GetColorForChannel(AZ::Crc32(value.c_str()));
|
||||
|
||||
m_cachedColorIcons.push_back(CreatePixmapForColor(channelColor));
|
||||
});
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
ConfigureAnnotationsModel::ConfigureAnnotationsModel(AnnotationsProvider* ptrProvider, QObject* pParent)
|
||||
: QAbstractTableModel(pParent)
|
||||
{
|
||||
m_ptrProvider = ptrProvider;
|
||||
connect(ptrProvider, &AnnotationsProvider::KnownAnnotationsChanged, this, &ConfigureAnnotationsModel::Recache);
|
||||
Recache();
|
||||
}
|
||||
|
||||
ConfigureAnnotationsModel::~ConfigureAnnotationsModel()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// ConfigureAnnotationsWindow
|
||||
///////////////////////////////
|
||||
|
||||
ConfigureAnnotationsWindow::ConfigureAnnotationsWindow(QWidget* pParent /* = NULL */)
|
||||
: QDialog(pParent)
|
||||
, m_proxyModel(nullptr)
|
||||
{
|
||||
m_ptrLoadedUI = azcreate(Ui::configureAnnotationsDialog, ());
|
||||
m_ptrLoadedUI->setupUi(this);
|
||||
}
|
||||
|
||||
ConfigureAnnotationsWindow::~ConfigureAnnotationsWindow()
|
||||
{
|
||||
AZStd::intrusive_ptr<AzToolsFramework::QWidgetSavedState> pState = AZ::UserSettings::CreateFind<AzToolsFramework::QWidgetSavedState>(AZ_CRC("CONFIGURE ANNOTATIONS WINDOW", 0x581c6568), AZ::UserSettings::CT_GLOBAL);
|
||||
if (pState)
|
||||
{
|
||||
pState->CaptureGeometry(this);
|
||||
}
|
||||
|
||||
azdestroy(m_ptrLoadedUI);
|
||||
}
|
||||
|
||||
void ConfigureAnnotationsWindow::Initialize(AnnotationsProvider* ptrProvider)
|
||||
{
|
||||
m_ptrProvider = ptrProvider;
|
||||
m_ptrModel = aznew ConfigureAnnotationsModel(ptrProvider, this);
|
||||
|
||||
m_proxyModel = new QSortFilterProxyModel(this);
|
||||
m_proxyModel->setDynamicSortFilter(false);
|
||||
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->setSourceModel(m_ptrModel);
|
||||
|
||||
m_ptrLoadedUI->statusTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_ptrLoadedUI->statusTable->setModel(m_proxyModel);
|
||||
m_ptrLoadedUI->statusTable->setItemDelegate(aznew AzToolsFramework::ColorPickerDelegate(this));
|
||||
m_ptrLoadedUI->statusTable->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder);
|
||||
|
||||
connect(m_ptrLoadedUI->searchField, SIGNAL(textChanged(const QString&)), this, SLOT(OnFilterChanged(const QString&)));
|
||||
|
||||
AZStd::intrusive_ptr<AzToolsFramework::QWidgetSavedState> windowState = AZ::UserSettings::Find<AzToolsFramework::QWidgetSavedState>(AZ_CRC("CONFIGURE ANNOTATIONS WINDOW", 0x581c6568), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
if (windowState)
|
||||
{
|
||||
windowState->RestoreGeometry(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureAnnotationsWindow::OnFilterChanged(const QString& filter)
|
||||
{
|
||||
m_proxyModel->setFilterFixedString(filter);
|
||||
}
|
||||
|
||||
void ConfigureAnnotationsWindow::closeEvent (QCloseEvent* e)
|
||||
{
|
||||
e->accept();
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/Annotations/moc_ConfigureAnnotationsWindow.cpp>
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONFIGURE_ANNOTATIONS_WINDOW_H
|
||||
#define CONFIGURE_ANNOTATIONS_WINDOW_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include <QAbstractTableModel>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#endif
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class configureAnnotationsDialog;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class ConfigureAnnotationsModel;
|
||||
|
||||
class ConfigureAnnotationsWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ConfigureAnnotationsWindow, AZ::SystemAllocator, 0);
|
||||
|
||||
ConfigureAnnotationsWindow(QWidget *pParent = NULL);
|
||||
virtual ~ConfigureAnnotationsWindow();
|
||||
|
||||
void Initialize(AnnotationsProvider* ptrProvider);
|
||||
|
||||
public slots:
|
||||
void OnFilterChanged(const QString&);
|
||||
|
||||
protected:
|
||||
Ui::configureAnnotationsDialog* m_ptrLoadedUI;
|
||||
QSortFilterProxyModel* m_proxyModel;
|
||||
ConfigureAnnotationsModel* m_ptrModel;
|
||||
AnnotationsProvider* m_ptrProvider;
|
||||
virtual void closeEvent ( QCloseEvent * e );
|
||||
};
|
||||
|
||||
|
||||
class ConfigureAnnotationsModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ConfigureAnnotationsModel, AZ::SystemAllocator, 0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// QAbstractTableModel
|
||||
int rowCount(const QModelIndex& index = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& index = QModelIndex()) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QVariant headerData ( int section, Qt::Orientation orientation, int role ) const override;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ConfigureAnnotationsModel(AnnotationsProvider* ptrProvider, QObject *pParent = NULL);
|
||||
|
||||
virtual ~ConfigureAnnotationsModel();
|
||||
|
||||
private:
|
||||
AnnotationsProvider* m_ptrProvider;
|
||||
AZStd::vector<QString> m_cache;
|
||||
AZStd::vector<QPixmap> m_cachedColorIcons;
|
||||
|
||||
QPixmap CreatePixmapForColor(QColor color);
|
||||
|
||||
private slots:
|
||||
void Recache();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //CONFIGURE_ANNOTATIONS_WINDOW_H
|
||||
@@ -1,635 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
#include <Source/Driller/Axis.hxx>
|
||||
|
||||
#include <Source/Driller/AreaChart.hxx>
|
||||
#include <Source/Driller/moc_AreaChart.cpp>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QMouseEvent>
|
||||
|
||||
namespace AreaChart
|
||||
{
|
||||
///////////////
|
||||
// LineSeries
|
||||
///////////////
|
||||
|
||||
LineSeries::LineSeries([[maybe_unused]] AreaChart* owner, size_t seriesId, const QString& name, const QColor& color, size_t seriesSize)
|
||||
: m_seriesId(seriesId)
|
||||
, m_name(name)
|
||||
, m_color(color)
|
||||
, m_highlighted(false)
|
||||
, m_enabled(true)
|
||||
, m_hasData(false)
|
||||
{
|
||||
if (seriesSize > 0)
|
||||
{
|
||||
m_linePoints.reserve(seriesSize);
|
||||
}
|
||||
}
|
||||
|
||||
LineSeries::~LineSeries()
|
||||
{
|
||||
}
|
||||
|
||||
size_t LineSeries::GetSeriesId() const
|
||||
{
|
||||
return m_seriesId;
|
||||
}
|
||||
|
||||
void LineSeries::AddPoint(const LinePoint& linePoint)
|
||||
{
|
||||
// Handle simple case first
|
||||
if (m_linePoints.empty() || m_linePoints.back().m_position < linePoint.m_position)
|
||||
{
|
||||
m_hasData |= linePoint.m_value > 0;
|
||||
m_linePoints.push_back(linePoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Handle the case of out of order insertion
|
||||
AZ_Error("LineSeries",false,"Trying to add series point out of order. Unsupported behavior");
|
||||
}
|
||||
}
|
||||
|
||||
void LineSeries::Reset()
|
||||
{
|
||||
m_linePoints.clear();
|
||||
}
|
||||
|
||||
bool LineSeries::IsHighlighted() const
|
||||
{
|
||||
return m_highlighted;
|
||||
}
|
||||
|
||||
bool LineSeries::IsEnabled() const
|
||||
{
|
||||
return m_enabled && m_hasData;
|
||||
}
|
||||
|
||||
const QColor& LineSeries::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void LineSeries::ResetPainterPath()
|
||||
{
|
||||
// Kind of silly that QPainterPath doesn't have a clear.
|
||||
m_painterPath = QPainterPath();
|
||||
}
|
||||
|
||||
QPainterPath& LineSeries::GetPainterPath()
|
||||
{
|
||||
return m_painterPath;
|
||||
}
|
||||
|
||||
const QPainterPath& LineSeries::GetPainterPath() const
|
||||
{
|
||||
return m_painterPath;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// AreaChart
|
||||
//////////////
|
||||
|
||||
const size_t AreaChart::k_invalidSeriesId = static_cast<size_t>(-1);
|
||||
|
||||
AreaChart::AreaChart(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_inspectionSeries(k_invalidSeriesId)
|
||||
, m_sizingDirty(true)
|
||||
, m_regenGraph(true)
|
||||
, m_axisMin(0)
|
||||
, m_horizontalAxis(nullptr)
|
||||
, m_verticalAxis(nullptr)
|
||||
, m_insetTop(16)
|
||||
, m_insetBottom(24)
|
||||
, m_insetLeft(56)
|
||||
, m_insetRight(16)
|
||||
, m_widgetBackground(32,32,32,255)
|
||||
, m_graphBackground(Qt::black)
|
||||
{
|
||||
setStyleSheet(QString("QToolTip { border: 1px solid white; padding: 1px; background: black; color: white; }"));
|
||||
|
||||
m_axisMax = m_axisMin;
|
||||
}
|
||||
|
||||
AreaChart::~AreaChart()
|
||||
{
|
||||
delete m_horizontalAxis;
|
||||
delete m_verticalAxis;
|
||||
}
|
||||
|
||||
bool AreaChart::IsMouseInspectionEnabled() const
|
||||
{
|
||||
return hasMouseTracking();
|
||||
}
|
||||
|
||||
void AreaChart::EnableMouseInspection(bool enabled)
|
||||
{
|
||||
setMouseTracking(enabled);
|
||||
}
|
||||
|
||||
void AreaChart::SetMinimumValueRange(unsigned int value)
|
||||
{
|
||||
m_axisMin = value;
|
||||
|
||||
m_axisMax = m_axisMin;
|
||||
|
||||
for (auto& sizingPair : m_maxSizing)
|
||||
{
|
||||
if (sizingPair.second > m_axisMax)
|
||||
{
|
||||
m_axisMax = sizingPair.second;
|
||||
}
|
||||
}
|
||||
|
||||
m_regenGraph = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void AreaChart::ResetChart()
|
||||
{
|
||||
m_axisMax = m_axisMin;
|
||||
m_maxSizing.clear();
|
||||
m_lineSeries.clear();
|
||||
m_markers.clear();
|
||||
|
||||
m_sizingDirty = true;
|
||||
m_regenGraph = true;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void AreaChart::ConfigureVerticalAxis(QString label, unsigned int minimumHeight)
|
||||
{
|
||||
SetMinimumValueRange(minimumHeight);
|
||||
|
||||
if (m_verticalAxis == nullptr)
|
||||
{
|
||||
m_verticalAxis = aznew Charts::Axis();
|
||||
}
|
||||
|
||||
if (m_verticalAxis)
|
||||
{
|
||||
m_verticalAxis->SetLabel(label);
|
||||
m_verticalAxis->SetAxisRange(0.0f, static_cast<float>(m_axisMax));
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::ConfigureHorizontalAxis(QString label, int minimum, int maximum)
|
||||
{
|
||||
if (m_horizontalAxis == nullptr)
|
||||
{
|
||||
m_horizontalAxis = aznew Charts::Axis();
|
||||
}
|
||||
|
||||
if (m_horizontalAxis)
|
||||
{
|
||||
m_horizontalAxis->SetLabel(label);
|
||||
m_horizontalAxis->SetAxisRange(static_cast<float>(minimum), static_cast<float>(maximum));
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::ResetSeries(AZ::u32 seriesId)
|
||||
{
|
||||
if (!IsValidSeriesId(seriesId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_lineSeries[seriesId].Reset();
|
||||
}
|
||||
|
||||
size_t AreaChart::CreateSeries(const QString& name, const QColor& color, size_t size)
|
||||
{
|
||||
size_t seriesKey = m_lineSeries.size();
|
||||
AZ_Error("AreaChart", seriesKey != k_invalidSeriesId,"Trying to use invalid key for series Id. Too many Area Series created.");
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
size = m_maxSizing.size();
|
||||
}
|
||||
|
||||
m_lineSeries.emplace_back(this, seriesKey, name, color, size);
|
||||
|
||||
return seriesKey;
|
||||
}
|
||||
|
||||
void AreaChart::AddPoint(size_t seriesId, int position, unsigned int value)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
LinePoint linePoint(position,value);
|
||||
AddPoint(seriesId,linePoint);
|
||||
}
|
||||
|
||||
void AreaChart::AddPoint(size_t seriesId, const LinePoint& linePoint)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
if (!IsValidSeriesId(seriesId))
|
||||
{
|
||||
AZ_Error("AreaChart", false, "Invalid SeriesId given.");
|
||||
return;
|
||||
}
|
||||
|
||||
LineSeries& lineSeries = m_lineSeries[seriesId];
|
||||
|
||||
lineSeries.AddPoint(linePoint);
|
||||
|
||||
auto sizingIter = m_maxSizing.find(linePoint.m_position);
|
||||
|
||||
if (sizingIter != m_maxSizing.end())
|
||||
{
|
||||
sizingIter->second += linePoint.m_value;
|
||||
|
||||
if (sizingIter->second > m_axisMax)
|
||||
{
|
||||
m_axisMax = sizingIter->second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_maxSizing[linePoint.m_position] = linePoint.m_value;
|
||||
|
||||
if (linePoint.m_value > m_axisMax)
|
||||
{
|
||||
m_axisMax = linePoint.m_value;
|
||||
}
|
||||
}
|
||||
|
||||
m_regenGraph = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void AreaChart::SetSeriesHighlight(size_t seriesId, bool highlighted)
|
||||
{
|
||||
if (IsValidSeriesId(seriesId))
|
||||
{
|
||||
LineSeries& lineSeries = m_lineSeries[seriesId];
|
||||
|
||||
lineSeries.m_highlighted = highlighted;
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::SetSeriesEnabled(size_t seriesId, bool enabled)
|
||||
{
|
||||
if (IsValidSeriesId(seriesId))
|
||||
{
|
||||
LineSeries& lineSeries = m_lineSeries[seriesId];
|
||||
|
||||
lineSeries.m_enabled = enabled;
|
||||
|
||||
// Need to regen our graph data here, since we've removed one from the listing
|
||||
m_regenGraph = true;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::AddMarker(Charts::AxisType axis, int position, const QColor& color)
|
||||
{
|
||||
m_markers.emplace_back(axis, position, color);
|
||||
}
|
||||
|
||||
void AreaChart::mouseMoveEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
if (IsMouseInspectionEnabled())
|
||||
{
|
||||
QPoint mousePos = mouseEvent->pos();
|
||||
size_t hoveredArea = k_invalidSeriesId;
|
||||
|
||||
if (m_graphRect.contains(mousePos) && m_hitAreas.size() > 0)
|
||||
{
|
||||
int offset = mousePos.x() - m_graphRect.left();
|
||||
|
||||
size_t counter = static_cast<size_t>(static_cast<float>(offset) / (static_cast<float>(m_graphRect.width())/m_hitAreas.size()));
|
||||
|
||||
bool escape = false;
|
||||
|
||||
// Need to handle the areas right at the edge of the polygons
|
||||
for (int i = -1; i <= 1; ++i)
|
||||
{
|
||||
if ((counter + i) >= m_hitAreas.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZStd::vector<HitArea>& hitAreas = m_hitAreas[counter + i];
|
||||
|
||||
for (const HitArea& hitArea : hitAreas)
|
||||
{
|
||||
QPolygon polygon = hitArea.m_polygon;
|
||||
|
||||
if (hitArea.m_polygon.containsPoint(mousePos,Qt::OddEvenFill))
|
||||
{
|
||||
hoveredArea = hitArea.m_seriesId;
|
||||
escape = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (escape)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hoveredArea != m_inspectionSeries)
|
||||
{
|
||||
m_inspectionSeries = hoveredArea;
|
||||
update();
|
||||
|
||||
// Signal out which series we are inspecting
|
||||
emit InspectedSeries(m_inspectionSeries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::leaveEvent(QEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
|
||||
if (m_inspectionSeries != k_invalidSeriesId)
|
||||
{
|
||||
m_inspectionSeries = k_invalidSeriesId;
|
||||
update();
|
||||
|
||||
// Signal out which series we are inspecting
|
||||
emit InspectedSeries(m_inspectionSeries);
|
||||
}
|
||||
|
||||
if (m_clicked)
|
||||
{
|
||||
m_clicked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::mousePressEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
if (IsMouseInspectionEnabled())
|
||||
{
|
||||
m_clicked = true;
|
||||
m_mouseDownPoint = mouseEvent->pos();
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::mouseReleaseEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
if (IsMouseInspectionEnabled() && m_clicked)
|
||||
{
|
||||
QPoint upPoint = mouseEvent->pos();
|
||||
|
||||
// Want it to be roughly the same spot.
|
||||
if ((m_mouseDownPoint - upPoint).manhattanLength() < 20)
|
||||
{
|
||||
int closestValue = 0;
|
||||
if (m_horizontalAxis && m_graphRect.width() > 0)
|
||||
{
|
||||
float ratio = static_cast<float>(upPoint.x() - m_graphRect.left()) / static_cast<float>(m_graphRect.width());
|
||||
closestValue = static_cast<int>(m_horizontalAxis->GetRangeMin()) + static_cast<int>((m_horizontalAxis->GetRange() * ratio) + 0.5f);
|
||||
}
|
||||
|
||||
emit SelectedSeries(m_inspectionSeries, closestValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AreaChart::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
|
||||
m_sizingDirty = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void AreaChart::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
(void)event;
|
||||
|
||||
if (m_sizingDirty)
|
||||
{
|
||||
m_sizingDirty = false;
|
||||
m_regenGraph = true;
|
||||
|
||||
QPoint topLeft(rect().left() + m_insetLeft, rect().top() + m_insetTop);
|
||||
QPoint bottomRight(rect().right() - m_insetRight, rect().bottom() - m_insetBottom);
|
||||
|
||||
m_graphRect = QRect(topLeft,bottomRight);
|
||||
}
|
||||
|
||||
if (m_regenGraph)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
m_regenGraph = false;
|
||||
|
||||
if (m_verticalAxis)
|
||||
{
|
||||
m_verticalAxis->SetAxisRange(0.0f, static_cast<float>(m_axisMax));
|
||||
}
|
||||
|
||||
m_hitAreas.clear();
|
||||
m_hitAreas.reserve(m_maxSizing.size());
|
||||
m_hitAreas.resize(m_maxSizing.size());
|
||||
|
||||
// Running tally of samples that we need to keep track of to manipulate our way through
|
||||
AZStd::vector<unsigned int> runningTotal(m_maxSizing.size(), 0);
|
||||
|
||||
for (LineSeries& lineSeries : m_lineSeries)
|
||||
{
|
||||
unsigned int counter = 0;
|
||||
|
||||
// Would have to special case out the single data point sample
|
||||
if (lineSeries.IsEnabled() && lineSeries.m_linePoints.size() > 1)
|
||||
{
|
||||
unsigned int currentValue = lineSeries.m_linePoints[counter].m_value;
|
||||
|
||||
unsigned int bottomLeft = runningTotal[counter];
|
||||
unsigned int topLeft = bottomLeft + currentValue;
|
||||
|
||||
runningTotal[counter] = topLeft;
|
||||
++counter;
|
||||
|
||||
lineSeries.ResetPainterPath();
|
||||
QPainterPath& painterPath = lineSeries.GetPainterPath();
|
||||
|
||||
AZ_Assert(runningTotal.size() == lineSeries.m_linePoints.size(), "Mismatched/missing sample values given to AreaChart");
|
||||
for (; counter < lineSeries.m_linePoints.size(); ++counter)
|
||||
{
|
||||
currentValue = lineSeries.m_linePoints[counter].m_value;
|
||||
|
||||
unsigned int bottomRight = runningTotal[counter];
|
||||
unsigned int topRight = bottomRight + currentValue;
|
||||
|
||||
runningTotal[counter] = topRight;
|
||||
|
||||
QPolygon polygon;
|
||||
polygon.append(ConvertToGraphPoint(counter - 1, bottomLeft));
|
||||
polygon.append(ConvertToGraphPoint(counter - 1, topLeft));
|
||||
polygon.append(ConvertToGraphPoint(counter, topRight));
|
||||
polygon.append(ConvertToGraphPoint(counter, bottomRight));
|
||||
|
||||
painterPath.addPolygon(polygon);
|
||||
|
||||
m_hitAreas[counter].emplace_back(polygon, lineSeries.GetSeriesId());
|
||||
|
||||
bottomLeft = bottomRight;
|
||||
topLeft = topRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QPen pen;
|
||||
QBrush brush;
|
||||
QPainter p(this);
|
||||
|
||||
p.fillRect(rect(),m_widgetBackground);
|
||||
p.fillRect(m_graphRect, m_graphBackground);
|
||||
|
||||
QRect widgetBounds = rect();
|
||||
|
||||
if (m_horizontalAxis)
|
||||
{
|
||||
m_horizontalAxis->PaintAxis(Charts::AxisType::Horizontal, &p, widgetBounds, m_graphRect, nullptr);
|
||||
}
|
||||
|
||||
if (m_verticalAxis)
|
||||
{
|
||||
m_verticalAxis->PaintAxis(Charts::AxisType::Vertical, &p, widgetBounds, m_graphRect, nullptr);
|
||||
}
|
||||
|
||||
p.setClipRect(m_graphRect.left(), m_graphRect.top() - 1, m_graphRect.width() + 2, m_graphRect.height() + 2);
|
||||
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
pen.setWidth(2);
|
||||
|
||||
for (LineSeries& lineSeries : m_lineSeries)
|
||||
{
|
||||
if (!lineSeries.IsEnabled())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
brush.setColor(lineSeries.GetColor());
|
||||
p.fillPath(lineSeries.GetPainterPath(), brush);
|
||||
|
||||
if (lineSeries.IsHighlighted()
|
||||
|| lineSeries.GetSeriesId() == m_inspectionSeries)
|
||||
{
|
||||
// Then highlight it
|
||||
pen.setColor(Qt::white);
|
||||
p.setPen(pen);
|
||||
|
||||
p.drawPath(lineSeries.GetPainterPath());
|
||||
}
|
||||
}
|
||||
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
pen.setColor( m_graphBackground );
|
||||
pen.setWidth(2);
|
||||
|
||||
p.setPen(pen);
|
||||
|
||||
for (GraphMarker& marker : m_markers)
|
||||
{
|
||||
brush.setColor(marker.m_color);
|
||||
switch (marker.m_axis)
|
||||
{
|
||||
case Charts::AxisType::Horizontal:
|
||||
{
|
||||
static const int k_barWidth = 4;
|
||||
static const int k_halfWidth = k_barWidth / 2;
|
||||
|
||||
if (!AZ::IsClose(m_horizontalAxis->GetRange(),0.0f,0.01f) )
|
||||
{
|
||||
float minRange = m_horizontalAxis->GetRangeMin();
|
||||
|
||||
float ratio = (marker.m_position - minRange) / m_horizontalAxis->GetRange();
|
||||
ratio = AZStd::GetMin(1.0f, ratio);
|
||||
|
||||
QPoint startPoint;
|
||||
startPoint.setX(m_graphRect.left() + static_cast<int>(m_graphRect.width() * ratio) - k_halfWidth);
|
||||
startPoint.setY(m_graphRect.top());
|
||||
|
||||
p.fillRect(startPoint.x(), startPoint.y(), k_barWidth, m_graphRect.height(), brush);
|
||||
p.drawRect(startPoint.x(), startPoint.y() + 1, k_barWidth, m_graphRect.height() - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Charts::AxisType::Vertical:
|
||||
{
|
||||
QPoint startPoint = ConvertToGraphPoint(0, static_cast<unsigned int>(marker.m_position));
|
||||
startPoint.setX(m_graphRect.right());
|
||||
|
||||
p.fillRect(startPoint.x(), startPoint.y(), m_graphRect.width(), 2, brush);
|
||||
p.drawRect(startPoint.x(), startPoint.y(), m_graphRect.width(), 2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Error("Standalone Tools", false, "Unknown axis type given to marker.");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Charts::Axis* AreaChart::GetAxis(Charts::AxisType axisType)
|
||||
{
|
||||
switch (axisType)
|
||||
{
|
||||
case Charts::AxisType::Horizontal:
|
||||
return m_horizontalAxis;
|
||||
case Charts::AxisType::Vertical:
|
||||
return m_verticalAxis;
|
||||
default:
|
||||
AZ_Error("AreaChart", false, "Unknown AxisType.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AreaChart::IsValidSeriesId(size_t seriesId) const
|
||||
{
|
||||
return seriesId < m_lineSeries.size();
|
||||
}
|
||||
|
||||
QPoint AreaChart::ConvertToGraphPoint(int index, unsigned int value)
|
||||
{
|
||||
QPoint graphPoint(m_graphRect.bottomLeft());
|
||||
|
||||
int maxSizes = static_cast<int>(m_maxSizing.size());
|
||||
|
||||
if (m_horizontalAxis)
|
||||
{
|
||||
maxSizes = AZStd::GetMax(maxSizes, static_cast<int>(m_horizontalAxis->GetRange()));
|
||||
}
|
||||
|
||||
if (maxSizes >= 2)
|
||||
{
|
||||
// -1, since the index is 0 based.
|
||||
graphPoint.setX(m_graphRect.left() + static_cast<int>(m_graphRect.width() * (static_cast<float>(index) / static_cast<float>(maxSizes - 1))));
|
||||
}
|
||||
|
||||
if (m_axisMax > 0)
|
||||
{
|
||||
graphPoint.setY(m_graphRect.bottom() - static_cast<int>(m_graphRect.height() * (static_cast<float>(value) / static_cast<float>(m_axisMax))));
|
||||
}
|
||||
|
||||
return graphPoint;
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef PROFILER_AREACHART_H
|
||||
#define PROFILER_AREACHART_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <QWidget>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include <Source/Driller/ChartTypes.hxx>
|
||||
#endif
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
class Axis;
|
||||
}
|
||||
|
||||
namespace AreaChart
|
||||
{
|
||||
class AreaChart;
|
||||
|
||||
struct LinePoint
|
||||
{
|
||||
public:
|
||||
LinePoint(int position, unsigned int value)
|
||||
: m_position(position)
|
||||
, m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
int m_position;
|
||||
unsigned int m_value;
|
||||
};
|
||||
|
||||
class LineSeries
|
||||
{
|
||||
private:
|
||||
friend class AreaChart;
|
||||
|
||||
typedef AZStd::vector< LinePoint > LinePoints;
|
||||
|
||||
public:
|
||||
LineSeries(AreaChart* owner, size_t seriesId, const QString& name, const QColor& color, size_t seriesSize = 0);
|
||||
~LineSeries();
|
||||
|
||||
size_t GetSeriesId() const;
|
||||
void AddPoint(const LinePoint& linePoint);
|
||||
void Reset();
|
||||
|
||||
bool IsHighlighted() const;
|
||||
bool IsEnabled() const;
|
||||
|
||||
const QColor& GetColor() const;
|
||||
|
||||
void ResetPainterPath();
|
||||
|
||||
QPainterPath& GetPainterPath();
|
||||
const QPainterPath& GetPainterPath() const;
|
||||
|
||||
private:
|
||||
|
||||
LinePoints m_linePoints;
|
||||
|
||||
size_t m_seriesId;
|
||||
QString m_name;
|
||||
QColor m_color;
|
||||
|
||||
QPainterPath m_painterPath;
|
||||
bool m_highlighted;
|
||||
bool m_enabled;
|
||||
bool m_hasData;
|
||||
};
|
||||
|
||||
class AreaChart
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int insetTop MEMBER m_insetTop)
|
||||
Q_PROPERTY(int insetBottom MEMBER m_insetBottom)
|
||||
Q_PROPERTY(int insetLeft MEMBER m_insetLeft)
|
||||
Q_PROPERTY(int insetRight MEMBER m_insetRight)
|
||||
Q_PROPERTY(QColor widgetBackground MEMBER m_widgetBackground)
|
||||
Q_PROPERTY(QColor graphBackground MEMBER m_graphBackground)
|
||||
|
||||
struct HitArea
|
||||
{
|
||||
HitArea(const QPolygon& polygon, size_t seriesId)
|
||||
: m_polygon(polygon)
|
||||
, m_seriesId(seriesId)
|
||||
{
|
||||
}
|
||||
|
||||
QPolygon m_polygon;
|
||||
size_t m_seriesId;
|
||||
};
|
||||
|
||||
struct GraphMarker
|
||||
{
|
||||
GraphMarker(Charts::AxisType axis, int position, const QColor& color)
|
||||
: m_axis(axis)
|
||||
, m_position(position)
|
||||
, m_color(color)
|
||||
{
|
||||
}
|
||||
|
||||
Charts::AxisType m_axis;
|
||||
int m_position;
|
||||
QColor m_color;
|
||||
};
|
||||
|
||||
public:
|
||||
static const size_t k_invalidSeriesId;
|
||||
|
||||
AreaChart(QWidget* parent = nullptr);
|
||||
~AreaChart();
|
||||
|
||||
bool IsMouseInspectionEnabled() const;
|
||||
void EnableMouseInspection(bool enabled);
|
||||
|
||||
void ResetChart();
|
||||
|
||||
void ConfigureVerticalAxis(QString label, unsigned int minimumHeight = -1);
|
||||
void ConfigureHorizontalAxis(QString label, int minimum, int maximum);
|
||||
|
||||
size_t CreateSeries(const QString& name, const QColor& color, size_t size = 0);
|
||||
void ResetSeries(AZ::u32);
|
||||
|
||||
// Methods of adding points
|
||||
void AddPoint(size_t seriesId, int position, unsigned int value);
|
||||
void AddPoint(size_t seriesId, const LinePoint& linePoint);
|
||||
|
||||
// Methods of manipulating series
|
||||
void SetSeriesHighlight(size_t seriesId, bool highlighted);
|
||||
void SetSeriesEnabled(size_t seriesId, bool enabled);
|
||||
|
||||
// Methods of adding markers
|
||||
void AddMarker(Charts::AxisType axis, int position, const QColor& color);
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void InspectedSeries(size_t seriesId);
|
||||
void SelectedSeries(size_t seriesId, int position);
|
||||
|
||||
protected:
|
||||
|
||||
// Mouse Inspection
|
||||
void mouseMoveEvent(QMouseEvent* mouseEvent) override;
|
||||
void leaveEvent(QEvent* mouseEvent) override;
|
||||
|
||||
// Mouse clicks
|
||||
void mousePressEvent(QMouseEvent* mouseEvent) override;
|
||||
void mouseReleaseEvent(QMouseEvent* mouseEvent) override;
|
||||
|
||||
void resizeEvent(QResizeEvent* resizeEvent) override;
|
||||
void paintEvent(QPaintEvent* paintEvent) override;
|
||||
|
||||
private:
|
||||
|
||||
void SetMinimumValueRange(unsigned int value);
|
||||
Charts::Axis* GetAxis(Charts::AxisType axisType);
|
||||
|
||||
bool IsValidSeriesId(size_t seriesId) const;
|
||||
|
||||
QPoint ConvertToGraphPoint(int index, unsigned int value);
|
||||
|
||||
AZStd::vector< GraphMarker > m_markers;
|
||||
AZStd::vector< LineSeries > m_lineSeries;
|
||||
|
||||
AZStd::unordered_map<int, unsigned int> m_maxSizing;
|
||||
|
||||
size_t m_inspectionSeries;
|
||||
|
||||
AZStd::vector< AZStd::vector<HitArea> > m_hitAreas;
|
||||
|
||||
bool m_clicked;
|
||||
QPoint m_mouseDownPoint;
|
||||
|
||||
QRect m_graphRect;
|
||||
bool m_sizingDirty;
|
||||
bool m_regenGraph;
|
||||
|
||||
unsigned int m_axisMin;
|
||||
unsigned int m_axisMax;
|
||||
|
||||
Charts::Axis* m_horizontalAxis;
|
||||
Charts::Axis* m_verticalAxis;
|
||||
|
||||
// Styling
|
||||
int m_insetTop;
|
||||
int m_insetBottom;
|
||||
int m_insetLeft;
|
||||
int m_insetRight;
|
||||
QColor m_widgetBackground;
|
||||
QColor m_graphBackground;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,648 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Debug/Profiler.h>
|
||||
#include <QPainter>
|
||||
|
||||
#include "Axis.hxx"
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Axis::Axis(QObject* pParent)
|
||||
: QObject(pParent)
|
||||
, m_lockRange(true)
|
||||
, m_lockZoom(true)
|
||||
, m_lockRight(false)
|
||||
, m_autoWindow(true)
|
||||
, m_rangeMin(0)
|
||||
, m_rangeMax(0)
|
||||
, m_windowMax(0)
|
||||
, m_windowMin(0)
|
||||
, m_rangeMaxInitialized(false)
|
||||
, m_rangeMinInitialized(false)
|
||||
{}
|
||||
Axis::~Axis()
|
||||
{
|
||||
}
|
||||
|
||||
bool Axis::GetValid() const
|
||||
{
|
||||
return ((m_rangeMinInitialized) && (m_rangeMaxInitialized) && (m_rangeMin < m_rangeMax) && (m_windowMin < m_windowMax));
|
||||
}
|
||||
|
||||
void Axis::Clear()
|
||||
{
|
||||
bool wasValid = GetValid();
|
||||
|
||||
m_rangeMinInitialized = false;
|
||||
m_rangeMaxInitialized = false;
|
||||
m_rangeMax = m_rangeMin = m_windowMax = m_windowMin = 0.0f;
|
||||
|
||||
if (wasValid)
|
||||
{
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::SetAxisRange(float minimum, float maximum)
|
||||
{
|
||||
float oldRangeMin = m_rangeMin;
|
||||
float oldRangeMax = m_rangeMax;
|
||||
float oldWindowMin = m_windowMin;
|
||||
float oldWindowMax = m_windowMax;
|
||||
|
||||
bool wasValid = GetValid();
|
||||
|
||||
if (m_lockRight)
|
||||
{
|
||||
m_windowMin += maximum - m_rangeMax;
|
||||
m_windowMax = m_rangeMax;
|
||||
}
|
||||
m_rangeMin = minimum;
|
||||
m_rangeMax = maximum;
|
||||
|
||||
if (m_autoWindow && !m_lockRight)
|
||||
{
|
||||
m_windowMin = m_rangeMin;
|
||||
m_windowMax = m_rangeMax;
|
||||
}
|
||||
|
||||
m_rangeMinInitialized = true;
|
||||
m_rangeMaxInitialized = true;
|
||||
|
||||
if ((oldRangeMax != m_rangeMax) ||
|
||||
(oldRangeMin != m_rangeMin) ||
|
||||
(oldWindowMin != m_windowMin) ||
|
||||
(oldWindowMax != m_windowMax) ||
|
||||
(wasValid != GetValid()))
|
||||
{
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::AddAxisRange(float value)
|
||||
{
|
||||
bool updateValues = false;
|
||||
float minRange = m_rangeMin;
|
||||
float maxRange = m_rangeMax;
|
||||
|
||||
if ((value < m_rangeMin) || !m_rangeMinInitialized)
|
||||
{
|
||||
updateValues = true;
|
||||
minRange = value;
|
||||
}
|
||||
|
||||
if ((m_rangeMax < value) || !m_rangeMaxInitialized)
|
||||
{
|
||||
updateValues = true;
|
||||
maxRange = value;
|
||||
}
|
||||
|
||||
if (updateValues)
|
||||
{
|
||||
SetAxisRange(minRange, maxRange);
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::SetRangeMax(float rangemax)
|
||||
{
|
||||
SetAxisRange(m_rangeMin, rangemax);
|
||||
}
|
||||
|
||||
void Axis::SetRangeMin(float rangemin)
|
||||
{
|
||||
SetAxisRange(rangemin, m_rangeMax);
|
||||
}
|
||||
|
||||
void Axis::UpdateWindowRange(float delta)
|
||||
{
|
||||
if (delta != 0.0f)
|
||||
{
|
||||
m_windowMax += delta;
|
||||
m_windowMin += delta;
|
||||
if (m_windowMax > m_rangeMax)
|
||||
{
|
||||
delta = m_windowMax - m_rangeMax;
|
||||
m_windowMax -= delta;
|
||||
m_windowMin -= delta;
|
||||
}
|
||||
|
||||
if (m_windowMin < m_rangeMin)
|
||||
{
|
||||
delta = m_rangeMin - m_windowMin;
|
||||
m_windowMax += delta;
|
||||
m_windowMin += delta;
|
||||
}
|
||||
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::SetViewFull()
|
||||
{
|
||||
float oldWindowMin = m_windowMin;
|
||||
float oldWindowMax = m_windowMax;
|
||||
|
||||
m_autoWindow = true;
|
||||
m_windowMin = m_rangeMin;
|
||||
m_windowMax = m_rangeMax;
|
||||
|
||||
if (
|
||||
(oldWindowMin != m_windowMin) ||
|
||||
(oldWindowMax != m_windowMax)
|
||||
)
|
||||
{
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::SetLabel(QString newLabel)
|
||||
{
|
||||
if (m_label != newLabel)
|
||||
{
|
||||
m_label = newLabel;
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
bool Axis::GetLockedRight() const
|
||||
{
|
||||
return m_lockRight;
|
||||
}
|
||||
|
||||
bool Axis::GetLockedRange() const
|
||||
{
|
||||
return m_lockRange;
|
||||
}
|
||||
|
||||
bool Axis::GetLockedZoom() const
|
||||
{
|
||||
return m_lockZoom;
|
||||
}
|
||||
|
||||
void Axis::SetLockedRange(bool newValue)
|
||||
{
|
||||
m_lockRange = newValue;
|
||||
}
|
||||
|
||||
void Axis::SetLockedZoom(bool newValue)
|
||||
{
|
||||
m_lockZoom = newValue;
|
||||
}
|
||||
|
||||
void Axis::SetLockedRight(bool newValue)
|
||||
{
|
||||
m_lockRight = newValue;
|
||||
}
|
||||
|
||||
void Axis::SetAutoWindow(bool autoWindow)
|
||||
{
|
||||
m_autoWindow = autoWindow;
|
||||
}
|
||||
|
||||
bool Axis::GetAutoWindow() const
|
||||
{
|
||||
return m_autoWindow;
|
||||
}
|
||||
|
||||
QString Axis::GetLabel() const
|
||||
{
|
||||
return m_label;
|
||||
}
|
||||
|
||||
float Axis::GetWindowMin() const
|
||||
{
|
||||
return m_windowMin;
|
||||
}
|
||||
|
||||
float Axis::GetWindowMax() const
|
||||
{
|
||||
return m_windowMax;
|
||||
}
|
||||
|
||||
float Axis::GetRangeMin() const
|
||||
{
|
||||
return m_rangeMin;
|
||||
}
|
||||
|
||||
float Axis::GetRangeMax() const
|
||||
{
|
||||
return m_rangeMax;
|
||||
}
|
||||
|
||||
void Axis::SetWindowMin(float newValue)
|
||||
{
|
||||
if (m_windowMin != newValue)
|
||||
{
|
||||
m_windowMin = newValue;
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::SetWindowMax(float newValue)
|
||||
{
|
||||
if (m_windowMax != newValue)
|
||||
{
|
||||
m_windowMax = newValue;
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
float Axis::GetWindowRange() const
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
return m_windowMax - m_windowMin;
|
||||
}
|
||||
|
||||
float Axis::GetRange() const
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
return m_rangeMax - m_rangeMin;
|
||||
}
|
||||
|
||||
// focuspoint is a number from 0 to 1 that indicates how far along that axis the focal point is
|
||||
// for example on a horizontal axis, 0 is the start, or GetwindowMin(), and 1 is the end, GetWindowMaX()
|
||||
|
||||
void Axis::Drag(float delta)
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLockedRange())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateWindowRange(delta);
|
||||
}
|
||||
|
||||
void Axis::ZoomToRange(float windowMin, float windowMax, bool clamp)
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float oldmin = m_windowMin;
|
||||
float oldmax = m_windowMax;
|
||||
m_windowMin = windowMin;
|
||||
m_windowMax = windowMax;
|
||||
|
||||
if (clamp)
|
||||
{
|
||||
if (m_windowMin < m_rangeMin)
|
||||
{
|
||||
m_windowMin = m_rangeMin;
|
||||
}
|
||||
|
||||
if (m_windowMax > m_rangeMax)
|
||||
{
|
||||
m_windowMax = m_rangeMax;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_windowMin != oldmin) || (m_windowMax != oldmax))
|
||||
{
|
||||
emit Invalidated();
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::Zoom(float ratio, float steps, float zoomLimit)
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLockedRight())
|
||||
{
|
||||
ratio = 1.0f;
|
||||
}
|
||||
if (!GetLockedZoom())
|
||||
{
|
||||
SetAutoWindow(false);
|
||||
|
||||
float testMin = GetWindowMin();
|
||||
float testMax = GetWindowMax();
|
||||
|
||||
testMin -= float(GetWindowRange()) * 0.05f * ratio * -steps;
|
||||
testMax += float(GetWindowRange()) * 0.05f * (1.0f - ratio) * -steps;
|
||||
|
||||
if ((testMax - testMin) > 0.0f)
|
||||
{
|
||||
if (testMax > GetRangeMax())
|
||||
{
|
||||
float offset = GetRangeMax() - testMax;
|
||||
testMax += offset;
|
||||
testMin += offset;
|
||||
}
|
||||
if (testMin < GetRangeMin())
|
||||
{
|
||||
float offset = testMin - GetRangeMin();
|
||||
testMax -= offset;
|
||||
testMin -= offset;
|
||||
}
|
||||
if (testMax - testMin >= zoomLimit)
|
||||
{
|
||||
SetWindowMin(testMin);
|
||||
SetWindowMax(testMax);
|
||||
}
|
||||
if ((testMax - testMin) > (GetRangeMax() - GetRangeMin()))
|
||||
{
|
||||
SetViewFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// given a width of a view in pixels, subdivide it and return a vector of domain units that
|
||||
// satisfy a human outlook on domain values:
|
||||
float Axis::ComputeAxisDivisions(float pixelWidth, AZStd::vector<float>& domainPointsOut, float minPixels, float maxPixels, bool allowFractions)
|
||||
{
|
||||
if (!GetValid())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float divisor = 1.0f;
|
||||
float windowRange = GetWindowRange();
|
||||
|
||||
// compute the divisor
|
||||
float currentDivisionWidthInPixels = pixelWidth / (windowRange / divisor);
|
||||
while (currentDivisionWidthInPixels > maxPixels)
|
||||
{
|
||||
// drop it down by 0.5 then by 0.1
|
||||
divisor /= 2.0f;
|
||||
currentDivisionWidthInPixels = pixelWidth / (windowRange / divisor);
|
||||
if (currentDivisionWidthInPixels <= maxPixels)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
divisor *= 0.2f; // 0.5f * 0.2f = 0.1
|
||||
currentDivisionWidthInPixels = pixelWidth / (windowRange / divisor);
|
||||
}
|
||||
// the min pixels is an absolute requirement to prevent text from overlapping
|
||||
// which is why we apply that constraint LAST.
|
||||
// so for example, if window shows 100 units, and divisor is 2.0, then that would yield 50 pieces.
|
||||
// 50 pieces over the span of 1000 pixels is 1000 / 50, 20 pixels each;
|
||||
// 100 pieces would be (num pieces / pixel space to draw in) pixels
|
||||
while (currentDivisionWidthInPixels < minPixels)
|
||||
{
|
||||
// the division width is too small, there are too many pieces. Make fewer pieces by choosing a larger
|
||||
// divisor
|
||||
// drop it down by 0.5 then by 0.1
|
||||
divisor *= 5.0f;
|
||||
currentDivisionWidthInPixels = pixelWidth / (windowRange / divisor);
|
||||
if (currentDivisionWidthInPixels >= minPixels)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
divisor *= 2.0f;
|
||||
currentDivisionWidthInPixels = pixelWidth / (windowRange / divisor);
|
||||
}
|
||||
|
||||
if ((divisor < 1.0f) && (!allowFractions))
|
||||
{
|
||||
divisor = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
// now lay out the domain starting with the first unit of that number:
|
||||
float startingUnit = floorf(m_windowMin / divisor) * divisor;
|
||||
|
||||
// to retain precision we are going to try to do the math around the origin.
|
||||
startingUnit -= m_windowMin;
|
||||
AZStd::size_t maximumAllowedUnitsBeforeSomethingTerribleHasOccurred = (AZStd::size_t)(pixelWidth / 4.0f);
|
||||
|
||||
// so for example if we've decided that the divisor is 10 units, and the window min is 12.5, then it will go to 1.25, chop off the .25, and go back to 10
|
||||
while (startingUnit <= windowRange)
|
||||
{
|
||||
if (startingUnit >= 0.0f)
|
||||
{
|
||||
domainPointsOut.push_back(startingUnit + m_windowMin);
|
||||
}
|
||||
startingUnit += divisor;
|
||||
|
||||
if (domainPointsOut.size() > maximumAllowedUnitsBeforeSomethingTerribleHasOccurred)
|
||||
{
|
||||
break; // you can put a break point here, but it usually means that we've lost enough precision. Change your axis range or numbering scheme!
|
||||
}
|
||||
}
|
||||
|
||||
return divisor;
|
||||
}
|
||||
void Axis::PaintAxis(AxisType axisType, QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter)
|
||||
{
|
||||
switch (axisType)
|
||||
{
|
||||
case AxisType::Horizontal:
|
||||
PaintAsHorizontalAxis(painter, widgetBounds, graphBounds, formatter);
|
||||
break;
|
||||
case AxisType::Vertical:
|
||||
PaintAsVerticalAxis(painter, widgetBounds, graphBounds, formatter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::PaintAsVerticalAxis(QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter)
|
||||
{
|
||||
(void)widgetBounds;
|
||||
|
||||
const QColor axisBrush = QColor(255, 255, 0, 255);
|
||||
const QColor axisPen = QColor(0, 255, 255, 255);
|
||||
const QColor dottedColor(64, 64, 64, 255);
|
||||
const QColor solidColor(0, 255, 255, 255);
|
||||
|
||||
QBrush brush;
|
||||
QPen pen;
|
||||
|
||||
brush.setColor(axisBrush);
|
||||
pen.setColor(axisPen);
|
||||
painter->setPen(pen);
|
||||
|
||||
QFont currentFont = painter->font();
|
||||
currentFont.setPointSize(currentFont.pointSize() - 1);
|
||||
painter->setFont(currentFont);
|
||||
|
||||
int w = painter->fontMetrics().horizontalAdvance(GetLabel());
|
||||
int h = painter->fontMetrics().height();
|
||||
|
||||
int centerHeight = graphBounds.top() + (graphBounds.height() / 2);
|
||||
|
||||
DrawRotatedText(GetLabel(), painter, 270, h, centerHeight + w / 2, 1.25f);
|
||||
|
||||
currentFont.setPointSize(currentFont.pointSize() + 1);
|
||||
painter->setFont(currentFont);
|
||||
|
||||
QPoint startPoint = graphBounds.topLeft();
|
||||
QPoint endPoint = graphBounds.bottomLeft();
|
||||
|
||||
int height = endPoint.y() - startPoint.y();
|
||||
int fontH = painter->fontMetrics().height();
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
height = 1;
|
||||
}
|
||||
|
||||
AZStd::vector<float> divisions;
|
||||
divisions.reserve(10);
|
||||
|
||||
float divisionSize = ComputeAxisDivisions(static_cast<float>(height), divisions, fontH * 2.0f, fontH * 2.0f);
|
||||
|
||||
QPen dottedPen;
|
||||
dottedPen.setStyle(Qt::DotLine);
|
||||
dottedPen.setColor(dottedColor);
|
||||
|
||||
QBrush solidBrush;
|
||||
QPen solidPen;
|
||||
solidPen.setStyle(Qt::SolidLine);
|
||||
solidPen.setColor(solidColor);
|
||||
solidPen.setWidth(1);
|
||||
|
||||
float fullRange = fabs(GetWindowRange());
|
||||
|
||||
for (float division : divisions)
|
||||
{
|
||||
float ratio = static_cast<float>(division - GetWindowMin()) / fullRange;
|
||||
|
||||
QPoint lineStart;
|
||||
lineStart.setX(endPoint.x());
|
||||
lineStart.setY(endPoint.y() - static_cast<int>(height*ratio));
|
||||
|
||||
QPoint lineEnd(static_cast<int>(lineStart.x() + graphBounds.width()), lineStart.y());
|
||||
|
||||
painter->setPen(dottedPen);
|
||||
painter->drawLine(lineStart, lineEnd);
|
||||
|
||||
QString text;
|
||||
|
||||
if (formatter)
|
||||
{
|
||||
text = formatter->convertAxisValueToText(Charts::AxisType::Vertical, division, divisions.front(), divisions.back(), divisionSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = QString("%1").arg((AZ::s64)division);
|
||||
}
|
||||
|
||||
int textW = painter->fontMetrics().horizontalAdvance(text);
|
||||
painter->setPen(solidPen);
|
||||
painter->drawText(lineStart.x() - textW - 2, (int)lineStart.y() + fontH / 2, text);
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::PaintAsHorizontalAxis(QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter)
|
||||
{
|
||||
const QColor axisBrush = QColor(255, 255, 0, 255);
|
||||
const QColor axisPen = QColor(0, 255, 255, 255);
|
||||
const QColor dottedColor(64, 64, 64,255);
|
||||
const QColor solidColor(0, 255, 255, 255);
|
||||
|
||||
QBrush brush;
|
||||
QPen pen;
|
||||
|
||||
brush.setColor(axisBrush);
|
||||
pen.setColor(axisPen);
|
||||
painter->setPen(pen);
|
||||
|
||||
QFont currentFont = painter->font();
|
||||
currentFont.setPointSize(currentFont.pointSize() - 1);
|
||||
painter->setFont(currentFont);
|
||||
|
||||
painter->drawText(0, 0, widgetBounds.width(), widgetBounds.height(), Qt::AlignHCenter | Qt::AlignBottom, GetLabel());
|
||||
|
||||
currentFont.setPointSize(currentFont.pointSize() + 1);
|
||||
painter->setFont(currentFont);
|
||||
|
||||
QPoint startPoint = graphBounds.bottomLeft();
|
||||
QPoint endPoint = graphBounds.bottomRight();
|
||||
int width = endPoint.x() - startPoint.x();
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
width = 1;
|
||||
}
|
||||
|
||||
float textSpaceRequired = (float)painter->fontMetrics().horizontalAdvance("9,999,999.99");
|
||||
|
||||
int fontH = painter->fontMetrics().height();
|
||||
|
||||
AZStd::vector<float> divisions;
|
||||
divisions.reserve(10);
|
||||
|
||||
float divisionSize = ComputeAxisDivisions(static_cast<float>(width), divisions, textSpaceRequired, textSpaceRequired);
|
||||
|
||||
QPen dottedPen;
|
||||
dottedPen.setStyle(Qt::DotLine);
|
||||
dottedPen.setColor(dottedColor);
|
||||
|
||||
QBrush solidBrush;
|
||||
QPen solidPen;
|
||||
solidPen.setStyle(Qt::SolidLine);
|
||||
solidPen.setColor(solidColor);
|
||||
solidPen.setWidth(1);
|
||||
|
||||
float fullRange = fabs(GetWindowRange());
|
||||
|
||||
for (float division : divisions)
|
||||
{
|
||||
float ratio = float(division - GetWindowMin()) / fullRange;
|
||||
|
||||
QPoint lineStart;
|
||||
lineStart.setX(startPoint.x() + static_cast<int>(width*ratio));
|
||||
lineStart.setY(startPoint.y());
|
||||
|
||||
QPoint lineEnd(lineStart.x(), static_cast<int>(startPoint.y() - graphBounds.height()));
|
||||
|
||||
painter->setPen(dottedPen);
|
||||
painter->drawLine(lineStart, lineEnd);
|
||||
|
||||
QString text;
|
||||
|
||||
if (formatter)
|
||||
{
|
||||
text = formatter->convertAxisValueToText(Charts::AxisType::Horizontal, division, divisions.front(), divisions.back(), divisionSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = QString("%1").arg((AZ::s64)division);
|
||||
}
|
||||
|
||||
int textW = painter->fontMetrics().horizontalAdvance(text);
|
||||
|
||||
painter->setPen(solidPen);
|
||||
painter->drawText(lineStart.x() - textW / 2, startPoint.y() + fontH, text);
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::DrawRotatedText(QString text, QPainter *painter, float degrees, int x, int y, float scale)
|
||||
{
|
||||
painter->save();
|
||||
painter->translate(x, y);
|
||||
painter->scale(scale, scale);
|
||||
painter->rotate(degrees);
|
||||
painter->drawText(0, 0, text);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Source/Driller/moc_Axis.cpp>
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHART_AXIS_H
|
||||
#define CHART_AXIS_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <Source/Driller/ChartTypes.hxx>
|
||||
#endif
|
||||
|
||||
class QPainter;
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
// the Axis represents one axis on a chart. its float-based
|
||||
// it contains information about window range and domain range.
|
||||
class Axis : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Axis,AZ::SystemAllocator,0);
|
||||
Axis(QObject* pParent = NULL);
|
||||
~Axis(); // not virtual
|
||||
|
||||
public:
|
||||
bool GetValid() const;
|
||||
bool GetAutoWindow() const;
|
||||
QString GetLabel() const;
|
||||
float GetWindowMin() const;
|
||||
float GetWindowMax() const;
|
||||
float GetRangeMin() const;
|
||||
float GetRangeMax() const;
|
||||
float GetWindowRange() const;
|
||||
float GetRange() const;
|
||||
bool GetLockedZoom() const;
|
||||
bool GetLockedRange() const;
|
||||
bool GetLockedRight() const;
|
||||
void Zoom(float focusPoint, float steps, float zoomLimit );
|
||||
void ZoomToRange(float windowMin, float windowMax, bool clamp);
|
||||
|
||||
void PaintAxis(AxisType axisType, QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter);
|
||||
|
||||
float ComputeAxisDivisions(float pixelWidth, AZStd::vector<float>& domainPointsOut, float minPixels, float maxPixels, bool allowFractions = true);
|
||||
|
||||
signals:
|
||||
void Invalidated(); // something has happened which should cause anyone using this axis to update themselves.
|
||||
|
||||
public slots:
|
||||
void SetAxisRange( float minimum, float maximum );
|
||||
void AddAxisRange( float value );
|
||||
void SetViewFull();
|
||||
void SetLabel(QString newLabel);
|
||||
void SetLockedRight(bool lockRight);
|
||||
void SetLockedRange(bool locked); // cannot pan
|
||||
void SetLockedZoom(bool locked); // cannot zoom.
|
||||
void Clear();
|
||||
void SetAutoWindow( bool autoWindow );
|
||||
void SetWindowMin(float newValue);
|
||||
void SetWindowMax(float newValue);
|
||||
void UpdateWindowRange(float delta);
|
||||
void SetRangeMax(float rangemax);
|
||||
void SetRangeMin(float rangemin);
|
||||
void Drag(float delta);
|
||||
|
||||
private:
|
||||
|
||||
void PaintAsVerticalAxis(QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter);
|
||||
void PaintAsHorizontalAxis(QPainter* painter, const QRect& widgetBounds, const QRect& graphBounds, QAbstractAxisFormatter* formatter);
|
||||
void DrawRotatedText(QString text, QPainter *painter, float degrees, int x, int y, float scale);
|
||||
|
||||
QString m_label;
|
||||
float m_rangeMin;
|
||||
float m_rangeMax;
|
||||
float m_windowMin;
|
||||
float m_windowMax;
|
||||
bool m_lockZoom; // zoom is always to the range
|
||||
bool m_lockRange; // you may only pan
|
||||
bool m_lockRight;
|
||||
bool m_autoWindow;
|
||||
bool m_rangeMinInitialized;
|
||||
bool m_rangeMaxInitialized; // these are false until you init them, and the axis is invalid until such a time.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_CSVEXPORTSETTINGS_H
|
||||
#define DRILLER_CSVEXPORTSETTINGS_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CSVExportSettings
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CSVExportSettings, AZ::SystemAllocator, 0);
|
||||
|
||||
CSVExportSettings()
|
||||
: m_shouldExportColumnDescriptor(true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CSVExportSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void SetShouldExportColumnDescriptors(bool shouldExport)
|
||||
{
|
||||
m_shouldExportColumnDescriptor = shouldExport;
|
||||
}
|
||||
|
||||
bool ShouldExportColumnDescriptors() const
|
||||
{
|
||||
return m_shouldExportColumnDescriptor;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_shouldExportColumnDescriptor;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,392 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Debug/Trace.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
|
||||
#include "CarrierDataAggregator.hxx"
|
||||
#include <Source/Driller/Carrier/moc_CarrierDataAggregator.cpp>
|
||||
#include "CarrierDataEvents.h"
|
||||
#include "CarrierDataView.hxx"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
/////////////////////////////
|
||||
// CarrierCSVExportSettings
|
||||
/////////////////////////////
|
||||
CarrierExportSettings::CarrierExportSettings()
|
||||
{
|
||||
m_columnDescriptors =
|
||||
{
|
||||
{ExportField::Data_Sent, "Data Sent(Bytes)"},
|
||||
{ExportField::Data_Received, "Data Received(Bytes)"},
|
||||
{ExportField::Data_Resent, "Data Resent(Bytes)"},
|
||||
{ExportField::Data_Acked, "Data Acked(Bytes)"},
|
||||
{ExportField::Packets_Sent, "Packets Sent"},
|
||||
{ExportField::Packets_Received, "Packets Received"},
|
||||
{ExportField::Packets_Lost, "Packets Lost"},
|
||||
{ExportField::Packets_Acked, "Packets Acked"},
|
||||
{ExportField::Packet_RTT, "Packet Round Trip Time"},
|
||||
{ExportField::Packet_Loss, "Packet Loss(%)"},
|
||||
{ExportField::Effective_Data_Sent, "Effective Data Sent(Bytes)"},
|
||||
{ExportField::Effective_Data_Received, "Effective Data Received(Bytes)"},
|
||||
{ExportField::Effective_Data_Resent, "Effective Data Resent(Bytes)"},
|
||||
{ExportField::Effective_Data_Acked, "Effective Data Acked(Bytes)"},
|
||||
{ExportField::Effective_Packets_Sent, "Effective Packets Sent"},
|
||||
{ExportField::Effective_Packets_Received, "Effective Packets Received"},
|
||||
{ExportField::Effective_Packets_Lost, "Effective Packets Lost"},
|
||||
{ExportField::Effective_Packets_Acked, "Effective Packets Acked"},
|
||||
{ExportField::Effective_Packet_RTT, "Effective Packet Round Trip Time"},
|
||||
{ExportField::Effective_Packet_Loss, "Effective Packet Loss(%)"}
|
||||
};
|
||||
|
||||
m_exportOrdering =
|
||||
{
|
||||
ExportField::Data_Sent,
|
||||
ExportField::Effective_Data_Sent,
|
||||
ExportField::Data_Received,
|
||||
ExportField::Effective_Data_Received,
|
||||
ExportField::Data_Resent,
|
||||
ExportField::Effective_Data_Resent,
|
||||
ExportField::Data_Acked,
|
||||
ExportField::Effective_Data_Acked,
|
||||
ExportField::Packets_Sent,
|
||||
ExportField::Effective_Packets_Sent,
|
||||
ExportField::Packets_Received,
|
||||
ExportField::Effective_Packets_Received,
|
||||
ExportField::Packets_Lost,
|
||||
ExportField::Effective_Packets_Lost,
|
||||
ExportField::Packets_Acked,
|
||||
ExportField::Effective_Packets_Acked,
|
||||
ExportField::Packet_RTT,
|
||||
ExportField::Effective_Packet_RTT,
|
||||
ExportField::Packet_Loss,
|
||||
ExportField::Effective_Packet_Loss
|
||||
};
|
||||
|
||||
for (const AZStd::pair< ExportField, AZStd::string >& item : m_columnDescriptors)
|
||||
{
|
||||
m_stringToExportEnum[item.second] = item.first;
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierExportSettings::GetExportItems(QStringList& items) const
|
||||
{
|
||||
for (const AZStd::pair< CarrierExportField, AZStd::string>& item : m_columnDescriptors)
|
||||
{
|
||||
items.push_back(QString(item.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierExportSettings::GetActiveExportItems(QStringList& items) const
|
||||
{
|
||||
for (CarrierExportField currentField : m_exportOrdering)
|
||||
{
|
||||
if (currentField != CarrierExportField::UNKNOWN)
|
||||
{
|
||||
items.push_back(QString(FindColumnDescriptor(currentField).c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierExportSettings::UpdateExportOrdering(const QStringList& activeItems)
|
||||
{
|
||||
m_exportOrdering.clear();
|
||||
|
||||
for (const QString& activeItem : activeItems)
|
||||
{
|
||||
ExportField field = FindExportFieldFromDescriptor(activeItem.toStdString().c_str());
|
||||
|
||||
AZ_Assert(field != ExportField::UNKNOWN, "Unknown descriptor %s", activeItem.toStdString().c_str());
|
||||
if (field != ExportField::UNKNOWN)
|
||||
{
|
||||
m_exportOrdering.push_back(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::vector< CarrierExportField >& CarrierExportSettings::GetExportOrder() const
|
||||
{
|
||||
return m_exportOrdering;
|
||||
}
|
||||
|
||||
const AZStd::string& CarrierExportSettings::FindColumnDescriptor(ExportField exportField) const
|
||||
{
|
||||
static const AZStd::string emptyDescriptor;
|
||||
|
||||
AZStd::unordered_map<ExportField, AZStd::string>::const_iterator descriptorIter = m_columnDescriptors.find(exportField);
|
||||
|
||||
if (descriptorIter == m_columnDescriptors.end())
|
||||
{
|
||||
AZ_Assert(false, "Unknown column descriptor in Carrier CSV Export");
|
||||
return emptyDescriptor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return descriptorIter->second;
|
||||
}
|
||||
}
|
||||
|
||||
CarrierExportField CarrierExportSettings::FindExportFieldFromDescriptor(const char* columnDescriptor) const
|
||||
{
|
||||
AZStd::unordered_map<AZStd::string, ExportField>::const_iterator exportIter = m_stringToExportEnum.find(columnDescriptor);
|
||||
|
||||
ExportField retVal = ExportField::UNKNOWN;
|
||||
|
||||
if (exportIter != m_stringToExportEnum.end())
|
||||
{
|
||||
retVal = exportIter->second;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// CarrierDataAggregator
|
||||
//////////////////////////
|
||||
float CarrierDataAggregator::GetTValueAtFrame(FrameNumberType frame, AZ::s64 maxValue)
|
||||
{
|
||||
float valueAtFrame = 0.0f;
|
||||
|
||||
size_t numEventsAtFrame = NumOfEventsAtFrame(frame);
|
||||
for (EventNumberType i = m_frameToEventIndex[frame]; i < static_cast<EventNumberType>(m_frameToEventIndex[frame] + numEventsAtFrame); i++)
|
||||
{
|
||||
CarrierDataEvent* event = static_cast<CarrierDataEvent*>(m_events[i]);
|
||||
// Consider the aggregation a sum of all data send and received (i.e. total bandwidth used).
|
||||
valueAtFrame += event->mLastSecond.mDataSend + event->mLastSecond.mDataReceived;
|
||||
}
|
||||
|
||||
if (valueAtFrame >= maxValue)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (valueAtFrame == 0.0f)
|
||||
{
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
float tValue = (valueAtFrame / (maxValue * 2)) - 1.0f;
|
||||
return tValue;
|
||||
}
|
||||
|
||||
CarrierDataAggregator::CarrierDataAggregator(int identity)
|
||||
: Aggregator(identity)
|
||||
, m_parser(this)
|
||||
{
|
||||
}
|
||||
|
||||
CustomizeCSVExportWidget* CarrierDataAggregator::CreateCSVExportCustomizationWidget()
|
||||
{
|
||||
return aznew GenericCustomizeCSVExportWidget(m_csvExportSettings);
|
||||
}
|
||||
|
||||
float CarrierDataAggregator::ValueAtFrame(FrameNumberType frame)
|
||||
{
|
||||
return GetTValueAtFrame(frame, (1024 * 20));
|
||||
}
|
||||
|
||||
QColor CarrierDataAggregator::GetColor() const
|
||||
{
|
||||
return QColor(255, 0, 0);
|
||||
}
|
||||
|
||||
QString CarrierDataAggregator::GetName() const
|
||||
{
|
||||
return QString("Carrier");
|
||||
}
|
||||
|
||||
QString CarrierDataAggregator::GetChannelName() const
|
||||
{
|
||||
return ChannelName();
|
||||
}
|
||||
|
||||
QString CarrierDataAggregator::GetDescription() const
|
||||
{
|
||||
return QString("GridMate Carrier Data");
|
||||
}
|
||||
|
||||
QString CarrierDataAggregator::GetToolTip() const
|
||||
{
|
||||
return QString("Information about overall bandwidth usage");
|
||||
}
|
||||
|
||||
AZ::Uuid CarrierDataAggregator::GetID() const
|
||||
{
|
||||
return AZ::Uuid("{927B208C-28E8-4BE7-BF4E-629D98F7097F}");
|
||||
}
|
||||
|
||||
QWidget* CarrierDataAggregator::DrillDownRequest(FrameNumberType frame)
|
||||
{
|
||||
(void)frame;
|
||||
|
||||
// Always provide a full view of the driller data.
|
||||
FrameNumberType lastFrame = static_cast<FrameNumberType>(m_frameToEventIndex.size() - 1);
|
||||
|
||||
// This pointer is cleaned up by qt when the window is closed.
|
||||
return aznew CarrierDataView(0, lastFrame, this);
|
||||
}
|
||||
|
||||
void CarrierDataAggregator::OptionsRequest()
|
||||
{
|
||||
}
|
||||
|
||||
void CarrierDataAggregator::ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings)
|
||||
{
|
||||
CarrierExportSettings* carrierExportSettings = static_cast<CarrierExportSettings*>(exportSettings);
|
||||
const AZStd::vector< CarrierExportField >& exportOrdering = carrierExportSettings->GetExportOrder();
|
||||
|
||||
bool addComma = false;
|
||||
|
||||
for (CarrierExportField currentField : exportOrdering)
|
||||
{
|
||||
if (addComma)
|
||||
{
|
||||
file.Write(",", 1);
|
||||
}
|
||||
|
||||
const AZStd::string& columnDescriptor = carrierExportSettings->FindColumnDescriptor(currentField);
|
||||
file.Write(columnDescriptor.c_str(), columnDescriptor.size());
|
||||
addComma = true;
|
||||
}
|
||||
|
||||
file.Write("\n", 1);
|
||||
}
|
||||
|
||||
void CarrierDataAggregator::ExportEventToCSV(AZ::IO::SystemFile& file, const DrillerEvent* drillerEvent, CSVExportSettings* exportSettings)
|
||||
{
|
||||
const CarrierDataEvent* carrierEvent = static_cast<const CarrierDataEvent*>(drillerEvent);
|
||||
|
||||
CarrierExportSettings* carrierExportSettings = static_cast<CarrierExportSettings*>(exportSettings);
|
||||
|
||||
const AZStd::vector< CarrierExportField >& exportOrdering = carrierExportSettings->GetExportOrder();
|
||||
bool addComma = false;
|
||||
|
||||
AZStd::string number;
|
||||
|
||||
for (CarrierExportField currentField : exportOrdering)
|
||||
{
|
||||
if (addComma)
|
||||
{
|
||||
file.Write(",", 1);
|
||||
}
|
||||
|
||||
switch (currentField)
|
||||
{
|
||||
case CarrierExportField::Data_Sent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mDataSend);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Data_Received:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mDataReceived);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Data_Resent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mDataResent);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Data_Acked:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mDataAcked);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packets_Sent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mPacketSend);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packets_Received:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mPacketReceived);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packets_Lost:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mPacketLost);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packets_Acked:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mPacketAcked);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packet_RTT:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mRTT);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Packet_Loss:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mLastSecond.mPacketLoss);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Data_Sent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mDataSend);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Data_Received:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mDataReceived);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Data_Resent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mDataResent);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Data_Acked:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mDataAcked);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packets_Sent:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mPacketSend);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packets_Received:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mPacketReceived);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packets_Lost:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mPacketLost);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packets_Acked:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mPacketAcked);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packet_RTT:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mRTT);
|
||||
break;
|
||||
}
|
||||
case CarrierExportField::Effective_Packet_Loss:
|
||||
{
|
||||
AZStd::to_string(number, carrierEvent->mEffectiveLastSecond.mPacketLoss);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unknown CarrierExportField");
|
||||
break;
|
||||
}
|
||||
|
||||
file.Write(number.c_str(), number.size());
|
||||
addComma = true;
|
||||
}
|
||||
|
||||
file.Write("\n", 1);
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_CARRIER_DATAAGGREGATOR_H
|
||||
#define DRILLER_CARRIER_DATAAGGREGATOR_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Source/Driller/DrillerAggregator.hxx"
|
||||
#include "CarrierDataParser.h"
|
||||
|
||||
#include "Source/Driller/GenericCustomizeCSVExportWidget.hxx"
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
struct CarrierData;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CarrierDataView;
|
||||
|
||||
class CarrierExportSettings
|
||||
: public GenericCSVExportSettings
|
||||
{
|
||||
public:
|
||||
enum class ExportField
|
||||
{
|
||||
Data_Sent,
|
||||
Data_Received,
|
||||
Data_Resent,
|
||||
Data_Acked,
|
||||
Packets_Sent,
|
||||
Packets_Received,
|
||||
Packets_Lost,
|
||||
Packets_Acked,
|
||||
Packet_RTT,
|
||||
Packet_Loss,
|
||||
Effective_Data_Sent,
|
||||
Effective_Data_Received,
|
||||
Effective_Data_Resent,
|
||||
Effective_Data_Acked,
|
||||
Effective_Packets_Sent,
|
||||
Effective_Packets_Received,
|
||||
Effective_Packets_Lost,
|
||||
Effective_Packets_Acked,
|
||||
Effective_Packet_RTT,
|
||||
Effective_Packet_Loss,
|
||||
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
private:
|
||||
AZStd::unordered_map<ExportField,AZStd::string> m_columnDescriptors;
|
||||
AZStd::unordered_map<AZStd::string, ExportField> m_stringToExportEnum;
|
||||
AZStd::vector< ExportField > m_exportOrdering;
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CarrierExportSettings, AZ::SystemAllocator, 0);
|
||||
|
||||
CarrierExportSettings();
|
||||
|
||||
void GetExportItems(QStringList& items) const override;
|
||||
void GetActiveExportItems(QStringList& items) const override;
|
||||
|
||||
const AZStd::vector< ExportField >& GetExportOrder() const;
|
||||
const AZStd::string& FindColumnDescriptor(ExportField exportField) const;
|
||||
|
||||
protected:
|
||||
void UpdateExportOrdering(const QStringList& activeItems) override;
|
||||
|
||||
private:
|
||||
ExportField FindExportFieldFromDescriptor(const char* descriptor) const;
|
||||
};
|
||||
|
||||
typedef CarrierExportSettings::ExportField CarrierExportField;
|
||||
|
||||
class CarrierDataAggregator : public Aggregator
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CarrierDataAggregator, AZ::SystemAllocator, 0);
|
||||
|
||||
CarrierDataAggregator(int identity = 0);
|
||||
|
||||
static AZ::u32 DrillerId() { return AZ_CRC("CarrierDriller"); }
|
||||
|
||||
// Driller::Aggregator.
|
||||
AZ::u32 GetDrillerId() const override
|
||||
{
|
||||
return DrillerId();
|
||||
}
|
||||
|
||||
static const char* ChannelName() { return "GridMate"; }
|
||||
|
||||
AZ::Crc32 GetChannelId() const override
|
||||
{
|
||||
return AZ::Crc32(ChannelName());
|
||||
}
|
||||
|
||||
|
||||
AZ::Debug::DrillerHandlerParser* GetDrillerDataParser() override
|
||||
{
|
||||
return &m_parser;
|
||||
}
|
||||
|
||||
bool CanExportToCSV() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CustomizeCSVExportWidget* CreateCSVExportCustomizationWidget() override;
|
||||
|
||||
// Driller::Aggregator.
|
||||
void ApplySettingsFromWorkspace(WorkspaceSettingsProvider*) override {}
|
||||
void ActivateWorkspaceSettings(WorkspaceSettingsProvider*) override {}
|
||||
void SaveSettingsToWorkspace(WorkspaceSettingsProvider*) override {}
|
||||
|
||||
public slots:
|
||||
// Driller::Aggregator.
|
||||
float ValueAtFrame(FrameNumberType frame) override;
|
||||
QColor GetColor() const override;
|
||||
QString GetName() const override;
|
||||
QString GetChannelName() const override;
|
||||
QString GetDescription() const override;
|
||||
QString GetToolTip() const override;
|
||||
AZ::Uuid GetID() const override;
|
||||
QWidget* DrillDownRequest(FrameNumberType frame) override;
|
||||
void OptionsRequest() override;
|
||||
|
||||
protected:
|
||||
void ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings) override;
|
||||
void ExportEventToCSV(AZ::IO::SystemFile& file, const DrillerEvent* drillerEvent, CSVExportSettings* exportSettings) override;
|
||||
|
||||
private:
|
||||
|
||||
// Aggregate all data events in a particular frame and return a normalized
|
||||
// value in the range [-1,1] based on the min/max range [0,maxValue].
|
||||
float GetTValueAtFrame(FrameNumberType frame, AZ::s64 maxValue);
|
||||
|
||||
CarrierExportSettings m_csvExportSettings;
|
||||
|
||||
// A parser that will parse carrier driller XML data and add events back
|
||||
// into this aggregator.
|
||||
CarrierDataParser m_parser;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_CARRIER_DATAEVENTS_H
|
||||
#define DRILLER_CARRIER_DATAEVENTS_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include "Source/Driller/DrillerEvent.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
namespace Carrier
|
||||
{
|
||||
enum CarrierEventType
|
||||
{
|
||||
CET_INFO = 1
|
||||
};
|
||||
}
|
||||
|
||||
struct CarrierData
|
||||
{
|
||||
AZ::s32 mDataSend; //< Data sent (bytes).
|
||||
AZ::s32 mDataReceived; //< Data received (bytes).
|
||||
AZ::s32 mDataResent; //< Data resent (bytes).
|
||||
AZ::s32 mDataAcked; //< Data acknowledged (bytes).
|
||||
AZ::s32 mPacketSend; //< Number of packets sent.
|
||||
AZ::s32 mPacketReceived; //< Number of packets received.
|
||||
AZ::s32 mPacketLost; //< Number of packets lost.
|
||||
AZ::s32 mPacketAcked; //< Number of packets acknowledged.
|
||||
float mRTT; //< Round-trip time.
|
||||
float mPacketLoss; //< Packet loss percentage.
|
||||
};
|
||||
|
||||
class CarrierDataEvent
|
||||
: public DrillerEvent
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CarrierDataEvent, AZ::SystemAllocator, 0);
|
||||
|
||||
CarrierDataEvent()
|
||||
: DrillerEvent(Carrier::CET_INFO)
|
||||
, mID("<none>")
|
||||
{
|
||||
};
|
||||
|
||||
virtual void StepForward(Aggregator* data) { (void)data; };
|
||||
virtual void StepBackward(Aggregator* data) { (void)data; };
|
||||
|
||||
AZStd::string mID;
|
||||
CarrierData mLastSecond;
|
||||
CarrierData mEffectiveLastSecond;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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 "CarrierDataEvents.h"
|
||||
#include "CarrierDataAggregator.hxx"
|
||||
#include "CarrierDataParser.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
CarrierDataParser::CarrierDataParser(CarrierDataAggregator* m_aggregator)
|
||||
: DrillerHandlerParser(false)
|
||||
, m_currentType(CDT_NONE)
|
||||
, m_aggregator(m_aggregator)
|
||||
{
|
||||
}
|
||||
|
||||
CarrierDataParser::~CarrierDataParser()
|
||||
{
|
||||
}
|
||||
|
||||
AZ::Debug::DrillerHandlerParser* CarrierDataParser::OnEnterTag(AZ::u32 tagName)
|
||||
{
|
||||
// Start of a new event.
|
||||
if (tagName == AZ_CRC("Statistics"))
|
||||
{
|
||||
m_currentType = CDT_STATISTICS;
|
||||
m_aggregator->AddEvent(aznew CarrierDataEvent);
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("LastSecond"))
|
||||
{
|
||||
m_currentType = CDT_LAST_SECOND;
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("EffectiveLastSecond"))
|
||||
{
|
||||
m_currentType = CDT_EFFECTIVE_LAST_SECOND;
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierDataParser::OnExitTag(AZ::Debug::DrillerHandlerParser* handler, AZ::u32 tagName)
|
||||
{
|
||||
(void)handler;
|
||||
|
||||
if (tagName == AZ_CRC("LastSecond") || tagName == AZ_CRC("EffectiveLastSecond"))
|
||||
{
|
||||
m_currentType = CDT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierDataParser::OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode)
|
||||
{
|
||||
// Ignore unsupported tags.
|
||||
if (m_currentType == CDT_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CarrierDataEvent* event = static_cast<CarrierDataEvent*>(m_aggregator->GetEvents().back());
|
||||
|
||||
if (m_currentType == CDT_STATISTICS)
|
||||
{
|
||||
dataNode.Read(event->mID);
|
||||
return;
|
||||
}
|
||||
|
||||
CarrierData* eventData = nullptr;
|
||||
switch (m_currentType)
|
||||
{
|
||||
case CDT_LAST_SECOND:
|
||||
eventData = &event->mLastSecond;
|
||||
break;
|
||||
case CDT_EFFECTIVE_LAST_SECOND:
|
||||
eventData = &event->mEffectiveLastSecond;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataNode.m_name == AZ_CRC("DataSend"))
|
||||
{
|
||||
dataNode.Read(eventData->mDataSend);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("DataReceived"))
|
||||
{
|
||||
dataNode.Read(eventData->mDataReceived);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("DataResent"))
|
||||
{
|
||||
dataNode.Read(eventData->mDataResent);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("DataAcked"))
|
||||
{
|
||||
dataNode.Read(eventData->mDataAcked);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("PacketSend"))
|
||||
{
|
||||
dataNode.Read(eventData->mPacketSend);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("PacketReceived"))
|
||||
{
|
||||
dataNode.Read(eventData->mPacketReceived);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("PacketLost"))
|
||||
{
|
||||
dataNode.Read(eventData->mPacketLost);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("PacketAcked"))
|
||||
{
|
||||
dataNode.Read(eventData->mPacketAcked);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("PacketLoss"))
|
||||
{
|
||||
dataNode.Read(eventData->mPacketLoss);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("rtt"))
|
||||
{
|
||||
dataNode.Read(eventData->mRTT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_CARRIER_DATAPARSER_H
|
||||
#define DRILLER_CARRIER_DATAPARSER_H
|
||||
|
||||
#include <AzCore/Driller/Stream.h>
|
||||
#include "CarrierDataEvents.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CarrierDataAggregator;
|
||||
|
||||
enum CarrierDataType
|
||||
{
|
||||
CDT_NONE,
|
||||
CDT_STATISTICS,
|
||||
CDT_LAST_SECOND,
|
||||
CDT_EFFECTIVE_LAST_SECOND
|
||||
};
|
||||
|
||||
class CarrierDataParser
|
||||
: public AZ::Debug::DrillerHandlerParser
|
||||
{
|
||||
public:
|
||||
// The parser will add events to a CarrierDataAggregator instance.
|
||||
CarrierDataParser(CarrierDataAggregator* m_aggregator);
|
||||
virtual ~CarrierDataParser();
|
||||
|
||||
// AZ::Debug::DrillerHandlerParser: Callbacks for entering, leaving and finding data
|
||||
// while parsing the driller XML data.
|
||||
AZ::Debug::DrillerHandlerParser* OnEnterTag(AZ::u32 tagName) override;
|
||||
void OnExitTag(AZ::Debug::DrillerHandlerParser* handler, AZ::u32 tagName) override;
|
||||
void OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode) override;
|
||||
|
||||
private:
|
||||
// The current tag type while parsing the driller XML data.
|
||||
CarrierDataType m_currentType;
|
||||
|
||||
// The aggregator where events are added as a result of parsing the XML data.
|
||||
CarrierDataAggregator* m_aggregator;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/std/containers/set.h>
|
||||
#include "CarrierDataEvents.h"
|
||||
#include "CarrierDataAggregator.hxx"
|
||||
#include "CarrierDataView.hxx"
|
||||
#include "CarrierOperationTelemetryEvent.h"
|
||||
|
||||
#include "Source/Driller/DrillerOperationTelemetryEvent.h"
|
||||
|
||||
#include <Source/Driller/Carrier/moc_CarrierDataView.cpp>
|
||||
#include <Source/Driller/Carrier/ui_CarrierDataView.h>
|
||||
#include <QString>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static AZ::s64 GetLargestDataValue(const CarrierDataView::DataPointList& dataPointList)
|
||||
{
|
||||
AZ::s64 maxDataValue = 0;
|
||||
for (auto dataPoint = dataPointList.begin(); dataPoint != dataPointList.end(); dataPoint++)
|
||||
{
|
||||
if (dataPoint->second > maxDataValue)
|
||||
{
|
||||
maxDataValue = static_cast<AZ::s64>(dataPoint->second);
|
||||
}
|
||||
}
|
||||
return maxDataValue;
|
||||
}
|
||||
|
||||
static void BuildEventList(const CarrierDataAggregator* aggr,
|
||||
FrameNumberType startFrame,
|
||||
FrameNumberType endFrame,
|
||||
AZStd::vector<EventNumberType>& eventIdxList)
|
||||
{
|
||||
eventIdxList.clear();
|
||||
for (FrameNumberType frame = startFrame; frame <= endFrame; frame++)
|
||||
{
|
||||
size_t numEvents = aggr->NumOfEventsAtFrame(frame);
|
||||
if (numEvents == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EventNumberType firstEventIdx = aggr->GetFirstIndexAtFrame(frame);
|
||||
for (EventNumberType eventIdx = firstEventIdx; eventIdx < static_cast<EventNumberType>(firstEventIdx + numEvents); eventIdx++)
|
||||
{
|
||||
eventIdxList.push_back(eventIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetEventIds(const CarrierDataAggregator* aggr,
|
||||
FrameNumberType startFrame,
|
||||
FrameNumberType endFrameIdx,
|
||||
AZStd::set<AZStd::string>& ids)
|
||||
{
|
||||
ids.clear();
|
||||
for (FrameNumberType frameId = startFrame; frameId <= endFrameIdx; frameId++)
|
||||
{
|
||||
size_t numEvents = aggr->NumOfEventsAtFrame(frameId);
|
||||
EventNumberType firstEventIndex = aggr->GetFirstIndexAtFrame(frameId);
|
||||
for (EventNumberType eventIndex = firstEventIndex; eventIndex < static_cast<EventNumberType>(firstEventIndex + numEvents); eventIndex++)
|
||||
{
|
||||
CarrierDataEvent* event = static_cast<CarrierDataEvent*>(aggr->GetEvents()[eventIndex]);
|
||||
ids.insert(event->mID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CarrierDataView::CarrierDataView(FrameNumberType startFrame, FrameNumberType endFrame, const CarrierDataAggregator* aggregator)
|
||||
: QDialog()
|
||||
, mStartFrame(0)
|
||||
, mEndFrame(0)
|
||||
, m_lifespanTelemetry("CarrierDataView")
|
||||
{
|
||||
// Create a window defined in CarrierDataView.ui.
|
||||
m_gui = azcreate(Ui::CarrierDataView, ());
|
||||
m_gui->setupUi(this);
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
|
||||
|
||||
mStartFrame = startFrame;
|
||||
mEndFrame = endFrame;
|
||||
mAggregator = aggregator;
|
||||
|
||||
// Prepare the dialog.
|
||||
show();
|
||||
raise();
|
||||
activateWindow();
|
||||
setFocus();
|
||||
|
||||
setWindowTitle(aggregator->GetDialogTitle());
|
||||
|
||||
// Find all unique ids and add them to the drop down box.
|
||||
AZStd::set<AZStd::string> ids;
|
||||
GetEventIds(aggregator, startFrame, endFrame, ids);
|
||||
|
||||
for (auto id = ids.begin(); id != ids.end(); id++)
|
||||
{
|
||||
m_gui->Filter->addItem((*id).c_str());
|
||||
}
|
||||
|
||||
QObject::connect(m_gui->Filter, SIGNAL(currentIndexChanged(int)), this, SLOT(OnCurrentFilterChanged()));
|
||||
|
||||
// Update the charts based on the current filter.
|
||||
OnCurrentFilterChanged();
|
||||
}
|
||||
|
||||
CarrierDataView::~CarrierDataView()
|
||||
{
|
||||
azdestroy(m_gui);
|
||||
}
|
||||
|
||||
void CarrierDataView::OnCurrentFilterChanged()
|
||||
{
|
||||
AZStd::string currentId = AZStd::string(m_gui->Filter->currentText().toUtf8().constData());
|
||||
SetupAllCharts(currentId, mAggregator, mStartFrame, mEndFrame);
|
||||
|
||||
CarrierOperationTelemetryEvent filterChanged;
|
||||
filterChanged.SetAttribute("IPFilterChanged", "");
|
||||
filterChanged.Log();
|
||||
}
|
||||
|
||||
void CarrierDataView::SetupAllCharts(AZStd::string id,
|
||||
const CarrierDataAggregator* aggr,
|
||||
FrameNumberType startFrame,
|
||||
FrameNumberType endFrame)
|
||||
{
|
||||
AZStd::vector<EventNumberType> eventIdxList;
|
||||
BuildEventList(aggr, startFrame, endFrame, eventIdxList);
|
||||
|
||||
DataPointList send;
|
||||
DataPointList recv;
|
||||
DataPointList effectiveSend;
|
||||
DataPointList effectiveRecv;
|
||||
DataPointList pktSend;
|
||||
DataPointList pktRecv;
|
||||
DataPointList rtt;
|
||||
DataPointList loss;
|
||||
|
||||
EventNumberType eventIndex = 0;
|
||||
for (auto eventItr = eventIdxList.begin(); eventItr != eventIdxList.end(); eventItr++)
|
||||
{
|
||||
EventNumberType realEventIndex = *eventItr;
|
||||
CarrierDataEvent* event = static_cast<CarrierDataEvent*>(aggr->GetEvents()[realEventIndex]);
|
||||
|
||||
if (event->mID.compare(id) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Total bytes sent and received.
|
||||
send.push_back(DataPoint(eventIndex, static_cast<float>(event->mLastSecond.mDataSend)));
|
||||
recv.push_back(DataPoint(eventIndex, static_cast<float>(event->mLastSecond.mDataReceived)));
|
||||
// Effective bytes sent and received (
|
||||
effectiveSend.push_back(DataPoint(eventIndex, static_cast<float>(event->mEffectiveLastSecond.mDataSend)));
|
||||
effectiveRecv.push_back(DataPoint(eventIndex, static_cast<float>(event->mEffectiveLastSecond.mDataReceived)));
|
||||
// Total packets send and received.
|
||||
pktSend.push_back(DataPoint(eventIndex, static_cast<float>(event->mLastSecond.mPacketSend)));
|
||||
pktRecv.push_back(DataPoint(eventIndex, static_cast<float>(event->mLastSecond.mPacketReceived)));
|
||||
// RTT
|
||||
rtt.push_back(DataPoint(eventIndex, event->mLastSecond.mRTT));
|
||||
// Loss
|
||||
loss.push_back(DataPoint(eventIndex, event->mLastSecond.mPacketLoss));
|
||||
|
||||
eventIndex++;
|
||||
}
|
||||
|
||||
SetupDualBytesChart(m_gui->sendRecvDataStrip, send, recv);
|
||||
SetupDualBytesChart(m_gui->effectiveSendRecvDataStrip, effectiveSend, effectiveRecv);
|
||||
SetupDualPacketChart(m_gui->packetSendRecvDataStrip, pktSend, pktRecv);
|
||||
SetupTimeChart(m_gui->rttDataStrip, rtt);
|
||||
}
|
||||
|
||||
void CarrierDataView::SetupDualBytesChart(StripChart::DataStrip* chart, const DataPointList& bytes0, const DataPointList& bytes1)
|
||||
{
|
||||
chart->Reset();
|
||||
AZ::s64 maxSend = GetLargestDataValue(bytes0);
|
||||
AZ::s64 maxRecv = GetLargestDataValue(bytes1);
|
||||
chart->AddAxis("Seconds", 0.0f, static_cast<float>(bytes0.size() > bytes1.size() ? bytes0.size() : bytes1.size()), false);
|
||||
chart->AddAxis("Bytes/second", 0.0f, (maxSend > maxRecv ? maxSend : maxRecv) * 1.2f, false);
|
||||
|
||||
int sendChannel = chart->AddChannel("Bytes0");
|
||||
int recvChannel = chart->AddChannel("Bytes1");
|
||||
chart->SetChannelColor(sendChannel, QColor(0, 255, 0));
|
||||
chart->SetChannelStyle(sendChannel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
chart->SetChannelColor(recvChannel, QColor(255, 0, 0));
|
||||
chart->SetChannelStyle(recvChannel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
|
||||
for (auto dataPoint = bytes0.begin(); dataPoint != bytes0.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(sendChannel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
|
||||
for (auto dataPoint = bytes1.begin(); dataPoint != bytes1.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(recvChannel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierDataView::SetupDualPacketChart(StripChart::DataStrip* chart, const DataPointList& packets0, const DataPointList& packets1)
|
||||
{
|
||||
chart->Reset();
|
||||
AZ::s64 maxSend = GetLargestDataValue(packets0);
|
||||
AZ::s64 maxRecv = GetLargestDataValue(packets1);
|
||||
chart->AddAxis("Seconds", 0.0f, static_cast<float>(packets0.size() > packets1.size() ? packets0.size() : packets1.size()), false);
|
||||
chart->AddAxis("Packets/second", 0.0f, (maxSend > maxRecv ? maxSend : maxRecv) * 1.2f, false);
|
||||
|
||||
int sendChannel = chart->AddChannel("Bytes0");
|
||||
int recvChannel = chart->AddChannel("Bytes1");
|
||||
chart->SetChannelColor(sendChannel, QColor(0, 255, 0));
|
||||
chart->SetChannelStyle(sendChannel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
chart->SetChannelColor(recvChannel, QColor(255, 0, 0));
|
||||
chart->SetChannelStyle(recvChannel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
|
||||
for (auto dataPoint = packets0.begin(); dataPoint != packets0.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(sendChannel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
|
||||
for (auto dataPoint = packets1.begin(); dataPoint != packets1.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(recvChannel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierDataView::SetupTimeChart(StripChart::DataStrip* chart, const DataPointList& time)
|
||||
{
|
||||
chart->Reset();
|
||||
|
||||
AZ::s64 maxRTT = GetLargestDataValue(time);
|
||||
chart->AddAxis("Seconds", 0.0f, static_cast<float>(time.size()), false);
|
||||
chart->AddAxis("Milliseconds", 0.0f, maxRTT * 1.2f);
|
||||
|
||||
int channel = chart->AddChannel("RTT");
|
||||
chart->SetChannelColor(channel, QColor(255, 0, 255));
|
||||
chart->SetChannelStyle(channel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
|
||||
for (auto dataPoint = time.begin(); dataPoint != time.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(channel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CarrierDataView::SetupPercentageChart(StripChart::DataStrip* chart, const DataPointList& percentage)
|
||||
{
|
||||
chart->Reset();
|
||||
|
||||
chart->AddAxis("Seconds", 0.0f, static_cast<float>(percentage.size()), false);
|
||||
chart->AddAxis("Percentage", 0.0f, 100.0f);
|
||||
|
||||
int channel = chart->AddChannel("Loss");
|
||||
chart->SetChannelColor(channel, QColor(255, 255, 255));
|
||||
chart->SetChannelStyle(channel, StripChart::Channel::STYLE_CONNECTED_LINE);
|
||||
|
||||
for (auto dataPoint = percentage.begin(); dataPoint != percentage.end(); dataPoint++)
|
||||
{
|
||||
chart->AddData(channel, 0, static_cast<float>(dataPoint->first), dataPoint->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CARRIER_DATAVIEW_H
|
||||
#define CARRIER_DATAVIEW_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
#include "Source/Driller/StripChart.hxx"
|
||||
#include "Source/Driller/DrillerOperationTelemetryEvent.h"
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CarrierDataView;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CarrierDataAggregator;
|
||||
|
||||
class CarrierDataView
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CarrierDataView, AZ::SystemAllocator, 0);
|
||||
CarrierDataView(FrameNumberType startFrame, FrameNumberType endFrame, const CarrierDataAggregator* aggr);
|
||||
virtual ~CarrierDataView();
|
||||
|
||||
// A data point is made up of a x and y value (first and second respectively)
|
||||
// which can be plotted onto a XY chart.
|
||||
typedef AZStd::pair<AZ::s64, float> DataPoint;
|
||||
typedef AZStd::vector<DataPoint> DataPointList;
|
||||
|
||||
public slots:
|
||||
void OnCurrentFilterChanged();
|
||||
|
||||
private:
|
||||
void SetupAllCharts(AZStd::string id,
|
||||
const CarrierDataAggregator* aggr,
|
||||
FrameNumberType startFrame,
|
||||
FrameNumberType endFrame);
|
||||
|
||||
void SetupDualBytesChart(StripChart::DataStrip* chart, const DataPointList& bytes0, const DataPointList& bytes1);
|
||||
void SetupDualPacketChart(StripChart::DataStrip* chart, const DataPointList& packets1, const DataPointList& packets2);
|
||||
void SetupTimeChart(StripChart::DataStrip* chart, const DataPointList& time);
|
||||
void SetupPercentageChart(StripChart::DataStrip* chart, const DataPointList& percentage);
|
||||
|
||||
const CarrierDataAggregator* mAggregator;
|
||||
FrameNumberType mStartFrame, mEndFrame;
|
||||
|
||||
DrillerWindowLifepsanTelemetry m_lifespanTelemetry;
|
||||
|
||||
// A QT widget defined in CarrierDataView.ui and compiled into ui_CarrierDataView.hpp.
|
||||
Ui::CarrierDataView* m_gui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,327 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CarrierDataView</class>
|
||||
<widget class="QDialog" name="CarrierDataView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>825</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Carrier Data View</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="Filter"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="StripChart::DataStrip" name="sendRecvDataStrip" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QLabel" name="SendLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>20</y>
|
||||
<width>111</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(0, 255, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Send</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="RecvLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>40</y>
|
||||
<width>111</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(255, 0, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Received</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="StripChart::DataStrip" name="effectiveSendRecvDataStrip" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QLabel" name="SendLabel_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>20</y>
|
||||
<width>141</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(0, 255, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>User Data Send</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="RecvLabel_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>40</y>
|
||||
<width>141</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(255, 0, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>User Data Received</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="StripChart::DataStrip" name="packetSendRecvDataStrip" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QLabel" name="SendLabel_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>20</y>
|
||||
<width>141</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(0, 255, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Packets Send</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="RecvLabel_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>40</y>
|
||||
<width>141</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(255, 0, 0); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Packets Received</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="StripChart::DataStrip" name="rttDataStrip" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QLabel" name="SendLabel_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>20</y>
|
||||
<width>181</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : rgb(255, 0, 255); }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Return Trip Time (Latency)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StripChart::DataStrip</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>../StripChart.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#ifndef DRILLER_CARRIER_CARRIEROPERATIONTELEMETRYEVENT_H
|
||||
#define DRILLER_CARRIER_CARRIEROPERATIONTELEMETRYEVENT_H
|
||||
|
||||
#include "Source/Telemetry/TelemetryEvent.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CarrierOperationTelemetryEvent
|
||||
: public Telemetry::TelemetryEvent
|
||||
{
|
||||
public:
|
||||
CarrierOperationTelemetryEvent()
|
||||
: Telemetry::TelemetryEvent("CarrierDataViewOperation")
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/ChannelConfigurationDialog.hxx"
|
||||
#include <Source/Driller/moc_ChannelConfigurationDialog.cpp>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
ChannelConfigurationDialog::ChannelConfigurationDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint);
|
||||
|
||||
QMargins margins(0, 0, 0, 0);
|
||||
setContentsMargins(margins);
|
||||
}
|
||||
|
||||
ChannelConfigurationDialog::~ChannelConfigurationDialog()
|
||||
{
|
||||
emit DialogClosed(this);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef PROFILER_CHANNELCONFIGURATIONDIALOG_H
|
||||
#define PROFILER_CHANNELCONFIGURATIONDIALOG_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class ChannelConfigurationDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ChannelConfigurationDialog,AZ::SystemAllocator,0);
|
||||
|
||||
ChannelConfigurationDialog(QWidget* parent = nullptr);
|
||||
~ChannelConfigurationDialog();
|
||||
|
||||
signals:
|
||||
|
||||
void DialogClosed(QDialog* dialog);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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 <Source/Driller/ChannelConfigurationWidget.hxx>
|
||||
#include <Source/Driller/moc_ChannelConfigurationWidget.cpp>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
///////////////////////////////
|
||||
// ChannelConfigurationWidget
|
||||
///////////////////////////////
|
||||
|
||||
ChannelConfigurationWidget::ChannelConfigurationWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef PROFILER_CHANNELCONFIGURATIONWIDGET_H
|
||||
#define PROFILER_CHANNELCONFIGURATIONWIDGET_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class ChannelConfigurationWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ChannelConfigurationWidget, AZ::SystemAllocator,0);
|
||||
|
||||
ChannelConfigurationWidget(QWidget* parent = nullptr);
|
||||
~ChannelConfigurationWidget() = default;
|
||||
|
||||
public slots:
|
||||
signals:
|
||||
void ConfigurationChanged();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,484 +0,0 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHANNEL_CONTROL_H
|
||||
#define CHANNEL_CONTROL_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "DrillerNetworkMessages.h"
|
||||
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
|
||||
// Generated Files
|
||||
#include <Source/Driller/ui_ChannelControl.h>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class ChannelConfigurationDialog;
|
||||
|
||||
/*
|
||||
Channel Control intermediates between one data Aggregator, the application's main window, and the renderer.
|
||||
This maintains state used by the renderer and passes changes both up and down via signal/slot.
|
||||
*/
|
||||
|
||||
class ChannelControl
|
||||
: public QWidget
|
||||
, private Ui::ChannelControl
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ChannelControl,AZ::SystemAllocator,0);
|
||||
ChannelControl( const char* channelName, AnnotationsProvider* ptrAnnotations, QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~ChannelControl(void);
|
||||
|
||||
struct
|
||||
{
|
||||
FrameNumberType m_EndFrame;
|
||||
FrameNumberType m_FramesInView;
|
||||
int m_ContractedHeight;
|
||||
FrameNumberType m_ScrubberFrame;
|
||||
FrameNumberType m_FrameOffset;
|
||||
FrameNumberType m_LoopBegin;
|
||||
FrameNumberType m_LoopEnd;
|
||||
} m_State;
|
||||
|
||||
bool m_isLive;
|
||||
|
||||
QList<QWidget*> m_OpenDrills;
|
||||
QList<QPoint> m_OpenDrillsPositions;
|
||||
|
||||
bool IsSetup() const;
|
||||
void SignalSetup();
|
||||
|
||||
bool IsActive() const;
|
||||
const AZStd::list< ChannelProfilerWidget* >& GetProfilers() const;
|
||||
|
||||
// Temporary solution, since eventually we'll want to display all of the information
|
||||
// we have at once. For now, since we can only have one. Get a "main" window.
|
||||
ChannelProfilerWidget* GetMainProfiler() const;
|
||||
ChannelProfilerWidget* AddAggregator(Aggregator* aggregator);
|
||||
bool RemoveAggregator(Aggregator* aggregator);
|
||||
|
||||
void SetAllProfilersEnabled(bool enabled);
|
||||
AZ::Crc32 GetChannelId() const;
|
||||
|
||||
void SetDataPointsInView( FrameNumberType count );
|
||||
void SetEndFrame( FrameNumberType frame );
|
||||
void SetSliderOffset( FrameNumberType frame );
|
||||
void SetLoopBegin( FrameNumberType frame );
|
||||
void SetLoopEnd( FrameNumberType frame );
|
||||
|
||||
bool IsInCaptureMode(CaptureMode captureMode) const;
|
||||
|
||||
public slots:
|
||||
void SetCaptureMode(CaptureMode captureMode);
|
||||
void OnContractedToggled( bool toggleState );
|
||||
void OnSuccessfulDrillDown(QWidget* drillerWidget);
|
||||
void SetScrubberFrame( FrameNumberType frame );
|
||||
void OnDrillDestroyed(QObject *drill);
|
||||
void OnShowCommand();
|
||||
void OnHideCommand();
|
||||
void OnRefreshView();
|
||||
void OnActivationChanged(ChannelProfilerWidget*,bool activated);
|
||||
void OnConfigureChannel();
|
||||
void OnDialogClosed(QDialog* dialog);
|
||||
|
||||
void OnConfigurationChanged();
|
||||
void OnNormalizedRangeChanged();
|
||||
|
||||
signals:
|
||||
|
||||
void OnCaptureModeChanged(CaptureMode captureMode);
|
||||
void RequestScrollToFrame( FrameNumberType frame );
|
||||
void InformOfMouseClick(Qt::MouseButton button, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseMove( FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseRelease(Qt::MouseButton button, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseWheel( FrameNumberType frame, int wheelAmount, FrameNumberType range, int modifiers );
|
||||
QWidget* DrillDownRequest(FrameNumberType atFrame);
|
||||
void OptionsRequest();
|
||||
void ExpandedContracted();
|
||||
|
||||
void AddConfigurationWidgets(QLayout* configurationLayout);
|
||||
|
||||
QString GetInspectionFileName() const;
|
||||
|
||||
private:
|
||||
|
||||
void ConnectProfilerWidget(ChannelProfilerWidget* profilerWidget);
|
||||
void ConfigureUI();
|
||||
|
||||
bool m_isSetup;
|
||||
|
||||
CaptureMode m_captureMode;
|
||||
AZ::Crc32 m_channelId;
|
||||
AZStd::list< ChannelProfilerWidget* > m_profilerWidgets;
|
||||
|
||||
ChannelConfigurationDialog* m_configurationDialog;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // CHANNEL_CONTROL_H
|
||||
@@ -1,218 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ChannelControl</class>
|
||||
<widget class="QWidget" name="ChannelControl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1023</width>
|
||||
<height>74</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="infoArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="channelName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configChannel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/driller/settings_icon</normaloff>:/driller/settings_icon</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="profilerFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="profilerLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Driller::ChannelDataView" name="channelDataView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::ChannelDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Source/Driller/ChannelDataView.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,870 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Math/MathUtils.h>
|
||||
|
||||
#include "ChannelDataView.hxx"
|
||||
#include <Source/Driller/moc_ChannelDataView.cpp>
|
||||
|
||||
#include "ChannelControl.hxx"
|
||||
#include "ChannelProfilerWidget.hxx"
|
||||
#include "DrillerAggregator.hxx"
|
||||
#include "Annotations/Annotations.hxx"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QToolTip>
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const int k_barHeight = 5;
|
||||
|
||||
////////////////////////
|
||||
// AggregatorDataPoint
|
||||
////////////////////////
|
||||
AggregatorDataPoint::AggregatorDataPoint()
|
||||
: m_isActive(true)
|
||||
, m_isShowingOverlay(false)
|
||||
, m_shouldOutline(false)
|
||||
{
|
||||
}
|
||||
|
||||
AggregatorDataPoint::AggregatorDataPoint(QRect rectangle, ChannelProfilerWidget* profilerWidget)
|
||||
: m_visualBlock(rectangle)
|
||||
, m_isActive(true)
|
||||
, m_isShowingOverlay(false)
|
||||
, m_shouldOutline(false)
|
||||
|
||||
{
|
||||
m_combinedProfilers.insert(profilerWidget);
|
||||
}
|
||||
|
||||
void AggregatorDataPoint::Draw(QPainter& painter, int leftEdge, float barWidth)
|
||||
{
|
||||
QColor drawColor;
|
||||
QColor outlineColor;
|
||||
|
||||
m_isActive = false;
|
||||
|
||||
for (ChannelProfilerWidget* currentProfiler : m_combinedProfilers)
|
||||
{
|
||||
if (currentProfiler->IsActive())
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
drawColor = QColor(255, 255, 255);
|
||||
outlineColor = QColor(255, 255, 0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_isActive = true;
|
||||
drawColor = currentProfiler->GetAggregator()->GetColor();
|
||||
|
||||
// right now this should never be used. If it eventually is used, we'll probably
|
||||
// want to add a flow to the aggregators to pass along this color. For now
|
||||
// some silly wrapping to do something noticeable.
|
||||
outlineColor = QColor((drawColor.red() + 100) % 255, (drawColor.green() + 100) % 255, (drawColor.blue() + 100) % 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isActive)
|
||||
{
|
||||
const int upAmount = static_cast<int>(ceilf(k_barHeight * 0.5f));
|
||||
|
||||
int centerHeight = m_visualBlock.center().y();
|
||||
int topEdge = static_cast<int>(centerHeight - upAmount);
|
||||
|
||||
if (m_shouldOutline)
|
||||
{
|
||||
static const int k_outlineSize = 1;
|
||||
|
||||
painter.fillRect(
|
||||
leftEdge,
|
||||
topEdge,
|
||||
static_cast<int>(barWidth),
|
||||
k_barHeight,
|
||||
outlineColor);
|
||||
|
||||
painter.fillRect(
|
||||
leftEdge + k_outlineSize,
|
||||
(int)topEdge + k_outlineSize,
|
||||
(int)barWidth - (2 * k_outlineSize), // overdraw on dense data > 1 event per pixel, optimize later
|
||||
k_barHeight - (2 * k_outlineSize),
|
||||
drawColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(
|
||||
leftEdge,
|
||||
topEdge,
|
||||
static_cast<int>(barWidth),
|
||||
k_barHeight,
|
||||
drawColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AggregatorDataPoint::IntersectsDataPoint(const AggregatorDataPoint& dataPoint)
|
||||
{
|
||||
return m_visualBlock.intersects(dataPoint.m_visualBlock);
|
||||
}
|
||||
|
||||
bool AggregatorDataPoint::ContainsPoint(const QPoint& point)
|
||||
{
|
||||
// Don't want to collide if we aren't visible.
|
||||
if (m_isActive)
|
||||
{
|
||||
// Our Visual block's horizontal information is only valid when it is created.
|
||||
// After that we lazily update information, so the only valid information that the block maintins is the vertical.
|
||||
// So we're going to rely on the DataView to manage the horizontal collision, and we'll manage the vertical.
|
||||
return (m_visualBlock.bottom() > point.y() && m_visualBlock.top() <= point.y());
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AggregatorDataPoint::AddAggregatorDataPoint(const AggregatorDataPoint& dataPoint)
|
||||
{
|
||||
m_drawColor = QColor(255, 255, 255);
|
||||
|
||||
// dataPointBottomRight
|
||||
QPoint dpBR = dataPoint.m_visualBlock.bottomRight();
|
||||
|
||||
// dataPointTopLeft
|
||||
QPoint dpTL = dataPoint.m_visualBlock.topLeft();
|
||||
|
||||
// visualBlockBottomRight
|
||||
QPoint vbBR = m_visualBlock.bottomRight();
|
||||
|
||||
// visualBlockTopLeft
|
||||
QPoint vbTL = m_visualBlock.topLeft();
|
||||
|
||||
QPoint bottomRight(AZStd::GetMax(dpBR.x(), vbBR.x()), AZStd::GetMax(dpBR.y(), vbBR.y()));
|
||||
QPoint topLeft(AZStd::GetMin(dpTL.x(), vbTL.x()), AZStd::GetMin(dpTL.y(), vbTL.y()));
|
||||
|
||||
m_visualBlock = QRect(topLeft, bottomRight);
|
||||
|
||||
m_combinedProfilers.insert(dataPoint.m_combinedProfilers.begin(), dataPoint.m_combinedProfilers.end());
|
||||
}
|
||||
|
||||
bool AggregatorDataPoint::SetOverlayEnabled(bool enabled)
|
||||
{
|
||||
if (m_isShowingOverlay != enabled)
|
||||
{
|
||||
m_isShowingOverlay = enabled;
|
||||
|
||||
if (m_isShowingOverlay)
|
||||
{
|
||||
int activeProfilers = 0;
|
||||
QString toolTip = "Multiple Profiler(s)";
|
||||
|
||||
for (ChannelProfilerWidget* channelProfiler : m_combinedProfilers)
|
||||
{
|
||||
if (channelProfiler->IsActive())
|
||||
{
|
||||
++activeProfilers;
|
||||
toolTip.append(QString("<BR> - <I>%1</I>").arg(channelProfiler->GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
if (activeProfilers >= 2)
|
||||
{
|
||||
m_shouldOutline = true;
|
||||
|
||||
// Since QToolTip::HideText doesn't seem to actually do anything, I'm trying to show
|
||||
// a second tool tip while the first one is being displayed. However,
|
||||
// if I use the same string for the tool tip, it doesn't actually update the position.
|
||||
// But since the cursor has moved away from the original postion, it begins the countdown
|
||||
// timer to hide the tool tip. Meaning, the new tool tip I was trying to generate hides.
|
||||
// Going to alternatingly append a space to the end to force it to be different to
|
||||
// avoid this nonsense.
|
||||
{
|
||||
static bool k_dumbToolTipHack = false;
|
||||
if (k_dumbToolTipHack)
|
||||
{
|
||||
toolTip.append(" ");
|
||||
}
|
||||
|
||||
k_dumbToolTipHack = !k_dumbToolTipHack;
|
||||
}
|
||||
|
||||
QToolTip::showText(QCursor::pos(), toolTip);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shouldOutline = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shouldOutline = false;
|
||||
QToolTip::hideText();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// BudgetMarker
|
||||
/////////////////
|
||||
|
||||
BudgetMarker::BudgetMarker(float value, QColor& drawColor)
|
||||
: m_value(value)
|
||||
, m_drawColor(drawColor)
|
||||
{
|
||||
}
|
||||
|
||||
BudgetMarker::~BudgetMarker()
|
||||
{
|
||||
}
|
||||
|
||||
float BudgetMarker::GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const QColor& BudgetMarker::GetColor() const
|
||||
{
|
||||
return m_drawColor;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// ChannelDataView
|
||||
////////////////////
|
||||
ChannelDataView::ChannelDataView(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_Channel(nullptr)
|
||||
, m_ptrAnnotations(nullptr)
|
||||
, m_minFrame(-1)
|
||||
, m_maxFrame(-1)
|
||||
, m_highlightedFrame(-1)
|
||||
, m_lastFrame(0)
|
||||
, m_xOffset(0)
|
||||
, m_initializeDrag(false)
|
||||
, m_dragInitialized(false)
|
||||
, m_shouldIgnorePoint(false)
|
||||
, m_mouseGrabbed(false)
|
||||
, m_dirtyGraph(true)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
ChannelDataView::~ChannelDataView()
|
||||
{
|
||||
}
|
||||
|
||||
void ChannelDataView::RegisterToChannel(ChannelControl* channel, AnnotationsProvider* annotations)
|
||||
{
|
||||
m_Channel = channel;
|
||||
m_ptrAnnotations = annotations;
|
||||
}
|
||||
|
||||
int ChannelDataView::FrameToPosition(FrameNumberType frameNumber)
|
||||
{
|
||||
int localOffset = 0;
|
||||
FrameNumberType frameDifference = 0;
|
||||
|
||||
if (frameNumber < m_Channel->m_State.m_FrameOffset)
|
||||
{
|
||||
frameDifference = frameNumber - m_Channel->m_State.m_FrameOffset;
|
||||
}
|
||||
else if (frameNumber >= (m_Channel->m_State.m_FrameOffset + (m_Channel->m_State.m_FramesInView - 1)))
|
||||
{
|
||||
frameDifference = frameNumber - (m_Channel->m_State.m_FrameOffset + (m_Channel->m_State.m_FramesInView - 1));
|
||||
localOffset = rect().width();
|
||||
}
|
||||
|
||||
localOffset += static_cast<int>(GetBarWidth() * frameDifference);
|
||||
|
||||
return mapToGlobal(QPoint(localOffset, 0)).x();
|
||||
}
|
||||
|
||||
FrameNumberType ChannelDataView::PositionToFrame(const QPoint& pt)
|
||||
{
|
||||
QRect wrect = rect();
|
||||
|
||||
FrameNumberType frame = m_Channel->m_State.m_FrameOffset + m_Channel->m_State.m_FramesInView - 1;
|
||||
frame = frame <= m_Channel->m_State.m_EndFrame ? frame : m_Channel->m_State.m_EndFrame;
|
||||
|
||||
float pct = (float)pt.x() / (float)wrect.width();
|
||||
FrameNumberType rCell = m_Channel->m_State.m_FramesInView - 1 - (int)((float)m_Channel->m_State.m_FramesInView * pct);
|
||||
FrameNumberType retFrame = frame - rCell;
|
||||
|
||||
return retFrame;
|
||||
}
|
||||
|
||||
FrameNumberType ChannelDataView::FramesPerPixel()
|
||||
{
|
||||
FrameNumberType range = PositionToFrame(QPoint(0, 0)) - PositionToFrame(QPoint(1, 0));
|
||||
return(range > 0 ? range : 1);
|
||||
}
|
||||
|
||||
float ChannelDataView::GetBarWidth()
|
||||
{
|
||||
return ((float)(rect().width()) / (float)(m_Channel->m_State.m_FramesInView));
|
||||
}
|
||||
|
||||
void ChannelDataView::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
|
||||
if (m_dirtyGraph)
|
||||
{
|
||||
m_dirtyGraph = false;
|
||||
RecalculateGraphedPoints();
|
||||
}
|
||||
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
pen.setBrush(brush);
|
||||
|
||||
QPainter painter(this);
|
||||
|
||||
painter.setPen(pen);
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
|
||||
FrameNumberType frame = m_Channel->m_State.m_FrameOffset + m_Channel->m_State.m_FramesInView - 1;
|
||||
frame = frame <= m_Channel->m_State.m_EndFrame ? frame : m_Channel->m_State.m_EndFrame;
|
||||
|
||||
QRect wrect = rect();
|
||||
|
||||
float barWidth = GetBarWidth();
|
||||
int barWidthHalf = (int)(barWidth / 2.0f);
|
||||
float drawBarWidth = ((barWidth - 1.0f) < 1.0f ? 1.0f : (barWidth - 1.0f));
|
||||
|
||||
if (m_Channel->IsActive())
|
||||
{
|
||||
// PLAYBACK LOOP MARKERS
|
||||
if (m_Channel->m_State.m_LoopBegin >= frame - m_Channel->m_State.m_FramesInView)
|
||||
{
|
||||
float l = rect().right() - barWidth / 2.0f - 1 - barWidth * (frame - m_Channel->m_State.m_LoopBegin);
|
||||
painter.fillRect((int)l, 0, 2, rect().height(), QColor(255, 255, 0, 255));
|
||||
}
|
||||
if (m_Channel->m_State.m_LoopEnd >= frame - m_Channel->m_State.m_FramesInView)
|
||||
{
|
||||
float l = rect().right() - barWidth / 2.0f - 1 - barWidth * (frame - m_Channel->m_State.m_LoopEnd);
|
||||
painter.fillRect((int)l, 0, 2, rect().height(), QColor(255, 255, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
brush.setStyle(Qt::Dense2Pattern);
|
||||
brush.setColor(Qt::red);
|
||||
int wrectHeight = wrect.height() / (m_Channel->m_State.m_ContractedHeight ? 2 : 1);
|
||||
|
||||
if (m_Channel->IsActive() && m_Channel->m_State.m_EndFrame)
|
||||
{
|
||||
// SCRUBBER
|
||||
if (m_Channel->m_State.m_ScrubberFrame >= frame - m_Channel->m_State.m_FramesInView)
|
||||
{
|
||||
float l = rect().right()-GetBarWidth()/2.0f - 1 - GetBarWidth() * (frame - m_Channel->m_State.m_ScrubberFrame);
|
||||
painter.fillRect( (int)l, 0, 2, rect().height(), brush );
|
||||
}
|
||||
|
||||
float rightEdgeOfBar = (float)wrect.right();
|
||||
float leftEdgeOfBar = rightEdgeOfBar - barWidth;
|
||||
|
||||
AZStd::list< ChannelProfilerWidget* > activeProfilers;
|
||||
|
||||
for (ChannelProfilerWidget* profiler : m_Channel->GetProfilers())
|
||||
{
|
||||
if (profiler->IsActive())
|
||||
{
|
||||
activeProfilers.push_back(profiler);
|
||||
}
|
||||
}
|
||||
|
||||
while (frame >= 0 && rightEdgeOfBar >= wrect.left())
|
||||
{
|
||||
int actualLeftEdge = (int)floorf(leftEdgeOfBar);
|
||||
|
||||
// Graph out precomputed points.
|
||||
DataPointList& dataPointList = m_graphedPoints[frame];
|
||||
|
||||
for (AggregatorDataPoint& dataPoint : dataPointList)
|
||||
{
|
||||
dataPoint.Draw(painter, actualLeftEdge, drawBarWidth);
|
||||
}
|
||||
|
||||
// annotations?
|
||||
AnnotationsProvider::ConstAnnotationIterator it = m_ptrAnnotations->GetFirstAnnotationForFrame(frame);
|
||||
AnnotationsProvider::ConstAnnotationIterator endIt = m_ptrAnnotations->GetEnd();
|
||||
|
||||
if (it != endIt)
|
||||
{
|
||||
painter.fillRect(actualLeftEdge + barWidthHalf, 0, 1, wrectHeight, m_ptrAnnotations->GetColorForChannel(it->GetChannelCRC()));
|
||||
//++it;
|
||||
}
|
||||
|
||||
--frame;
|
||||
rightEdgeOfBar -= barWidth;
|
||||
leftEdgeOfBar -= barWidth;
|
||||
}
|
||||
|
||||
// Styling the budget markers.
|
||||
// Mildly ugly, but not a lot of pixels to work with
|
||||
// to make it look better.
|
||||
pen = QPen(Qt::black);
|
||||
pen.setWidth(1);
|
||||
|
||||
painter.setPen(pen);
|
||||
brush.setStyle(Qt::BrushStyle::SolidPattern);
|
||||
|
||||
// Budget Markers
|
||||
for (BudgetMarkerMap::value_type& mapPair : m_budgetMarkers)
|
||||
{
|
||||
BudgetMarker& budgetMarker = mapPair.second;
|
||||
|
||||
QColor drawColor = budgetMarker.GetColor();
|
||||
|
||||
int x = rect().left();
|
||||
float normalizedValue = ((budgetMarker.GetValue() + 1.0f) / 2.0f);
|
||||
int y = static_cast<int>(rect().bottom() - (rect().height() * normalizedValue));
|
||||
int width = rect().width();
|
||||
int height = 4;
|
||||
brush.setColor(drawColor);
|
||||
|
||||
// Want to make sure we always draw the entire box.
|
||||
if (y > rect().bottom() - height)
|
||||
{
|
||||
y = rect().bottom() - height;
|
||||
}
|
||||
|
||||
painter.fillRect(
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
brush);
|
||||
|
||||
painter.drawRect(
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelDataView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (m_Channel->IsInCaptureMode(CaptureMode::Capturing))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Channel->IsActive())
|
||||
{
|
||||
if (m_mouseGrabbed)
|
||||
{
|
||||
if (m_shouldIgnorePoint && event->globalPos() == m_centerPoint)
|
||||
{
|
||||
m_shouldIgnorePoint = false;
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint mousePoint = event->globalPos();
|
||||
int mouseDelta = (mousePoint.x() - m_centerPoint.x());
|
||||
|
||||
if (m_initializeDrag)
|
||||
{
|
||||
m_initializeDrag = false;
|
||||
m_dragInitialized = true;
|
||||
|
||||
QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||
|
||||
QRect screenGeometry = QApplication::primaryScreen()->geometry();
|
||||
m_centerPoint = screenGeometry.center();
|
||||
|
||||
mouseDelta = (mousePoint.x() - mapToGlobal(m_simulatedPoint).x());
|
||||
}
|
||||
|
||||
m_simulatedPoint.setX(m_simulatedPoint.x() + mouseDelta);
|
||||
|
||||
QPoint framePoint = m_simulatedPoint;
|
||||
framePoint.setX(framePoint.x() + m_xOffset);
|
||||
|
||||
FrameNumberType frame = PositionToFrame(framePoint);
|
||||
FrameNumberType framesPerPixel = FramesPerPixel();
|
||||
|
||||
// raw frame, sanitized by the controller
|
||||
emit InformOfMouseMove(frame, framesPerPixel, event->modifiers());
|
||||
event->ignore();
|
||||
|
||||
QRect boundingRect = rect();
|
||||
|
||||
m_shouldIgnorePoint = true;
|
||||
QCursor::setPos(m_centerPoint);
|
||||
m_xOffset += mouseDelta;
|
||||
|
||||
if (!boundingRect.contains(m_simulatedPoint))
|
||||
{
|
||||
m_simulatedPoint.setX(AZ::GetClamp(m_simulatedPoint.x(), boundingRect.left(), boundingRect.right()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_xOffset = 0;
|
||||
}
|
||||
|
||||
if (m_lastFrame != frame)
|
||||
{
|
||||
m_lastFrame = frame;
|
||||
|
||||
if (framesPerPixel == 1)
|
||||
{
|
||||
int barWidth = static_cast<int>(ceilf(GetBarWidth()));
|
||||
m_xOffset %= barWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_xOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't scroll beyond the minimum frame.
|
||||
if (m_lastFrame == 0 && m_xOffset < 0)
|
||||
{
|
||||
m_xOffset = 0;
|
||||
}
|
||||
// Can't scroll beyond the maximum frame.
|
||||
else if (m_lastFrame == m_Channel->m_State.m_EndFrame && m_xOffset > 0)
|
||||
{
|
||||
m_xOffset = 0;
|
||||
}
|
||||
}
|
||||
// If we aren't dragging, we need to deal with highlighting
|
||||
else
|
||||
{
|
||||
QPoint pos = event->localPos().toPoint();
|
||||
|
||||
// This guy expects relative position to parent. Not local space.
|
||||
FrameNumberType frameNumber = PositionToFrame(event->pos());
|
||||
|
||||
FramePointMapping::iterator dataPointIter = m_graphedPoints.find(frameNumber);
|
||||
|
||||
if (dataPointIter != m_graphedPoints.end())
|
||||
{
|
||||
if (frameNumber != m_highlightedFrame)
|
||||
{
|
||||
RemoveHighlight();
|
||||
}
|
||||
|
||||
bool needsUpdate = false;
|
||||
|
||||
DataPointList& dataPointList = dataPointIter->second;
|
||||
AggregatorDataPoint* overlayPoint = nullptr;
|
||||
|
||||
for (AggregatorDataPoint& dataPoint : dataPointList)
|
||||
{
|
||||
if (dataPoint.ContainsPoint(pos))
|
||||
{
|
||||
m_highlightedFrame = frameNumber;
|
||||
overlayPoint = &dataPoint;
|
||||
}
|
||||
else if (dataPoint.SetOverlayEnabled(false))
|
||||
{
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayPoint)
|
||||
{
|
||||
if (overlayPoint->SetOverlayEnabled(true))
|
||||
{
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_highlightedFrame = -1;
|
||||
}
|
||||
|
||||
if (needsUpdate)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveHighlight();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelDataView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!m_Channel->IsInCaptureMode(CaptureMode::Capturing) && m_Channel->IsActive())
|
||||
{
|
||||
emit InformOfMouseClick(event->button(), PositionToFrame(event->pos()), FramesPerPixel(), event->modifiers());
|
||||
event->ignore();
|
||||
|
||||
// Only want to perform dragging actions on left clicks.
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
grabMouse();
|
||||
|
||||
m_initializeDrag = true;
|
||||
m_simulatedPoint = event->pos();
|
||||
|
||||
m_mouseGrabbed = true;
|
||||
m_xOffset = 0;
|
||||
|
||||
m_lastFrame = m_Channel->m_State.m_ScrubberFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelDataView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!m_Channel->IsInCaptureMode(CaptureMode::Capturing) && m_Channel->IsActive())
|
||||
{
|
||||
if (m_mouseGrabbed)
|
||||
{
|
||||
FrameNumberType frame = PositionToFrame(m_simulatedPoint);
|
||||
emit InformOfMouseRelease(event->button(), frame, FramesPerPixel(), event->modifiers());
|
||||
event->ignore();
|
||||
|
||||
m_mouseGrabbed = false;
|
||||
|
||||
if (m_dragInitialized)
|
||||
{
|
||||
m_shouldIgnorePoint = true;
|
||||
|
||||
QCursor::setPos(mapToGlobal(m_simulatedPoint));
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
releaseMouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelDataView::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
if (event->angleDelta().y() == 0)
|
||||
{
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
emit InformOfMouseWheel(PositionToFrame(event->position().toPoint()), event->angleDelta().y(), FramesPerPixel(), event->modifiers());
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void ChannelDataView::leaveEvent(QEvent* event)
|
||||
{
|
||||
(void)event;
|
||||
RemoveHighlight();
|
||||
}
|
||||
|
||||
void ChannelDataView::DirtyGraphData()
|
||||
{
|
||||
m_dirtyGraph = true;
|
||||
}
|
||||
|
||||
void ChannelDataView::RefreshGraphData()
|
||||
{
|
||||
for (ChannelProfilerWidget* profilerWidget : m_Channel->GetProfilers())
|
||||
{
|
||||
profilerWidget->GetAggregator()->AnnotateChannelView(this);
|
||||
}
|
||||
|
||||
m_graphedPoints.clear();
|
||||
DirtyGraphData();
|
||||
update();
|
||||
}
|
||||
|
||||
BudgetMarkerTicket ChannelDataView::AddBudgetMarker(float value, QColor color)
|
||||
{
|
||||
++m_budgetMarkerCounter;
|
||||
|
||||
if (m_budgetMarkerCounter == 0 || m_budgetMarkers.find(m_budgetMarkerCounter) != m_budgetMarkers.end())
|
||||
{
|
||||
BudgetMarkerTicket startTicket = m_budgetMarkerCounter;
|
||||
|
||||
do
|
||||
{
|
||||
++m_budgetMarkerCounter;
|
||||
} while ((m_budgetMarkerCounter == 0 || m_budgetMarkers.find(m_budgetMarkerCounter) != m_budgetMarkers.end()) && m_budgetMarkerCounter != startTicket);
|
||||
|
||||
AZ_Assert(m_budgetMarkers.find(m_budgetMarkerCounter) == m_budgetMarkers.end(),"Ran out of tickets inside of budget marker creation.");
|
||||
}
|
||||
|
||||
m_budgetMarkers.insert(BudgetMarkerMap::value_type(m_budgetMarkerCounter, BudgetMarker(value, color)));
|
||||
return m_budgetMarkerCounter;
|
||||
}
|
||||
|
||||
void ChannelDataView::RemoveBudgetMarker(BudgetMarkerTicket ticket)
|
||||
{
|
||||
m_budgetMarkers.erase(ticket);
|
||||
}
|
||||
|
||||
void ChannelDataView::resizeEvent(QResizeEvent* newSize)
|
||||
{
|
||||
QWidget::resizeEvent(newSize);
|
||||
|
||||
// Graph data relies on the size of the graph, so we need to update it whenever we resize.
|
||||
DirtyGraphData();
|
||||
}
|
||||
|
||||
void ChannelDataView::RecalculateGraphedPoints()
|
||||
{
|
||||
FrameNumberType frame = m_Channel->m_State.m_FrameOffset + m_Channel->m_State.m_FramesInView - 1;
|
||||
frame = AZ::GetMin(frame, m_Channel->m_State.m_EndFrame);
|
||||
|
||||
QRect wrect = rect();
|
||||
int wrectHeight = wrect.height() / (m_Channel->m_State.m_ContractedHeight ? 2 : 1);
|
||||
|
||||
float barWidth = GetBarWidth();
|
||||
|
||||
if (m_Channel->m_State.m_EndFrame)
|
||||
{
|
||||
float vRange = (float)(wrectHeight - k_barHeight);
|
||||
float half = vRange / 2.0f;
|
||||
|
||||
float rectBarWidth = (barWidth < 1.0f ? 1.0f : barWidth);
|
||||
|
||||
float rightEdgeOfBar = (float)wrect.right();
|
||||
float leftEdgeOfBar = rightEdgeOfBar - barWidth;
|
||||
|
||||
FrameNumberType newMax = frame;
|
||||
|
||||
while (frame >= 0 && rightEdgeOfBar >= wrect.left())
|
||||
{
|
||||
// If the frame is a new frame we need to parse it's data.
|
||||
if (m_graphedPoints.find(frame) == m_graphedPoints.end())
|
||||
{
|
||||
int actualLeftEdge = (int)floorf(leftEdgeOfBar);
|
||||
int actualWidth = (int)floorf(rectBarWidth - 1.0f);
|
||||
|
||||
if (actualWidth < 1)
|
||||
{
|
||||
actualWidth = 1;
|
||||
}
|
||||
|
||||
AZStd::list<AggregatorDataPoint> dataPoints;
|
||||
|
||||
for (ChannelProfilerWidget* currentProfiler : m_Channel->GetProfilers())
|
||||
{
|
||||
float vaf = currentProfiler->GetAggregator()->ValueAtFrame(frame);
|
||||
int topOfBar = (int)(half - (vaf * half));
|
||||
|
||||
QRect drawRect(actualLeftEdge, topOfBar, actualWidth, k_barHeight);
|
||||
|
||||
dataPoints.emplace_back(drawRect, currentProfiler);
|
||||
}
|
||||
|
||||
while (!dataPoints.empty())
|
||||
{
|
||||
AggregatorDataPoint currentPoint = dataPoints.front();
|
||||
dataPoints.pop_front();
|
||||
|
||||
bool intersected = false;
|
||||
AZStd::list<AggregatorDataPoint>::iterator aggregatorIter = dataPoints.begin();
|
||||
|
||||
do
|
||||
{
|
||||
intersected = false;
|
||||
aggregatorIter = dataPoints.begin();
|
||||
|
||||
while (aggregatorIter != dataPoints.end())
|
||||
{
|
||||
if (currentPoint.IntersectsDataPoint((*aggregatorIter)))
|
||||
{
|
||||
intersected = true;
|
||||
currentPoint.AddAggregatorDataPoint((*aggregatorIter));
|
||||
aggregatorIter = dataPoints.erase(aggregatorIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++aggregatorIter;
|
||||
}
|
||||
}
|
||||
} while (intersected);
|
||||
|
||||
m_graphedPoints[frame].push_back(currentPoint);
|
||||
}
|
||||
}
|
||||
|
||||
--frame;
|
||||
rightEdgeOfBar -= barWidth;
|
||||
leftEdgeOfBar -= barWidth;
|
||||
}
|
||||
|
||||
FrameNumberType newMin = AZ::GetMax(0, frame + 1);
|
||||
|
||||
if (m_minFrame >= 0)
|
||||
{
|
||||
while (m_minFrame < newMin)
|
||||
{
|
||||
m_graphedPoints.erase(m_minFrame);
|
||||
++m_minFrame;
|
||||
}
|
||||
}
|
||||
|
||||
m_minFrame = newMin;
|
||||
|
||||
if (m_maxFrame >= 0)
|
||||
{
|
||||
while (m_maxFrame >= 0 && m_maxFrame > newMax)
|
||||
{
|
||||
m_graphedPoints.erase(m_maxFrame);
|
||||
--m_maxFrame;
|
||||
}
|
||||
}
|
||||
|
||||
m_maxFrame = newMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_minFrame = -1;
|
||||
m_maxFrame = -1;
|
||||
m_graphedPoints.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelDataView::RemoveHighlight()
|
||||
{
|
||||
if (m_highlightedFrame >= 0)
|
||||
{
|
||||
FramePointMapping::iterator dataPointIter = m_graphedPoints.find(m_highlightedFrame);
|
||||
|
||||
if (dataPointIter != m_graphedPoints.end())
|
||||
{
|
||||
bool needsUpdate = false;
|
||||
DataPointList& dataPointList = dataPointIter->second;
|
||||
|
||||
for (AggregatorDataPoint& dataPoint : dataPointList)
|
||||
{
|
||||
needsUpdate = dataPoint.SetOverlayEnabled(false) || needsUpdate;
|
||||
}
|
||||
|
||||
if (needsUpdate)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
m_highlightedFrame = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHANNEL_DATA_VIEW_H
|
||||
#define CHANNEL_DATA_VIEW_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AnnotationsProvider;
|
||||
class ChannelControl;
|
||||
class ChannelDataView;
|
||||
class ChannelProfilerWidget;
|
||||
class Aggregator;
|
||||
|
||||
class AggregatorDataPoint
|
||||
{
|
||||
public:
|
||||
AggregatorDataPoint();
|
||||
AggregatorDataPoint(QRect rectangle,ChannelProfilerWidget* profiler);
|
||||
|
||||
void Draw(QPainter& painter, int leftEdge, float barWidth);
|
||||
bool ContainsPoint(const QPoint& point);
|
||||
|
||||
bool IntersectsDataPoint(const AggregatorDataPoint& dataPoint);
|
||||
void AddAggregatorDataPoint(const AggregatorDataPoint& dataPoint);
|
||||
|
||||
bool SetOverlayEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
|
||||
bool m_isActive;
|
||||
bool m_isShowingOverlay;
|
||||
bool m_shouldOutline;
|
||||
QColor m_drawColor;
|
||||
QRect m_visualBlock;
|
||||
|
||||
AZStd::unordered_set< ChannelProfilerWidget* > m_combinedProfilers;
|
||||
};
|
||||
|
||||
class BudgetMarker
|
||||
{
|
||||
public:
|
||||
BudgetMarker(float value, QColor& drawColor);
|
||||
~BudgetMarker();
|
||||
|
||||
float GetValue() const;
|
||||
const QColor& GetColor() const;
|
||||
|
||||
private:
|
||||
|
||||
float m_value;
|
||||
QColor m_drawColor;
|
||||
};
|
||||
|
||||
typedef unsigned int BudgetMarkerTicket;
|
||||
|
||||
/*
|
||||
Channel Data View handles all rendering of the scrolling data graph.
|
||||
To do this it caches pointer access to its owning Channel
|
||||
and pulls state information directly from there.
|
||||
|
||||
Mouse events are passed upwards to its owning Channel via signal/slot.
|
||||
*/
|
||||
|
||||
class ChannelDataView : public QWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ChannelDataView, AZ::SystemAllocator, 0);
|
||||
ChannelDataView( QWidget* parent = nullptr );
|
||||
|
||||
virtual ~ChannelDataView();
|
||||
|
||||
void RegisterToChannel(ChannelControl* channel, AnnotationsProvider* annotations);
|
||||
|
||||
QPainter *m_Painter;
|
||||
ChannelControl *m_Channel;
|
||||
AnnotationsProvider *m_ptrAnnotations;
|
||||
|
||||
int FrameToPosition(FrameNumberType frameNumber);
|
||||
FrameNumberType PositionToFrame( const QPoint &pt );
|
||||
FrameNumberType FramesPerPixel();
|
||||
|
||||
float GetBarWidth();
|
||||
|
||||
virtual void paintEvent( QPaintEvent *event );
|
||||
virtual void mouseMoveEvent( QMouseEvent *event );
|
||||
virtual void mousePressEvent( QMouseEvent *event );
|
||||
virtual void mouseReleaseEvent( QMouseEvent *event );
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
virtual void leaveEvent( QEvent* event );
|
||||
|
||||
void DirtyGraphData();
|
||||
void RefreshGraphData();
|
||||
|
||||
BudgetMarkerTicket AddBudgetMarker(float value, QColor color);
|
||||
void RemoveBudgetMarker(BudgetMarkerTicket ticket);
|
||||
|
||||
signals:
|
||||
void InformOfMouseClick(Qt::MouseButton button, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseMove( FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseRelease(Qt::MouseButton button, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void InformOfMouseWheel( FrameNumberType frame, int wheelAmount, FrameNumberType range, int modifiers );
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
|
||||
void RecalculateGraphedPoints();
|
||||
void RemoveHighlight();
|
||||
|
||||
typedef AZStd::list< AggregatorDataPoint > DataPointList;
|
||||
typedef AZStd::unordered_map<FrameNumberType, DataPointList > FramePointMapping;
|
||||
|
||||
typedef AZStd::unordered_map<BudgetMarkerTicket, BudgetMarker > BudgetMarkerMap;
|
||||
|
||||
BudgetMarkerTicket m_budgetMarkerCounter;
|
||||
BudgetMarkerMap m_budgetMarkers;
|
||||
|
||||
FramePointMapping m_graphedPoints;
|
||||
AZStd::list< ChannelProfilerWidget* > m_profilerWidgets;
|
||||
|
||||
FrameNumberType m_minFrame;
|
||||
FrameNumberType m_maxFrame;
|
||||
FrameNumberType m_highlightedFrame;
|
||||
|
||||
FrameNumberType m_lastFrame;
|
||||
int m_xOffset;
|
||||
|
||||
bool m_initializeDrag;
|
||||
bool m_dragInitialized;
|
||||
|
||||
bool m_shouldIgnorePoint;
|
||||
|
||||
QPoint m_simulatedPoint;
|
||||
QPoint m_centerPoint;
|
||||
|
||||
bool m_mouseGrabbed;
|
||||
bool m_dirtyGraph;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // CHANNEL_DATA_VIEW_H
|
||||
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/ChannelProfilerWidget.hxx"
|
||||
#include <Source/Driller/moc_ChannelProfilerWidget.cpp>
|
||||
|
||||
#include "Source/Driller/DrillerAggregator.hxx"
|
||||
#include "Source/Driller/ChannelControl.hxx"
|
||||
#include "Source/Driller/CollapsiblePanel.hxx"
|
||||
#include "Source/Driller/CustomizeCSVExportWidget.hxx"
|
||||
#include "Source/Driller/DrillerOperationTelemetryEvent.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QColor>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
void ColorizeIcon(QIcon& icon, const char* iconPath, Aggregator* aggregator)
|
||||
{
|
||||
QImage alphaImage(iconPath);
|
||||
alphaImage = alphaImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QImage colorizedImage(alphaImage.width(), alphaImage.height(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QColor color = aggregator->GetColor();
|
||||
color.setAlphaF(1.0f);
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(&colorizedImage);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.fillRect(colorizedImage.rect(), color);
|
||||
painter.end();
|
||||
|
||||
colorizedImage.setAlphaChannel(alphaImage);
|
||||
|
||||
icon.addPixmap(QPixmap::fromImage(colorizedImage));
|
||||
}
|
||||
|
||||
ChannelProfilerWidget::ChannelProfilerWidget(ChannelControl* channelControl, Aggregator* aggregator)
|
||||
: QWidget(channelControl)
|
||||
, m_channelControl(channelControl)
|
||||
, m_drilledWidget(nullptr)
|
||||
, m_aggregator(aggregator)
|
||||
, m_captureMode(CaptureMode::Unknown)
|
||||
, m_isActive(true)
|
||||
, m_activeIcon()
|
||||
, m_inactiveIcon()
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
connect(this, SIGNAL(DrillDownRequest(FrameNumberType)), m_aggregator, SLOT(DrillDownRequest(FrameNumberType)));
|
||||
connect(this, SIGNAL(ExportToCSVRequest(const char*, CSVExportSettings*)), m_aggregator, SLOT(ExportToCSVRequest(const char*, CSVExportSettings*)));
|
||||
|
||||
connect(m_aggregator, SIGNAL(GetInspectionFileName()), m_channelControl, SIGNAL(GetInspectionFileName()));
|
||||
|
||||
connect(profilerName, SIGNAL(clicked()), this, SLOT(OnActivationToggled()));
|
||||
connect(enableChannel, SIGNAL(clicked()), this, SLOT(OnActivationToggled()));
|
||||
//connect(channelOptions,SIGNAL(clicked()),this, SLOT(OnConfigureChannel()));
|
||||
connect(drillDown, SIGNAL(clicked()), this, SLOT(OnDrillDown()));
|
||||
connect(exportData, SIGNAL(clicked()), this, SLOT(OnExportToCSV()));
|
||||
|
||||
ColorizeIcon(m_activeIcon, ":/driller/active_color_swatch", aggregator);
|
||||
ColorizeIcon(m_inactiveIcon, ":/driller/inactive_color_swatch", aggregator);
|
||||
|
||||
profilerName->setToolTip(aggregator->GetToolTip());
|
||||
profilerName->setText(GetName());
|
||||
|
||||
UpdateActivationIcon();
|
||||
ConfigureUI();
|
||||
}
|
||||
|
||||
ChannelProfilerWidget::~ChannelProfilerWidget()
|
||||
{
|
||||
}
|
||||
|
||||
Aggregator* ChannelProfilerWidget::GetAggregator() const
|
||||
{
|
||||
return m_aggregator;
|
||||
}
|
||||
|
||||
bool ChannelProfilerWidget::IsActive() const
|
||||
{
|
||||
return m_isActive;
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::SetIsActive(bool isActive)
|
||||
{
|
||||
if (m_isActive != isActive)
|
||||
{
|
||||
m_isActive = isActive;
|
||||
UpdateActivationIcon();
|
||||
|
||||
if (m_aggregator && m_captureMode == Driller::CaptureMode::Configuration)
|
||||
{
|
||||
m_aggregator->EnableCapture(isActive);
|
||||
}
|
||||
|
||||
emit OnActivationChanged(this, m_isActive);
|
||||
}
|
||||
}
|
||||
|
||||
QString ChannelProfilerWidget::GetName() const
|
||||
{
|
||||
return (m_aggregator ? m_aggregator->GetName() : "Unknown Profiler");
|
||||
}
|
||||
|
||||
AZ::Uuid ChannelProfilerWidget::GetID()
|
||||
{
|
||||
return (m_aggregator ? m_aggregator->GetID() : AZ::Uuid::CreateNull());
|
||||
}
|
||||
|
||||
ChannelConfigurationWidget* ChannelProfilerWidget::CreateConfigurationWidget()
|
||||
{
|
||||
ChannelConfigurationWidget* configurationWidget = nullptr;
|
||||
|
||||
if (m_aggregator)
|
||||
{
|
||||
configurationWidget = m_aggregator->CreateConfigurationWidget();
|
||||
}
|
||||
|
||||
return configurationWidget;
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::OnActivationToggled()
|
||||
{
|
||||
SetIsActive(!IsActive());
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::SetCaptureMode(CaptureMode captureMode)
|
||||
{
|
||||
if (m_captureMode != captureMode)
|
||||
{
|
||||
m_captureMode = captureMode;
|
||||
|
||||
ConfigureUI();
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::OnDrillDown()
|
||||
{
|
||||
if (m_channelControl && IsInCaptureMode(CaptureMode::Inspecting))
|
||||
{
|
||||
char traceStr[AZ::Uuid::MaxStringBuffer];
|
||||
m_aggregator->GetID().ToString(traceStr, AZ_ARRAY_SIZE(traceStr));
|
||||
AZ_TracePrintf("Driller", "Drill Down ID = %s\n", traceStr);
|
||||
|
||||
if (m_drilledWidget == nullptr)
|
||||
{
|
||||
m_drilledWidget = emit DrillDownRequest(m_channelControl->m_State.m_ScrubberFrame);
|
||||
if (m_drilledWidget)
|
||||
{
|
||||
connect(m_drilledWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnDrillDestroyed(QObject*)));
|
||||
emit OnSuccessfulDrillDown(m_drilledWidget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_drilledWidget->isMinimized())
|
||||
{
|
||||
m_drilledWidget->showNormal();
|
||||
}
|
||||
|
||||
m_drilledWidget->raise();
|
||||
m_drilledWidget->activateWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::OnDrillDestroyed(QObject* widget)
|
||||
{
|
||||
if (widget == m_drilledWidget)
|
||||
{
|
||||
m_drilledWidget = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::OnExportToCSV()
|
||||
{
|
||||
DrillerOperationTelemetryEvent exportToCSVEvent;
|
||||
exportToCSVEvent.SetAttribute("ExportToCSV", m_aggregator->GetName().toStdString().c_str());
|
||||
exportToCSVEvent.Log();
|
||||
|
||||
char traceStr[AZ::Uuid::MaxStringBuffer];
|
||||
m_aggregator->GetID().ToString(traceStr, AZ_ARRAY_SIZE(traceStr));
|
||||
AZ_TracePrintf("Driller", "Export Request for ID = %s\n", traceStr);
|
||||
|
||||
QFileDialog fileDialog;
|
||||
|
||||
CustomizeCSVExportWidget* customizeWidget = m_aggregator->CreateCSVExportCustomizationWidget();
|
||||
|
||||
// Always use the Qt dialog for consistency
|
||||
fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
|
||||
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
fileDialog.setWindowTitle(QString("Export %1 To CSV").arg(m_aggregator->GetName()));
|
||||
fileDialog.setNameFilter("CSV (*.csv)");
|
||||
fileDialog.setDefaultSuffix("csv");
|
||||
|
||||
if (customizeWidget)
|
||||
{
|
||||
CollapsiblePanel* collapsiblePanel = aznew CollapsiblePanel(&fileDialog);
|
||||
|
||||
collapsiblePanel->SetTitle("Customize");
|
||||
collapsiblePanel->SetContent(customizeWidget);
|
||||
|
||||
// I don't know why the decided to use a GridLayout here instead of nested layouts. But whatever.
|
||||
QGridLayout* gridLayout = static_cast<QGridLayout*>(fileDialog.layout());
|
||||
int numRows = gridLayout->rowCount();
|
||||
|
||||
gridLayout->addWidget(collapsiblePanel, numRows, 0, 1, gridLayout->columnCount());
|
||||
}
|
||||
|
||||
QString fileName;
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
QStringList fileList = fileDialog.selectedFiles();
|
||||
|
||||
for (const QString& file : fileList)
|
||||
{
|
||||
if (!file.isEmpty())
|
||||
{
|
||||
fileName = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
CSVExportSettings* exportSettings = nullptr;
|
||||
|
||||
if (customizeWidget)
|
||||
{
|
||||
customizeWidget->FinalizeSettings();
|
||||
exportSettings = customizeWidget->GetExportSettings();
|
||||
}
|
||||
|
||||
emit ExportToCSVRequest(fileName.toStdString().c_str(), exportSettings);
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelProfilerWidget::AllowCSVExport() const
|
||||
{
|
||||
return (m_aggregator ? m_aggregator->CanExportToCSV() : false);
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::UpdateActivationIcon()
|
||||
{
|
||||
if (IsActive())
|
||||
{
|
||||
enableChannel->setIcon(m_activeIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
enableChannel->setIcon(m_inactiveIcon);
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelProfilerWidget::IsInCaptureMode(CaptureMode captureMode) const
|
||||
{
|
||||
return m_captureMode == captureMode;
|
||||
}
|
||||
|
||||
void ChannelProfilerWidget::ConfigureUI()
|
||||
{
|
||||
switch (m_captureMode)
|
||||
{
|
||||
case CaptureMode::Configuration:
|
||||
enableChannel->setEnabled(true);
|
||||
drillDown->setVisible(false);
|
||||
exportData->setVisible(false);
|
||||
break;
|
||||
case CaptureMode::Capturing:
|
||||
enableChannel->setEnabled(false);
|
||||
drillDown->setVisible(false);
|
||||
exportData->setVisible(false);
|
||||
break;
|
||||
case CaptureMode::Inspecting:
|
||||
enableChannel->setEnabled(true);
|
||||
drillDown->setVisible(true);
|
||||
exportData->setVisible(AllowCSVExport());
|
||||
exportData->setEnabled(AllowCSVExport());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef DRILLER_CHANNELPROFILERWIDGET_H
|
||||
#define DRILLER_CHANNELPROFILERWIDGET_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "Source/Driller/DrillerDataTypes.h"
|
||||
|
||||
// Generated Files
|
||||
#include <Source/Driller/ui_ChannelProfilerWidget.h>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class Aggregator;
|
||||
class ChannelControl;
|
||||
class CSVExportSettings;
|
||||
class ChannelConfigurationWidget;
|
||||
|
||||
class ChannelProfilerWidget
|
||||
: public QWidget
|
||||
, private Ui::ChannelProfilerWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ChannelProfilerWidget, AZ::SystemAllocator,0);
|
||||
|
||||
ChannelProfilerWidget(ChannelControl* channelControl, Aggregator* aggregator);
|
||||
virtual ~ChannelProfilerWidget();
|
||||
|
||||
Aggregator* GetAggregator() const;
|
||||
|
||||
bool IsActive() const;
|
||||
void SetIsActive(bool isActive);
|
||||
|
||||
QString GetName() const;
|
||||
AZ::Uuid GetID();
|
||||
|
||||
ChannelConfigurationWidget* CreateConfigurationWidget();
|
||||
|
||||
public slots:
|
||||
void OnActivationToggled();
|
||||
void SetCaptureMode(CaptureMode mode);
|
||||
|
||||
void OnDrillDown();
|
||||
void OnDrillDestroyed(QObject* drill);
|
||||
|
||||
void OnExportToCSV();
|
||||
|
||||
signals:
|
||||
void OnActivationChanged(ChannelProfilerWidget*,bool activated);
|
||||
|
||||
QWidget* DrillDownRequest(FrameNumberType atFrame);
|
||||
void ExportToCSVRequest(const char* filename, CSVExportSettings* customizeWidget);
|
||||
|
||||
void OnSuccessfulDrillDown(QWidget* widget);
|
||||
|
||||
private:
|
||||
|
||||
bool AllowCSVExport() const;
|
||||
void UpdateActivationIcon();
|
||||
|
||||
bool IsInCaptureMode(CaptureMode captureMode) const;
|
||||
void ConfigureUI();
|
||||
|
||||
ChannelControl* m_channelControl;
|
||||
QWidget* m_drilledWidget;
|
||||
Aggregator* m_aggregator;
|
||||
|
||||
CaptureMode m_captureMode;
|
||||
bool m_isActive;
|
||||
|
||||
QImage m_inactiveImage;
|
||||
QImage m_activeImage;
|
||||
QIcon m_activeIcon;
|
||||
QIcon m_inactiveIcon;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,150 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ChannelProfilerWidget</class>
|
||||
<widget class="QWidget" name="ChannelProfilerWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>374</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ChannelProfilerWidget</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="enableChannel">
|
||||
<property name="toolTip">
|
||||
<string>Toggle this Profiler On/Off</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>12</width>
|
||||
<height>12</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzToolsFramework::ClickableLabel" name="profilerName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>13</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="exportData">
|
||||
<property name="toolTip">
|
||||
<string>Save to CSV</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/driller/export_button_enabled</normaloff>
|
||||
<disabledoff>:/driller/export_button_disabled</disabledoff>
|
||||
<disabledon>:/driller/export_button_disabled</disabledon>:/driller/export_button_enabled</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="drillDown">
|
||||
<property name="toolTip">
|
||||
<string>Detailed Profiling Information</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/driller/drill_down_enabled</normaloff>
|
||||
<disabledoff>:/driller/drill_down_disabled</disabledoff>
|
||||
<disabledon>:/driller/drill_down_disabled</disabledon>:/driller/drill_down_enabled</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::ClickableLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzToolsFramework/UI/UICore/ClickableLabel.hxx</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 "ChartNumberFormats.h"
|
||||
|
||||
namespace DrillerCharts
|
||||
{
|
||||
QString FriendlyFormat(AZ::s64 n)
|
||||
{
|
||||
QString str;
|
||||
|
||||
str = QString("%L1").arg(n);
|
||||
|
||||
//if (n < 0)
|
||||
//{
|
||||
// str = "-";
|
||||
//}
|
||||
|
||||
//AZ::s64 b = n / 1000000000l;
|
||||
//n %= 1000000000l;
|
||||
|
||||
//AZ::s64 m = n / 1000000l;
|
||||
//n %= 1000000l;
|
||||
|
||||
//AZ::s64 k = n / 1000l;
|
||||
//n %= 1000l;
|
||||
|
||||
//if (b)
|
||||
//{
|
||||
// str += QString("%0b").arg(abs(b));
|
||||
//}
|
||||
//if (m)
|
||||
//{
|
||||
// str += QString("%0m").arg(abs(m));
|
||||
//}
|
||||
//if (k)
|
||||
//{
|
||||
// str += QString("%0k").arg(abs(k));
|
||||
//}
|
||||
//if (n)
|
||||
//{
|
||||
// str += QString("%0").arg(abs(n));
|
||||
//}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHARTNUMBERFORMATS_H
|
||||
#define CHARTNUMBERFORMATS_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <QString>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace DrillerCharts
|
||||
{
|
||||
QString FriendlyFormat(AZ::s64 n);
|
||||
}
|
||||
|
||||
#endif //CHARTNUMBERFORMATS_H
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/ChartTypes.hxx"
|
||||
#include <Source/Driller/moc_ChartTypes.cpp>
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
QAbstractAxisFormatter::QAbstractAxisFormatter(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef PROFILER_CHARTTYPES_H
|
||||
#define PROFILER_CHARTTYPES_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QObject>
|
||||
#endif
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
enum class AxisType
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
};
|
||||
|
||||
// Plug this guy into the chart if you wish to custom format axes
|
||||
class QAbstractAxisFormatter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QAbstractAxisFormatter(QObject *pParent);
|
||||
|
||||
/** convertAxisValueToText
|
||||
* Expects you to return a QString with the value for the axis.
|
||||
* value : value it wants the label for.
|
||||
* minDisplayedValue : what value is at the bottom of the axis in the display
|
||||
* maxDisplayedValue : what value is at the top of this axis in the display
|
||||
* divisionSize : what each tickmark is, in domain units.
|
||||
* So for example, if the axis is from 938 to 2114 and its got a tickmark every 250, and it wants to know what you'd like it to draw for 1250
|
||||
* then you'll get Value = 1250, minDisplayedValue = 1000, maxDisplayedValue = 2000, divisionSize = 250.
|
||||
*/
|
||||
virtual QString convertAxisValueToText(AxisType axisType, float value, float minDisplayedValue, float maxDisplayedValue, float divisionSize) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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 "CollapsiblePanel.hxx"
|
||||
#include <Source/Driller/ui_CollapsiblePanel.h>
|
||||
#include <Source/Driller/moc_CollapsiblePanel.cpp>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
CollapsiblePanel::CollapsiblePanel(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_isCollapsed(false)
|
||||
, m_content(nullptr)
|
||||
, m_gui(nullptr)
|
||||
{
|
||||
m_gui = azcreate(Ui::CollapsiblePanel, ());
|
||||
m_gui->setupUi(this);
|
||||
|
||||
// Default to collapsed, need to initialize the variable to true to trigger the delta.
|
||||
SetCollapsed(true);
|
||||
|
||||
QObject::connect(m_gui->stateIcon, SIGNAL(clicked()), this, SLOT(OnClicked()));
|
||||
}
|
||||
|
||||
CollapsiblePanel::~CollapsiblePanel()
|
||||
{
|
||||
azdestroy(m_gui);
|
||||
m_gui = nullptr;
|
||||
}
|
||||
|
||||
void CollapsiblePanel::SetTitle(const QString& title)
|
||||
{
|
||||
m_gui->description->setText(title);
|
||||
}
|
||||
|
||||
void CollapsiblePanel::SetContent(QWidget* content)
|
||||
{
|
||||
if (m_content)
|
||||
{
|
||||
m_gui->contentLayout->removeWidget(content);
|
||||
m_content = nullptr;
|
||||
}
|
||||
|
||||
m_content = content;
|
||||
|
||||
if (m_content)
|
||||
{
|
||||
m_gui->contentLayout->addWidget(m_content);
|
||||
}
|
||||
}
|
||||
|
||||
void CollapsiblePanel::SetCollapsed(bool collapsed)
|
||||
{
|
||||
if (m_isCollapsed != collapsed)
|
||||
{
|
||||
m_isCollapsed = collapsed;
|
||||
|
||||
m_gui->groupBox->setVisible(!m_isCollapsed);
|
||||
|
||||
if (m_isCollapsed)
|
||||
{
|
||||
m_gui->stateIcon->setArrowType(Qt::RightArrow);
|
||||
emit Collapsed();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gui->stateIcon->setArrowType(Qt::DownArrow);
|
||||
emit Expanded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CollapsiblePanel::IsCollapsed() const
|
||||
{
|
||||
return m_isCollapsed;
|
||||
}
|
||||
|
||||
void CollapsiblePanel::OnClicked()
|
||||
{
|
||||
SetCollapsed(!m_isCollapsed);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_COLLAPSIBLEPANEL_H
|
||||
#define DRILLER_COLLAPSIBLEPANEL_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CollapsiblePanel;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CollapsiblePanel
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CollapsiblePanel, AZ::SystemAllocator, 0);
|
||||
|
||||
CollapsiblePanel(QWidget* parent = nullptr);
|
||||
~CollapsiblePanel();
|
||||
|
||||
void SetTitle(const QString& title);
|
||||
void SetContent(QWidget* content);
|
||||
|
||||
void SetCollapsed(bool collapsed);
|
||||
bool IsCollapsed() const;
|
||||
|
||||
public slots:
|
||||
void OnClicked();
|
||||
|
||||
signals:
|
||||
void Collapsed();
|
||||
void Expanded();
|
||||
|
||||
private:
|
||||
|
||||
bool m_isCollapsed;
|
||||
|
||||
QWidget* m_content;
|
||||
Ui::CollapsiblePanel* m_gui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CollapsiblePanel</class>
|
||||
<widget class="QWidget" name="CollapsiblePanel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>591</width>
|
||||
<height>421</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="stateIcon">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="description">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Panel Name ggggMMMWWWW</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="contentLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* 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 <QtWidgets/QGridLayout>
|
||||
|
||||
#include "CombinedEventsControl.hxx"
|
||||
#include <Source/Driller/moc_CombinedEventsControl.cpp>
|
||||
|
||||
#include "Annotations/AnnotationsHeaderView_Events.hxx"
|
||||
#include "Axis.hxx"
|
||||
#include "CollapsiblePanel.hxx"
|
||||
#include "ChannelDataView.hxx"
|
||||
#include "DrillerAggregator.hxx"
|
||||
#include "DrillerEvent.h"
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
using namespace Racetrack;
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static const int k_raceTrackMinSize = 50;
|
||||
static const int k_eventTrackSize = 20;
|
||||
|
||||
CombinedEventsControl::CombinedEventsControl(QWidget* parent, Qt::WindowFlags flags)
|
||||
: QDockWidget(parent, flags)
|
||||
{
|
||||
m_ScrubberIndex = 0;
|
||||
|
||||
m_FirstIndex = 0;
|
||||
m_LastIndex = 0;
|
||||
|
||||
QWidget* nullBar = new QWidget();
|
||||
setTitleBarWidget(nullBar);
|
||||
|
||||
setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
setAllowedAreas(Qt::BottomDockWidgetArea);
|
||||
|
||||
m_collapsiblePanel = new CollapsiblePanel(this);
|
||||
this->setWidget(m_collapsiblePanel);
|
||||
|
||||
m_Contents = new QWidget(this);
|
||||
m_Contents->setGeometry(0, 22, 542, 34);
|
||||
m_Contents->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(2);
|
||||
|
||||
m_Contents->setLayout(layout);
|
||||
m_collapsiblePanel->SetContent(m_Contents);
|
||||
m_collapsiblePanel->SetTitle("Detailed Event View");
|
||||
|
||||
m_EventTrack = aznew CEQDataTrack(this);
|
||||
m_EventTrack->SetupAxis("", 0.0f, 1.0f, false);
|
||||
m_EventTrack->SetMarkerColor(Qt::darkMagenta);
|
||||
m_EventTrack->setMinimumHeight(k_raceTrackMinSize);
|
||||
|
||||
m_annotationHeaderView = aznew AnnotationHeaderView_Events(this);
|
||||
|
||||
m_Contents->layout()->addWidget(m_annotationHeaderView);
|
||||
m_Contents->layout()->addWidget(m_EventTrack);
|
||||
|
||||
m_EventTrack->installEventFilter(this);
|
||||
|
||||
connect(m_EventTrack, SIGNAL(EventRequestEventFocus(Driller::EventNumberType)), this, SLOT(OnEventTrackRequestEventFocus(Driller::EventNumberType)));
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SetIdentity(int identity)
|
||||
{
|
||||
m_identity = identity;
|
||||
DrillerEventWindowMessages::Handler::BusConnect(m_identity);
|
||||
}
|
||||
|
||||
bool CombinedEventsControl::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize)
|
||||
{
|
||||
if (obj == m_EventTrack)
|
||||
{
|
||||
QRect eventTrackGeometry = m_EventTrack->geometry();
|
||||
QSize actualSize = QSize(eventTrackGeometry.x(), eventTrackGeometry.height());
|
||||
emit InfoAreaGeometryChanged(actualSize);
|
||||
}
|
||||
}
|
||||
|
||||
// hand it to the owner
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
Charts::Axis* CombinedEventsControl::GetAxis() const
|
||||
{
|
||||
return m_EventTrack->GetAxis();
|
||||
}
|
||||
|
||||
|
||||
CombinedEventsControl::~CombinedEventsControl()
|
||||
{
|
||||
DrillerEventWindowMessages::Handler::BusDisconnect(m_identity);
|
||||
|
||||
if (m_EventTrack)
|
||||
{
|
||||
delete m_EventTrack;
|
||||
}
|
||||
}
|
||||
|
||||
void CombinedEventsControl::ClearAggregatorList()
|
||||
{
|
||||
m_Aggregators.clear();
|
||||
m_EventTrack->Clear();
|
||||
m_EventTrack->setMinimumHeight(k_raceTrackMinSize);
|
||||
|
||||
m_ScrubberIndex = 0;
|
||||
m_FirstIndex = 0;
|
||||
m_LastIndex = 0;
|
||||
}
|
||||
|
||||
void CombinedEventsControl::AddAggregatorList(DrillerNetworkMessages::AggregatorList& theList)
|
||||
{
|
||||
// m_EventStrip clear all existing channels and the channel axis
|
||||
m_EventTrack->Clear();
|
||||
for (DrillerNetworkMessages::AggregatorList::iterator iter = theList.begin(); iter != theList.end(); ++iter)
|
||||
{
|
||||
m_Aggregators.push_back(*iter);
|
||||
|
||||
int channelID = m_EventTrack->AddChannel((*iter)->GetName());
|
||||
m_EventTrack->SetChannelColor(channelID, (*iter)->GetColor());
|
||||
}
|
||||
|
||||
m_EventTrack->setMinimumHeight(k_raceTrackMinSize + static_cast<int>(m_Aggregators.size()) * k_eventTrackSize);
|
||||
}
|
||||
void CombinedEventsControl::AddAggregator(Aggregator& theAggregator)
|
||||
{
|
||||
m_Aggregators.push_back(&theAggregator);
|
||||
|
||||
int channelID = m_EventTrack->AddChannel(theAggregator.GetName());
|
||||
m_EventTrack->SetChannelColor(channelID, theAggregator.GetColor());
|
||||
|
||||
m_EventTrack->setMinimumHeight(k_raceTrackMinSize + static_cast<int>(m_Aggregators.size()) * k_eventTrackSize);
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SetAnnotationsProvider(AnnotationsProvider* ptrAnnotations)
|
||||
{
|
||||
m_annotationHeaderView->AttachToAxis(ptrAnnotations, GetAxis());
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SetEndFrame(FrameNumberType /*frame*/)
|
||||
{
|
||||
m_EventTrack->update();
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SetSliderOffset(FrameNumberType /*frame*/)
|
||||
{
|
||||
}
|
||||
|
||||
void CombinedEventsControl::MouseClickInformed(int newValue)
|
||||
{
|
||||
emit InformOfMouseClick(newValue, 1, 0);
|
||||
}
|
||||
|
||||
void CombinedEventsControl::MouseMoveInformed(int newValue)
|
||||
{
|
||||
emit InformOfMouseMove(newValue, 1, 0);
|
||||
}
|
||||
|
||||
void CombinedEventsControl::OnEventScrubberboxChanged(int newValue)
|
||||
{
|
||||
emit EventRequestEventFocus(static_cast<EventNumberType>(newValue));
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SetScrubberFrame(FrameNumberType frame)
|
||||
{
|
||||
m_EventTrack->GetAxis()->Clear();
|
||||
|
||||
int temp_m_FirstIndex = 0x7fffffff;
|
||||
int temp_m_LastIndex = 0;
|
||||
|
||||
AZ::s64 highestCount = 0;
|
||||
int channelIdx = 0;
|
||||
for (AZStd::list<Aggregator*>::iterator iter = m_Aggregators.begin(); iter != m_Aggregators.end(); ++iter, ++channelIdx)
|
||||
{
|
||||
m_EventTrack->ClearData(channelIdx);
|
||||
|
||||
size_t numEvents = (*iter)->NumOfEventsAtFrame(frame);
|
||||
|
||||
if (numEvents)
|
||||
{
|
||||
highestCount += numEvents;
|
||||
EventNumberType eventIndexOffset = (*iter)->GetFirstIndexAtFrame(frame);
|
||||
|
||||
for (EventNumberType eventIndex = 0; eventIndex < static_cast<EventNumberType>(numEvents); ++eventIndex)
|
||||
{
|
||||
DrillerEvent* dep = (*iter)->GetEvents()[ eventIndex + eventIndexOffset ];
|
||||
AZ::s64 geid = dep->GetGlobalEventId();
|
||||
|
||||
temp_m_FirstIndex = (int)geid < temp_m_FirstIndex ? (int)geid : temp_m_FirstIndex;
|
||||
temp_m_LastIndex = (int)geid > temp_m_LastIndex ? (int)geid : temp_m_LastIndex;
|
||||
|
||||
//AZ_TracePrintf("LUA","First %d Last %d\n",temp_m_FirstIndex, temp_m_LastIndex);
|
||||
|
||||
m_EventTrack->AddData(channelIdx, (float)geid, (float)channelIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_FirstIndex = temp_m_FirstIndex;
|
||||
m_LastIndex = temp_m_LastIndex;
|
||||
|
||||
m_EventTrack->GetAxis()->SetAxisRange((float)m_FirstIndex, (float)m_LastIndex);
|
||||
m_EventTrack->GetAxis()->SetViewFull();
|
||||
SanitizeScrubberIndex();
|
||||
emit EventRequestEventFocus(m_ScrubberIndex);
|
||||
}
|
||||
|
||||
void CombinedEventsControl::OnEventTrackRequestEventFocus(Driller::EventNumberType eventIndex)
|
||||
{
|
||||
emit EventRequestEventFocus(eventIndex);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Window Messages
|
||||
void CombinedEventsControl::EventFocusChanged(EventNumberType eventIdx)
|
||||
{
|
||||
m_ScrubberIndex = eventIdx;
|
||||
SanitizeScrubberIndex();
|
||||
m_EventTrack->SetMarkerPosition((float)m_ScrubberIndex);
|
||||
}
|
||||
|
||||
void CombinedEventsControl::SanitizeScrubberIndex()
|
||||
{
|
||||
m_ScrubberIndex = m_ScrubberIndex < m_FirstIndex ? m_FirstIndex : m_ScrubberIndex;
|
||||
m_ScrubberIndex = m_ScrubberIndex > m_LastIndex ? m_LastIndex : m_ScrubberIndex;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEQDataTrack::CEQDataTrack(QWidget* parent, Qt::WindowFlags flags)
|
||||
: DataRacetrack(parent, flags)
|
||||
{
|
||||
m_InsetT = 4;
|
||||
m_InsetB = 12;
|
||||
SetZeroBasedAxisNumbering(true);
|
||||
setAutoFillBackground(false);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
}
|
||||
CEQDataTrack::~CEQDataTrack()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMBINEDEVENTS_CONTROL_H
|
||||
#define COMBINEDEVENTS_CONTROL_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDockWidget>
|
||||
|
||||
#include "DrillerNetworkMessages.h"
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
#include "RacetrackChart.hxx"
|
||||
#include "Annotations/AnnotationsHeaderView_Events.hxx"
|
||||
#endif
|
||||
|
||||
namespace Charts
|
||||
{
|
||||
class Axis;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class Aggregator;
|
||||
class CEQDataTrack;
|
||||
class CollapsiblePanel;
|
||||
class AnnotationsProvider;
|
||||
|
||||
/*
|
||||
Channel Control intermediates between one data Aggregator, the application's main window, and the renderer.
|
||||
This maintains state used by the renderer and passes changes both up and down via signal/slot.
|
||||
*/
|
||||
|
||||
class CombinedEventsControl
|
||||
: public QDockWidget
|
||||
, public Driller::DrillerEventWindowMessages::Bus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CombinedEventsControl,AZ::SystemAllocator,0);
|
||||
CombinedEventsControl( QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~CombinedEventsControl(void);
|
||||
|
||||
void SetIdentity(int identity);
|
||||
|
||||
void ClearAggregatorList();
|
||||
void AddAggregatorList(DrillerNetworkMessages::AggregatorList &theList);
|
||||
void AddAggregator(Aggregator &theAggregator);
|
||||
|
||||
void SetAnnotationsProvider(AnnotationsProvider* ptrAnnotations);
|
||||
|
||||
AZStd::list<Aggregator *>m_Aggregators;
|
||||
|
||||
int m_identity;
|
||||
EventNumberType m_ScrubberIndex;
|
||||
void SanitizeScrubberIndex();
|
||||
|
||||
QWidget *m_Contents;
|
||||
|
||||
CollapsiblePanel* m_collapsiblePanel;
|
||||
|
||||
AnnotationHeaderView_Events* m_annotationHeaderView;
|
||||
CEQDataTrack* m_EventTrack;
|
||||
|
||||
int m_FirstIndex;
|
||||
int m_LastIndex;
|
||||
int m_IndexCount;
|
||||
|
||||
void SetActive( int active );
|
||||
void SetEndFrame( FrameNumberType frame );
|
||||
void SetSliderOffset( FrameNumberType frame );
|
||||
|
||||
Charts::Axis* GetAxis() const;
|
||||
|
||||
virtual void EventFocusChanged(EventNumberType eventIdx);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
public slots:
|
||||
void MouseClickInformed( int newValue );
|
||||
void MouseMoveInformed( int newValue );
|
||||
void OnEventScrubberboxChanged( int newValue );
|
||||
void SetScrubberFrame( FrameNumberType frame );
|
||||
void OnEventTrackRequestEventFocus(Driller::EventNumberType);
|
||||
|
||||
signals:
|
||||
void InformOfMouseClick( int newValue, int range, int modifiers );
|
||||
void InformOfMouseMove( int newValue, int range, int modifiers );
|
||||
void InfoAreaGeometryChanged ( QSize newSize);
|
||||
void EventRequestEventFocus(EventNumberType);
|
||||
};
|
||||
|
||||
class CEQDataTrack
|
||||
: public Racetrack::DataRacetrack
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(CEQDataTrack,AZ::SystemAllocator,0);
|
||||
CEQDataTrack( QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~CEQDataTrack(void);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // COMBINEDEVENTS_CONTROL_H
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/CustomizeCSVExportWidget.hxx"
|
||||
#include <Source/Driller/moc_CustomizeCSVExportWidget.cpp>
|
||||
|
||||
#include "Source/Driller/CSVExportSettings.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
/////////////////////////////
|
||||
// CustomizeCSVExportWidget
|
||||
/////////////////////////////
|
||||
|
||||
CustomizeCSVExportWidget::CustomizeCSVExportWidget(CSVExportSettings& exportSettings, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_exportSettings(exportSettings)
|
||||
{
|
||||
}
|
||||
|
||||
CustomizeCSVExportWidget::~CustomizeCSVExportWidget()
|
||||
{
|
||||
}
|
||||
|
||||
CSVExportSettings* CustomizeCSVExportWidget::GetExportSettings() const
|
||||
{
|
||||
return (&m_exportSettings);
|
||||
}
|
||||
|
||||
void CustomizeCSVExportWidget::OnShouldExportStateDescriptorChecked(int state)
|
||||
{
|
||||
m_exportSettings.SetShouldExportColumnDescriptors(state == Qt::Checked);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_CUSTOMIZECSVEXPORTWIDGET_H
|
||||
#define DRILLER_CUSTOMIZECSVEXPORTWIDGET_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class CSVExportSettings;
|
||||
|
||||
class CustomizeCSVExportWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CustomizeCSVExportWidget(CSVExportSettings& customSettings, QWidget* parent);
|
||||
virtual ~CustomizeCSVExportWidget();
|
||||
|
||||
virtual void FinalizeSettings() = 0;
|
||||
CSVExportSettings* GetExportSettings() const;
|
||||
|
||||
public slots:
|
||||
void OnShouldExportStateDescriptorChecked(int);
|
||||
|
||||
protected:
|
||||
CSVExportSettings& m_exportSettings;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* 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 "DoubleListSelector.hxx"
|
||||
#include <Source/Driller/moc_DoubleListSelector.cpp>
|
||||
#include <Source/Driller/ui_DoubleListSelector.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
///////////////////////
|
||||
// DoubleListSelector
|
||||
///////////////////////
|
||||
|
||||
DoubleListSelector::DoubleListSelector(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_gui(new Ui::DoubleListSelector())
|
||||
{
|
||||
m_gui->setupUi(this);
|
||||
|
||||
m_gui->activateButton->setAutoDefault(false);
|
||||
m_gui->deactivateButton->setAutoDefault(false);
|
||||
|
||||
QObject::connect(m_gui->activateButton, SIGNAL(clicked()), this, SLOT(activateSelected()));
|
||||
QObject::connect(m_gui->deactivateButton, SIGNAL(clicked()), this, SLOT(deactivateSelected()));
|
||||
}
|
||||
|
||||
DoubleListSelector::~DoubleListSelector()
|
||||
{
|
||||
delete m_gui;
|
||||
}
|
||||
|
||||
void DoubleListSelector::setItemList(const QStringList& items, bool maintainActiveList)
|
||||
{
|
||||
if (maintainActiveList)
|
||||
{
|
||||
m_gui->inactiveList->clearItems();
|
||||
|
||||
const QStringList& activeItems = m_gui->activeList->getAllItems();
|
||||
|
||||
QStringList newActiveItems;
|
||||
QStringList inactiveItems;
|
||||
|
||||
for (const QString& currentItem : items)
|
||||
{
|
||||
if (activeItems.contains(currentItem))
|
||||
{
|
||||
newActiveItems.push_back(currentItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
inactiveItems.push_back(currentItem);
|
||||
}
|
||||
}
|
||||
|
||||
m_gui->activeList->clearItems();
|
||||
|
||||
m_gui->inactiveList->addItems(inactiveItems);
|
||||
m_gui->activeList->addItems(newActiveItems);
|
||||
|
||||
emit ActiveItemsChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gui->inactiveList->clearItems();
|
||||
m_gui->inactiveList->addItems(items);
|
||||
m_gui->activeList->clearItems();
|
||||
}
|
||||
}
|
||||
|
||||
void DoubleListSelector::setActiveItems(const QStringList& items)
|
||||
{
|
||||
QStringList inactiveItems = m_gui->inactiveList->getAllItems();
|
||||
const QStringList& activeItems = m_gui->activeList->getAllItems();
|
||||
|
||||
inactiveItems.append(activeItems);
|
||||
|
||||
m_gui->inactiveList->clearItems();
|
||||
m_gui->activeList->clearItems();
|
||||
|
||||
for (const QString& currentItem : items)
|
||||
{
|
||||
QStringList::iterator itemIter = inactiveItems.begin();
|
||||
|
||||
while (itemIter != inactiveItems.end())
|
||||
{
|
||||
if ((*itemIter).compare(currentItem) == 0)
|
||||
{
|
||||
inactiveItems.erase(itemIter);
|
||||
break;
|
||||
}
|
||||
|
||||
++itemIter;
|
||||
}
|
||||
}
|
||||
|
||||
m_gui->inactiveList->addItems(inactiveItems);
|
||||
m_gui->activeList->addItems(items);
|
||||
|
||||
emit ActiveItemsChanged();
|
||||
}
|
||||
|
||||
const QStringList& DoubleListSelector::getActiveItems() const
|
||||
{
|
||||
return m_gui->activeList->getAllItems();
|
||||
}
|
||||
|
||||
void DoubleListSelector::setActiveTitle(const QString& title)
|
||||
{
|
||||
m_gui->activeGroupBox->setTitle(title);
|
||||
}
|
||||
|
||||
void DoubleListSelector::setInactiveTitle(const QString& title)
|
||||
{
|
||||
m_gui->inactiveGroupBox->setTitle(title);
|
||||
}
|
||||
|
||||
void DoubleListSelector::activateSelected()
|
||||
{
|
||||
QStringList activateItems;
|
||||
|
||||
m_gui->inactiveList->getSelectedItems(activateItems);
|
||||
m_gui->inactiveList->removeSelected();
|
||||
|
||||
m_gui->activeList->addItems(activateItems);
|
||||
|
||||
emit ActiveItemsChanged();
|
||||
}
|
||||
|
||||
void DoubleListSelector::deactivateSelected()
|
||||
{
|
||||
QStringList activateItems;
|
||||
|
||||
m_gui->activeList->getSelectedItems(activateItems);
|
||||
m_gui->activeList->removeSelected();
|
||||
|
||||
m_gui->inactiveList->addItems(activateItems);
|
||||
|
||||
emit ActiveItemsChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AZTOOLSFRAMEWORK_UI_UICORE_DOUBLELISTSELECTOR_H
|
||||
#define AZTOOLSFRAMEWORK_UI_UICORE_DOUBLELISTSELECTOR_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DoubleListSelector;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class DoubleListSelector
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(DoubleListSelector, AZ::SystemAllocator,0);
|
||||
|
||||
explicit DoubleListSelector(QWidget* parent = nullptr);
|
||||
~DoubleListSelector();
|
||||
|
||||
void setItemList(const QStringList& items, bool maintainActiveList = true);
|
||||
void setActiveItems(const QStringList& items);
|
||||
|
||||
const QStringList& getActiveItems() const;
|
||||
|
||||
void setActiveTitle(const QString& title);
|
||||
void setInactiveTitle(const QString& title);
|
||||
|
||||
public slots:
|
||||
void activateSelected();
|
||||
void deactivateSelected();
|
||||
|
||||
signals:
|
||||
void ActiveItemsChanged();
|
||||
|
||||
private:
|
||||
|
||||
Ui::DoubleListSelector* m_gui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,174 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DoubleListSelector</class>
|
||||
<widget class="QWidget" name="DoubleListSelector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>527</width>
|
||||
<height>449</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="inactiveGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Inactive</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="Driller::FilteredListView" name="inactiveList" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>75</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="activateButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>>></string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deactivateButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><<</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="activeGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Active</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="Driller::FilteredListView" name="activeList" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::FilteredListView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Source/Driller/FilteredListView.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerAggregator.hxx"
|
||||
#include <Source/Driller/moc_DrillerAggregator.cpp>
|
||||
|
||||
#include "DrillerEvent.h"
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include "Source/Driller/CSVExportSettings.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class AggregatorSavedState
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AggregatorSavedState, "{9AAB69CE-8061-4CB6-8387-DB60FD8DBB75}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(AggregatorSavedState, AZ::SystemAllocator, 0);
|
||||
AggregatorSavedState() {}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<AggregatorSavedState>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Aggregator::Aggregator(int identity)
|
||||
: QObject()
|
||||
, m_identity(identity)
|
||||
, m_currentEvent(Driller::kInvalidEventIndex)
|
||||
, m_isCaptureEnabled(true)
|
||||
{
|
||||
DrillerMainWindowMessages::Handler::BusConnect(m_identity);
|
||||
DrillerWorkspaceWindowMessages::Handler::BusConnect(m_identity);
|
||||
|
||||
// subclassed aggregators should work with settingsDocument at this point
|
||||
// to retrieve state
|
||||
}
|
||||
Aggregator::~Aggregator()
|
||||
{
|
||||
// subclassed aggregators should work with settingsDocument at this point
|
||||
// to store the current state so it can be retrieved when constructed again
|
||||
|
||||
DrillerWorkspaceWindowMessages::Handler::BusDisconnect(m_identity);
|
||||
DrillerMainWindowMessages::Handler::BusDisconnect(m_identity);
|
||||
|
||||
for (EventListType::iterator it = m_events.begin(); it != m_events.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void Aggregator::Reset()
|
||||
{
|
||||
for (EventListType::iterator it = m_events.begin(); it != m_events.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
|
||||
m_events.clear();
|
||||
m_frameToEventIndex.clear();
|
||||
m_currentEvent = kInvalidEventIndex;
|
||||
}
|
||||
bool Aggregator::IsValid()
|
||||
{
|
||||
return m_events.size() > 0;
|
||||
}
|
||||
|
||||
void Aggregator::AddNewFrame()
|
||||
{
|
||||
m_frameToEventIndex.push_back(m_events.size());
|
||||
}
|
||||
|
||||
bool Aggregator::DataAtFrame(FrameNumberType frame)
|
||||
{
|
||||
return NumOfEventsAtFrame(frame) > 0;
|
||||
}
|
||||
|
||||
void Aggregator::ExportToCSVRequest(const char* filename, CSVExportSettings* exportSettings)
|
||||
{
|
||||
AZ::IO::SystemFile exportFile;
|
||||
|
||||
if (exportFile.Open(filename, AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY))
|
||||
{
|
||||
if (exportSettings == nullptr || exportSettings->ShouldExportColumnDescriptors())
|
||||
{
|
||||
ExportColumnDescriptorToCSV(exportFile, exportSettings);
|
||||
}
|
||||
|
||||
for (DrillerEvent* drillerEvent : m_events)
|
||||
{
|
||||
ExportEventToCSV(exportFile, drillerEvent, exportSettings);
|
||||
}
|
||||
|
||||
exportFile.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Error Opening File", QString("Could not open file %1").arg(filename), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Aggregator::NumOfEventsAtFrame(FrameNumberType frame) const
|
||||
{
|
||||
size_t numFrames = m_frameToEventIndex.size();
|
||||
if (numFrames == 1)
|
||||
{
|
||||
return m_events.size();
|
||||
}
|
||||
|
||||
if (frame == numFrames - 1)
|
||||
{
|
||||
return m_events.size() - m_frameToEventIndex[frame]; // last frame
|
||||
}
|
||||
|
||||
if (numFrames >= 2)
|
||||
{
|
||||
EventNumberType ftei1 = m_frameToEventIndex[frame + 1];
|
||||
EventNumberType ftei0 = m_frameToEventIndex[frame];
|
||||
size_t fte = (ftei1 - ftei0);
|
||||
return fte;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString Aggregator::GetDialogTitle() const
|
||||
{
|
||||
return QString("%1 - %2").arg(GetName()).arg(GetInspectionFileName());
|
||||
}
|
||||
|
||||
void Aggregator::FrameChanged(FrameNumberType frame)
|
||||
{
|
||||
size_t numFrames = m_frameToEventIndex.size();
|
||||
if (numFrames)
|
||||
{
|
||||
EventNumberType targetEventIndex;
|
||||
|
||||
if (frame == numFrames - 1)
|
||||
{
|
||||
targetEventIndex = m_events.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetEventIndex = m_frameToEventIndex[frame + 1];
|
||||
|
||||
// the current targetEventIndex belongs to the next frame "frame+1" minus 1
|
||||
--targetEventIndex;
|
||||
}
|
||||
|
||||
EventChanged(targetEventIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void Aggregator::EventChanged(EventNumberType eventIndex)
|
||||
{
|
||||
if (eventIndex == m_currentEvent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: If we are at the end and we click at the start, we can start from the START as it's a known state
|
||||
if (eventIndex > m_currentEvent)
|
||||
{
|
||||
// forward (m_currentEvent has already been executed so start currentEvent+1)
|
||||
for (EventNumberType i = m_currentEvent + 1; i <= eventIndex; ++i)
|
||||
{
|
||||
m_events[i]->StepForward(this);
|
||||
}
|
||||
}
|
||||
else if (eventIndex < m_currentEvent)
|
||||
{
|
||||
// backward (current event has executed so revert it
|
||||
for (EventNumberType i = m_currentEvent; i > eventIndex; --i)
|
||||
{
|
||||
m_events[i]->StepBackward(this);
|
||||
}
|
||||
}
|
||||
|
||||
m_currentEvent = eventIndex;
|
||||
emit OnDataCurrentEventChanged();
|
||||
}
|
||||
|
||||
void Aggregator::ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings)
|
||||
{
|
||||
(void)file;
|
||||
(void)exportSettings;
|
||||
}
|
||||
|
||||
void Aggregator::ExportEventToCSV(AZ::IO::SystemFile& file, const DrillerEvent* drillerEvent, CSVExportSettings* exportSettings)
|
||||
{
|
||||
(void)file;
|
||||
(void)drillerEvent;
|
||||
(void)exportSettings;
|
||||
}
|
||||
|
||||
void Aggregator::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
AggregatorSavedState::Reflect(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLERAGGREGATOR_H
|
||||
#define DRILLER_DRILLERAGGREGATOR_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Driller/Stream.h>
|
||||
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
#include "DrillerDataTypes.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QObject>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace IO
|
||||
{
|
||||
class SystemFile;
|
||||
}
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class DrillerEvent;
|
||||
class AnnotationsProvider;
|
||||
class CSVExportSettings;
|
||||
class CustomizeCSVExportWidget;
|
||||
|
||||
class ChannelDataView;
|
||||
class ChannelConfigurationWidget;
|
||||
|
||||
/*
|
||||
Aggregator is a pure virtual data source that packages its data
|
||||
into easily digestible, single frame chunks for external consumption.
|
||||
It is a pull, not a push, source.
|
||||
|
||||
Separately, aggregators are responsible for handling their own Options and Drill Down displays.
|
||||
*/
|
||||
|
||||
class Aggregator
|
||||
: public QObject
|
||||
, public Driller::DrillerMainWindowMessages::Bus::Handler
|
||||
, public Driller::DrillerWorkspaceWindowMessages::Bus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
typedef AZStd::vector<DrillerEvent*> EventListType;
|
||||
typedef AZStd::vector<EventNumberType> FrameToEventIndexType;
|
||||
|
||||
Aggregator(int identity);
|
||||
virtual ~Aggregator();
|
||||
// MainWindow Bus Commands
|
||||
|
||||
virtual AZ::Crc32 GetChannelId() const { return 0; }
|
||||
virtual AZ::u32 GetDrillerId() const { return 0; }
|
||||
virtual AZ::Debug::DrillerHandlerParser* GetDrillerDataParser() { return nullptr; }
|
||||
virtual void EnableCapture(bool enabled) { m_isCaptureEnabled = enabled; }
|
||||
bool IsCaptureEnabled() const { return m_isCaptureEnabled; }
|
||||
int GetIdentity() const { return m_identity; }
|
||||
|
||||
virtual bool CanExportToCSV() const { return false; }
|
||||
virtual CustomizeCSVExportWidget* CreateCSVExportCustomizationWidget() { return nullptr; }
|
||||
|
||||
virtual bool HasConfigurations() const { return false; }
|
||||
virtual ChannelConfigurationWidget* CreateConfigurationWidget() { return nullptr; }
|
||||
virtual void OnConfigurationChanged() { }
|
||||
|
||||
virtual void AnnotateChannelView(ChannelDataView* dataView) { (void)dataView; }
|
||||
virtual void RemoveChannelAnnotation(ChannelDataView* dataView) { (void)dataView; }
|
||||
|
||||
/// reset for another data run
|
||||
virtual void Reset();
|
||||
virtual bool IsValid();
|
||||
|
||||
/// Make a game frame.
|
||||
virtual void AddNewFrame();
|
||||
/// Adds new event. We can have many events (or none) for each game frame.
|
||||
void AddEvent(DrillerEvent* event) { m_events.push_back(event); emit OnDataAddEvent();}
|
||||
void FinalizeEvent() { emit OnEventFinalized(m_events.back()); }
|
||||
EventListType& GetEvents() { return m_events; }
|
||||
const EventListType& GetEvents() const { return m_events; }
|
||||
size_t NumOfEventsAtFrame(FrameNumberType frame) const;
|
||||
EventNumberType GetCurrentEvent() const { return m_currentEvent; }
|
||||
|
||||
EventNumberType GetFirstIndexAtFrame(FrameNumberType frame ) const { return m_frameToEventIndex[frame]; }
|
||||
|
||||
size_t GetFrameCount() const { return m_frameToEventIndex.size(); }
|
||||
|
||||
// ----- annotation functionality ----
|
||||
|
||||
// emit all annotations that match the provider's filter, given the start and end frame:
|
||||
virtual void EmitAllAnnotationsForFrameRange( FrameNumberType startFrameInclusive, FrameNumberType endFrameInclusive , AnnotationsProvider* ptrProvider) { (void)startFrameInclusive; (void)endFrameInclusive; (void)ptrProvider; }
|
||||
|
||||
// emit all channels that you are aware of existing within that frame range (You may emit duplicate channels, they will be ignored)
|
||||
virtual void EmitAnnotationChannelsForFrameRange( FrameNumberType startFrameInclusive, FrameNumberType endFrameInclusive , AnnotationsProvider* ptrProvider) { (void)startFrameInclusive; (void)endFrameInclusive; (void)ptrProvider; }
|
||||
|
||||
QString GetDialogTitle() const;
|
||||
|
||||
signals:
|
||||
|
||||
void NormalizedRangeChanged();
|
||||
|
||||
void OnDataCurrentEventChanged();
|
||||
void OnDataAddEvent();
|
||||
void OnEventFinalized(DrillerEvent* event);
|
||||
|
||||
QString GetInspectionFileName() const;
|
||||
|
||||
public slots:
|
||||
// Queries
|
||||
virtual bool DataAtFrame(FrameNumberType frame );
|
||||
virtual float ValueAtFrame(FrameNumberType frame ) = 0;
|
||||
virtual QColor GetColor() const = 0;
|
||||
virtual QString GetChannelName() const = 0;
|
||||
virtual QString GetName() const = 0;
|
||||
virtual QString GetDescription() const = 0;
|
||||
virtual QString GetToolTip() const = 0;
|
||||
virtual QString GetDrillDownIcon() { return ":/general/callstack"; }
|
||||
virtual AZ::Uuid GetID() const = 0;
|
||||
virtual QWidget* DrillDownRequest(FrameNumberType atFrame) = 0;
|
||||
virtual void OptionsRequest() = 0;
|
||||
|
||||
void ExportToCSVRequest(const char* filename, CSVExportSettings* exportSettings);
|
||||
|
||||
protected:
|
||||
Aggregator(const Aggregator&) = delete;
|
||||
virtual void FrameChanged(FrameNumberType frame);
|
||||
virtual void EventChanged(EventNumberType eventIndex);
|
||||
|
||||
virtual void ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings);
|
||||
virtual void ExportEventToCSV(AZ::IO::SystemFile& file, const DrillerEvent* drillerEvent, CSVExportSettings* exportSettings);
|
||||
|
||||
EventNumberType m_currentEvent; ///< Current event points last executed event
|
||||
EventListType m_events;
|
||||
FrameToEventIndexType m_frameToEventIndex;
|
||||
bool m_isCaptureEnabled;
|
||||
int m_identity;
|
||||
|
||||
public:
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLER_DRILLERAGGREGATOR_H
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLERAGGREGATOR_OPTIONS_H
|
||||
#define DRILLER_DRILLERAGGREGATOR_OPTIONS_H
|
||||
|
||||
#include "QtGui/qcolor.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class Aggregator;
|
||||
|
||||
class AggregatorOptions
|
||||
{
|
||||
public:
|
||||
|
||||
AggregatorOptions( Aggregator *owner )
|
||||
: m_Owner(owner)
|
||||
{
|
||||
}
|
||||
virtual ~AggregatorOptions()
|
||||
{
|
||||
}
|
||||
|
||||
Aggregator *m_Owner;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLER_DRILLERAGGREGATOR_OPTIONS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DrillerCaptureWindow_H
|
||||
#define DRILLER_DrillerCaptureWindow_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
#include "DrillerNetworkMessages.h"
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
#include "AzFramework/TargetManagement/TargetManagementAPI.h"
|
||||
#include <AzToolsFramework/UI/LegacyFramework/MainWindowSavedState.h>
|
||||
#include "Workspaces/Workspace.h"
|
||||
#include "Annotations/Annotations.hxx"
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
class QMenu;
|
||||
class QAction;
|
||||
class QToolbar;
|
||||
class QSettings;
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QDockWidget>
|
||||
#include <Source/Driller/DrillerMainWindowMessages.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DrillerCaptureWindow;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class ChannelControl;
|
||||
class DrillerDataContainer;
|
||||
class CombinedEventsControl;
|
||||
class AnnotationHeaderView;
|
||||
class ConfigureAnnotationsWindow;
|
||||
|
||||
/*
|
||||
This is the original guts of the singular Driller Main Window
|
||||
|
||||
Home of the real commands, channels created from external aggregators when connected, and the floating control panel.
|
||||
All inputs end up here where they are interpreted and passed downwards to all channels, to maintain consistency.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Main Window
|
||||
class DrillerCaptureWindow
|
||||
: public QDockWidget
|
||||
, public Driller::DrillerNetworkMessages::Bus::Handler
|
||||
, public Driller::DrillerCaptureWindowRequestBus::Handler
|
||||
, private AzFramework::TargetManagerClient::Bus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_TYPE_INFO(DrillerCaptureWindow, "08AF3402-FCFA-4441-910D-9F994BD0D146");
|
||||
AZ_CLASS_ALLOCATOR(DrillerCaptureWindow,AZ::SystemAllocator,0);
|
||||
DrillerCaptureWindow(CaptureMode captureMode, int identity, QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
DrillerCaptureWindow(const DrillerCaptureWindow&)
|
||||
: m_identity(0)
|
||||
{
|
||||
// TODO: Once AZ_NO_COPY macros is in the branch in use it!
|
||||
AZ_Assert(false, "You can't copy this class!");
|
||||
}
|
||||
virtual ~DrillerCaptureWindow(void);
|
||||
|
||||
bool OnGetPermissionToShutDown();
|
||||
|
||||
// DrillerCaptureWindowRequestBus
|
||||
void ScrubToFrameRequest(FrameNumberType frameType) override;
|
||||
|
||||
public:
|
||||
|
||||
// Driller network messages
|
||||
virtual void ConnectedToNetwork();
|
||||
virtual void NewAggregatorList( AggregatorList &theList );
|
||||
virtual void AddAggregator( Aggregator &theAggregator );
|
||||
virtual void DiscardAggregators();
|
||||
virtual void DisconnectedFromNetwork();
|
||||
virtual void EndFrame(FrameNumberType frame);
|
||||
virtual void NewAggregatorsAvailable();
|
||||
|
||||
// Data Viewer request messages
|
||||
// implement AzFramework::TargetManagerClient::Bus::Handler
|
||||
void DesiredTargetConnected(bool connected);
|
||||
|
||||
public:
|
||||
// MainWindow Messages and states.
|
||||
void SaveWindowState();
|
||||
AZStd::set<AZ::Uuid> m_inactiveChannels;
|
||||
|
||||
void OnContractAllChannels();
|
||||
void OnExpandAllChannels();
|
||||
void OnDisableAllChannels();
|
||||
void OnEnableAllChannels();
|
||||
QString GetDataFileName() { return m_currentDataFilename; }
|
||||
|
||||
private:
|
||||
// how the main window identifies us
|
||||
const int m_identity;
|
||||
CaptureMode m_captureMode;
|
||||
|
||||
// internal workings
|
||||
typedef QList<ChannelControl *> SortedChannels;
|
||||
SortedChannels m_channels;
|
||||
|
||||
void SetCaptureMode(CaptureMode captureMode);
|
||||
void ResetCaptureControls();
|
||||
bool IsInLiveMode() const;
|
||||
bool IsInCaptureMode(CaptureMode captureMode) const;
|
||||
|
||||
void ClearExistingChannels();
|
||||
void ClearChannelDisplay( bool withDeletion );
|
||||
void SortChannels();
|
||||
void PopulateChannelDisplay();
|
||||
ChannelControl* FindChannelControl(Aggregator* aggregator);
|
||||
void AddChannelDisplay(ChannelControl *);
|
||||
|
||||
protected:
|
||||
// Qt Events
|
||||
virtual void closeEvent(QCloseEvent* event);
|
||||
virtual void showEvent( QShowEvent * event );
|
||||
virtual void hideEvent( QHideEvent * event );
|
||||
virtual bool event(QEvent *evt);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void StateReset();
|
||||
QString PrepDataFileForSaving( QString filename, QString workspaceName );
|
||||
QString PrepTempFile( QString filename );
|
||||
|
||||
void ScrubberToBegin();
|
||||
void ScrubberToEnd();
|
||||
void SetScrubberFrame( FrameNumberType frame );
|
||||
FrameNumberType GetScrubberFrame() { return m_scrubberCurrentFrame; }
|
||||
void SetPlaybackLoopBegin( FrameNumberType frame );
|
||||
FrameNumberType GetPlaybackLoopBegin() { return m_playbackLoopBegin; }
|
||||
void SetPlaybackLoopEnd( FrameNumberType frame );
|
||||
FrameNumberType GetPlaybackLoopEnd() { return m_playbackLoopEnd; }
|
||||
void SetFrameRangeBegin( FrameNumberType frame );
|
||||
FrameNumberType GetFrameRangeBegin() { return m_frameRangeBegin; }
|
||||
void SetFrameRangeEnd( FrameNumberType frame);
|
||||
FrameNumberType GetFrameRangeEnd() { return m_frameRangeEnd; }
|
||||
|
||||
void UpdateFrameScrubberbox();
|
||||
void ScrubberFrame(FrameNumberType frame);
|
||||
|
||||
void UpdateEventScrubberbox();
|
||||
void SetScrubberEvent( EventNumberType eventIdx );
|
||||
|
||||
void UpdateScrollbar( int diff = 0 );
|
||||
void FocusScrollbar( FrameNumberType focusFrame );
|
||||
void UpdatePlaybackLoopPoints();
|
||||
|
||||
void ConnectChannelControl(ChannelControl *dc);
|
||||
|
||||
void SetCaptureDirty( bool isDirty );
|
||||
|
||||
void UpdateLiveControls();
|
||||
|
||||
AZ::u32 m_windowStateCRC;
|
||||
|
||||
FrameNumberType m_scrubberCurrentFrame;
|
||||
FrameNumberType m_frameRangeBegin;
|
||||
FrameNumberType m_frameRangeEnd;
|
||||
FrameNumberType m_visibleFrames;
|
||||
EventNumberType m_scrubberCurrentEvent;
|
||||
bool m_captureIsDirty;
|
||||
|
||||
int m_playbackIsActive;
|
||||
FrameNumberType m_playbackLoopBegin;
|
||||
FrameNumberType m_playbackLoopEnd;
|
||||
bool m_draggingPlaybackLoopBegin;
|
||||
bool m_draggingPlaybackLoopEnd;
|
||||
bool m_draggingAnything;
|
||||
bool m_manipulatingScrollBar;
|
||||
DrillerDataContainer* m_data; ///< Pointer to driller data class.
|
||||
QString m_tmpCaptureFilename;
|
||||
QString m_currentDataFilename;
|
||||
AnnotationsProvider m_AnnotationProvider;
|
||||
|
||||
bool m_isLoadingFile;
|
||||
|
||||
AnnotationHeaderView* m_ptrAnnotationsHeaderView;
|
||||
ConfigureAnnotationsWindow *m_ptrConfigureAnnotationsWindow;
|
||||
AZStd::vector<Annotation> m_collectedAnnotations;
|
||||
bool m_bForceNextScrub;
|
||||
|
||||
int m_captureId;
|
||||
|
||||
// are we viewing stored data or are we live drilling?
|
||||
bool m_TargetConnected;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int s_availableFrameQuantities[];
|
||||
|
||||
public slots:
|
||||
void RepopulateAnnotations();
|
||||
void RestoreWindowState();
|
||||
void OnMenuCloseCurrentWindow();
|
||||
void OnOpen();
|
||||
void OnClose();
|
||||
void OnCloseFile();
|
||||
void OnToBegin();
|
||||
void OnToEnd();
|
||||
void OnPlayToggled(bool toggleState);
|
||||
void OnCaptureToggled(bool toggleState);
|
||||
void OnSliderPressed();
|
||||
void OnNewSliderValue(int newValue);
|
||||
void OnFrameScrubberboxChanged(int newValue);
|
||||
void OnQuantMenuFinal( int range );
|
||||
void HandleScrollToFrameRequest( FrameNumberType frame);
|
||||
void OnChannelControlMouseDown( Qt::MouseButton whichButton, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void OnChannelControlMouseMove( FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void OnChannelControlMouseUp( Qt::MouseButton whichButton, FrameNumberType frame, FrameNumberType range, int modifiers );
|
||||
void OnChannelControlMouseWheel( FrameNumberType frame, int wheelAmount, FrameNumberType range, int modifiers );
|
||||
void OnOpenDrillerFile();
|
||||
void OnOpenDrillerFile(QString fileName);
|
||||
void OnOpenDrillerFileForWorkspace(QString fileName, QString workspaceFileName);
|
||||
void OnOpenWorkspaceFile(QString fileName, bool openDrillerFileAlso); // just open it
|
||||
void OnApplyWorkspaceFile(QString fileName);
|
||||
void OnSaveDrillerFile();
|
||||
void OnSaveWorkspaceFile(QString fileName, bool automated = false);
|
||||
|
||||
void PlaybackTick();
|
||||
void OnUpdateScrollSize();
|
||||
void EventRequestEventFocus(EventNumberType eventIdx);
|
||||
|
||||
// --- annotations:
|
||||
void OnSelectedAnnotationChannelsChanged();
|
||||
void OnAnnotationOptionsClick();
|
||||
void InformOfMouseOverAnnotation(const Annotation& annotation);
|
||||
void InformOfClickAnnotation(const Annotation& annotation);
|
||||
void OnAnnotationsDialogDestroyed();
|
||||
void CommitAnnotationsCollected();
|
||||
|
||||
void UpdateEndFrameInControls();
|
||||
|
||||
QString GetOpenFileName() const;
|
||||
|
||||
signals:
|
||||
void ScrubberFrameUpdate( FrameNumberType frame );
|
||||
void ShowYourself();
|
||||
void HideYourself();
|
||||
void OnCaptureModeChange(CaptureMode);
|
||||
void CaptureWindowSetToLive(bool);
|
||||
|
||||
public:
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
private:
|
||||
|
||||
Ui::DrillerCaptureWindow* m_gui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLER_DrillerCaptureWindow_H
|
||||
@@ -1,610 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DrillerCaptureWindow</class>
|
||||
<widget class="QDockWidget" name="DrillerCaptureWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1046</width>
|
||||
<height>497</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>677</width>
|
||||
<height>177</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/general/hex_profiler_icon</normaloff>:/general/hex_profiler_icon</iconset>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::NoDockWidgetFeatures</set>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea</set>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Driller</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="targetFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzToolsFramework::TargetSelectorButton" name="targetButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select the target Application to be profiled.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Target: None</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="captureButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Begin capturing Application data</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Capture</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>C</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameFPS">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Playback Speed</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="fpsBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Playback FPS</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="playButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Play</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Space</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Frame</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="frameScrubberBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Scrubbed Frame</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="quantityButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The number of frames visible in the graphs</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show: 1000</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>72</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="dockWidgetContents_4" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzToolsFramework::AZAutoSizingScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1040</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="channelLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>14</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollBar" name="controlScrollBar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Driller::CombinedEventsControl" name="combinedEventsWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<action name="actionCapture">
|
||||
<property name="text">
|
||||
<string>Capture</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start Capturing Data From the Active Drills</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFreeze">
|
||||
<property name="text">
|
||||
<string>Freeze</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Stop Capturing From the Drills and Freeze the Data</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose">
|
||||
<property name="text">
|
||||
<string>Close Current File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+F4</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::CombinedEventsControl</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>CombinedEventsControl.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::AZAutoSizingScrollArea</class>
|
||||
<extends>QScrollArea</extends>
|
||||
<header>AzToolsFramework/UI/UICore/AZAutoSizingScrollArea.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::TargetSelectorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>AzToolsFramework/UI/UICore/TargetSelectorButton.hxx</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>fpsBox</tabstop>
|
||||
<tabstop>frameScrubberBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerContext.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Script/ScriptContext.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <QMessageBox>
|
||||
#include <AzToolsFramework/UI/UICore/SaveChangesDialog.hxx>
|
||||
#include <AzToolsFramework/UI/LegacyFramework/UIFrameworkAPI.h>
|
||||
#include <Source/Telemetry/TelemetryBus.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/Asset/AssetSystemComponent.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
const char* DrillerDebugName = "Profiler";
|
||||
const char* DrillerInfoName = "Profiler";
|
||||
|
||||
class DrillerSavedState
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(DrillerSavedState, "{CBA064FC-B144-4B9D-92B8-F696B0A15E4D}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(DrillerSavedState, AZ::SystemAllocator, 0);
|
||||
|
||||
bool m_MainDrillerWindowIsVisible;
|
||||
bool m_MainDrillerWindowIsOpen;
|
||||
|
||||
DrillerSavedState()
|
||||
: m_MainDrillerWindowIsVisible(true)
|
||||
, m_MainDrillerWindowIsOpen(true) {}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DrillerSavedState>()
|
||||
->Version(1)
|
||||
->Field("m_MainDrillerWindowIsVisible", &DrillerSavedState::m_MainDrillerWindowIsVisible)
|
||||
->Field("m_MainDrillerWindowIsOpen", &DrillerSavedState::m_MainDrillerWindowIsOpen);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AZ::Uuid ContextID("FB8B7094-63FF-4CD1-9857-3AEFA8E2CFDC");
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Context
|
||||
Context::Context()
|
||||
: m_pDrillerMainWindow(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component
|
||||
void Context::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void Context::Activate()
|
||||
{
|
||||
ContextInterface::Handler::BusConnect(ContextID);
|
||||
LegacyFramework::CoreMessageBus::Handler::BusConnect();
|
||||
|
||||
AzToolsFramework::MainWindowDescription desc;
|
||||
desc.name = "Profiler";
|
||||
desc.ContextID = ContextID;
|
||||
desc.hotkeyDesc = AzToolsFramework::HotkeyDescription(AZ_CRC("DrillerOpen", 0x1cbbd497), "Ctrl+Shift+D", "Open Profiler", "General", 1, AzToolsFramework::HotkeyDescription::SCOPE_WINDOW);
|
||||
EBUS_EVENT(AzToolsFramework::FrameworkMessages::Bus, AddComponentInfo, desc);
|
||||
|
||||
bool connectedToAssetProcessor = false;
|
||||
|
||||
// When the AssetProcessor is already launched it should take less than a second to perform a connection
|
||||
// but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize
|
||||
// and able to negotiate a connection when running a debug build
|
||||
// and to negotiate a connection
|
||||
|
||||
AzFramework::AssetSystem::ConnectionSettings connectionSettings;
|
||||
AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings);
|
||||
connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor;
|
||||
connectionSettings.m_connectionIdentifier = desc.name;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor,
|
||||
&AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings);
|
||||
}
|
||||
|
||||
void Context::Deactivate()
|
||||
{
|
||||
LegacyFramework::CoreMessageBus::Handler::BusDisconnect();
|
||||
ContextInterface::Handler::BusDisconnect(ContextID);
|
||||
}
|
||||
|
||||
void Context::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
DrillerMainWindow::Reflect(context);
|
||||
DrillerSavedState::Reflect(context);
|
||||
|
||||
serialize->Class<Context, AZ::Component>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ApplicationDeactivated()
|
||||
{
|
||||
}
|
||||
|
||||
void Context::ApplicationActivated()
|
||||
{
|
||||
}
|
||||
|
||||
void Context::ApplicationShow(AZ::Uuid id)
|
||||
{
|
||||
if (ContextID == id)
|
||||
{
|
||||
ProvisionalShowAndFocus(true);
|
||||
}
|
||||
}
|
||||
void Context::ApplicationHide(AZ::Uuid id)
|
||||
{
|
||||
if (ContextID == id)
|
||||
{
|
||||
m_pDrillerMainWindow->hide();
|
||||
AZStd::intrusive_ptr<DrillerSavedState> newState = AZ::UserSettings::CreateFind<DrillerSavedState>(AZ_CRC("LUA DRILLER CONTEXT STATE", 0x95052376), AZ::UserSettings::CT_GLOBAL);
|
||||
newState->m_MainDrillerWindowIsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ApplicationCensus()
|
||||
{
|
||||
AZStd::intrusive_ptr<DrillerSavedState> newState = AZ::UserSettings::CreateFind<DrillerSavedState>(AZ_CRC("LUA DRILLER CONTEXT STATE", 0x95052376), AZ::UserSettings::CT_GLOBAL);
|
||||
EBUS_EVENT(AzToolsFramework::FrameworkMessages::Bus, ApplicationCensusReply, newState->m_MainDrillerWindowIsVisible);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EditorFramework CoreMessages
|
||||
void Context::OnRestoreState()
|
||||
{
|
||||
const AZStd::string k_launchString = "launch";
|
||||
const AZStd::string k_drillerString = "driller";
|
||||
|
||||
bool GUIMode = true;
|
||||
EBUS_EVENT_RESULT(GUIMode, LegacyFramework::FrameworkApplicationMessages::Bus, IsRunningInGUIMode);
|
||||
if (!GUIMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const AzFramework::CommandLine* commandLine = nullptr;
|
||||
|
||||
EBUS_EVENT_RESULT(commandLine, LegacyFramework::FrameworkApplicationMessages::Bus, GetCommandLineParser);
|
||||
|
||||
bool forceShow = false;
|
||||
bool forceHide = false;
|
||||
|
||||
if (commandLine->HasSwitch(k_launchString))
|
||||
{
|
||||
forceHide = true;
|
||||
|
||||
size_t numSwitchValues = commandLine->GetNumSwitchValues(k_launchString);
|
||||
|
||||
for (size_t i = 0; i < numSwitchValues; ++i)
|
||||
{
|
||||
AZStd::string inputValue = commandLine->GetSwitchValue(k_launchString, i);
|
||||
|
||||
if (inputValue.compare(k_drillerString) == 0)
|
||||
{
|
||||
forceShow = true;
|
||||
forceHide = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProvisionalShowAndFocus(forceShow, forceHide);
|
||||
}
|
||||
|
||||
bool Context::OnGetPermissionToShutDown() // until everyone returns true, we can't shut down.
|
||||
{
|
||||
AZ_TracePrintf(DrillerDebugName, "Context::OnGetPermissionToShutDown()\n");
|
||||
|
||||
if (m_pDrillerMainWindow)
|
||||
{
|
||||
if (!m_pDrillerMainWindow->OnGetPermissionToShutDown())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// until everyone returns true, we can't shut down.
|
||||
bool Context::CheckOkayToShutDown()
|
||||
{
|
||||
if (m_pDrillerMainWindow)
|
||||
{
|
||||
// confirmation that we're quitting.
|
||||
if (m_pDrillerMainWindow->isVisible())
|
||||
{
|
||||
m_pDrillerMainWindow->setEnabled(false);
|
||||
m_pDrillerMainWindow->hide();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::OnSaveState()
|
||||
{
|
||||
// notify main view to persist?
|
||||
if (m_pDrillerMainWindow)
|
||||
{
|
||||
m_pDrillerMainWindow->SaveWindowState();
|
||||
}
|
||||
}
|
||||
|
||||
void Context::OnDestroyState()
|
||||
{
|
||||
if (m_pDrillerMainWindow)
|
||||
{
|
||||
delete m_pDrillerMainWindow;
|
||||
}
|
||||
m_pDrillerMainWindow = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Utility
|
||||
void Context::ProvisionalShowAndFocus(bool forcedShow, bool forcedHide)
|
||||
{
|
||||
AZStd::intrusive_ptr<DrillerSavedState> newState = AZ::UserSettings::CreateFind<DrillerSavedState>(AZ_CRC("LUA DRILLER CONTEXT STATE", 0x95052376), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
if (forcedShow)
|
||||
{
|
||||
newState->m_MainDrillerWindowIsOpen = true;
|
||||
newState->m_MainDrillerWindowIsVisible = true;
|
||||
}
|
||||
else if (forcedHide)
|
||||
{
|
||||
newState->m_MainDrillerWindowIsOpen = false;
|
||||
newState->m_MainDrillerWindowIsVisible = false;
|
||||
}
|
||||
|
||||
if (newState->m_MainDrillerWindowIsOpen)
|
||||
{
|
||||
if (newState->m_MainDrillerWindowIsVisible)
|
||||
{
|
||||
if (!m_pDrillerMainWindow)
|
||||
{
|
||||
m_pDrillerMainWindow = aznew DrillerMainWindow();
|
||||
}
|
||||
|
||||
m_pDrillerMainWindow->show();
|
||||
m_pDrillerMainWindow->raise();
|
||||
m_pDrillerMainWindow->activateWindow();
|
||||
m_pDrillerMainWindow->setFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pDrillerMainWindow)
|
||||
{
|
||||
m_pDrillerMainWindow->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//ContextInterface
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Context::ShowDrillerView()
|
||||
{
|
||||
ProvisionalShowAndFocus(true);
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Component/Component.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkAPI.h>
|
||||
#include "DrillerContextInterface.h"
|
||||
#include "DrillerMainWindow.hxx"
|
||||
|
||||
#include <QStandardItem>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Context
|
||||
// all editor components are responsible for maintaining the list of documents they are responsible for
|
||||
// and setting up editing facilities on those asset types in that "space".
|
||||
// editor contexts are components and have component ID's because we will communicate to them via buses.
|
||||
|
||||
// this is the data side of drilling.
|
||||
// for example, data flow, discovery, that sort of thing.
|
||||
|
||||
class Context
|
||||
: public AZ::Component
|
||||
, private LegacyFramework::CoreMessageBus::Handler
|
||||
, private ContextInterface::Handler
|
||||
{
|
||||
friend class ContextFactory;
|
||||
public:
|
||||
AZ_COMPONENT(Driller::Context, "{60EC92BD-1D96-4E37-AB46-DF89A5497617}")
|
||||
|
||||
Context();
|
||||
virtual ~Context();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component
|
||||
virtual void Init();
|
||||
virtual void Activate();
|
||||
virtual void Deactivate();
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EditorFramework CoreMessages
|
||||
virtual void OnRestoreState(); // sent when everything is registered up and ready to go, this is what bootstraps stuff to get going.
|
||||
virtual bool OnGetPermissionToShutDown();
|
||||
virtual bool CheckOkayToShutDown();
|
||||
virtual void OnSaveState(); // sent to everything when the app is about to shut down - do what you need to do.
|
||||
virtual void OnDestroyState();
|
||||
virtual void ApplicationDeactivated();
|
||||
virtual void ApplicationActivated();
|
||||
virtual void ApplicationShow(AZ::Uuid id);
|
||||
virtual void ApplicationHide(AZ::Uuid id);
|
||||
virtual void ApplicationCensus();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EditorFramework::AssetManagementMessages
|
||||
//virtual bool RawFileOpenRequested(const EditorFramework::RegisteredAssetType& registeredTypeID, const char *fullPathName);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void ShowDrillerView();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// internal data structure for the class/member/property reference panel
|
||||
// this is what we serialize and work with
|
||||
DrillerMainWindow* m_pDrillerMainWindow;
|
||||
|
||||
private:
|
||||
|
||||
// utility
|
||||
void ProvisionalShowAndFocus(bool forceShow = false, bool forceHide = false);
|
||||
};
|
||||
|
||||
class ClassReferenceItem
|
||||
: public QStandardItem
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ClassReferenceItem, AZ::SystemAllocator, 0);
|
||||
|
||||
ClassReferenceItem(const QIcon& icon, const QString& text, size_t id);
|
||||
ClassReferenceItem(const QString& text, size_t id);
|
||||
~ClassReferenceItem() {}
|
||||
|
||||
size_t GetTypeID() {return m_ID; }
|
||||
protected:
|
||||
size_t m_ID;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLERCONTEXTINTERFACE_H
|
||||
#define DRILLERCONTEXTINTERFACE_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzToolsFramework/UI/LegacyFramework/Core/EditorContextBus.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class ContextInterface
|
||||
: public LegacyFramework::EditorContextMessages
|
||||
{
|
||||
public:
|
||||
typedef AZ::EBus<ContextInterface> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
virtual void ShowDrillerView() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLERCONTEXTINTERFACE_H
|
||||
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerDataContainer.h"
|
||||
|
||||
#include <AzCore/Driller/Stream.h>
|
||||
#include <AzCore/Driller/DrillerRootHandler.h>
|
||||
#include <AzCore/Driller/DefaultStringPool.h>
|
||||
|
||||
#include <AzCore/IO/SystemFile.h> // temp for DebugHackProcessFile
|
||||
|
||||
#include <AzCore/XML/rapidxml_print.h> // metadata is stored this way
|
||||
|
||||
#include "Unsupported/UnsupportedDataAggregator.hxx"
|
||||
#include "Memory/MemoryDataAggregator.hxx"
|
||||
#include "Trace/TraceMessageDataAggregator.hxx"
|
||||
#include "Profiler/ProfilerDataAggregator.hxx"
|
||||
#include "Carrier/CarrierDataAggregator.hxx"
|
||||
#include "Replica/ReplicaDataAggregator.hxx"
|
||||
#include "Rendering/VRAM/VRAMDataAggregator.hxx"
|
||||
#include "EventTrace/EventTraceDataAggregator.h"
|
||||
// IMPORTANT: include new aggregators above
|
||||
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class DrillerDataHandler : public AZ::Debug::DrillerHandlerParser
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(DrillerDataHandler,AZ::SystemAllocator,0)
|
||||
|
||||
DrillerDataHandler(int identity, DrillerDataContainer* container)
|
||||
: AZ::Debug::DrillerHandlerParser(/*true*/false)
|
||||
, m_identity(identity)
|
||||
, m_currentFrame(-1)
|
||||
, m_dataContainer(container)
|
||||
, m_dataParser(nullptr)
|
||||
{
|
||||
m_drillerSessionInfo.m_platform = static_cast<int>(AZ::g_currentPlatform); /// Init with current platform so no endian swapping till we read all the initial settings.
|
||||
m_inputStream.SetStringPool(&m_stringPool);
|
||||
m_dataParser = aznew AZ::Debug::DrillerSAXParserHandler(this);
|
||||
}
|
||||
|
||||
~DrillerDataHandler()
|
||||
{
|
||||
delete m_dataParser;
|
||||
}
|
||||
|
||||
virtual AZ::Debug::DrillerHandlerParser* OnEnterTag(AZ::u32 tagName)
|
||||
{
|
||||
if( tagName == AZ_CRC("StartData", 0xecf3f53f) )
|
||||
return &m_drillerSessionInfo;
|
||||
if( tagName == AZ_CRC("Frame", 0xb5f83ccd) )
|
||||
return this;
|
||||
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
|
||||
{
|
||||
if( (*it)->GetDrillerId() == tagName )
|
||||
return (*it)->GetDrillerDataParser();
|
||||
}
|
||||
|
||||
AZ_TracePrintf("Driller", "We should never get here as we should have added 'Unsupported driller(s)' in OnExitTag('StartData')");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void OnExitTag(DrillerHandlerParser* handler, AZ::u32 tagName)
|
||||
{
|
||||
(void)handler;
|
||||
if( tagName == AZ_CRC("StartData", 0xecf3f53f) )
|
||||
{
|
||||
// create all drillers that were in the session data
|
||||
for(AZ::Debug::DrillerManager::DrillerListType::iterator itDriller = m_drillerSessionInfo.m_drillers.begin(); itDriller != m_drillerSessionInfo.m_drillers.end(); ++itDriller )
|
||||
{
|
||||
AZ::u32 drillerId = itDriller->id;
|
||||
bool isCreated = false;
|
||||
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
|
||||
{
|
||||
if( (*it)->GetDrillerId() == drillerId )
|
||||
{
|
||||
isCreated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !isCreated )
|
||||
{
|
||||
// Create the aggregator, if the driller is missing add UnsupportedAggregator
|
||||
Aggregator* aggr = m_dataContainer->CreateAggregator(drillerId, true);
|
||||
if( aggr )
|
||||
m_dataContainer->m_aggregators.push_back(aggr);
|
||||
|
||||
// two ways to add aggregators:
|
||||
// 1) "NewAggregatorList" send an entire list which replaces the current setup, which is most efficient
|
||||
// 2) "AddAggregator" send a single aggregator which gets appended
|
||||
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus,AddAggregator, *m_dataContainer->m_aggregators.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode)
|
||||
{
|
||||
if( dataNode.m_name == AZ_CRC("FrameNum", 0x85a1a919) )
|
||||
{
|
||||
// Send event that previous frame has finished
|
||||
if( m_currentFrame != -1 )
|
||||
{
|
||||
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus,EndFrame, m_currentFrame);
|
||||
}
|
||||
dataNode.Read(m_currentFrame);
|
||||
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
|
||||
{
|
||||
(*it)->AddNewFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessStream(const char* streamIdentifier, const void* data, unsigned int dataSize)
|
||||
{
|
||||
m_inputStream.SetData(streamIdentifier, data, dataSize);
|
||||
m_dataParser->ProcessStream(m_inputStream);
|
||||
}
|
||||
|
||||
AZ::Debug::DrillerStartdataHandler m_drillerSessionInfo;
|
||||
int m_currentFrame;
|
||||
DrillerDataContainer* m_dataContainer;
|
||||
AZ::Debug::DrillerSAXParserHandler* m_dataParser;
|
||||
AZ::Debug::DrillerInputMemoryStream m_inputStream;
|
||||
AZ::Debug::DrillerDefaultStringPool m_stringPool;
|
||||
int m_identity;
|
||||
};
|
||||
|
||||
DrillerDataContainer::DrillerDataContainer(int identity, const char* tmpCaptureFilename)
|
||||
: m_dataHandler(nullptr)
|
||||
, m_identity(identity)
|
||||
, m_tmpCaptureFilename(tmpCaptureFilename)
|
||||
{
|
||||
AzFramework::DrillerNetworkConsoleEventBus::Handler::BusConnect();
|
||||
EBUS_EVENT(AzFramework::DrillerNetworkConsoleCommandBus, EnumerateAvailableDrillers);
|
||||
}
|
||||
|
||||
DrillerDataContainer::~DrillerDataContainer()
|
||||
{
|
||||
AzFramework::DrillerNetworkConsoleEventBus::Handler::BusDisconnect();
|
||||
DestroyAggregators();
|
||||
|
||||
delete m_dataHandler;
|
||||
}
|
||||
|
||||
void DrillerDataContainer::OnReceivedDrillerEnumeration(const AzFramework::DrillerInfoListType& availableDrillers)
|
||||
{
|
||||
// TODO: Decide how the available driller list should influence the behavior of the driller
|
||||
// display. For now we will display whatever is available.
|
||||
m_availableDrillers = availableDrillers;
|
||||
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, NewAggregatorsAvailable);
|
||||
}
|
||||
|
||||
void DrillerDataContainer::CreateAggregators()
|
||||
{
|
||||
DestroyAggregators();
|
||||
|
||||
if (m_availableDrillers.size())
|
||||
{
|
||||
for (size_t i = 0; i < m_availableDrillers.size(); ++i)
|
||||
{
|
||||
Aggregator* aggr = CreateAggregator(m_availableDrillers[i].m_id, true);
|
||||
if( aggr )
|
||||
m_aggregators.push_back(aggr);
|
||||
}
|
||||
}
|
||||
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, NewAggregatorList,m_aggregators);
|
||||
}
|
||||
|
||||
void DrillerDataContainer::DestroyAggregators()
|
||||
{
|
||||
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, DiscardAggregators);
|
||||
|
||||
for(DrillerNetworkMessages::AggregatorList::iterator it = m_aggregators.begin(); it != m_aggregators.end(); ++it )
|
||||
delete *it;
|
||||
m_aggregators.clear();
|
||||
}
|
||||
|
||||
Aggregator* DrillerDataContainer::CreateAggregator(AZ::u32 id, bool createUnsupported)
|
||||
{
|
||||
if( id == MemoryDataAggregator::DrillerId() )
|
||||
{
|
||||
return aznew MemoryDataAggregator(m_identity);
|
||||
}
|
||||
else if( id == TraceMessageDataAggregator::DrillerId() )
|
||||
{
|
||||
return aznew TraceMessageDataAggregator(m_identity);
|
||||
}
|
||||
else if (id == ProfilerDataAggregator::DrillerId() )
|
||||
{
|
||||
return aznew ProfilerDataAggregator(m_identity);
|
||||
}
|
||||
else if(id == CarrierDataAggregator::DrillerId())
|
||||
{
|
||||
return aznew CarrierDataAggregator(m_identity);
|
||||
}
|
||||
else if(id == ReplicaDataAggregator::DrillerId())
|
||||
{
|
||||
return aznew ReplicaDataAggregator(m_identity);
|
||||
}
|
||||
else if(id == VRAM::VRAMDataAggregator::DrillerId())
|
||||
{
|
||||
return aznew VRAM::VRAMDataAggregator(m_identity);
|
||||
}
|
||||
else if (id == EventTraceDataAggregator::DrillerId())
|
||||
{
|
||||
return aznew EventTraceDataAggregator(m_identity);
|
||||
}
|
||||
// IMPORTANT: Add new aggregators here
|
||||
|
||||
return createUnsupported ? aznew UnsupportedDataAggregator(id) : nullptr;
|
||||
}
|
||||
|
||||
void DrillerDataContainer::ProcessIncomingDrillerData(const char* streamIdentifier, const void* data, size_t dataSize)
|
||||
{
|
||||
AZ_Assert(m_dataHandler,"You must have a valid data handler parser to parse the data!");
|
||||
m_dataHandler->ProcessStream(streamIdentifier, data, static_cast<unsigned int>(dataSize));
|
||||
}
|
||||
|
||||
void DrillerDataContainer::OnDrillerConnectionLost()
|
||||
{
|
||||
StopDrilling();
|
||||
}
|
||||
|
||||
void DrillerDataContainer::StartDrilling()
|
||||
{
|
||||
DrillerEvent::ResetGlobalEventId();
|
||||
|
||||
AzFramework::DrillerListType drillersToStart;
|
||||
for(DrillerNetworkMessages::AggregatorList::iterator it = m_aggregators.begin(); it != m_aggregators.end(); ++it)
|
||||
{
|
||||
(*it)->Reset();
|
||||
|
||||
if ((*it)->IsCaptureEnabled())
|
||||
{
|
||||
drillersToStart.push_back((*it)->GetDrillerId());
|
||||
}
|
||||
}
|
||||
if (drillersToStart.size())
|
||||
{
|
||||
delete m_dataHandler;
|
||||
m_dataHandler = aznew DrillerDataHandler(m_identity, this);
|
||||
|
||||
AzFramework::DrillerRemoteSession::StartDrilling(drillersToStart, m_tmpCaptureFilename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerDataContainer::LoadCaptureData(const char* fileName)
|
||||
{
|
||||
DrillerEvent::ResetGlobalEventId();
|
||||
// Reset data
|
||||
DestroyAggregators();
|
||||
|
||||
AZStd::string baseFilename( fileName );
|
||||
|
||||
delete m_dataHandler;
|
||||
m_dataHandler = aznew DrillerDataHandler(m_identity, this);
|
||||
AzFramework::DrillerRemoteSession::LoadCaptureData(fileName);
|
||||
}
|
||||
|
||||
void DrillerDataContainer::CloseCaptureData()
|
||||
{
|
||||
StopDrilling();
|
||||
DestroyAggregators();
|
||||
}
|
||||
|
||||
void DrillerDataContainer::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
MemoryDataAggregator::Reflect(context);
|
||||
TraceMessageDataAggregator::Reflect(context);
|
||||
ProfilerDataAggregator::Reflect(context);
|
||||
ReplicaDataAggregator::Reflect(context);
|
||||
}
|
||||
|
||||
}//namespace Driller
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLER_DATA_CONTAINER
|
||||
#define DRILLER_DRILLER_DATA_CONTAINER
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#include "DrillerNetworkMessages.h"
|
||||
|
||||
#include "AzFramework/Driller/RemoteDrillerInterface.h"
|
||||
|
||||
namespace DH
|
||||
{
|
||||
namespace Debug
|
||||
{
|
||||
class DrillerInputMemoryStream;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class DrillerDataHandler;
|
||||
|
||||
/**
|
||||
* Driller data container. Contains all the data (aggregators)
|
||||
* for a driller session. It interfaces with with DrillerSession
|
||||
* for local file caching (TODO) and remote data transfer.
|
||||
*/
|
||||
class DrillerDataContainer
|
||||
: public AzFramework::DrillerRemoteSession
|
||||
, public AzFramework::DrillerNetworkConsoleEventBus::Handler
|
||||
{
|
||||
friend class DrillerDataHandler;
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(DrillerDataContainer, AZ::SystemAllocator, 0)
|
||||
|
||||
DrillerDataContainer(int identity, const char* tmpCaptureFilename);
|
||||
~DrillerDataContainer();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DrillerRemoteSession
|
||||
virtual void ProcessIncomingDrillerData(const char* streamIdentifier, const void* data, size_t dataSize);
|
||||
virtual void OnDrillerConnectionLost();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DrillerNetworkConsoleEvents
|
||||
virtual void OnReceivedDrillerEnumeration(const AzFramework::DrillerInfoListType& availableDrillers);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StartDrilling();
|
||||
void LoadCaptureData(const char* fileName);
|
||||
void CloseCaptureData();
|
||||
void CreateAggregators();
|
||||
|
||||
protected:
|
||||
void DestroyAggregators();
|
||||
Aggregator* CreateAggregator(AZ::u32 id, bool createUnsupported = false);
|
||||
|
||||
DrillerNetworkMessages::AggregatorList m_aggregators;
|
||||
DrillerDataHandler* m_dataHandler;
|
||||
AzFramework::DrillerInfoListType m_availableDrillers;
|
||||
AZStd::string m_tmpCaptureFilename;
|
||||
int m_identity;
|
||||
|
||||
public:
|
||||
// data container is the one place that knows about all the aggregators
|
||||
// and indeed is responsible for creating them
|
||||
// and thus the best place to centralize their reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLER_DRILLER_DATA_CONTAINER
|
||||
#pragma once
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DATATYPES_H
|
||||
#define DRILLER_DATATYPES_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
typedef AZ::s32 FrameNumberType;
|
||||
typedef AZ::s64 EventNumberType;
|
||||
|
||||
static const EventNumberType kInvalidEventIndex = -1;
|
||||
|
||||
enum class CaptureMode
|
||||
{
|
||||
Unknown,
|
||||
Configuration,
|
||||
Capturing,
|
||||
Inspecting
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerEvent.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Globals
|
||||
unsigned int DrillerEvent::s_globalEventId = 0;
|
||||
} // namespace Driller
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLER_EVENT_H
|
||||
#define DRILLER_DRILLER_EVENT_H
|
||||
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class Aggregator;
|
||||
|
||||
/**
|
||||
* Base class for a driller events. All events collected in aggregators should use this class as a base.
|
||||
*
|
||||
* IMPORTANT: It's very important to note that DrillerEvents will NEVER be removed during a driller session
|
||||
* this allows you to RELY on the fact that data which the event contains will be present at all times. This is important
|
||||
* because it's heavily used to support StepBackward/StepForward in sequential driller events (almost all driller events are deltas
|
||||
* and in that sense they are sequential - we can't just jump to a state directly).
|
||||
*/
|
||||
class DrillerEvent
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(DrillerEvent, "{3B0B15CF-A359-47AA-B8D3-DCEFA39BD097}");
|
||||
DrillerEvent(unsigned int eventType)
|
||||
: m_eventType(eventType)
|
||||
, m_globalEventId(s_globalEventId++) {}
|
||||
virtual ~DrillerEvent() {}
|
||||
|
||||
virtual void StepForward(Aggregator* data) = 0;
|
||||
virtual void StepBackward(Aggregator* data) = 0;
|
||||
|
||||
static inline unsigned int GetNumGlobalEvents() { return s_globalEventId; }
|
||||
static inline void ResetGlobalEventId() { s_globalEventId = 0; }
|
||||
|
||||
unsigned int GetGlobalEventId() const { return m_globalEventId; }
|
||||
unsigned int GetEventType() const { return m_eventType; }
|
||||
|
||||
protected:
|
||||
unsigned int m_eventType;
|
||||
unsigned int m_globalEventId; ///< Event unique ID, which is the global event index (in order) too.
|
||||
|
||||
private:
|
||||
static unsigned int s_globalEventId; ///< Current number of events used in all aggregators.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,147 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>channelsViewWidget</class>
|
||||
<widget class="QWidget" name="channelsViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1041</width>
|
||||
<height>777</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Channels View</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="UIFramework::DHAutoSizingScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1018</width>
|
||||
<height>591</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="channelLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollBar" name="controlScrollBar">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Driller::AnnotationHeaderView_Events" name="eventAnnotationView" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Driller::CombinedEventsControl" name="combinedEventsWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::CombinedEventsControl</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>combinedeventscontrol.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Driller::AnnotationHeaderView_Events</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Source/riller/Annotations/annotationsheaderview_events.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIFramework::DHAutoSizingScrollArea</class>
|
||||
<extends>QScrollArea</extends>
|
||||
<header>UICore/DHAutoSizingScrollArea.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerMainWindow.hxx"
|
||||
#include <Source/Driller/moc_DrillerMainWindow.cpp>
|
||||
|
||||
#include "DrillerCaptureWindow.hxx"
|
||||
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
#include "DrillerAggregator.hxx"
|
||||
#include "ChannelControl.hxx"
|
||||
#include "CombinedEventsControl.hxx"
|
||||
#include "DrillerDataContainer.h"
|
||||
#include "Workspaces/Workspace.h"
|
||||
|
||||
#include <AzToolsFramework/UI/LegacyFramework/UIFrameworkAPI.h>
|
||||
#include <AzToolsFramework/UI/LegacyFramework/CustomMenus/CustomMenusAPI.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/delegate/delegate.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
#include <QtGui/QPalette>
|
||||
|
||||
#include <AzCore/std/sort.h>
|
||||
|
||||
#include <Source/Driller/ui_DrillerMainWindow.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QTabBar>
|
||||
#include <QCloseEvent>
|
||||
#include <QStandardPaths>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace Driller::MainWindow
|
||||
{
|
||||
const char* drillerDebugName = "Driller";
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class DrillerMainWindowSavedState
|
||||
: public AzToolsFramework::MainWindowSavedState
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(DrillerMainWindowSavedState, "{77A8D5DB-38EB-4F9B-BEA2-F42D725A8177}", AzToolsFramework::MainWindowSavedState);
|
||||
AZ_CLASS_ALLOCATOR(DrillerMainWindowSavedState, AZ::SystemAllocator, 0);
|
||||
|
||||
AZStd::string m_priorSaveFolder;
|
||||
AZStd::string m_priorOpenFolder;
|
||||
|
||||
DrillerMainWindowSavedState() {}
|
||||
|
||||
void Init(const QByteArray& windowState, const QByteArray& windowGeom)
|
||||
{
|
||||
AzToolsFramework::MainWindowSavedState::Init(windowState, windowGeom);
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DrillerMainWindowSavedState, AzToolsFramework::MainWindowSavedState >()
|
||||
->Field("m_priorSaveFolder", &DrillerMainWindowSavedState::m_priorSaveFolder)
|
||||
->Field("m_priorOpenFolder", &DrillerMainWindowSavedState::m_priorOpenFolder)
|
||||
->Version(8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// WORKSPACES are files loaded and stored independent of the global application
|
||||
// designed to be used for DRL data specific view settings and to pass around
|
||||
class DrillerMainWindowWorkspace
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(DrillerMainWindowWorkspace, "{E7DAC981-84E9-490E-AF1B-DADC116B3B10}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(DrillerMainWindowWorkspace, AZ::SystemAllocator, 0);
|
||||
|
||||
AZStd::vector<AZStd::string> m_openDataFileNames;
|
||||
|
||||
DrillerMainWindowWorkspace() {}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DrillerMainWindowWorkspace>()
|
||||
->Field("m_openDataFileNames", &DrillerMainWindowWorkspace::m_openDataFileNames)
|
||||
->Version(8);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
extern AZ::Uuid ContextID;
|
||||
|
||||
Driller::DrillerMainWindow* s_drillerMainWindowScriptPtr = NULL; // for script access
|
||||
|
||||
int DrillerMainWindow::m_ascendingIdentity = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//DrillerMainWindow
|
||||
DrillerMainWindow::DrillerMainWindow(QWidget* parent, Qt::WindowFlags flags)
|
||||
: QMainWindow(parent, flags)
|
||||
{
|
||||
s_drillerMainWindowScriptPtr = this;
|
||||
|
||||
m_isLoadingFile = false;
|
||||
m_panningMainView = false;
|
||||
m_panningMainViewStartPoint = 0;
|
||||
|
||||
m_gui = azcreate(Ui::DrillerMainWindow, ());
|
||||
m_gui->setupUi(this);
|
||||
|
||||
QMenu* theMenu = new QMenu(this);
|
||||
(void)theMenu->addAction(
|
||||
"Close Profiler App",
|
||||
this,
|
||||
SLOT(OnMenuCloseCurrentWindow()),
|
||||
QKeySequence("Alt+F4")
|
||||
);
|
||||
|
||||
EBUS_EVENT(AzToolsFramework::FrameworkMessages::Bus, PopulateApplicationMenu, theMenu);
|
||||
menuBar()->insertMenu(m_gui->menuDriller->menuAction(), theMenu);
|
||||
|
||||
connect(m_gui->actionContract, SIGNAL(triggered()), this, SLOT(OnContractAllChannels()));
|
||||
connect(m_gui->actionExpand, SIGNAL(triggered()), this, SLOT(OnExpandAllChannels()));
|
||||
connect(m_gui->actionDisable, SIGNAL(triggered()), this, SLOT(OnDisableAllChannels()));
|
||||
connect(m_gui->actionEnable, SIGNAL(triggered()), this, SLOT(OnEnableAllChannels()));
|
||||
|
||||
DrillerDataViewMessages::Handler::BusConnect();
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(RestoreWindowState()));
|
||||
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusConnect();
|
||||
|
||||
m_gui->actionSave->setEnabled(false);
|
||||
m_gui->actionSaveWorkspace->setEnabled(true);
|
||||
|
||||
// default identity == 0 Live tab
|
||||
auto captureWindow = aznew DrillerCaptureWindow(CaptureMode::Configuration, m_ascendingIdentity, this);
|
||||
captureWindow->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
m_captureWindows.insert(AZStd::make_pair(captureWindow, m_ascendingIdentity));
|
||||
++m_ascendingIdentity;
|
||||
|
||||
m_gui->tabbedContents->addTab(captureWindow, QString("LIVE"));
|
||||
|
||||
// Enabling close buttons on our widgets, and hiding the close button on the live
|
||||
// tab for now.
|
||||
m_gui->tabbedContents->setTabsClosable(true);
|
||||
m_gui->tabbedContents->tabBar()->setTabButton(0, QTabBar::ButtonPosition::RightSide, nullptr);
|
||||
m_gui->tabbedContents->tabBar()->setTabButton(0, QTabBar::ButtonPosition::LeftSide, nullptr);
|
||||
|
||||
connect(m_gui->tabbedContents, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)));
|
||||
connect(m_gui->tabbedContents, SIGNAL(tabCloseRequested(int)), this, SLOT(CloseTab(int)));
|
||||
|
||||
connect(captureWindow, SIGNAL(destroyed(QObject*)), this, SLOT(OnCaptureWindowDestroyed(QObject*)));
|
||||
|
||||
EBUS_EVENT(LegacyFramework::CustomMenusMessages::Bus, RegisterMenu, LegacyFramework::CustomMenusCommon::Driller::Application, theMenu);
|
||||
EBUS_EVENT(LegacyFramework::CustomMenusMessages::Bus, RegisterMenu, LegacyFramework::CustomMenusCommon::Driller::DrillerMenu, m_gui->menuDriller);
|
||||
EBUS_EVENT(LegacyFramework::CustomMenusMessages::Bus, RegisterMenu, LegacyFramework::CustomMenusCommon::Driller::Channels, m_gui->menuChannels);
|
||||
|
||||
UpdateTabBarDisplay();
|
||||
}
|
||||
|
||||
DrillerMainWindow::~DrillerMainWindow(void)
|
||||
{
|
||||
AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect();
|
||||
|
||||
s_drillerMainWindowScriptPtr = NULL;
|
||||
DrillerDataViewMessages::Handler::BusDisconnect();
|
||||
|
||||
azdestroy(m_gui);
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnTabChanged(int toWhich)
|
||||
{
|
||||
// first tab is always Live
|
||||
if (toWhich)
|
||||
{
|
||||
m_gui->actionSave->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gui->actionSave->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::CloseTab(int closeTab)
|
||||
{
|
||||
// We never want to close the live tab.
|
||||
if (closeTab != 0)
|
||||
{
|
||||
DrillerCaptureWindow* captureWindow = static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->widget(closeTab));
|
||||
|
||||
if (captureWindow)
|
||||
{
|
||||
captureWindow->OnClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnCaptureWindowDestroyed(QObject* cWindow)
|
||||
{
|
||||
auto captureWindow = static_cast<DrillerCaptureWindow*>(cWindow);
|
||||
m_gui->tabbedContents->removeTab(m_gui->tabbedContents->indexOf(captureWindow));
|
||||
m_captureWindows.erase(captureWindow);
|
||||
|
||||
UpdateTabBarDisplay();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Data Viewer Request Messages
|
||||
void DrillerMainWindow::EventRequestOpenFile(AZStd::string fileName)
|
||||
{
|
||||
OnOpenDrillerFile(fileName.c_str());
|
||||
}
|
||||
void DrillerMainWindow::EventRequestOpenWorkspace(AZStd::string fileName)
|
||||
{
|
||||
OnOpenWorkspaceFile(fileName.c_str(), true);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GUI Messages
|
||||
void DrillerMainWindow::OnMenuCloseCurrentWindow()
|
||||
{
|
||||
AZ_TracePrintf(Driller::MainWindow::drillerDebugName, "Close requested\n");
|
||||
|
||||
SaveWindowState();
|
||||
|
||||
EBUS_EVENT(AzToolsFramework::FrameworkMessages::Bus, RequestMainWindowClose, ContextID);
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnOpen()
|
||||
{
|
||||
AZ_TracePrintf(Driller::MainWindow::drillerDebugName, "Open requested\n");
|
||||
|
||||
this->show();
|
||||
emit ShowYourself();
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnClose()
|
||||
{
|
||||
AZ_TracePrintf(Driller::MainWindow::drillerDebugName, "Close requested of window (not file)\n");
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnContractAllChannels()
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnContractAllChannels();
|
||||
}
|
||||
void DrillerMainWindow::OnExpandAllChannels()
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnExpandAllChannels();
|
||||
}
|
||||
void DrillerMainWindow::OnDisableAllChannels()
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnDisableAllChannels();
|
||||
}
|
||||
void DrillerMainWindow::OnEnableAllChannels()
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnEnableAllChannels();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// when the Editor Main window is requested to close, it is not destroyed.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Qt Events
|
||||
void DrillerMainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
OnMenuCloseCurrentWindow();
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void DrillerMainWindow::showEvent(QShowEvent* /*event*/)
|
||||
{
|
||||
emit ShowYourself();
|
||||
}
|
||||
void DrillerMainWindow::hideEvent(QHideEvent* /*event*/)
|
||||
{
|
||||
emit HideYourself();
|
||||
}
|
||||
|
||||
bool DrillerMainWindow::OnGetPermissionToShutDown()
|
||||
{
|
||||
for (auto idx = 0; idx < m_gui->tabbedContents->count(); ++idx)
|
||||
{
|
||||
bool willShutDown = static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->widget(idx))->OnGetPermissionToShutDown();
|
||||
if (!willShutDown)
|
||||
{
|
||||
AZ_TracePrintf(Driller::MainWindow::drillerDebugName, " ShutDown Denied\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_TracePrintf(Driller::MainWindow::drillerDebugName, " willShutDown == 1\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrillerMainWindow::SaveWindowState()
|
||||
{
|
||||
// build state and store it.
|
||||
auto newState = AZ::UserSettings::CreateFind<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
newState->Init(saveState(), saveGeometry());
|
||||
|
||||
for (auto iter = m_captureWindows.begin(); iter != m_captureWindows.end(); ++iter)
|
||||
{
|
||||
iter->first->SaveWindowState();
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::UpdateTabBarDisplay()
|
||||
{
|
||||
// We will always have one window open(live), and we don't want to show
|
||||
// the tab bar unless we have more then one.
|
||||
m_gui->tabbedContents->tabBar()->setVisible(m_captureWindows.size() > 1);
|
||||
}
|
||||
|
||||
void DrillerMainWindow::RestoreWindowState() // call this after you have rebuilt everything.
|
||||
{
|
||||
// load the state from our state block:
|
||||
auto savedState = AZ::UserSettings::Find<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
if (savedState)
|
||||
{
|
||||
QByteArray geomData((const char*)savedState->m_windowGeometry.data(), (int)savedState->m_windowGeometry.size());
|
||||
QByteArray stateData((const char*)savedState->GetWindowState().data(), (int)savedState->GetWindowState().size());
|
||||
|
||||
restoreGeometry(geomData);
|
||||
if (this->isMaximized())
|
||||
{
|
||||
this->showNormal();
|
||||
this->showMaximized();
|
||||
}
|
||||
restoreState(stateData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// default state!
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnOpenDrillerFile()
|
||||
{
|
||||
QString capturePath;
|
||||
|
||||
auto newState = AZ::UserSettings::CreateFind<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
if (!newState->m_priorOpenFolder.empty())
|
||||
{
|
||||
capturePath = newState->m_priorOpenFolder.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
|
||||
if (capturePath.isEmpty())
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
}
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Open Driller File", capturePath, "Driller Files (*.drl)");
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
OnOpenDrillerFile(fileName);
|
||||
newState->m_priorOpenFolder = QFileInfo(fileName).dir().canonicalPath().toUtf8().data();
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnOpenDrillerFile(QString fileName)
|
||||
{
|
||||
auto captureWindow = aznew DrillerCaptureWindow(CaptureMode::Inspecting, m_ascendingIdentity, this);
|
||||
if (captureWindow)
|
||||
{
|
||||
m_captureWindows.insert(AZStd::make_pair(captureWindow, m_ascendingIdentity));
|
||||
++m_ascendingIdentity;
|
||||
|
||||
captureWindow->OnOpenDrillerFile(fileName);
|
||||
connect(captureWindow, SIGNAL(destroyed(QObject*)), this, SLOT(OnCaptureWindowDestroyed(QObject*)));
|
||||
|
||||
m_gui->tabbedContents->setCurrentIndex(m_gui->tabbedContents->addTab(captureWindow, fileName));
|
||||
UpdateTabBarDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnOpenWorkspaceFile()
|
||||
{
|
||||
QString capturePath;
|
||||
|
||||
auto newState = AZ::UserSettings::CreateFind<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
if (!newState->m_priorOpenFolder.empty())
|
||||
{
|
||||
capturePath = newState->m_priorOpenFolder.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (capturePath.isEmpty())
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
}
|
||||
}
|
||||
|
||||
QString workspaceFileName = QFileDialog::getOpenFileName(this, tr("Open Workspace File"), capturePath, tr("Workspace Files (*.drw)"));
|
||||
if (!workspaceFileName.isNull())
|
||||
{
|
||||
OnOpenWorkspaceFile(workspaceFileName, true);
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnOpenWorkspaceFile(QString workspaceFileName, bool openDrillerFileAlso)
|
||||
{
|
||||
auto captureWindow = aznew DrillerCaptureWindow(CaptureMode::Inspecting, m_ascendingIdentity, this);
|
||||
if (captureWindow)
|
||||
{
|
||||
m_captureWindows.insert(AZStd::make_pair(captureWindow, m_ascendingIdentity));
|
||||
++m_ascendingIdentity;
|
||||
|
||||
captureWindow->OnOpenWorkspaceFile(workspaceFileName, openDrillerFileAlso);
|
||||
connect(captureWindow, SIGNAL(destroyed(QObject*)), this, SLOT(OnCaptureWindowDestroyed(QObject*)));
|
||||
|
||||
m_gui->tabbedContents->setCurrentIndex(m_gui->tabbedContents->addTab(captureWindow, captureWindow->GetDataFileName()));
|
||||
UpdateTabBarDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnApplyWorkspaceFile()
|
||||
{
|
||||
QString capturePath;
|
||||
|
||||
auto newState = AZ::UserSettings::CreateFind<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
if (!newState->m_priorOpenFolder.empty())
|
||||
{
|
||||
capturePath = newState->m_priorOpenFolder.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (capturePath.isEmpty())
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
}
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Apply Workspace", capturePath, "Workspace Files (*.drw)");
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnApplyWorkspaceFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void DrillerMainWindow::OnSaveWorkspaceFile()
|
||||
{
|
||||
QString capturePath;
|
||||
|
||||
auto newState = AZ::UserSettings::CreateFind<DrillerMainWindowSavedState>(AZ_CRC("DRILLER MAIN WINDOW STATE", 0x9c98b7f6), AZ::UserSettings::CT_GLOBAL);
|
||||
if (!newState->m_priorOpenFolder.empty())
|
||||
{
|
||||
capturePath = newState->m_priorOpenFolder.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
if (capturePath.isEmpty())
|
||||
{
|
||||
capturePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
}
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, "Save Workspace", capturePath, "Workspace Files (*.drw)");
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
static_cast<DrillerCaptureWindow*>(m_gui->tabbedContents->currentWidget())->OnSaveWorkspaceFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Target Manager Messages
|
||||
void DrillerMainWindow::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
// data container is the one place that knows about all the aggregators
|
||||
// and indeed is responsible for creating them
|
||||
Driller::WorkspaceSettingsProvider::Reflect(context);
|
||||
DrillerMainWindowWorkspace::Reflect(context);
|
||||
DrillerMainWindowSavedState::Reflect(context);
|
||||
DrillerCaptureWindow::Reflect(context);
|
||||
|
||||
// reflect data for script, serialization, editing...
|
||||
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<DrillerMainWindow>("DrillerMainWindow")->
|
||||
Method("ShowWindow", &DrillerMainWindow::OnOpen)->
|
||||
Method("HideWindow", &DrillerMainWindow::OnClose);
|
||||
|
||||
behaviorContext->Property("DrillerMainWindow", BehaviorValueGetter(&s_drillerMainWindowScriptPtr), nullptr);
|
||||
}
|
||||
}
|
||||
}//namespace Driller
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLERMAINWINDOW_H
|
||||
#define DRILLER_DRILLERMAINWINDOW_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
|
||||
#include <AzToolsFramework/UI/LegacyFramework/MainWindowSavedState.h>
|
||||
#include "Workspaces/Workspace.h"
|
||||
#include "DrillerNetworkMessages.h"
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
class QMenu;
|
||||
class QAction;
|
||||
class QToolbar;
|
||||
class QDockWidget;
|
||||
class QSettings;
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DrillerMainWindow;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class ChannelControl;
|
||||
class DrillerDataContainer;
|
||||
class CombinedEventsControl;
|
||||
class DrillerCaptureWindow;
|
||||
|
||||
/*
|
||||
Driller Main Window : Now with simultaneous data sets
|
||||
|
||||
Home of the real commands, channels created from external aggregators when connected, and the floating control panel.
|
||||
All inputs end up here where they are interpreted and passed downwards to all channels, to maintain consistency.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Main Window
|
||||
class DrillerMainWindow
|
||||
: public QMainWindow
|
||||
, public Driller::DrillerDataViewMessages::Bus::Handler
|
||||
, private AzFramework::TargetManagerClient::Bus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_TYPE_INFO(DrillerMainWindow, "{91E48678-AEF8-474F-BB20-DDC51ACAA43A}");
|
||||
AZ_CLASS_ALLOCATOR(DrillerMainWindow,AZ::SystemAllocator,0);
|
||||
DrillerMainWindow(QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~DrillerMainWindow(void);
|
||||
DrillerMainWindow(const DrillerMainWindow&)
|
||||
{
|
||||
// TODO: Once AZ_NO_COPY macros is in the branch in use it!
|
||||
AZ_Assert(false, "You can't copy this class!");
|
||||
}
|
||||
|
||||
bool OnGetPermissionToShutDown();
|
||||
|
||||
public:
|
||||
|
||||
// Data Viewer request messages
|
||||
void EventRequestOpenFile(AZStd::string fileName) override;
|
||||
void EventRequestOpenWorkspace(AZStd::string fileName) override;
|
||||
|
||||
public:
|
||||
// MainWindow Messages and states.
|
||||
void SaveWindowState();
|
||||
|
||||
private:
|
||||
// internal workings
|
||||
void UpdateTabBarDisplay();
|
||||
|
||||
protected:
|
||||
static int m_ascendingIdentity;
|
||||
AZStd::map<DrillerCaptureWindow*, int> m_captureWindows;
|
||||
|
||||
// Qt Events
|
||||
virtual void closeEvent(QCloseEvent* event);
|
||||
virtual void showEvent( QShowEvent * event );
|
||||
virtual void hideEvent( QHideEvent * event );
|
||||
|
||||
bool m_panningMainView;
|
||||
int m_panningMainViewStartPoint;
|
||||
|
||||
QString m_tmpCaptureFilename;
|
||||
QString m_currentDataFilename;
|
||||
|
||||
bool m_isLoadingFile;
|
||||
bool m_bForceNextScrub;
|
||||
|
||||
public slots:
|
||||
void RestoreWindowState();
|
||||
void OnMenuCloseCurrentWindow();
|
||||
void OnOpen();
|
||||
void OnClose();
|
||||
void OnContractAllChannels();
|
||||
void OnExpandAllChannels();
|
||||
void OnDisableAllChannels();
|
||||
void OnEnableAllChannels();
|
||||
void OnOpenDrillerFile();
|
||||
void OnOpenDrillerFile(QString fileName);
|
||||
void OnOpenWorkspaceFile(); // prompt user
|
||||
void OnOpenWorkspaceFile(QString fileName, bool openDrillerFileAlso); // just open it
|
||||
void OnApplyWorkspaceFile();
|
||||
void OnSaveWorkspaceFile();
|
||||
void OnCaptureWindowDestroyed(QObject*);
|
||||
void OnTabChanged(int toWhich);
|
||||
void CloseTab(int closeTab);
|
||||
|
||||
signals:
|
||||
void ScrubberFrameUpdate( int frame );
|
||||
void ShowYourself();
|
||||
void HideYourself();
|
||||
|
||||
public:
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
private:
|
||||
|
||||
Ui::DrillerMainWindow* m_gui;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DRILLER_DRILLERMAINWINDOW_H
|
||||
@@ -1,245 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DrillerMainWindow</class>
|
||||
<widget class="QMainWindow" name="DrillerMainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>704</width>
|
||||
<height>595</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Profiler (PREVIEW)</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc">
|
||||
<normaloff>:/general/hex_profiler_icon</normaloff>:/general/hex_profiler_icon</iconset>
|
||||
</property>
|
||||
<property name="dockOptions">
|
||||
<set>QMainWindow::AllowNestedDocks|QMainWindow::AnimatedDocks</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabbedContents">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="m_menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>704</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuDriller">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionOpenWorkspace"/>
|
||||
<addaction name="actionApplyWorkspace"/>
|
||||
<addaction name="actionSave"/>
|
||||
<addaction name="actionSaveWorkspace"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuChannels">
|
||||
<property name="title">
|
||||
<string>Channels</string>
|
||||
</property>
|
||||
<addaction name="actionDisable"/>
|
||||
<addaction name="actionEnable"/>
|
||||
</widget>
|
||||
<addaction name="menuDriller"/>
|
||||
<addaction name="menuChannels"/>
|
||||
</widget>
|
||||
<action name="actionCapture">
|
||||
<property name="text">
|
||||
<string>Capture</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start Capturing Data From the Active Drills</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFreeze">
|
||||
<property name="text">
|
||||
<string>Freeze</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Stop Capturing From the Drills and Freeze the Data</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionContract">
|
||||
<property name="text">
|
||||
<string>Contract All</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExpand">
|
||||
<property name="text">
|
||||
<string>Expand All</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisable">
|
||||
<property name="text">
|
||||
<string>Disable All</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Do not record any drill data</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnable">
|
||||
<property name="text">
|
||||
<string>Enable All</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Record incoming drill data</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open Data</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenWorkspace">
|
||||
<property name="text">
|
||||
<string>Open Workspace</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Replace your current environment with both DRL data and a matching Workspace setup</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionApplyWorkspace">
|
||||
<property name="text">
|
||||
<string>Apply Workspace</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Apply this Workspace setup but leave the current DRL data untouched</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="text">
|
||||
<string>Save Data</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveWorkspace">
|
||||
<property name="text">
|
||||
<string>Save Workspace</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../../Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Resources/sharedResources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionOpen</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DrillerMainWindow</receiver>
|
||||
<slot>OnOpenDrillerFile()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>387</x>
|
||||
<y>302</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionOpenWorkspace</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DrillerMainWindow</receiver>
|
||||
<slot>OnOpenWorkspaceFile()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>387</x>
|
||||
<y>302</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionApplyWorkspace</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DrillerMainWindow</receiver>
|
||||
<slot>OnApplyWorkspaceFile()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>387</x>
|
||||
<y>302</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionSaveWorkspace</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DrillerMainWindow</receiver>
|
||||
<slot>OnSaveWorkspaceFile()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>387</x>
|
||||
<y>302</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>OnOpenDrillerFile()</slot>
|
||||
<slot>OnOpenWorkspaceFile()</slot>
|
||||
<slot>OnApplyWorkspaceFile()</slot>
|
||||
<slot>OnSaveWorkspaceFile()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/Serialization/SerializeContext.h>
|
||||
#include "DrillerMainWindowMessages.h"
|
||||
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLERMAINWINDOWMESSAGES_H
|
||||
#define DRILLER_DRILLERMAINWINDOWMESSAGES_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <Source/Driller/DrillerDataTypes.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// messages going FROM the Driller Main Window Context TO anyone interested in frame scrubber control
|
||||
class DrillerMainWindowMessages
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; // components have an actual ID that they report back on
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef int BusIdType;
|
||||
typedef AZ::EBus<DrillerMainWindowMessages> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
virtual void FrameChanged(FrameNumberType frame) = 0;
|
||||
virtual void PlaybackLoopBeginChanged(FrameNumberType frame){(void)frame; }
|
||||
virtual void PlaybackLoopEndChanged(FrameNumberType frame){(void)frame; }
|
||||
/// Important: eventIndex is the event index for the aggregator, NOT global event id.
|
||||
virtual void EventChanged(EventNumberType eventIndex) = 0;
|
||||
|
||||
virtual ~DrillerMainWindowMessages() {}
|
||||
};
|
||||
|
||||
// messages going FROM the main window TO (data viewers) anyone interested in event actions
|
||||
class DrillerEventWindowMessages
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; // components have an actual ID that they report back on
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef int BusIdType;
|
||||
typedef AZ::EBus<DrillerEventWindowMessages> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
virtual void EventFocusChanged(EventNumberType eventIdx) = 0;
|
||||
|
||||
virtual ~DrillerEventWindowMessages() {}
|
||||
};
|
||||
|
||||
// messages going FROM the main window TO (aggregators and their data viewers) anyone using Driller Workspace files
|
||||
class WorkspaceSettingsProvider;
|
||||
class DrillerWorkspaceWindowMessages
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; // components have an actual ID that they report back on
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef int BusIdType;
|
||||
typedef AZ::EBus<DrillerWorkspaceWindowMessages> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
// overlay anything you want from the provider into your internal state.
|
||||
virtual void ApplySettingsFromWorkspace(WorkspaceSettingsProvider*) = 0;
|
||||
|
||||
// now open windows / etc that are specified in your internal saved state.
|
||||
virtual void ActivateWorkspaceSettings(WorkspaceSettingsProvider*) = 0;
|
||||
virtual void SaveSettingsToWorkspace(WorkspaceSettingsProvider*) = 0;
|
||||
|
||||
virtual ~DrillerWorkspaceWindowMessages() {}
|
||||
};
|
||||
|
||||
// messages going FROM any data viewers TO the global window to request action
|
||||
class DrillerDataViewMessages
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // we have one bus that we always broadcast to
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef AZ::EBus<DrillerDataViewMessages> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
//virtual void EventRequestEventFocus(AZ::s64 eventIdx) = 0;
|
||||
virtual void EventRequestOpenFile(AZStd::string fileName) = 0;
|
||||
virtual void EventRequestOpenWorkspace(AZStd::string fileName) = 0;
|
||||
|
||||
virtual ~DrillerDataViewMessages() {}
|
||||
};
|
||||
|
||||
// messages going FROM any data viewers TO the capture window
|
||||
class DrillerCaptureWindowInterface : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; // components have an actual ID that they report back on
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef int BusIdType;
|
||||
|
||||
virtual void ScrubToFrameRequest(FrameNumberType frameType) = 0;
|
||||
};
|
||||
|
||||
typedef AZ::EBus<DrillerCaptureWindowInterface> DrillerCaptureWindowRequestBus;
|
||||
|
||||
}
|
||||
|
||||
#endif//DRILLER_DRILLERMAINWINDOWMESSAGES_H
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLERNETWORKMESSAGES_H
|
||||
#define DRILLER_DRILLERNETWORKMESSAGES_H
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <AzCore/std/containers/list.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// forward declarations
|
||||
class Aggregator;
|
||||
|
||||
// messages going FROM the Driller Network TO anyone interested in watching data (ie. driller main window)
|
||||
|
||||
class DrillerNetworkMessages
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bus configuration
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; // components have an actual ID that they report back on
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ:: EBusHandlerPolicy::Multiple; // we can have multiple listeners
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef int BusIdType;
|
||||
typedef AZ::EBus<DrillerNetworkMessages> Bus;
|
||||
typedef Bus::Handler Handler;
|
||||
|
||||
typedef AZStd::vector<Aggregator*> AggregatorList;
|
||||
|
||||
virtual void ConnectedToNetwork() = 0;
|
||||
virtual void NewAggregatorList(AggregatorList& theList) = 0;
|
||||
virtual void AddAggregator(Aggregator& theAggregator) = 0;
|
||||
virtual void DiscardAggregators() = 0;
|
||||
virtual void DisconnectedFromNetwork() = 0;
|
||||
virtual void EndFrame(int frame) = 0;
|
||||
virtual void NewAggregatorsAvailable() = 0;
|
||||
|
||||
virtual ~DrillerNetworkMessages() {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif//DRILLER_DRILLERNETWORKMESSAGES_H
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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 "DrillerOperationTelemetryEvent.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
static int k_windowId = 0;
|
||||
|
||||
DrillerWindowLifepsanTelemetry::DrillerWindowLifepsanTelemetry(const char* windowName)
|
||||
: m_windowId(k_windowId++)
|
||||
, m_windowName(windowName)
|
||||
{
|
||||
m_telemetryEvent.SetAttribute("WindowOpen", m_windowName);
|
||||
m_telemetryEvent.SetMetric("WindowId", m_windowId);
|
||||
m_telemetryEvent.Log();
|
||||
m_telemetryEvent.ResetEvent();
|
||||
}
|
||||
|
||||
DrillerWindowLifepsanTelemetry::~DrillerWindowLifepsanTelemetry()
|
||||
{
|
||||
m_telemetryEvent.SetAttribute("WindowClose", m_windowName);
|
||||
m_telemetryEvent.SetMetric("WindowId", m_windowId);
|
||||
m_telemetryEvent.Log();
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_DRILLEROPERATIONTELEMETRYEVENT_H
|
||||
#define DRILLER_DRILLEROPERATIONTELEMETRYEVENT_H
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#include "Source/Telemetry/TelemetryEvent.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// A class for any general Driller Operations(i.e. something which doesn't strictly related
|
||||
// to a specific window, for those a localized window operation should be used).
|
||||
class DrillerOperationTelemetryEvent
|
||||
: public Telemetry::TelemetryEvent
|
||||
{
|
||||
public:
|
||||
DrillerOperationTelemetryEvent()
|
||||
: Telemetry::TelemetryEvent("DrillerOperation")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DrillerWindowLifepsanTelemetry
|
||||
{
|
||||
public:
|
||||
DrillerWindowLifepsanTelemetry(const char* windowName);
|
||||
virtual ~DrillerWindowLifepsanTelemetry();
|
||||
|
||||
private:
|
||||
int m_windowId;
|
||||
AZStd::string m_windowName;
|
||||
DrillerOperationTelemetryEvent m_telemetryEvent;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* 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 <Source/Driller/Workspaces/Workspace.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
#include <AzCore/JSON/prettywriter.h>
|
||||
|
||||
#include "EventTraceDataAggregator.h"
|
||||
#include "EventTraceEvents.h"
|
||||
|
||||
#include <Source/Driller/EventTrace/moc_EventTraceDataAggregator.cpp>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QCoreApplication>
|
||||
#include <QFontInfo>
|
||||
#include <QDir>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
void LaunchExplorerSelect(const QString& filePath);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
const QString ExportFolder = "EventTrace";
|
||||
}
|
||||
|
||||
EventTraceDataAggregator::EventTraceDataAggregator(int identity)
|
||||
: Aggregator(identity)
|
||||
{
|
||||
m_parser.SetAggregator(this);
|
||||
}
|
||||
|
||||
EventTraceDataAggregator::~EventTraceDataAggregator()
|
||||
{
|
||||
}
|
||||
|
||||
float EventTraceDataAggregator::ValueAtFrame(FrameNumberType frame)
|
||||
{
|
||||
const float maxEventsPerFrame = 1000.0f; // just a scale number
|
||||
float numEventsPerFrame = static_cast<float>(NumOfEventsAtFrame(frame));
|
||||
return AZStd::GetMin(numEventsPerFrame / maxEventsPerFrame, 1.0f) * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
QColor EventTraceDataAggregator::GetColor() const
|
||||
{
|
||||
return QColor(0, 255, 255);
|
||||
}
|
||||
|
||||
QString EventTraceDataAggregator::GetName() const
|
||||
{
|
||||
return "Chrome Tracing";
|
||||
}
|
||||
|
||||
QString EventTraceDataAggregator::GetChannelName() const
|
||||
{
|
||||
return ChannelName();
|
||||
}
|
||||
|
||||
QString EventTraceDataAggregator::GetDescription() const
|
||||
{
|
||||
return "Timed scope driller";
|
||||
}
|
||||
|
||||
QString EventTraceDataAggregator::GetToolTip() const
|
||||
{
|
||||
return "Timed scope event profiler which exports to Chrome Tracing";
|
||||
}
|
||||
|
||||
AZ::Uuid EventTraceDataAggregator::GetID() const
|
||||
{
|
||||
return AZ::Uuid("{3E47A533-55A4-4E36-B420-063270E4D5DF}");
|
||||
}
|
||||
|
||||
rapidjson::Document EventTraceDataAggregator::MakeJsonRepresentation(
|
||||
FrameNumberType frameBegin,
|
||||
FrameNumberType frameEnd) const
|
||||
{
|
||||
AZ_Assert(frameBegin >= 0 && frameEnd < GetFrameCount() && frameBegin <= frameEnd, "Invalid frame range for chrome trace export");
|
||||
|
||||
rapidjson::Document rootObj(rapidjson::kObjectType);
|
||||
auto& allocator = rootObj.GetAllocator();
|
||||
|
||||
rapidjson::Value traceEvents(rapidjson::kArrayType);
|
||||
|
||||
auto addMemberStr = [&allocator](rapidjson::Value& obj, const char* key, const char* str)
|
||||
{
|
||||
rapidjson::Value k(rapidjson::StringRef(key), allocator);
|
||||
rapidjson::Value v(rapidjson::StringRef(str), allocator);
|
||||
obj.AddMember(k.Move(), v.Move(), allocator);
|
||||
};
|
||||
|
||||
auto addMemberU64 = [&allocator](rapidjson::Value& obj, const char* key, AZ::u64 value)
|
||||
{
|
||||
rapidjson::Value k(rapidjson::StringRef(key), allocator);
|
||||
rapidjson::Value v(static_cast<uint64_t>(value));
|
||||
obj.AddMember(k.Move(), v.Move(), allocator);
|
||||
};
|
||||
|
||||
auto addMemberObj = [&allocator](rapidjson::Value& obj, const char* key, rapidjson::Value& value)
|
||||
{
|
||||
rapidjson::Value k(rapidjson::StringRef(key), allocator);
|
||||
obj.AddMember(k.Move(), value.Move(), allocator);
|
||||
};
|
||||
|
||||
const EventNumberType FrameBeginIndex = GetFirstIndexAtFrame(frameBegin);
|
||||
const EventNumberType FrameEndIndex = GetFirstIndexAtFrame(frameEnd) + NumOfEventsAtFrame(frameEnd);
|
||||
|
||||
for (EventNumberType index = FrameBeginIndex; index < FrameEndIndex; ++index)
|
||||
{
|
||||
const DrillerEvent& event = static_cast<const DrillerEvent&>(*GetEvents()[index]);
|
||||
|
||||
switch (event.GetEventType())
|
||||
{
|
||||
case EventTrace::ET_SLICE:
|
||||
{
|
||||
const EventTrace::SliceEvent& slice = static_cast<const EventTrace::SliceEvent&>(event);
|
||||
rapidjson::Value obj(rapidjson::kObjectType);
|
||||
addMemberStr(obj, "name", slice.m_Name);
|
||||
addMemberStr(obj, "cat", slice.m_Category);
|
||||
addMemberStr(obj, "ph", "X");
|
||||
addMemberU64(obj, "ts", slice.m_Timestamp);
|
||||
addMemberU64(obj, "dur", slice.m_Duration);
|
||||
addMemberU64(obj, "tid", slice.m_ThreadId);
|
||||
addMemberU64(obj, "pid", 0);
|
||||
|
||||
traceEvents.PushBack(obj, allocator);
|
||||
} break;
|
||||
|
||||
case EventTrace::ET_INSTANT:
|
||||
{
|
||||
const EventTrace::InstantEvent& instant = static_cast<const EventTrace::InstantEvent&>(event);
|
||||
|
||||
rapidjson::Value obj(rapidjson::kObjectType);
|
||||
addMemberStr(obj, "name", instant.m_Name);
|
||||
addMemberStr(obj, "cat", instant.m_Category);
|
||||
addMemberStr(obj, "ph", "i");
|
||||
addMemberU64(obj, "ts", instant.m_Timestamp);
|
||||
addMemberStr(obj, "s", instant.GetScopeName());
|
||||
addMemberU64(obj, "tid", instant.m_ThreadId);
|
||||
addMemberU64(obj, "pid", 0);
|
||||
|
||||
traceEvents.PushBack(obj, allocator);
|
||||
|
||||
} break;
|
||||
|
||||
case EventTrace::ET_THREAD_INFO:
|
||||
{
|
||||
const EventTrace::ThreadInfoEvent& threadInfo = static_cast<const EventTrace::ThreadInfoEvent&>(event);
|
||||
rapidjson::Value obj(rapidjson::kObjectType);
|
||||
|
||||
rapidjson::Value args(rapidjson::kObjectType);
|
||||
addMemberStr(args, "name", threadInfo.m_Name);
|
||||
|
||||
addMemberStr(obj, "name", "thread_name");
|
||||
addMemberStr(obj, "ph", "M");
|
||||
addMemberU64(obj, "pid", 0);
|
||||
addMemberU64(obj, "tid", threadInfo.m_ThreadId);
|
||||
addMemberObj(obj, "args", args);
|
||||
|
||||
traceEvents.PushBack(obj, allocator);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
addMemberObj(rootObj, "traceEvents", traceEvents);
|
||||
return rootObj;
|
||||
}
|
||||
|
||||
QWidget* EventTraceDataAggregator::DrillDownRequest(FrameNumberType atFrame)
|
||||
{
|
||||
const FrameNumberType FrameCountToExport = 10;
|
||||
const FrameNumberType FrameCountToExportDiv2 = FrameCountToExport / 2;
|
||||
|
||||
QString filename = "Frame_" + QString::number(atFrame) + ".chrometrace";
|
||||
QFileInfo fileInfo(QCoreApplication::applicationDirPath() + "/" + ExportFolder, filename);
|
||||
ExportChromeTrace(fileInfo.absoluteFilePath(), atFrame - FrameCountToExportDiv2, atFrame + FrameCountToExportDiv2);
|
||||
Platform::LaunchExplorerSelect(fileInfo.absoluteFilePath());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EventTraceDataAggregator::ExportChromeTrace(const QString& filename, FrameNumberType frameStart, FrameNumberType frameEnd) const
|
||||
{
|
||||
AZ::IO::SystemFile exportFile;
|
||||
if (exportFile.Open(filename.toStdString().c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY))
|
||||
{
|
||||
ExportChromeTrace(exportFile, frameStart, frameEnd);
|
||||
}
|
||||
exportFile.Close();
|
||||
}
|
||||
|
||||
void EventTraceDataAggregator::ExportChromeTrace(AZ::IO::SystemFile& file, FrameNumberType frameStart, FrameNumberType frameEnd) const
|
||||
{
|
||||
frameStart = AZStd::max(frameStart, 0);
|
||||
frameEnd = AZStd::min(frameEnd, (FrameNumberType)GetFrameCount() - 1);
|
||||
|
||||
if (frameStart <= frameEnd)
|
||||
{
|
||||
rapidjson::Document jsonRep = MakeJsonRepresentation(frameStart, frameEnd);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
jsonRep.Accept(writer);
|
||||
|
||||
file.Write(buffer.GetString(), buffer.GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
void EventTraceDataAggregator::ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings)
|
||||
{
|
||||
(void)exportSettings;
|
||||
ExportChromeTrace(file, 0, (FrameNumberType)GetFrameCount() - 1);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <Source/Driller/DrillerAggregator.hxx>
|
||||
#include <Source/Driller/DrillerAggregatorOptions.hxx>
|
||||
#include <Source/Driller/GenericCustomizeCSVExportWidget.hxx>
|
||||
#include "EventTraceDataParser.h"
|
||||
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <QProcess>
|
||||
#endif
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class EventTraceDataAggregator
|
||||
: public Aggregator
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_RTTI(EventTraceDataAggregator, "{D82CC9CF-5477-4A3E-8809-C064D19963F8}");
|
||||
AZ_CLASS_ALLOCATOR(EventTraceDataAggregator, AZ::SystemAllocator, 0);
|
||||
|
||||
EventTraceDataAggregator(int identity = 0);
|
||||
virtual ~EventTraceDataAggregator();
|
||||
|
||||
static AZ::u32 DrillerId()
|
||||
{
|
||||
return EventTraceDataParser::GetDrillerId();
|
||||
}
|
||||
|
||||
AZ::u32 GetDrillerId() const override
|
||||
{
|
||||
return DrillerId();
|
||||
}
|
||||
|
||||
static const char* ChannelName()
|
||||
{
|
||||
return "ChromeTracing";
|
||||
}
|
||||
|
||||
AZ::Crc32 GetChannelId() const override
|
||||
{
|
||||
return AZ::Crc32(ChannelName());
|
||||
}
|
||||
|
||||
AZ::Debug::DrillerHandlerParser* GetDrillerDataParser() override
|
||||
{
|
||||
return &m_parser;
|
||||
}
|
||||
|
||||
bool CanExportToCSV() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportColumnDescriptorToCSV(AZ::IO::SystemFile& file, CSVExportSettings* exportSettings) override;
|
||||
|
||||
void ApplySettingsFromWorkspace(WorkspaceSettingsProvider*) override {}
|
||||
void ActivateWorkspaceSettings(WorkspaceSettingsProvider*) override {}
|
||||
void SaveSettingsToWorkspace(WorkspaceSettingsProvider*) override {}
|
||||
|
||||
public slots:
|
||||
float ValueAtFrame(FrameNumberType frame) override;
|
||||
QColor GetColor() const override;
|
||||
QString GetChannelName() const override;
|
||||
QString GetName() const override;
|
||||
QString GetDescription() const override;
|
||||
QString GetToolTip() const override;
|
||||
AZ::Uuid GetID() const override;
|
||||
void OptionsRequest() override {}
|
||||
|
||||
QWidget* DrillDownRequest(FrameNumberType frame) override;
|
||||
|
||||
private:
|
||||
rapidjson::Document MakeJsonRepresentation(FrameNumberType frameStart, FrameNumberType frameEnd) const;
|
||||
void ExportChromeTrace(AZ::IO::SystemFile& file, FrameNumberType frameStart, FrameNumberType frameEnd) const;
|
||||
void ExportChromeTrace(const QString& filename, FrameNumberType frameStart, FrameNumberType frameEnd) const;
|
||||
|
||||
EventTraceDataParser m_parser;
|
||||
};
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* 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 "EventTraceDataParser.h"
|
||||
#include "EventTraceDataAggregator.h"
|
||||
#include "EventTraceEvents.h"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
AZ::Debug::DrillerHandlerParser* EventTraceDataParser::OnEnterTag(AZ::u32 tagName)
|
||||
{
|
||||
AZ_Assert(m_data, "You must set a valid aggregator before we can process the data!");
|
||||
if (tagName == AZ_CRC("Slice"))
|
||||
{
|
||||
m_data->AddEvent(aznew EventTrace::SliceEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("Instant"))
|
||||
{
|
||||
m_data->AddEvent(aznew EventTrace::InstantEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("ThreadInfo"))
|
||||
{
|
||||
m_data->AddEvent(aznew EventTrace::ThreadInfoEvent());
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EventTraceDataParser::OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode)
|
||||
{
|
||||
AZ_Assert(m_data, "You must set a valid aggregator before we can process the data!");
|
||||
|
||||
DrillerEvent& drillerEvent = static_cast<DrillerEvent&>(*m_data->GetEvents().back());
|
||||
|
||||
switch (drillerEvent.GetEventType())
|
||||
{
|
||||
case EventTrace::ET_SLICE:
|
||||
{
|
||||
EventTrace::SliceEvent& slice = static_cast<EventTrace::SliceEvent&>(drillerEvent);
|
||||
if (dataNode.m_name == AZ_CRC("Name"))
|
||||
{
|
||||
slice.m_Name = dataNode.ReadPooledString();
|
||||
}
|
||||
if (dataNode.m_name == AZ_CRC("Category"))
|
||||
{
|
||||
slice.m_Category = dataNode.ReadPooledString();
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("ThreadId"))
|
||||
{
|
||||
dataNode.Read(slice.m_ThreadId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp"))
|
||||
{
|
||||
dataNode.Read(slice.m_Timestamp);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Duration"))
|
||||
{
|
||||
dataNode.Read(slice.m_Duration);
|
||||
}
|
||||
} break;
|
||||
|
||||
case EventTrace::ET_INSTANT:
|
||||
{
|
||||
EventTrace::InstantEvent& instant = static_cast<EventTrace::InstantEvent&>(drillerEvent);
|
||||
if (dataNode.m_name == AZ_CRC("Name"))
|
||||
{
|
||||
instant.m_Name = dataNode.ReadPooledString();
|
||||
}
|
||||
if (dataNode.m_name == AZ_CRC("Category"))
|
||||
{
|
||||
instant.m_Category = dataNode.ReadPooledString();
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("ThreadId"))
|
||||
{
|
||||
dataNode.Read(instant.m_ThreadId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp"))
|
||||
{
|
||||
dataNode.Read(instant.m_Timestamp);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case EventTrace::ET_THREAD_INFO:
|
||||
{
|
||||
EventTrace::ThreadInfoEvent& threadInfo = static_cast<EventTrace::ThreadInfoEvent&>(drillerEvent);
|
||||
if (dataNode.m_name == AZ_CRC("Name"))
|
||||
{
|
||||
threadInfo.m_Name = dataNode.ReadPooledString();
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("ThreadId"))
|
||||
{
|
||||
dataNode.Read(threadInfo.m_ThreadId);
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} // namespace Driller
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Driller/Stream.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class EventTraceDataAggregator;
|
||||
|
||||
class EventTraceDataParser
|
||||
: public AZ::Debug::DrillerHandlerParser
|
||||
{
|
||||
public:
|
||||
EventTraceDataParser()
|
||||
: m_data(NULL)
|
||||
{}
|
||||
|
||||
static AZ::u32 GetDrillerId()
|
||||
{
|
||||
return AZ_CRC("EventTraceDriller");
|
||||
}
|
||||
|
||||
void SetAggregator(EventTraceDataAggregator* data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
virtual AZ::Debug::DrillerHandlerParser* OnEnterTag(AZ::u32 tagName);
|
||||
virtual void OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode);
|
||||
|
||||
protected:
|
||||
EventTraceDataAggregator* m_data;
|
||||
};
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Source/Driller/DrillerEvent.h>
|
||||
#include <AzCore/Debug/EventTraceDrillerBus.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
namespace EventTrace
|
||||
{
|
||||
enum EventType
|
||||
{
|
||||
ET_SLICE,
|
||||
ET_INSTANT,
|
||||
ET_THREAD_INFO
|
||||
};
|
||||
|
||||
class SliceEvent : public DrillerEvent
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(SliceEvent, AZ::SystemAllocator, 0)
|
||||
|
||||
SliceEvent()
|
||||
: DrillerEvent(ET_SLICE)
|
||||
, m_Name{ "" }
|
||||
, m_Category{ "" }
|
||||
, m_ThreadId{}
|
||||
, m_Timestamp{}
|
||||
, m_Duration{}
|
||||
{}
|
||||
|
||||
// no stepping as we can just traverse the list of events
|
||||
virtual void StepForward(Aggregator* data) { (void)data; }
|
||||
virtual void StepBackward(Aggregator* data) { (void)data; }
|
||||
|
||||
const char* m_Name;
|
||||
const char* m_Category;
|
||||
size_t m_ThreadId;
|
||||
AZStd::sys_time_t m_Timestamp;
|
||||
AZStd::sys_time_t m_Duration;
|
||||
};
|
||||
|
||||
class InstantEvent : public DrillerEvent
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(InstantEvent, AZ::SystemAllocator, 0)
|
||||
|
||||
InstantEvent()
|
||||
: DrillerEvent(ET_INSTANT)
|
||||
, m_Name{ "" }
|
||||
, m_Category{ "" }
|
||||
, m_ThreadId{}
|
||||
, m_Timestamp{}
|
||||
{}
|
||||
|
||||
// no stepping as we can just traverse the list of events
|
||||
virtual void StepForward(Aggregator* data) { (void)data; }
|
||||
virtual void StepBackward(Aggregator* data) { (void)data; }
|
||||
|
||||
const char* GetScopeName() const
|
||||
{
|
||||
return (m_ThreadId == 0) ? "g" : "t";
|
||||
}
|
||||
|
||||
const char* m_Name;
|
||||
const char* m_Category;
|
||||
size_t m_ThreadId;
|
||||
AZStd::sys_time_t m_Timestamp;
|
||||
};
|
||||
|
||||
class ThreadInfoEvent : public DrillerEvent
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ThreadInfoEvent, AZ::SystemAllocator, 0)
|
||||
|
||||
ThreadInfoEvent()
|
||||
: DrillerEvent(ET_THREAD_INFO)
|
||||
, m_ThreadId{}
|
||||
, m_Name{ "" }
|
||||
{}
|
||||
|
||||
// no stepping as we can just traverse the list of events
|
||||
virtual void StepForward(Aggregator* data) { (void)data; }
|
||||
virtual void StepBackward(Aggregator* data) { (void)data; }
|
||||
|
||||
size_t m_ThreadId;
|
||||
const char* m_Name;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Driller
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/FilteredListView.hxx"
|
||||
#include <Source/Driller/moc_FilteredListView.cpp>
|
||||
#include <Source/Driller/ui_FilteredListView.h>
|
||||
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
#include <qtextdocument.h>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
/////////////////////
|
||||
// FilteredListView
|
||||
/////////////////////
|
||||
|
||||
FilteredListView::FilteredListView(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_gui(new Ui::FilteredListView())
|
||||
, m_enableCustomOrdering(true)
|
||||
{
|
||||
m_gui->setupUi(this);
|
||||
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
m_filteredModel.setSourceModel(&m_stringListModel);
|
||||
|
||||
m_gui->listView->setModel(&m_filteredModel);
|
||||
m_gui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
||||
QObject::connect(m_gui->filter, SIGNAL(textChanged(const QString&)), this, SLOT(filterEdited(const QString&)));
|
||||
QObject::connect(m_gui->moveUp, SIGNAL(clicked()), this, SLOT(moveSelectionUp()));
|
||||
QObject::connect(m_gui->moveDown, SIGNAL(clicked()), this, SLOT(moveSelectionDown()));
|
||||
|
||||
m_gui->moveUp->setAutoDefault(false);
|
||||
m_gui->moveDown->setAutoDefault(false);
|
||||
}
|
||||
|
||||
FilteredListView::~FilteredListView()
|
||||
{
|
||||
delete m_gui;
|
||||
}
|
||||
|
||||
void FilteredListView::addItem(const char* item)
|
||||
{
|
||||
m_stringList.push_back(QString(item));
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
void FilteredListView::addItems(const QStringList& items)
|
||||
{
|
||||
m_stringList.append(items);
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
void FilteredListView::removeItem(const char* item)
|
||||
{
|
||||
m_stringList.removeOne(QString(item));
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
void FilteredListView::removeItems(const QStringList& items)
|
||||
{
|
||||
for (const QString& item : items)
|
||||
{
|
||||
m_stringList.removeOne(item);
|
||||
}
|
||||
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
void FilteredListView::clearItems()
|
||||
{
|
||||
m_stringList.clear();
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
void FilteredListView::removeSelected()
|
||||
{
|
||||
const QModelIndexList& selectedIndexes = m_gui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
for (const QModelIndex& modelIndex : selectedIndexes)
|
||||
{
|
||||
QString item = modelIndex.data(Qt::DisplayRole).toString();
|
||||
|
||||
m_stringList.removeOne(item);
|
||||
}
|
||||
|
||||
m_gui->listView->selectionModel()->clearSelection();
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
}
|
||||
|
||||
const QStringList& FilteredListView::getAllItems() const
|
||||
{
|
||||
return m_stringList;
|
||||
}
|
||||
|
||||
void FilteredListView::getSelectedItems(QStringList& selectedItems) const
|
||||
{
|
||||
const QModelIndexList& selectedIndexes = m_gui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
for (const QModelIndex& modelIndex : selectedIndexes)
|
||||
{
|
||||
QString item = modelIndex.data(Qt::DisplayRole).toString();
|
||||
selectedItems.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredListView::enableCustomOrdering(bool enabled)
|
||||
{
|
||||
m_enableCustomOrdering = enabled;
|
||||
|
||||
setButtonsEnabled(m_enableCustomOrdering);
|
||||
}
|
||||
|
||||
void FilteredListView::filterEdited(const QString& eventFilter)
|
||||
{
|
||||
m_gui->listView->selectionModel()->clearSelection();
|
||||
m_filteredModel.setFilterRegExp(eventFilter);
|
||||
setButtonsEnabled(eventFilter.isEmpty() && m_enableCustomOrdering);
|
||||
}
|
||||
|
||||
void FilteredListView::moveSelectionUp()
|
||||
{
|
||||
const QModelIndexList& selectedIndexes = m_gui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
AZStd::set<int> sortedIndexes;
|
||||
|
||||
for (const QModelIndex& index : selectedIndexes)
|
||||
{
|
||||
sortedIndexes.insert(index.row());
|
||||
}
|
||||
|
||||
int lastSelectedRow = -1;
|
||||
AZStd::unordered_set<int> selectedRows;
|
||||
|
||||
for (int row : sortedIndexes)
|
||||
{
|
||||
if (row > 0 && row > lastSelectedRow + 1)
|
||||
{
|
||||
m_stringList.swapItemsAt(row, row - 1);
|
||||
|
||||
// Update the row to reflect it's new position.
|
||||
row = row - 1;
|
||||
}
|
||||
|
||||
lastSelectedRow = row;
|
||||
selectedRows.insert(row);
|
||||
}
|
||||
|
||||
m_gui->listView->selectionModel()->clear();
|
||||
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
|
||||
for (int row : selectedRows)
|
||||
{
|
||||
m_gui->listView->selectionModel()->select(m_stringListModel.index(row, 0), QItemSelectionModel::Select);
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredListView::moveSelectionDown()
|
||||
{
|
||||
const QModelIndexList& selectedIndexes = m_gui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
AZStd::set<int> sortedIndexes;
|
||||
|
||||
for (const QModelIndex& index : selectedIndexes)
|
||||
{
|
||||
sortedIndexes.insert(index.row());
|
||||
}
|
||||
|
||||
int lastSelectedRow = m_stringList.size();
|
||||
AZStd::unordered_set<int> selectedRows;
|
||||
|
||||
for (AZStd::set<int>::reverse_iterator iter = sortedIndexes.rbegin();
|
||||
iter != sortedIndexes.rend();
|
||||
++iter)
|
||||
{
|
||||
int row = (*iter);
|
||||
|
||||
if (row < m_stringList.size() - 1 && row < lastSelectedRow - 1)
|
||||
{
|
||||
m_stringList.swapItemsAt(row, row + 1);
|
||||
row = row + 1;
|
||||
}
|
||||
|
||||
lastSelectedRow = row;
|
||||
selectedRows.insert(row);
|
||||
}
|
||||
|
||||
m_gui->listView->selectionModel()->clear();
|
||||
|
||||
m_stringListModel.setStringList(m_stringList);
|
||||
|
||||
for (int row : selectedRows)
|
||||
{
|
||||
m_gui->listView->selectionModel()->select(m_stringListModel.index(row, 0), QItemSelectionModel::Select);
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredListView::setButtonsEnabled(bool enabled)
|
||||
{
|
||||
m_gui->moveDown->setEnabled(enabled);
|
||||
m_gui->moveUp->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AZTOOLSFRAMEWORK_UI_UICORE_FILTEREDLISTVIEW_H
|
||||
#define AZTOOLSFRAMEWORK_UI_UICORE_FILTEREDLISTVIEW_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtWidgets/QListView>
|
||||
#include <qstringlistmodel.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qsortfilterproxymodel.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class FilteredListView;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
// This widget allows for easy access to a filtered list view that can also be rearranged by the user.
|
||||
// Useful for things like determining column order, or export fields.
|
||||
class FilteredListView
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// Apparently we can't just have a non-sorted model...
|
||||
class FilteredProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
void sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
(void) column; (void)order;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FilteredListView, AZ::SystemAllocator,0);
|
||||
|
||||
explicit FilteredListView(QWidget* parent = nullptr);
|
||||
~FilteredListView();
|
||||
|
||||
void addItem(const char* item);
|
||||
void addItems(const QStringList& items);
|
||||
|
||||
void removeItem(const char* item);
|
||||
void removeItems(const QStringList& items);
|
||||
|
||||
void clearItems();
|
||||
|
||||
void removeSelected();
|
||||
|
||||
void setFilterString(const char* filterString);
|
||||
const char* getFilterString() const;
|
||||
|
||||
const QStringList& getAllItems() const;
|
||||
void getSelectedItems(QStringList& selectedItems) const;
|
||||
|
||||
void enableCustomOrdering(bool enabled);
|
||||
|
||||
public slots:
|
||||
void filterEdited(const QString& eventFilter);
|
||||
void moveSelectionUp();
|
||||
void moveSelectionDown();
|
||||
|
||||
private:
|
||||
|
||||
void setButtonsEnabled(bool enabled);
|
||||
|
||||
Ui::FilteredListView* m_gui;
|
||||
bool m_enableCustomOrdering;
|
||||
FilteredProxyModel m_filteredModel;
|
||||
QStringListModel m_stringListModel;
|
||||
QStringList m_stringList;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,124 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FilteredListView</class>
|
||||
<widget class="QWidget" name="FilteredListView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filter"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="uniformItemSizes">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveUp">
|
||||
<property name="text">
|
||||
<string>^</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveDown">
|
||||
<property name="text">
|
||||
<string>V</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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 "Source/Driller/GenericCustomizeCSVExportWidget.hxx"
|
||||
#include <Source/Driller/ui_GenericCustomizeCSVExportWidget.h>
|
||||
#include <Source/Driller/moc_GenericCustomizeCSVExportWidget.cpp>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
////////////////////////////////////
|
||||
// GenericCustomizeCSVExportWidget
|
||||
////////////////////////////////////
|
||||
|
||||
GenericCustomizeCSVExportWidget::GenericCustomizeCSVExportWidget(GenericCSVExportSettings& genericSettings, QWidget* parent)
|
||||
: CustomizeCSVExportWidget(genericSettings, parent)
|
||||
, m_exportFieldsDirty(false)
|
||||
, m_gui(nullptr)
|
||||
{
|
||||
m_gui = azcreate(Ui::GenericCustomizeCSVExportWidget, ());
|
||||
m_gui->setupUi(this);
|
||||
|
||||
QStringList items;
|
||||
genericSettings.GetExportItems(items);
|
||||
m_gui->exportFieldSelector->setItemList(items);
|
||||
|
||||
items.clear();
|
||||
|
||||
genericSettings.GetActiveExportItems(items);
|
||||
m_gui->exportFieldSelector->setActiveItems(items);
|
||||
items.clear();
|
||||
|
||||
m_gui->exportFieldSelector->setActiveTitle("Exported Fields");
|
||||
m_gui->exportFieldSelector->setInactiveTitle("Unused Fields");
|
||||
|
||||
QObject::connect(m_gui->exportFieldSelector, SIGNAL(ActiveItemsChanged()), this, SLOT(OnActiveItemsChanged()));
|
||||
QObject::connect(m_gui->addDescriptor, SIGNAL(stateChanged(int)), this, SLOT(OnShouldExportStateDescriptorChecked(int)));
|
||||
}
|
||||
|
||||
GenericCustomizeCSVExportWidget::~GenericCustomizeCSVExportWidget()
|
||||
{
|
||||
azdestroy(m_gui);
|
||||
}
|
||||
|
||||
void GenericCustomizeCSVExportWidget::FinalizeSettings()
|
||||
{
|
||||
if (m_exportFieldsDirty)
|
||||
{
|
||||
m_exportFieldsDirty = false;
|
||||
|
||||
GenericCSVExportSettings& exportSettings = static_cast<GenericCSVExportSettings&>(m_exportSettings);
|
||||
const QStringList& activeItems = m_gui->exportFieldSelector->getActiveItems();
|
||||
|
||||
exportSettings.UpdateExportOrdering(activeItems);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericCustomizeCSVExportWidget::OnActiveItemsChanged()
|
||||
{
|
||||
m_exportFieldsDirty = true;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRILLER_GENERICCUSTOMIZECSVEXPORTPANEL_H
|
||||
#define DRILLER_GENERICCUSTOMIZECSVEXPORTPANEL_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Source/Driller/CustomizeCSVExportWidget.hxx"
|
||||
#include "Source/Driller/CSVExportSettings.h"
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class GenericCustomizeCSVExportWidget;
|
||||
}
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class GenericCSVExportSettings;
|
||||
|
||||
class GenericCustomizeCSVExportWidget
|
||||
: public CustomizeCSVExportWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(GenericCustomizeCSVExportWidget, AZ::SystemAllocator, 0);
|
||||
|
||||
GenericCustomizeCSVExportWidget(GenericCSVExportSettings& exportSettings, QWidget* parent = nullptr);
|
||||
~GenericCustomizeCSVExportWidget();
|
||||
|
||||
void FinalizeSettings() override;
|
||||
|
||||
public slots:
|
||||
|
||||
void OnActiveItemsChanged();
|
||||
|
||||
private:
|
||||
|
||||
bool m_exportFieldsDirty;
|
||||
|
||||
Ui::GenericCustomizeCSVExportWidget* m_gui;
|
||||
};
|
||||
|
||||
class GenericCSVExportSettings
|
||||
: public CSVExportSettings
|
||||
{
|
||||
friend class GenericCustomizeCSVExportWidget;
|
||||
public:
|
||||
GenericCSVExportSettings()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void GetExportItems(QStringList& items) const = 0;
|
||||
virtual void GetActiveExportItems(QStringList& items) const = 0;
|
||||
|
||||
protected:
|
||||
virtual void UpdateExportOrdering(const QStringList& items) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GenericCustomizeCSVExportWidget</class>
|
||||
<widget class="QWidget" name="GenericCustomizeCSVExportWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>887</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="Driller::DoubleListSelector" name="exportFieldSelector" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="addDescriptor">
|
||||
<property name="text">
|
||||
<string>Add Column Descriptor</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Driller::DoubleListSelector</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Source/Driller/DoubleListSelector.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,584 +0,0 @@
|
||||
/*
|
||||
* 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 "StreamerDataAggregator.hxx"
|
||||
#include <Woodpecker/Driller/IO/moc_StreamerDataAggregator.cpp>
|
||||
|
||||
#include "StreamerDrillerDialog.hxx"
|
||||
#include "StreamerEvents.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include "Woodpecker/Driller/Workspaces/Workspace.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
class StreamerDataAggregatorSavedState
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(StreamerDataAggregatorSavedState, "{0174A3EE-C555-482F-9E7B-7D67D9B4B0A7}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(StreamerDataAggregatorSavedState, AZ::SystemAllocator, 0);
|
||||
StreamerDataAggregatorSavedState() {}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<StreamerDataAggregatorSavedState>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// WORKSPACES are files loaded and stored independent of the global application
|
||||
// designed to be used for DRL data specific view settings and to pass around
|
||||
class StreamerDataAggregatorWorkspace
|
||||
: public AZ::UserSettings
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(StreamerDataAggregatorWorkspace, "{D35E8CCA-6FA7-47F6-8A24-8E12EF237E40}", AZ::UserSettings);
|
||||
AZ_CLASS_ALLOCATOR(StreamerDataAggregatorWorkspace, AZ::SystemAllocator, 0);
|
||||
|
||||
int m_activeViewCount;
|
||||
AZStd::vector<int> m_activeViewTypes;
|
||||
|
||||
StreamerDataAggregatorWorkspace()
|
||||
: m_activeViewCount(0)
|
||||
{}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<StreamerDataAggregatorWorkspace>()
|
||||
->Field("m_activeViewCount", &StreamerDataAggregatorWorkspace::m_activeViewCount)
|
||||
->Field("m_activeViewTypes", &StreamerDataAggregatorWorkspace::m_activeViewTypes)
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
StreamerDataAggregator::StreamerDataAggregator(int identity)
|
||||
: Aggregator(identity)
|
||||
, m_activeViewCount(0)
|
||||
, m_highwaterFrame(-1)
|
||||
{
|
||||
m_parser.SetAggregator(this);
|
||||
ResetTrackingInfo();
|
||||
}
|
||||
|
||||
StreamerDataAggregator::~StreamerDataAggregator()
|
||||
{
|
||||
KillAllViews();
|
||||
}
|
||||
|
||||
// gross generalization of activity based on total number of all events this frame
|
||||
float StreamerDataAggregator::ValueAtFrame(FrameNumberType frame)
|
||||
{
|
||||
const float maxEventsPerFrame = 10.0f; // just a scale number
|
||||
float numEventsPerFrame = static_cast<float>(NumOfEventsAtFrame(frame));
|
||||
return AZStd::GetMin(numEventsPerFrame / maxEventsPerFrame, 1.0f) * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
QColor StreamerDataAggregator::GetColor() const
|
||||
{
|
||||
return QColor(0, 255, 255);
|
||||
}
|
||||
|
||||
QString StreamerDataAggregator::GetName() const
|
||||
{
|
||||
return "Streamer";
|
||||
}
|
||||
|
||||
QString StreamerDataAggregator::GetChannelName() const
|
||||
{
|
||||
return ChannelName();
|
||||
}
|
||||
|
||||
QString StreamerDataAggregator::GetDescription() const
|
||||
{
|
||||
return "Streamer events driller";
|
||||
}
|
||||
|
||||
QString StreamerDataAggregator::GetToolTip() const
|
||||
{
|
||||
return "Streamer Events";
|
||||
}
|
||||
|
||||
AZ::Uuid StreamerDataAggregator::GetID() const
|
||||
{
|
||||
return AZ::Uuid("{9A2854C8-8106-4075-9287-3E047821D934}");
|
||||
}
|
||||
|
||||
QWidget* StreamerDataAggregator::DrillDownRequest(FrameNumberType frame)
|
||||
{
|
||||
StreamerDrillerDialog* dialog = NULL;
|
||||
|
||||
AZ::u32 availableIdx = 0;
|
||||
bool foundASpot = true;
|
||||
do
|
||||
{
|
||||
foundASpot = true;
|
||||
for (DataViewMap::iterator iter = m_dataViews.begin(); iter != m_dataViews.end(); ++iter)
|
||||
{
|
||||
if (iter->second == availableIdx)
|
||||
{
|
||||
foundASpot = false;
|
||||
++availableIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!foundASpot);
|
||||
|
||||
dialog = aznew StreamerDrillerDialog(this, frame, (1024 * GetIdentity()) + availableIdx);
|
||||
if (dialog)
|
||||
{
|
||||
m_dataViews[dialog] = availableIdx;
|
||||
connect(dialog, SIGNAL(destroyed(QObject*)), this, SLOT(OnDataViewDestroyed(QObject*)));
|
||||
++m_activeViewCount;
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
QWidget* StreamerDataAggregator::DrillDownRequest(FrameNumberType frame, int type)
|
||||
{
|
||||
StreamerDrillerDialog* view = static_cast<StreamerDrillerDialog*>(DrillDownRequest(frame));
|
||||
if (view)
|
||||
{
|
||||
view->SetChartType(type);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::OptionsRequest()
|
||||
{
|
||||
QMenu* popupMenu = new QMenu();
|
||||
QMenu* cachedHitsTypeMenu = new QMenu(tr("Cached Hits"));
|
||||
cachedHitsTypeMenu->addAction(tr("Do Not Report Cache Hits"));
|
||||
cachedHitsTypeMenu->addAction(tr("Report Cache Hits"));
|
||||
popupMenu->addMenu(cachedHitsTypeMenu);
|
||||
QAction* act = cachedHitsTypeMenu->exec(QCursor::pos());
|
||||
if (act)
|
||||
{
|
||||
if (act->text() == tr("Report Cache Hits"))
|
||||
{
|
||||
m_parser.AllowCacheHitsInReportedStream(true);
|
||||
}
|
||||
if (act->text() == tr("Do Not Report Cache Hits"))
|
||||
{
|
||||
m_parser.AllowCacheHitsInReportedStream(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::OnDataViewDestroyed(QObject* dataView)
|
||||
{
|
||||
m_dataViews.erase(dataView);
|
||||
--m_activeViewCount;
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::KillAllViews()
|
||||
{
|
||||
do
|
||||
{
|
||||
DataViewMap::iterator iter = m_dataViews.begin();
|
||||
if (iter != m_dataViews.end())
|
||||
{
|
||||
delete iter->first;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::ApplySettingsFromWorkspace(WorkspaceSettingsProvider* provider)
|
||||
{
|
||||
StreamerDataAggregatorWorkspace* workspace = provider->FindSetting<StreamerDataAggregatorWorkspace>(AZ_CRC("STREAMER DATA AGGREGATOR WORKSPACE", 0x105be192));
|
||||
if (workspace)
|
||||
{
|
||||
m_activeViewCount = workspace->m_activeViewCount;
|
||||
}
|
||||
}
|
||||
void StreamerDataAggregator::ActivateWorkspaceSettings(WorkspaceSettingsProvider* provider)
|
||||
{
|
||||
StreamerDataAggregatorWorkspace* workspace = provider->FindSetting<StreamerDataAggregatorWorkspace>(AZ_CRC("STREAMER DATA AGGREGATOR WORKSPACE", 0x105be192));
|
||||
if (workspace)
|
||||
{
|
||||
// kill all existing data view windows in preparation of opening the workspace specified ones
|
||||
KillAllViews();
|
||||
|
||||
// the internal count should be 0 from the above house cleaning
|
||||
// and incremented back up from the workspace instantiations
|
||||
m_activeViewCount = 0;
|
||||
for (int i = 0; i < workspace->m_activeViewCount; ++i)
|
||||
{
|
||||
//// start this check to default
|
||||
int discoveredType = 0;
|
||||
if (workspace->m_activeViewTypes.size() > i)
|
||||
{
|
||||
discoveredType = workspace->m_activeViewTypes[i];
|
||||
}
|
||||
|
||||
Driller::StreamerDrillerDialog* dataView = qobject_cast<Driller::StreamerDrillerDialog*>(DrillDownRequest(1, discoveredType));
|
||||
if (dataView)
|
||||
{
|
||||
// apply will overlay the workspace settings on top of the local user settings
|
||||
dataView->ApplySettingsFromWorkspace(provider);
|
||||
// activate will do the heavy lifting
|
||||
dataView->ActivateWorkspaceSettings(provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void StreamerDataAggregator::SaveSettingsToWorkspace(WorkspaceSettingsProvider* provider)
|
||||
{
|
||||
StreamerDataAggregatorWorkspace* workspace = provider->CreateSetting<StreamerDataAggregatorWorkspace>(AZ_CRC("STREAMER DATA AGGREGATOR WORKSPACE", 0x105be192));
|
||||
if (workspace)
|
||||
{
|
||||
workspace->m_activeViewTypes.clear();
|
||||
workspace->m_activeViewCount = m_activeViewCount;
|
||||
|
||||
for (DataViewMap::iterator iter = m_dataViews.begin(); iter != m_dataViews.end(); ++iter)
|
||||
{
|
||||
Driller::StreamerDrillerDialog* dataView = qobject_cast<Driller::StreamerDrillerDialog* >(iter->first);
|
||||
if (dataView)
|
||||
{
|
||||
workspace->m_activeViewTypes.push_back(dataView->GetViewType());
|
||||
dataView->SaveSettingsToWorkspace(provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Reset
|
||||
// [7/10/2013]
|
||||
//=========================================================================
|
||||
void StreamerDataAggregator::Reset()
|
||||
{
|
||||
m_devices.clear();
|
||||
m_streams.clear();
|
||||
m_requests.clear();
|
||||
m_seeksInfo.clear();
|
||||
ResetTrackingInfo();
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::ResetTrackingInfo()
|
||||
{
|
||||
m_seekTracking.clear();
|
||||
m_highwaterFrame = -1;
|
||||
|
||||
// default device with ID := 0
|
||||
SeekTrackingInfo seekTrackingInfo;
|
||||
seekTrackingInfo.m_currentStreamId = 0;
|
||||
seekTrackingInfo.m_offset = 0;
|
||||
m_seekTracking.insert(AZStd::make_pair(0, seekTrackingInfo));
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
StreamerDataAggregatorSavedState::Reflect(context);
|
||||
StreamerDataAggregatorWorkspace::Reflect(context);
|
||||
StreamerDrillerDialog::Reflect(context);
|
||||
|
||||
serialize->Class<StreamerDataAggregator>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerDataAggregator::AdvanceToFrame(FrameNumberType frame)
|
||||
{
|
||||
while (m_highwaterFrame < frame)
|
||||
{
|
||||
++m_highwaterFrame;
|
||||
FrameChanged(m_highwaterFrame);
|
||||
|
||||
m_frameInfo.push_back();
|
||||
m_frameInfo.back().m_computedSeeksCount = 0;
|
||||
m_frameInfo.back().m_computedThroughput = 0;
|
||||
|
||||
AZ::s64 numEvents = NumOfEventsAtFrame(m_highwaterFrame);
|
||||
if (numEvents)
|
||||
{
|
||||
AZ::s64 firstIndex = GetFirstIndexAtFrame(m_highwaterFrame);
|
||||
|
||||
for (AZ::s64 idx = 0; idx < numEvents; ++idx)
|
||||
{
|
||||
DrillerEvent* dep = m_events[ idx + firstIndex ];
|
||||
AZ::u64 geid = dep->GetGlobalEventId();
|
||||
|
||||
switch (dep->GetEventType())
|
||||
{
|
||||
case Driller::Streamer::SET_DEVICE_MOUNTED:
|
||||
{
|
||||
SeekTrackingInfo seekTrackingInfo;
|
||||
seekTrackingInfo.m_currentStreamId = 0;
|
||||
seekTrackingInfo.m_offset = 0;
|
||||
m_seekTracking.insert(AZStd::make_pair(static_cast<StreamerMountDeviceEvent*>(dep)->m_deviceData.m_id, seekTrackingInfo));
|
||||
break;
|
||||
}
|
||||
case Driller::Streamer::SET_DEVICE_UNMOUNTED:
|
||||
{
|
||||
m_seekTracking.erase(static_cast<StreamerUnmountDeviceEvent*>(dep)->m_unmountedDeviceData->m_id);
|
||||
break;
|
||||
}
|
||||
case Driller::Streamer::SET_ADD_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Driller::Streamer::SET_CANCEL_REQUEST:
|
||||
case Driller::Streamer::SET_RESCHEDULE_REQUEST:
|
||||
case Driller::Streamer::SET_COMPLETE_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Driller::Streamer::SET_REGISTER_STREAM:
|
||||
case Driller::Streamer::SET_UNREGISTER_STREAM:
|
||||
{
|
||||
break;
|
||||
}
|
||||
// m_stream := possibly NULL in these two cases
|
||||
case Driller::Streamer::SET_OPERATION_START:
|
||||
{
|
||||
auto depEvt = static_cast<StreamerOperationStartEvent*>(dep);
|
||||
if (depEvt->m_stream)
|
||||
{
|
||||
auto trackedDevice = m_seekTracking.find(depEvt->m_stream->m_deviceId);
|
||||
if (trackedDevice == m_seekTracking.end())
|
||||
{
|
||||
SeekTrackingInfo seekTrackingInfo;
|
||||
seekTrackingInfo.m_currentStreamId = 0;
|
||||
seekTrackingInfo.m_offset = 0;
|
||||
|
||||
m_seekTracking.insert(AZStd::make_pair(depEvt->m_stream->m_deviceId, seekTrackingInfo));
|
||||
trackedDevice = m_seekTracking.find(depEvt->m_stream->m_deviceId);
|
||||
}
|
||||
// reasons a device might SEEK
|
||||
if (trackedDevice->second.m_currentStreamId != depEvt->m_streamId)
|
||||
{
|
||||
if (
|
||||
(depEvt->m_stream->m_isCompressed && depEvt->m_operation.m_type == Streamer::SOP_COMPRESSOR_READ)
|
||||
||
|
||||
(!depEvt->m_stream->m_isCompressed)
|
||||
)
|
||||
{
|
||||
m_frameInfo.back().m_seekInfo.push_back();
|
||||
m_frameInfo.back().m_seekInfo.back().m_eventId = geid;
|
||||
m_frameInfo.back().m_seekInfo.back().m_eventReason = SEEK_EVENT_SWITCH;
|
||||
trackedDevice->second.m_currentStreamId = depEvt->m_streamId;
|
||||
trackedDevice->second.m_offset = depEvt->m_operation.m_offset;
|
||||
++m_frameInfo.back().m_computedSeeksCount;
|
||||
m_seeksInfo.insert(AZStd::make_pair(geid, SEEK_EVENT_SWITCH));
|
||||
}
|
||||
}
|
||||
else if (trackedDevice->second.m_offset != depEvt->m_operation.m_offset)
|
||||
{
|
||||
if (
|
||||
(depEvt->m_stream->m_isCompressed && depEvt->m_operation.m_type == Streamer::SOP_COMPRESSOR_READ)
|
||||
||
|
||||
(!depEvt->m_stream->m_isCompressed)
|
||||
)
|
||||
{
|
||||
m_frameInfo.back().m_seekInfo.push_back();
|
||||
m_frameInfo.back().m_seekInfo.back().m_eventId = geid;
|
||||
m_frameInfo.back().m_seekInfo.back().m_eventReason = SEEK_EVENT_SKIP;
|
||||
trackedDevice->second.m_offset = depEvt->m_operation.m_offset;
|
||||
++m_frameInfo.back().m_computedSeeksCount;
|
||||
m_seeksInfo.insert(AZStd::make_pair(geid, SEEK_EVENT_SKIP));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Driller::Streamer::SET_OPERATION_COMPLETE:
|
||||
{
|
||||
auto depEvt = azdynamic_cast<StreamerOperationCompleteEvent*>(dep);
|
||||
|
||||
if (depEvt->m_stream)
|
||||
{
|
||||
m_frameInfo.back().m_transferInfo.push_back();
|
||||
m_frameInfo.back().m_transferInfo.back().m_eventId = geid;
|
||||
m_frameInfo.back().m_transferInfo.back().m_eventReason = (TransferEventType)(depEvt->m_type);
|
||||
|
||||
auto trackedDevice = m_seekTracking.find(depEvt->m_stream->m_deviceId);
|
||||
if (trackedDevice == m_seekTracking.end())
|
||||
{
|
||||
SeekTrackingInfo seekTrackingInfo;
|
||||
seekTrackingInfo.m_currentStreamId = 0;
|
||||
seekTrackingInfo.m_offset = 0;
|
||||
|
||||
m_seekTracking.insert(AZStd::make_pair(depEvt->m_stream->m_deviceId, seekTrackingInfo));
|
||||
trackedDevice = m_seekTracking.find(depEvt->m_stream->m_deviceId);
|
||||
}
|
||||
|
||||
if (depEvt->m_stream->m_isCompressed)
|
||||
{
|
||||
if (static_cast<TransferEventType>(depEvt->m_type) == TRANSFER_EVENT_COMPRESSOR_READ || static_cast<TransferEventType>(depEvt->m_type) == TRANSFER_EVENT_COMPRESSOR_WRITE)
|
||||
{
|
||||
m_frameInfo.back().m_transferInfo.back().m_byteCount = depEvt->m_bytesTransferred;
|
||||
m_frameInfo.back().m_computedThroughput += depEvt->m_bytesTransferred;
|
||||
trackedDevice->second.m_offset += depEvt->m_bytesTransferred;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_frameInfo.back().m_transferInfo.back().m_byteCount = depEvt->m_bytesTransferred;
|
||||
m_frameInfo.back().m_computedThroughput += depEvt->m_bytesTransferred;
|
||||
trackedDevice->second.m_offset += depEvt->m_bytesTransferred;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* StreamerDataAggregator::GetFilenameFromStreamId(unsigned int globalEventId, AZ::u64 streamId)
|
||||
{
|
||||
// starting at eventId, skip backwards through the events until a register stream is found
|
||||
while (1)
|
||||
{
|
||||
if (globalEventId > m_events.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto event = m_events[globalEventId];
|
||||
auto registerEvent = azdynamic_cast<StreamerRegisterStreamEvent*>(event);
|
||||
if (registerEvent && registerEvent->m_streamData.m_id == streamId)
|
||||
{
|
||||
return registerEvent->m_streamData.m_name;
|
||||
}
|
||||
|
||||
if (globalEventId == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
--globalEventId;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* StreamerDataAggregator::GetDebugNameFromStreamId(unsigned int globalEventId, AZ::u64 streamId)
|
||||
{
|
||||
// starting at eventId, skip backwards through the events until a request added (which has debug info) is found
|
||||
while (1)
|
||||
{
|
||||
if (globalEventId > m_events.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto event = m_events[globalEventId];
|
||||
auto requestEvent = azdynamic_cast<StreamerAddRequestEvent*>(event);
|
||||
if (requestEvent && requestEvent->m_requestData.m_streamId == streamId)
|
||||
{
|
||||
if (requestEvent->m_requestData.m_debugName)
|
||||
{
|
||||
return requestEvent->m_requestData.m_debugName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if (globalEventId == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
--globalEventId;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
const AZ::u64 StreamerDataAggregator::GetOffsetFromStreamId(unsigned int globalEventId, AZ::u64 streamId)
|
||||
{
|
||||
// starting at eventId, skip backwards through the events until the start operation related to this ID is found
|
||||
while (1)
|
||||
{
|
||||
if (globalEventId > m_events.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto event = m_events[globalEventId];
|
||||
auto startEvent = azdynamic_cast<StreamerOperationStartEvent*>(event);
|
||||
if (startEvent && startEvent->m_streamId == streamId)
|
||||
{
|
||||
return startEvent->m_operation.m_offset;
|
||||
}
|
||||
|
||||
if (globalEventId == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
--globalEventId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float StreamerDataAggregator::ThroughputAtFrame(FrameNumberType frame)
|
||||
{
|
||||
if (frame >= 0)
|
||||
{
|
||||
AdvanceToFrame(frame);
|
||||
return (float)m_frameInfo[frame].m_computedThroughput;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
float StreamerDataAggregator::SeeksAtFrame(FrameNumberType frame)
|
||||
{
|
||||
if (frame >= 0)
|
||||
{
|
||||
AdvanceToFrame(frame);
|
||||
return (float)m_frameInfo[frame].m_computedSeeksCount;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
Driller::StreamerDataAggregator::TransferBreakoutType& StreamerDataAggregator::ThroughputAtFrameBreakout(FrameNumberType frame)
|
||||
{
|
||||
AdvanceToFrame(frame);
|
||||
return m_frameInfo[frame].m_transferInfo;
|
||||
}
|
||||
Driller::StreamerDataAggregator::SeeksBreakoutType& StreamerDataAggregator::SeeksAtFrameBreakout(FrameNumberType frame)
|
||||
{
|
||||
AdvanceToFrame(frame);
|
||||
return m_frameInfo[frame].m_seekInfo;
|
||||
}
|
||||
StreamerDataAggregator::SeekEventType StreamerDataAggregator::GetSeekType(AZ::s64 id)
|
||||
{
|
||||
auto iter = m_seeksInfo.find(id);
|
||||
if (iter != m_seeksInfo.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return SEEK_EVENT_NONE;
|
||||
}
|
||||
} // namespace Driller
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* 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 "StreamerDataAggregator.hxx"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
AZ::Debug::DrillerHandlerParser* StreamerDrillerHandlerParser::OnEnterTag(AZ::u32 tagName)
|
||||
{
|
||||
AZ_Assert(m_data, "You must set a valid memory aggregator before we can process the data!");
|
||||
|
||||
if (tagName == AZ_CRC("OnDeviceMounted", 0xc6bdd55e))
|
||||
{
|
||||
m_subTag = ST_DEVICE_MOUNTED;
|
||||
m_data->AddEvent(aznew StreamerMountDeviceEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnRegisterStream", 0x893513c1))
|
||||
{
|
||||
m_subTag = ST_STREAM_REGISTER;
|
||||
m_data->AddEvent(aznew StreamerRegisterStreamEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnReadCacheHit", 0xd4535712))
|
||||
{
|
||||
m_subTag = ST_READ_CACHE_HIT;
|
||||
if (m_allowCacheHitsInReportedStream)
|
||||
{
|
||||
m_data->AddEvent(aznew StreamerReadCacheHit());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnAddRequest", 0xee41c96e))
|
||||
{
|
||||
m_subTag = ST_REQUEST_ADD;
|
||||
m_data->AddEvent(aznew StreamerAddRequestEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnCompleteRequest", 0x7f6b66f7))
|
||||
{
|
||||
m_subTag = ST_REQUEST_COMPLETE;
|
||||
m_data->AddEvent(aznew StreamerCompleteRequestEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnRescheduleRequest", 0x883b3e85))
|
||||
{
|
||||
m_subTag = ST_REQUEST_RESCHEDULE;
|
||||
m_data->AddEvent(aznew StreamerRescheduleRequestEvent());
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnRead", 0xd7714b7b))
|
||||
{
|
||||
m_subTag = ST_OPERATION_READ;
|
||||
m_data->AddEvent(aznew StreamerOperationStartEvent(Streamer::SOP_READ));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnReadComplete", 0x0efa014b))
|
||||
{
|
||||
m_subTag = ST_OPERATION_READ_COMPLETE;
|
||||
m_data->AddEvent(aznew StreamerOperationCompleteEvent(Streamer::SOP_READ));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnWrite", 0x6925001a))
|
||||
{
|
||||
m_subTag = ST_OPERATION_WRITE;
|
||||
m_data->AddEvent(aznew StreamerOperationStartEvent(Streamer::SOP_WRITE));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnWriteComplete", 0x6c5f7c79))
|
||||
{
|
||||
m_subTag = ST_OPERATION_WRITE_COMPLETE;
|
||||
m_data->AddEvent(aznew StreamerOperationCompleteEvent(Streamer::SOP_WRITE));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnCompressorRead", 0xbd093b22))
|
||||
{
|
||||
m_subTag = ST_OPERATION_COMPRESSOR_READ;
|
||||
m_data->AddEvent(aznew StreamerOperationStartEvent(Streamer::SOP_COMPRESSOR_READ));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnCompressorReadComplete", 0x9c08d9cd))
|
||||
{
|
||||
m_subTag = ST_OPERATION_COMPRESSOR_READ_COMPLETE;
|
||||
m_data->AddEvent(aznew StreamerOperationCompleteEvent(Streamer::SOP_COMPRESSOR_READ));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnCompressorWrite", 0x7bf8913a))
|
||||
{
|
||||
m_subTag = ST_OPERATION_COMPRESSOR_WRITE;
|
||||
m_data->AddEvent(aznew StreamerOperationStartEvent(Streamer::SOP_COMPRESSOR_WRITE));
|
||||
return this;
|
||||
}
|
||||
else if (tagName == AZ_CRC("OnCompressorWriteComplete", 0x6816a8b4))
|
||||
{
|
||||
m_subTag = ST_OPERATION_COMPRESSOR_WRITE_COMPLETE;
|
||||
m_data->AddEvent(aznew StreamerOperationCompleteEvent(Streamer::SOP_COMPRESSOR_WRITE));
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_subTag = ST_NONE;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StreamerDrillerHandlerParser::OnExitTag(DrillerHandlerParser* handler, AZ::u32 tagName)
|
||||
{
|
||||
(void)tagName;
|
||||
if (handler != nullptr)
|
||||
{
|
||||
m_subTag = ST_NONE; // we have only one level just go back to the default state
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerDrillerHandlerParser::OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode)
|
||||
{
|
||||
AZ_Assert(m_data, "You must set a valid memory aggregator before we can process the data!");
|
||||
(void)dataNode;
|
||||
switch (m_subTag)
|
||||
{
|
||||
case ST_NONE:
|
||||
{
|
||||
if (dataNode.m_name == AZ_CRC("OnDeviceUnmounted", 0x7395545a))
|
||||
{
|
||||
StreamerUnmountDeviceEvent* event = aznew StreamerUnmountDeviceEvent();
|
||||
dataNode.Read(event->m_deviceId);
|
||||
m_data->AddEvent(event);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("OnUnregisterStream", 0x3374d0cb))
|
||||
{
|
||||
StreamerUnregisterStreamEvent* event = aznew StreamerUnregisterStreamEvent();
|
||||
dataNode.Read(event->m_streamId);
|
||||
m_data->AddEvent(event);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("OnCancelRequest", 0x89d4ea74))
|
||||
{
|
||||
StreamerCancelRequestEvent* event = aznew StreamerCancelRequestEvent();
|
||||
dataNode.Read(event->m_requestId);
|
||||
m_data->AddEvent(event);
|
||||
}
|
||||
} break;
|
||||
case ST_DEVICE_MOUNTED:
|
||||
{
|
||||
StreamerMountDeviceEvent* event = static_cast<StreamerMountDeviceEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("DeviceId", 0x383bcd03))
|
||||
{
|
||||
dataNode.Read(event->m_deviceData.m_id);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Name", 0x5e237e06))
|
||||
{
|
||||
event->m_deviceData.m_name = dataNode.ReadPooledString();
|
||||
}
|
||||
} break;
|
||||
case ST_STREAM_REGISTER:
|
||||
{
|
||||
StreamerRegisterStreamEvent* event = static_cast<StreamerRegisterStreamEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("DeviceId", 0x383bcd03))
|
||||
{
|
||||
dataNode.Read(event->m_streamData.m_deviceId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("StreamId", 0x7597546f))
|
||||
{
|
||||
dataNode.Read(event->m_streamData.m_id);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Name", 0x5e237e06))
|
||||
{
|
||||
event->m_streamData.m_name = dataNode.ReadPooledString();
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Flags", 0x0b0541ba))
|
||||
{
|
||||
dataNode.Read(event->m_streamData.m_flags);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Size", 0xf7c0246a))
|
||||
{
|
||||
dataNode.Read(event->m_streamData.m_size);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("IsCompressed", 0xdd32876c))
|
||||
{
|
||||
dataNode.Read(event->m_streamData.m_isCompressed);
|
||||
}
|
||||
} break;
|
||||
case ST_READ_CACHE_HIT:
|
||||
{
|
||||
if (m_allowCacheHitsInReportedStream)
|
||||
{
|
||||
StreamerReadCacheHit* event = static_cast<StreamerReadCacheHit*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("StreamId", 0x7597546f))
|
||||
{
|
||||
dataNode.Read(event->m_streamId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Offset", 0x590acad0))
|
||||
{
|
||||
dataNode.Read(event->m_offset);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Size", 0xf7c0246a))
|
||||
{
|
||||
dataNode.Read(event->m_size);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("DebugName", 0x6c3ea120))
|
||||
{
|
||||
event->m_debugName = dataNode.ReadPooledString();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case ST_REQUEST_ADD:
|
||||
{
|
||||
StreamerAddRequestEvent* event = static_cast<StreamerAddRequestEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("RequestId", 0x34e754a3))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_id);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("StreamId", 0x7597546f))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_streamId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Offset", 0x590acad0))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_offset);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Size", 0xf7c0246a))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_size);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Deadline", 0xb74774f2))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_deadline);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Priority", 0x62a6dc27))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_priority);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Operation", 0x1981a66d))
|
||||
{
|
||||
dataNode.Read(event->m_requestData.m_operation);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("DebugName", 0x6c3ea120))
|
||||
{
|
||||
event->m_requestData.m_debugName = dataNode.ReadPooledString();
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp", 0xa5d6e63e))
|
||||
{
|
||||
dataNode.Read(event->m_timeStamp);
|
||||
}
|
||||
} break;
|
||||
case ST_REQUEST_COMPLETE:
|
||||
{
|
||||
StreamerCompleteRequestEvent* event = static_cast<StreamerCompleteRequestEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("RequestId", 0x34e754a3))
|
||||
{
|
||||
dataNode.Read(event->m_requestId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("State", 0xa393d2fb))
|
||||
{
|
||||
dataNode.Read(event->m_state);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp", 0xa5d6e63e))
|
||||
{
|
||||
dataNode.Read(event->m_timeStamp);
|
||||
}
|
||||
} break;
|
||||
case ST_REQUEST_RESCHEDULE:
|
||||
{
|
||||
StreamerRescheduleRequestEvent* event = static_cast<StreamerRescheduleRequestEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("RequestId", 0x34e754a3))
|
||||
{
|
||||
dataNode.Read(event->m_requestId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("NewDeadLine", 0x184cc661))
|
||||
{
|
||||
dataNode.Read(event->m_newDeadline);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("NewPriority", 0xcdad6eb4))
|
||||
{
|
||||
dataNode.Read(event->m_newPriority);
|
||||
}
|
||||
} break;
|
||||
case ST_OPERATION_READ:
|
||||
case ST_OPERATION_WRITE:
|
||||
case ST_OPERATION_COMPRESSOR_READ:
|
||||
case ST_OPERATION_COMPRESSOR_WRITE:
|
||||
{
|
||||
StreamerOperationStartEvent* event = static_cast<StreamerOperationStartEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("StreamId", 0x7597546f))
|
||||
{
|
||||
dataNode.Read(event->m_streamId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Size", 0xf7c0246a))
|
||||
{
|
||||
dataNode.Read(event->m_operation.m_size);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Offset", 0x590acad0))
|
||||
{
|
||||
dataNode.Read(event->m_operation.m_offset);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp", 0xa5d6e63e))
|
||||
{
|
||||
dataNode.Read(event->m_timeStamp);
|
||||
}
|
||||
} break;
|
||||
|
||||
case ST_OPERATION_READ_COMPLETE:
|
||||
case ST_OPERATION_WRITE_COMPLETE:
|
||||
case ST_OPERATION_COMPRESSOR_READ_COMPLETE:
|
||||
case ST_OPERATION_COMPRESSOR_WRITE_COMPLETE:
|
||||
{
|
||||
StreamerOperationCompleteEvent* event = static_cast<StreamerOperationCompleteEvent*>(m_data->GetEvents().back());
|
||||
if (dataNode.m_name == AZ_CRC("StreamId", 0x7597546f))
|
||||
{
|
||||
dataNode.Read(event->m_streamId);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("bytesTransferred", 0x35684b99))
|
||||
{
|
||||
dataNode.Read(event->m_bytesTransferred);
|
||||
}
|
||||
else if (dataNode.m_name == AZ_CRC("Timestamp", 0xa5d6e63e))
|
||||
{
|
||||
dataNode.Read(event->m_timeStamp);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} // namespace Driller
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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 "StreamerDataView.hxx"
|
||||
#include <Woodpecker/Driller/IO/moc_StreamerDataView.cpp>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QScrollBar>
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
StreamerDrillerTableView::StreamerDrillerTableView(QWidget* pParent)
|
||||
: QTableView(pParent)
|
||||
, m_isScrollAfterInsert(true)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
m_scheduledMaxScroll = false;
|
||||
}
|
||||
|
||||
StreamerDrillerTableView::~StreamerDrillerTableView()
|
||||
{
|
||||
}
|
||||
|
||||
void StreamerDrillerTableView::rowsAboutToBeInserted()
|
||||
{
|
||||
m_isScrollAfterInsert = IsAtMaxScroll();
|
||||
}
|
||||
|
||||
void StreamerDrillerTableView::rowsInserted()
|
||||
{
|
||||
if ((m_isScrollAfterInsert) && (!m_scheduledMaxScroll))
|
||||
{
|
||||
m_scheduledMaxScroll = true;
|
||||
QTimer::singleShot(0, this, SLOT(doScrollToBottom()));
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerDrillerTableView::doScrollToBottom()
|
||||
{
|
||||
m_scheduledMaxScroll = false;
|
||||
scrollToBottom();
|
||||
m_isScrollAfterInsert = true;
|
||||
}
|
||||
|
||||
bool StreamerDrillerTableView::IsAtMaxScroll() const
|
||||
{
|
||||
return (verticalScrollBar()->value() == verticalScrollBar()->maximum());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* 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 "StreamerEvents.h"
|
||||
|
||||
#include "StreamerDataAggregator.hxx"
|
||||
|
||||
namespace Driller
|
||||
{
|
||||
void StreamerMountDeviceEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_devices.push_back(&m_deviceData);
|
||||
}
|
||||
|
||||
void StreamerMountDeviceEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::DeviceArrayType::iterator it = AZStd::find(aggr->m_devices.begin(), aggr->m_devices.end(), &m_deviceData);
|
||||
if (it != aggr->m_devices.end()) // we can potentially not have registered the device if we did NOT capture the full state! TODO: warn about this
|
||||
{
|
||||
aggr->m_devices.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerUnmountDeviceEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
for (StreamerDataAggregator::DeviceArrayType::iterator it = aggr->m_devices.begin(); it != aggr->m_devices.end(); ++it)
|
||||
{
|
||||
if ((*it)->m_id == m_deviceId)
|
||||
{
|
||||
m_unmountedDeviceData = *it;
|
||||
aggr->m_devices.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerUnmountDeviceEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_devices.push_back(m_unmountedDeviceData);
|
||||
}
|
||||
|
||||
void StreamerRegisterStreamEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_streams.insert(AZStd::make_pair(m_streamData.m_id, &m_streamData));
|
||||
}
|
||||
|
||||
void StreamerRegisterStreamEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_streams.erase(m_streamData.m_id);
|
||||
}
|
||||
|
||||
void StreamerUnregisterStreamEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::StreamMapType::iterator it = aggr->m_streams.find(m_streamId);
|
||||
if (it != aggr->m_streams.end())
|
||||
{
|
||||
m_removedStreamData = it->second;
|
||||
aggr->m_streams.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerUnregisterStreamEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
if (m_removedStreamData != nullptr)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_streams.insert(AZStd::make_pair(m_streamId, m_removedStreamData));
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerReadCacheHit::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
(void)aggr; // Add to read cache hit map
|
||||
}
|
||||
|
||||
void StreamerReadCacheHit::StepBackward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
(void)aggr; // Remove from read cache hit map
|
||||
}
|
||||
|
||||
void StreamerAddRequestEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_requests.insert(AZStd::make_pair(m_requestData.m_id, &m_requestData));
|
||||
}
|
||||
|
||||
void StreamerAddRequestEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_requests.erase(m_requestData.m_id);
|
||||
}
|
||||
|
||||
void StreamerCompleteRequestEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::RequestMapType::iterator it = aggr->m_requests.find(m_requestId);
|
||||
if (it != aggr->m_requests.end())
|
||||
{
|
||||
m_removedRequest = it->second;
|
||||
m_oldState = m_removedRequest->m_completeState;
|
||||
m_removedRequest->m_completeState = m_state;
|
||||
aggr->m_requests.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO warn, this is possible if we did not capture the full state from the beginning
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerCompleteRequestEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
if (m_removedRequest != nullptr)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
m_removedRequest->m_completeState = m_oldState;
|
||||
aggr->m_requests.insert(AZStd::make_pair(m_requestId, m_removedRequest));
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerCancelRequestEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::RequestMapType::iterator it = aggr->m_requests.find(m_requestId);
|
||||
if (it != aggr->m_requests.end())
|
||||
{
|
||||
m_cancelledRequestData = it->second;
|
||||
aggr->m_requests.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerCancelRequestEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
if (m_cancelledRequestData != nullptr)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
aggr->m_requests.insert(AZStd::make_pair(m_requestId, m_cancelledRequestData));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StreamerRescheduleRequestEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::RequestMapType::iterator it = aggr->m_requests.find(m_requestId);
|
||||
if (it != aggr->m_requests.end())
|
||||
{
|
||||
m_rescheduledRequestData = it->second;
|
||||
m_oldDeadline = m_rescheduledRequestData->m_deadline;
|
||||
m_oldPriority = m_rescheduledRequestData->m_priority;
|
||||
m_rescheduledRequestData->m_deadline = m_newDeadline;
|
||||
m_rescheduledRequestData->m_priority = m_newPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO warn, this is possible if we did not capture the full state from the beginning
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerRescheduleRequestEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
(void)data;
|
||||
if (m_rescheduledRequestData != nullptr)
|
||||
{
|
||||
m_rescheduledRequestData->m_deadline = m_oldDeadline;
|
||||
m_rescheduledRequestData->m_priority = m_oldPriority;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerOperationStartEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::StreamMapType::iterator it = aggr->m_streams.find(m_streamId);
|
||||
if (it != aggr->m_streams.end())
|
||||
{
|
||||
m_stream = it->second;
|
||||
m_previousOperation = m_stream->m_operation;
|
||||
m_stream->m_operation = &m_operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO warn in a smart way too many warnings while scrubbing
|
||||
//AZ_Warning("Streamer Driller",false,"Operation could not find a stream 0x%08x this can be ok deoending on the streamer mode (if it captures the inital state or not)!",m_streamId);
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerOperationStartEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
(void)data;
|
||||
if (m_stream != nullptr)
|
||||
{
|
||||
m_stream->m_operation = m_previousOperation;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerOperationCompleteEvent::StepForward(Aggregator* data)
|
||||
{
|
||||
StreamerDataAggregator* aggr = static_cast<StreamerDataAggregator*>(data);
|
||||
StreamerDataAggregator::StreamMapType::iterator it = aggr->m_streams.find(m_streamId);
|
||||
if (it != aggr->m_streams.end())
|
||||
{
|
||||
m_stream = it->second;
|
||||
m_stream->m_operation->m_bytesTransferred = m_bytesTransferred;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamerOperationCompleteEvent::StepBackward(Aggregator* data)
|
||||
{
|
||||
(void)data;
|
||||
if (m_stream != nullptr)
|
||||
{
|
||||
m_stream->m_operation->m_bytesTransferred = 0;
|
||||
}
|
||||
}
|
||||
} // namespace Driller
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user