ImGui histogram container improvements (#4630)
* Added auto scale mode that uses a running average to expand and shrink the visible vertical range. * Added option to set the move direction and either push new values to the front of the buffer (left) and make the histogram move to the right or the inverse. * Changed the camera monitor to use auto scaling as well as the current one was not showing anything because of an outlier. * Pre-fill the histogram with zeros so that the first pushed sample moves in without horizontal scaling effects which made it hard to read out any information from the histogram. Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
@@ -18,8 +18,7 @@ namespace ImGui
|
||||
namespace LYImGuiUtils
|
||||
{
|
||||
/**
|
||||
* A small class to help manage values for an ImGui Histogram ( ImGui doesn't want to manage the values itself ).
|
||||
* Nothing crazy, just helps reduce boiler plate if you are ImGui::PlotHistogram()'ing
|
||||
* A small class to help manage values for an ImGui Histogram (ImGui is not managing values itself).
|
||||
*/
|
||||
class HistogramContainer
|
||||
{
|
||||
@@ -40,9 +39,24 @@ namespace ImGui
|
||||
// Static Type to String function
|
||||
static const char* ViewTypeToString(ViewType viewType);
|
||||
|
||||
//! Horizontal move direction of the histogram when pushing new values.
|
||||
enum MoveDirection : AZ::u8
|
||||
{
|
||||
PushLeftMoveRight = 0, //! Push new values to the front of the buffer, which corresponds to the left side, and make the histogram move to the right.
|
||||
PushRightMoveLeft = 1, //! Push new values to the back of the buffer, which corresponds to the right side, and make the histogram move to the left.
|
||||
};
|
||||
|
||||
//! Mode determining the min and max values for the visible range of the vertical axis for the histogram.
|
||||
enum ScaleMode : AZ::u8
|
||||
{
|
||||
NoAutoScale = 0, //! Use the min and max values given by Init() as visible range.
|
||||
AutoExpand = 1, //! Expand scale in case a sample is out of the current bounds. Does only expand the scale but not decrease it back again.
|
||||
AutoScale = 2, //! Use a running average to expand and shrink the visible range.
|
||||
};
|
||||
|
||||
// Do all of the set up via Init
|
||||
void Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale
|
||||
, bool autoExpandScale, bool startCollapsed = false, bool drawMostRecentValue = true);
|
||||
void Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale,
|
||||
ScaleMode scaleMode = AutoScale, bool startCollapsed = false, bool drawMostRecentValue = true);
|
||||
|
||||
// How many values are in the container currently
|
||||
int GetSize() { return static_cast<int>(m_values.size()); }
|
||||
@@ -50,9 +64,6 @@ namespace ImGui
|
||||
// What is the max size of the container
|
||||
int GetMaxSize() { return m_maxSize; }
|
||||
|
||||
// Set the Max Size and clear the container
|
||||
void SetMaxSize(int size) { m_values.clear(); m_maxSize = size; }
|
||||
|
||||
// Push a value to this histogram container
|
||||
void PushValue(float val);
|
||||
|
||||
@@ -65,7 +76,18 @@ namespace ImGui
|
||||
// Draw this histogram with ImGui
|
||||
void Draw(float histogramWidth, float histogramHeight);
|
||||
|
||||
//! Adjust the scale mode to determine the min and max values for the visible range of the vertical axis for the histogram.
|
||||
void SetScaleMode(ScaleMode scaleMode) { m_scaleMode = scaleMode; }
|
||||
|
||||
//! Adjust the horizontal move direction of the histogram when pushing new values.
|
||||
void SetMoveDirection(MoveDirection moveDirection) { m_moveDirection = moveDirection; }
|
||||
|
||||
//! Calculate the min and maximum values for the present samples.
|
||||
void CalcMinMaxValues(float& outMin, float& outMax);
|
||||
|
||||
private:
|
||||
// Set the Max Size and clear the container
|
||||
void SetMaxSize(int size);
|
||||
|
||||
AZStd::string m_histogramName;
|
||||
AZStd::deque<float> m_values;
|
||||
@@ -73,8 +95,10 @@ namespace ImGui
|
||||
ViewType m_viewType = ViewType::Histogram;
|
||||
float m_minScale;
|
||||
float m_maxScale;
|
||||
MoveDirection m_moveDirection = PushLeftMoveRight; //! Specify if values will be added on the left and the histogram moves right or the other way around.
|
||||
bool m_dispalyOverlays;
|
||||
bool m_autoExpandScale;
|
||||
ScaleMode m_scaleMode; //! Determines if the vertical range of the histogram will be manually specified, auto-expanded or automatically scaled based on the samples.
|
||||
float m_autoScaleSpeed = 0.05f; //! Indicates how fast the min max values and the visible vertical range are adapting to new samples.
|
||||
bool m_collapsed;
|
||||
bool m_drawMostRecentValueText;
|
||||
};
|
||||
|
||||
@@ -34,13 +34,13 @@ namespace ImGui
|
||||
ImGuiCameraMonitorRequestBus::Handler::BusConnect();
|
||||
|
||||
// Init Histogram Containers
|
||||
m_dofMinZHisto.Init( "DOF Min Z", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true);
|
||||
m_dofMinZBlendMultHisto.Init( "DOF Min Z Blend Mult", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f, true);
|
||||
m_dofMinZScaleHisto.Init( "DOF Min Z Scale", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f, true);
|
||||
m_dofMinZHisto.Init( "DOF Min Z", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f);
|
||||
m_dofMinZBlendMultHisto.Init( "DOF Min Z Blend Mult", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f);
|
||||
m_dofMinZScaleHisto.Init( "DOF Min Z Scale", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f);
|
||||
|
||||
m_globalActiveCamInfo.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f, true);
|
||||
m_globalActiveCamInfo.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true);
|
||||
m_globalActiveCamInfo.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true);
|
||||
m_globalActiveCamInfo.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f);
|
||||
m_globalActiveCamInfo.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f);
|
||||
m_globalActiveCamInfo.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void ImGuiLYCameraMonitor::Shutdown()
|
||||
@@ -214,7 +214,7 @@ namespace ImGui
|
||||
}
|
||||
// save this cam off as the current one
|
||||
m_currentCamera = newCamId;
|
||||
|
||||
|
||||
// create a new empty CameraInfo in the queue
|
||||
m_cameraHistory.push_front(CameraInfo());
|
||||
|
||||
@@ -224,9 +224,9 @@ namespace ImGui
|
||||
AZ::ComponentApplicationBus::BroadcastResult(newCam.m_camName, &AZ::ComponentApplicationBus::Events::GetEntityName, m_currentCamera);
|
||||
newCam.m_activeTime = 0.0f;
|
||||
newCam.m_activeFrames = 0;
|
||||
newCam.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f, true);
|
||||
newCam.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true);
|
||||
newCam.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true);
|
||||
newCam.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f);
|
||||
newCam.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f);
|
||||
newCam.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f);
|
||||
|
||||
// reset a few variables on the global camera info
|
||||
m_globalActiveCamInfo.m_camId = newCam.m_camId;
|
||||
|
||||
@@ -16,45 +16,92 @@ namespace ImGui
|
||||
{
|
||||
namespace LYImGuiUtils
|
||||
{
|
||||
void HistogramContainer::Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale
|
||||
, bool autoExpandScale, bool startCollapsed/* = false*/, bool drawMostRecentValue/* = true*/)
|
||||
void HistogramContainer::Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale,
|
||||
ScaleMode scaleMode, bool startCollapsed/* = false*/, bool drawMostRecentValue/* = true*/)
|
||||
{
|
||||
m_histogramName = histogramName;
|
||||
m_minScale = minScale;
|
||||
m_maxScale = maxScale;
|
||||
m_viewType = viewType;
|
||||
m_dispalyOverlays = displayOverlays;
|
||||
m_autoExpandScale = autoExpandScale;
|
||||
m_scaleMode = scaleMode;
|
||||
m_collapsed = startCollapsed;
|
||||
m_drawMostRecentValueText = drawMostRecentValue;
|
||||
SetMaxSize(maxValueCountSize);
|
||||
}
|
||||
|
||||
void HistogramContainer::PushValue(float val)
|
||||
void HistogramContainer::SetMaxSize(int size)
|
||||
{
|
||||
m_values.resize(size);
|
||||
m_maxSize = size;
|
||||
|
||||
// Pre-fill the histogram with zeros so that the bars do not fill the space and
|
||||
// scale horizontally when there are not enough samples yet.
|
||||
for (float& value : m_values)
|
||||
{
|
||||
value = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void HistogramContainer::PushValue(float value)
|
||||
{
|
||||
if (m_maxSize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_values.size() == m_maxSize)
|
||||
{
|
||||
m_values.pop_back();
|
||||
if (m_moveDirection == PushLeftMoveRight)
|
||||
{
|
||||
m_values.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_values.pop_front();
|
||||
}
|
||||
}
|
||||
else if (m_values.size() > m_maxSize)
|
||||
{
|
||||
m_values.erase(m_values.begin() + (m_maxSize - 1), m_values.end());
|
||||
}
|
||||
m_values.push_front(val);
|
||||
|
||||
if (m_autoExpandScale)
|
||||
if (m_moveDirection == PushLeftMoveRight)
|
||||
{
|
||||
if (val < m_minScale)
|
||||
m_values.push_front(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_values.push_back(value);
|
||||
}
|
||||
|
||||
switch (m_scaleMode)
|
||||
{
|
||||
case AutoExpand:
|
||||
{
|
||||
m_minScale = val;
|
||||
if (value < m_minScale)
|
||||
{
|
||||
m_minScale = value;
|
||||
}
|
||||
else if (value > m_maxScale)
|
||||
{
|
||||
m_maxScale = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (val > m_maxScale)
|
||||
case AutoScale:
|
||||
{
|
||||
m_maxScale = val;
|
||||
float min = 0.0f;
|
||||
float max = 0.0f;
|
||||
CalcMinMaxValues(min, max);
|
||||
|
||||
m_minScale = AZ::Lerp(m_minScale, min, m_autoScaleSpeed);
|
||||
m_maxScale = AZ::Lerp(m_maxScale, max, m_autoScaleSpeed);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +133,6 @@ namespace ImGui
|
||||
ImGui::DragInt("History Size", &m_maxSize, 1, 1, 1000, "%f");
|
||||
ImGui::DragFloat("Max Scale", &m_maxScale, 0.0001f, -100.0f, 100.0f);
|
||||
ImGui::DragFloat("Min Scale", &m_minScale, 0.0001f, -100.0f, 100.0f);
|
||||
ImGui::Checkbox("Auto Expand Scale", &m_autoExpandScale);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -157,6 +203,26 @@ namespace ImGui
|
||||
return "Lines";
|
||||
}
|
||||
}
|
||||
|
||||
void HistogramContainer::CalcMinMaxValues(float& outMin, float& outMax)
|
||||
{
|
||||
// Use the manually set min and max scale values in case there are no samples.
|
||||
if (m_values.empty())
|
||||
{
|
||||
outMin = m_minScale;
|
||||
outMax = m_maxScale;
|
||||
return;
|
||||
}
|
||||
|
||||
outMin = +AZ::Constants::FloatMax;
|
||||
outMax = -AZ::Constants::FloatMax;
|
||||
|
||||
for (const float x : m_values)
|
||||
{
|
||||
outMin = AZ::GetMin(outMin, x);
|
||||
outMax = AZ::GetMax(outMax, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #ifdef IMGUI_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user