Files
o3de/Code/Editor/Plugins/EditorCommon/DrawingPrimitives/Ruler.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

192 lines
7.2 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "Ruler.h"
#include <QPainter>
#include <QPalette>
#include <AzCore/Casting/numeric_cast.h>
namespace DrawingPrimitives
{
enum
{
RULER_MIN_PIXELS_PER_TICK = 3,
};
std::vector<STick> CalculateTicks(uint size, Range visibleRange, Range rulerRange, int* pRulerPrecision, Range* pScreenRulerRange)
{
std::vector<STick> ticks;
if (size == 0)
{
if (pRulerPrecision)
{
*pRulerPrecision = 0;
}
return ticks;
}
const float pixelsPerUnit = visibleRange.Length() > 0.0f ? (float)size / visibleRange.Length() : 1.0f;
const float startTime = rulerRange.start;
const float endTime = rulerRange.end;
const float totalDuration = endTime - startTime;
const float ticksMinPower = log10f(RULER_MIN_PIXELS_PER_TICK);
const float ticksPowerDelta = ticksMinPower - log10f(pixelsPerUnit);
const int digitsAfterPoint = AZStd::max(-int(ceil(ticksPowerDelta)) - 1, 0);
if (pRulerPrecision)
{
*pRulerPrecision = digitsAfterPoint;
}
const float scaleStep = powf(10.0f, ceil(ticksPowerDelta));
const float scaleStepPixels = scaleStep * pixelsPerUnit;
const int numMarkers = int(totalDuration / scaleStep) + 1;
const float startTimeRound = int(startTime / scaleStep) * scaleStep;
const int startOffsetMod = int(startTime / scaleStep) % 10;
const int scaleOffsetPixels = aznumeric_cast<int>((startTime - startTimeRound) * pixelsPerUnit);
const int startX = aznumeric_cast<int>((rulerRange.start - visibleRange.start) * pixelsPerUnit);
const int endX = aznumeric_cast<int>(startX + (numMarkers - 1) * scaleStepPixels - scaleOffsetPixels);
if (pScreenRulerRange)
{
*pScreenRulerRange = Range(aznumeric_cast<float>(startX), aznumeric_cast<float>(endX));
}
const int startLoop = std::max((int)((scaleOffsetPixels - startX) / scaleStepPixels) - 1, 0);
const int endLoop = std::min((int)((size + scaleOffsetPixels - startX) / scaleStepPixels) + 1, numMarkers);
for (int i = startLoop; i < endLoop; ++i)
{
STick tick;
const int x = aznumeric_cast<int>(startX + i * scaleStepPixels - scaleOffsetPixels);
const float value = startTimeRound + i * scaleStep;
tick.m_bTenth = (startOffsetMod + i) % 10 != 0;
tick.m_position = x;
tick.m_value = value;
ticks.push_back(tick);
}
return ticks;
}
QColor Interpolate(const QColor& a, const QColor& b, float k)
{
float mk = 1.0f - k;
return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
aznumeric_cast<int>(a.green() * mk + b.green() * k),
aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
}
void DrawTicks(const std::vector<STick>& ticks, QPainter& painter, const QPalette& palette, const STickOptions& options)
{
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
painter.setPen(QPen(midDark));
const int height = options.m_rect.height();
const int top = options.m_rect.top();
for (const STick& tick : ticks)
{
const int x = tick.m_position + options.m_rect.left();
if (tick.m_bTenth)
{
painter.drawLine(QPoint(x, top + height - options.m_markHeight / 2), QPoint(x, top + height));
}
else
{
painter.drawLine(QPoint(x, top + height - options.m_markHeight), QPoint(x, top + height));
}
}
}
void DrawTicks(QPainter& painter, const QPalette& palette, const SRulerOptions& options)
{
const std::vector<STick> ticks = CalculateTicks(options.m_rect.width(), options.m_visibleRange, options.m_rulerRange, nullptr, nullptr);
DrawTicks(ticks, painter, palette, options);
}
void DrawRuler(QPainter& painter, const QPalette& palette, const SRulerOptions& options, int* pRulerPrecision)
{
int rulerPrecision;
Range screenRulerRange;
const std::vector<STick> ticks = CalculateTicks(options.m_rect.width(), options.m_visibleRange, options.m_rulerRange, &rulerPrecision, &screenRulerRange);
if (pRulerPrecision)
{
*pRulerPrecision = rulerPrecision;
}
if (options.m_shadowSize > 0)
{
QRect shadowRect = QRect(options.m_rect.left(), options.m_rect.height(), options.m_rect.width(), options.m_shadowSize);
QLinearGradient upperGradient(shadowRect.left(), shadowRect.top(), shadowRect.left(), shadowRect.bottom());
upperGradient.setColorAt(0.0f, QColor(0, 0, 0, 128));
upperGradient.setColorAt(1.0f, QColor(0, 0, 0, 0));
QBrush upperBrush(upperGradient);
painter.fillRect(shadowRect, upperBrush);
}
painter.fillRect(options.m_rect, DrawingPrimitives::Interpolate(palette.color(QPalette::Button), palette.color(QPalette::Midlight), 0.25f));
if (options.m_drawBackgroundCallback)
{
options.m_drawBackgroundCallback();
}
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
painter.setPen(QPen(midDark));
QFont font;
font.setPixelSize(10);
painter.setFont(font);
char format[16] = "";
azsprintf(format, "%%.%df", rulerPrecision);
const int height = options.m_rect.height();
const int top = options.m_rect.top();
QString str;
for (const STick& tick : ticks)
{
const int x = tick.m_position + options.m_rect.left();
const float value = tick.m_value;
if (tick.m_bTenth)
{
painter.drawLine(QPoint(x, top + height - options.m_markHeight / 2), QPoint(x, top + height));
}
else
{
painter.drawLine(QPoint(x, top + height - options.m_markHeight), QPoint(x, top + height));
painter.setPen(palette.color(QPalette::Disabled, QPalette::Text));
str.asprintf(format, value);
painter.drawText(QPoint(x + 2, top + height - options.m_markHeight + 1), str);
painter.setPen(midDark);
}
}
painter.setPen(QPen(palette.color(QPalette::Dark)));
painter.drawLine(QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.start), 0), QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.start), options.m_rect.top() + height));
painter.drawLine(QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.end), 0), QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.end), options.m_rect.top() + height));
}
}