Merge branch 'development' into memory/benchmarks

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2021-12-08 10:45:48 -08:00
279 changed files with 7879 additions and 3700 deletions
+5 -8
View File
@@ -2810,14 +2810,11 @@ void CCryEditApp::OpenProjectManager(const AZStd::string& screen)
{
// provide the current project path for in case we want to update the project
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
const char* argumentQuoteString = R"(")";
#else
const char* argumentQuoteString = R"(\")";
#endif
const AZStd::string commandLineOptions = AZStd::string::format(R"( --screen %s --project-path %s%s%s)",
screen.c_str(),
argumentQuoteString, projectPath.c_str(), argumentQuoteString);
const AZStd::vector<AZStd::string> commandLineOptions {
"--screen", screen,
"--project-path", AZStd::string::format(R"("%s")", projectPath.c_str()) };
bool launchSuccess = AzFramework::ProjectManager::LaunchProjectManager(commandLineOptions);
if (!launchSuccess)
{
@@ -356,7 +356,8 @@ namespace SandboxEditor
AZ::TransformBus::EventResult(worldFromLocal, viewEntityId, &AZ::TransformBus::Events::GetWorldTM);
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::StartTrackingTransform, worldFromLocal);
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::StartTrackingTransform,
worldFromLocal);
}
else
{
@@ -367,8 +368,10 @@ namespace SandboxEditor
void EditorModularViewportCameraComposer::OnTick(const float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
const float delta = [duration = &ed_cameraDefaultOrbitFadeDuration, deltaTime] {
if (*duration == 0.0f) {
const float delta = [duration = &ed_cameraDefaultOrbitFadeDuration, deltaTime]
{
if (*duration == 0.0f)
{
return 1.0f;
}
return deltaTime / *duration;
+28 -14
View File
@@ -6,7 +6,6 @@
*
*/
#include "GotoPositionDlg.h"
#include "EditorDefs.h"
@@ -25,6 +24,17 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_GotoPositionDlg.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
void GotoPositionPitchConstraints::DeterminePitchRange(const AngleRangeConfigureFn& configurePitchRangeFn) const
{
const auto [pitchMinRadians, pitchMaxRadians] = AzFramework::CameraPitchMinMaxRadians();
configurePitchRangeFn(AZ::RadToDeg(pitchMinRadians), AZ::RadToDeg(pitchMaxRadians));
}
float GotoPositionPitchConstraints::PitchClampedRadians(float pitchDegrees) const
{
return AzFramework::ClampPitchRotation(AZ::DegToRad(pitchDegrees));
}
GotoPositionDialog::GotoPositionDialog(QWidget* parent)
: QDialog(parent)
, m_ui(new Ui::GotoPositionDialog)
@@ -55,20 +65,23 @@ void GotoPositionDialog::OnInitDialog()
const auto yawDegrees = AZ::RadToDeg(cameraRotation.GetZ());
// position
m_ui->m_dymX->setRange(-64000.0, 64000.0);
const double CameraPositionExtent = 64000.0;
m_ui->m_dymX->setRange(-CameraPositionExtent, CameraPositionExtent);
m_ui->m_dymX->setValue(cameraTranslation.GetX());
m_ui->m_dymY->setRange(-64000.0, 64000.0);
m_ui->m_dymY->setRange(-CameraPositionExtent, CameraPositionExtent);
m_ui->m_dymY->setValue(cameraTranslation.GetY());
m_ui->m_dymZ->setRange(-64000.0, 64000.0);
m_ui->m_dymZ->setRange(-CameraPositionExtent, CameraPositionExtent);
m_ui->m_dymZ->setValue(cameraTranslation.GetZ());
// rotation
m_ui->m_dymAnglePitch->setRange(-180.0, 180.0);
m_gotoPositionPitchConstraints.DeterminePitchRange(
[this](const float minPitchDegrees, const float maxPitchDegrees)
{
m_ui->m_dymAnglePitch->setRange(minPitchDegrees, maxPitchDegrees);
});
m_ui->m_dymAnglePitch->setValue(pitchDegrees);
m_ui->m_dymAngleYaw->setRange(-180.0, 180.0);
m_ui->m_dymAngleYaw->setRange(-360, 360);
m_ui->m_dymAngleYaw->setValue(yawDegrees);
// ensure the goto button is highlighted correctly.
@@ -108,12 +121,13 @@ void GotoPositionDialog::OnUpdateNumbers()
void GotoPositionDialog::accept()
{
SandboxEditor::InterpolateDefaultViewportCameraToTransform(
AZ::Vector3(
aznumeric_cast<float>(m_ui->m_dymX->value()), aznumeric_cast<float>(m_ui->m_dymY->value()),
aznumeric_cast<float>(m_ui->m_dymZ->value())),
AZ::DegToRad(aznumeric_cast<float>(m_ui->m_dymAnglePitch->value())),
AZ::DegToRad(aznumeric_cast<float>(m_ui->m_dymAngleYaw->value())));
const auto position = AZ::Vector3(
aznumeric_cast<float>(m_ui->m_dymX->value()), aznumeric_cast<float>(m_ui->m_dymY->value()),
aznumeric_cast<float>(m_ui->m_dymZ->value()));
const auto pitchRadians = m_gotoPositionPitchConstraints.PitchClampedRadians(aznumeric_cast<float>(m_ui->m_dymAnglePitch->value()));
const auto yawRadians = AZ::DegToRad(aznumeric_cast<float>(m_ui->m_dymAngleYaw->value()));
SandboxEditor::InterpolateDefaultViewportCameraToTransform(position, pitchRadians, yawRadians);
QDialog::accept();
}
+16 -3
View File
@@ -6,21 +6,33 @@
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QDialog>
#endif
#include <SandboxAPI.h>
#include <AzCore/std/functional.h>
namespace Ui
{
class GotoPositionDialog;
}
//! Utility to deal with ensuring camera pitch values are in the expected range.
struct GotoPositionPitchConstraints
{
using AngleRangeConfigureFn = AZStd::function<void(float, float)>;
//! Notify a callback with the min and max camera pitch constraints (no tolerance included).
SANDBOX_API void DeterminePitchRange(const AngleRangeConfigureFn& configurePitchRangeFn) const;
//! Returns the clamped pitch value (including tolerance with range extents).
SANDBOX_API float PitchClampedRadians(float pitchDegrees) const;
};
//! GotoPositionDialog for setting camera position and rotation.
class GotoPositionDialog
: public QDialog
class GotoPositionDialog : public QDialog
{
Q_OBJECT
@@ -39,5 +51,6 @@ public:
QString m_transform;
private:
GotoPositionPitchConstraints m_gotoPositionPitchConstraints;
QScopedPointer<Ui::GotoPositionDialog> m_ui;
};
@@ -15,6 +15,8 @@
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <EditorModularViewportCameraComposer.h>
#include <GotoPositionDlg.h>
namespace UnitTest
{
class EditorCameraFixture : public ::testing::Test
@@ -257,4 +259,35 @@ namespace UnitTest
EXPECT_THAT(interpolating, ::testing::IsFalse());
EXPECT_THAT(nextInterpolationBegan, ::testing::IsTrue());
}
TEST(GotoPositionPitchConstraints, GoToPositionPitchIsSetToPlusOrMinusNinetyDegrees)
{
float minPitch = 0.0f;
float maxPitch = 0.0f;
GotoPositionPitchConstraints m_gotoPositionContraints;
m_gotoPositionContraints.DeterminePitchRange(
[&minPitch, &maxPitch](const float minPitchDegrees, const float maxPitchDegrees)
{
minPitch = minPitchDegrees;
maxPitch = maxPitchDegrees;
});
using ::testing::FloatNear;
EXPECT_THAT(minPitch, FloatNear(-90.0f, AZ::Constants::FloatEpsilon));
EXPECT_THAT(maxPitch, FloatNear(90.0f, AZ::Constants::FloatEpsilon));
}
TEST(GotoPositionPitchConstraints, GoToPositionPitchClampsFinalPitchValueWithTolerance)
{
const auto [expectedMinPitchRadians, expectedMaxPitchRadians] = AzFramework::CameraPitchMinMaxRadiansWithTolerance();
GotoPositionPitchConstraints m_gotoPositionContraints;
const float minClampedPitchRadians = m_gotoPositionContraints.PitchClampedRadians(-90.0f);
const float maxClampedPitchRadians = m_gotoPositionContraints.PitchClampedRadians(90.0f);
using ::testing::FloatNear;
EXPECT_THAT(minClampedPitchRadians, FloatNear(expectedMinPitchRadians, AZ::Constants::FloatEpsilon));
EXPECT_THAT(maxClampedPitchRadians, FloatNear(expectedMaxPitchRadians, AZ::Constants::FloatEpsilon));
}
} // namespace UnitTest
@@ -9,7 +9,6 @@
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/smart_ptr/scoped_ptr.h>
#include <AzCore/std/parallel/thread.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
@@ -22,7 +21,7 @@ namespace AzFramework
AZStd::scoped_ptr<ProcessWatcher> pWatcher(LaunchProcess(processLaunchInfo, communicationType));
if (!pWatcher)
{
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to launch process '%s %s'\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to launch process '%s %s'\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.GetCommandLineParametersAsString().c_str());
return false;
}
else
@@ -31,7 +30,7 @@ namespace AzFramework
ProcessCommunicator* pCommunicator = pWatcher->GetCommunicator();
if (!pCommunicator || !pCommunicator->IsValid())
{
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: No communicator for watcher's process (%s %s)!\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: No communicator for watcher's process (%s %s)!\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.GetCommandLineParametersAsString().c_str());
return false;
}
else
@@ -13,6 +13,7 @@
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <AzFramework/Process/ProcessCommon_fwd.h>
#include <AzCore/std/containers/variant.h>
namespace AzFramework
{
@@ -37,7 +38,7 @@ namespace AzFramework
* On windows, the command line will be passed as-is to the shell (with quotes)
* on UNIX/OSX, the command line will be converted as appropriate (quotes removed, but used to chop up parameters)
*/
AZStd::string m_commandlineParameters;
AZStd::variant<AZStd::string, AZStd::vector<AZStd::string>> m_commandlineParameters;
/**
* (optional) If you specify a working directory, the command will be executed with that directory as the current directory.
@@ -50,6 +51,8 @@ namespace AzFramework
//Not Supported On Mac
bool m_showWindow = true;
AZStd::string GetCommandLineParametersAsString() const;
};
static const AZ::u32 INFINITE_TIMEOUT = (AZ::u32) -1;
@@ -83,7 +83,7 @@ namespace AzFramework::ProjectManager
return ProjectPathCheckResult::ProjectManagerLaunchFailed;
}
bool LaunchProjectManager([[maybe_unused]]const AZStd::string& commandLineArgs)
bool LaunchProjectManager([[maybe_unused]] const AZStd::vector<AZStd::string>& commandLineArgs)
{
bool launchSuccess = false;
#if (AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER)
@@ -105,7 +105,12 @@ namespace AzFramework::ProjectManager
}
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = executablePath.String() + commandLineArgs;
AZStd::vector<AZStd::string> launchCmd = { executablePath.String() };
launchCmd.insert(launchCmd.end(), commandLineArgs.begin(), commandLineArgs.end());
processLaunchInfo.m_commandlineParameters = AZStd::move(launchCmd);
launchSuccess = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
}
if (ownsSystemAllocator)
@@ -8,6 +8,7 @@
#pragma once
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
namespace AzFramework::ProjectManager
@@ -29,5 +30,5 @@ namespace AzFramework::ProjectManager
//! current executable. Requires the o3de cli and python.
//! @param commandLineArgs additional command line arguments to provide to the project manager
//! @return true on success, false if failed to find or launch the executable
bool LaunchProjectManager(const AZStd::string& commandLineArgs = "");
bool LaunchProjectManager(const AZStd::vector<AZStd::string>& commandLineArgs = {});
} // AzFramework::ProjectManager
@@ -63,25 +63,30 @@ namespace AzFramework::Terrain
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Terrain")
->Attribute(AZ::Script::Attributes::Module, "terrain")
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
->Event("GetMaxSurfaceWeightFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromVector2)
->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeights)
->Event("GetSurfaceWeightsFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeightsFromVector2)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetHeight)
->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetHeightFromFloats)
->Event("GetHeightFromVector2", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetHeightFromVector2)
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetNormal)
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetMaxSurfaceWeight)
->Event(
"GetMaxSurfaceWeightFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetMaxSurfaceWeightFromVector2)
->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetSurfaceWeights)
->Event(
"GetSurfaceWeightsFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetSurfaceWeightsFromVector2)
->Event("GetIsHole", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHole)
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
->Event("GetSurfacePoint", &AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetSurfacePoint)
->Event("GetSurfacePointFromVector2",
->Event(
"GetSurfacePointFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::BehaviorContextGetSurfacePointFromVector2)
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
->Event("GetTerrainHeightQueryResolution",
->Event(
"GetTerrainHeightQueryResolution",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightVal)
->Event("GetHeightFromVector2", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightValFromVector2)
->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightValFromFloats)
;
;
behaviorContext->EBus<AzFramework::Terrain::TerrainDataNotificationBus>("TerrainDataNotificationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
@@ -150,24 +150,49 @@ namespace AzFramework
GetSurfacePointFromVector2(inPosition, result, sampleFilter);
return result;
}
// Functions without the optional bool* parameter that can be used from Python tests.
float GetHeightVal(AZ::Vector3 position, Sampler sampler = Sampler::BILINEAR) const
// Private variations of the GetHeight.., GetNormal..., GetMaxSurfaceWeight..., GetSurfaceWeights... APIs
// exposed to BehaviorContext that does not use the terrainExists "out" parameter.
float BehaviorContextGetHeight(const AZ::Vector3& position, Sampler sampler = Sampler::BILINEAR)
{
bool terrainExists;
return GetHeight(position, sampler, &terrainExists);
return GetHeight(position, sampler, nullptr);
}
float GetHeightValFromVector2(AZ::Vector2 position, Sampler sampler = Sampler::BILINEAR) const
float BehaviorContextGetHeightFromVector2(const AZ::Vector2& position, Sampler sampler = Sampler::BILINEAR)
{
bool terrainExists;
return GetHeightFromVector2(position, sampler, &terrainExists);
return GetHeightFromVector2(position, sampler, nullptr);
}
float GetHeightValFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR) const
float BehaviorContextGetHeightFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR)
{
bool terrainExists;
return GetHeightFromFloats(x, y, sampler, &terrainExists);
return GetHeightFromFloats(x, y, sampler, nullptr);
}
AZ::Vector3 BehaviorContextGetNormal(const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR)
{
return GetNormal(position, sampleFilter, nullptr);
}
SurfaceData::SurfaceTagWeight BehaviorContextGetMaxSurfaceWeight(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR)
{
return GetMaxSurfaceWeight(position, sampleFilter, nullptr);
}
SurfaceData::SurfaceTagWeight BehaviorContextGetMaxSurfaceWeightFromVector2(
const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT)
{
return GetMaxSurfaceWeightFromVector2(inPosition, sampleFilter, nullptr);
}
SurfaceData::SurfaceTagWeightList BehaviorContextGetSurfaceWeights(
const AZ::Vector3& inPosition,
Sampler sampleFilter = Sampler::DEFAULT)
{
SurfaceData::SurfaceTagWeightList list;
GetSurfaceWeights(inPosition, list, sampleFilter, nullptr);
return list;
}
SurfaceData::SurfaceTagWeightList BehaviorContextGetSurfaceWeightsFromVector2(
const AZ::Vector2& inPosition,
Sampler sampleFilter = Sampler::DEFAULT)
{
SurfaceData::SurfaceTagWeightList list;
GetSurfaceWeightsFromVector2(inPosition, list, sampleFilter, nullptr);
return list;
}
};
using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>;
@@ -335,10 +335,13 @@ namespace AzFramework
Camera nextCamera = targetCamera;
const float rotateSpeed = m_rotateSpeedFn();
nextCamera.m_pitch -= float(cursorDelta.m_y) * rotateSpeed * Invert(m_invertPitchFn());
nextCamera.m_yaw -= float(cursorDelta.m_x) * rotateSpeed * Invert(m_invertYawFn());
const float deltaPitch = aznumeric_cast<float>(cursorDelta.m_y) * rotateSpeed * Invert(m_invertPitchFn());
const float deltaYaw = aznumeric_cast<float>(cursorDelta.m_x) * rotateSpeed * Invert(m_invertYawFn());
nextCamera.m_pitch -= deltaPitch;
nextCamera.m_yaw -= deltaYaw;
nextCamera.m_yaw = WrapYawRotation(nextCamera.m_yaw);
if (m_constrainPitch())
{
nextCamera.m_pitch = ClampPitchRotation(nextCamera.m_pitch);
@@ -25,6 +25,9 @@ namespace AzFramework
struct WindowSize;
//! Tolerance to use when limiting pitch to avoid reaching +/-Pi/2 exactly.
constexpr float CameraPitchTolerance = 1.0e-4f;
//! Returns Euler angles (pitch, roll, yaw) for the incoming orientation.
//! @note Order of rotation is Z, Y, X.
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation);
@@ -318,11 +321,26 @@ namespace AzFramework
return m_handlingEvents;
}
//! Clamps pitch to be +/-90 degrees (-Pi/2, Pi/2).
//! Returns min/max values for camera pitch (in radians).
inline AZStd::tuple<float, float> CameraPitchMinMaxRadians()
{
return { -AZ::Constants::HalfPi, AZ::Constants::HalfPi };
}
//! Returns min/max values for camera pitch (in radians) including a small tolerance at each
//! extreme (looking directly up or down) to avoid floating point accuracy issues.
inline AZStd::tuple<float, float> CameraPitchMinMaxRadiansWithTolerance()
{
const auto [pitchMinRadians, pitchMaxRadians] = CameraPitchMinMaxRadians();
return { pitchMinRadians + CameraPitchTolerance, pitchMaxRadians - CameraPitchTolerance };
}
//! Clamps pitch to be +/-90 degrees (-Pi/2, Pi/2) with a minor tolerance at each extreme.
//! @param pitch Pitch angle in radians.
inline float ClampPitchRotation(const float pitch)
{
return AZ::GetClamp(pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi);
const auto [pitchMin, pitchMax] = CameraPitchMinMaxRadiansWithTolerance();
return AZ::GetClamp(pitch, pitchMin, pitchMax);
}
//! Ensures yaw wraps between 0 and 360 degrees (0, 2Pi).
@@ -6,10 +6,10 @@
*
*/
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
namespace AzFramework
{
@@ -83,4 +83,23 @@ namespace AzFramework
{
}
AZStd::string ProcessLauncher::ProcessLaunchInfo::GetCommandLineParametersAsString() const
{
struct CommandLineParametersVisitor
{
AZStd::string operator()(const AZStd::string& commandLine) const
{
return commandLine;
}
AZStd::string operator()(const AZStd::vector<AZStd::string>& commandLineArray) const
{
AZStd::string commandLineResult;
AZ::StringFunc::Join(commandLineResult, commandLineArray.begin(), commandLineArray.end(), " ");
return commandLineResult;
}
};
return AZStd::visit(CommandLineParametersVisitor{}, m_commandlineParameters);
}
} //namespace AzFramework
@@ -10,12 +10,11 @@
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <iostream>
#include <errno.h>
@@ -220,36 +219,52 @@ namespace AzFramework
// this is so that the callers (which could be numerous) do not have to worry about this and sprinkle ifdefs
// all over their code.
// We'll convert this to UNIX style command line parameters by counting and eliminating quotes:
AZStd::vector<AZStd::string> commandTokens;
AZStd::string outputString;
bool inQuotes = false;
for (const char currentChar : processLaunchInfo.m_commandlineParameters)
{
if (currentChar == '"')
{
inQuotes = !inQuotes;
}
else if ((currentChar == ' ') && (!inQuotes))
{
// its a space outside of quotes, so it ends the current parameter
commandTokens.push_back(outputString);
outputString.clear();
}
else
{
// Its a normal character, or its a space inside quotes
outputString.push_back(currentChar);
}
}
if (!outputString.empty())
// Struct uses overloaded operator() to quote command line arguments based
// on whether a string or a vector<string> was supplied
struct EscapeCommandArguments
{
commandTokens.push_back(outputString);
outputString.clear();
}
void operator()(const AZStd::string& commandParameterString)
{
AZStd::string outputString;
bool inQuotes = false;
for (size_t pos = 0; pos < commandParameterString.size(); ++pos)
{
char currentChar = commandParameterString[pos];
if (currentChar == '"')
{
inQuotes = !inQuotes;
}
else if ((currentChar == ' ') && (!inQuotes))
{
// its a space outside of quotes, so it ends the current parameter
commandArray.push_back(outputString);
outputString.clear();
}
else
{
// Its a normal character, or its a space inside quotes
outputString.push_back(currentChar);
}
}
if (!outputString.empty())
{
commandArray.push_back(outputString);
outputString.clear();
}
}
void operator()(const AZStd::vector<AZStd::string>& commandParameterArray)
{
commandArray = commandParameterArray;
}
AZStd::vector<AZStd::string>& commandArray;
};
AZStd::vector<AZStd::string> commandTokens;
AZStd::visit(EscapeCommandArguments{ commandTokens }, processLaunchInfo.m_commandlineParameters);
if (!processLaunchInfo.m_processExecutableString.empty())
{
commandTokens.insert(commandTokens.begin(), processLaunchInfo.m_processExecutableString);
@@ -452,4 +467,23 @@ namespace AzFramework
kill(m_pWatcherData->m_childProcessId, SIGKILL);
}
AZStd::string ProcessLauncher::ProcessLaunchInfo::GetCommandLineParametersAsString() const
{
struct CommandLineParametersVisitor
{
AZStd::string operator()(const AZStd::string& commandLine) const
{
return commandLine;
}
AZStd::string operator()(const AZStd::vector<AZStd::string>& commandLineArray) const
{
AZStd::string commandLineResult;
AZ::StringFunc::Join(commandLineResult, commandLineArray.begin(), commandLineArray.end(), " ");
return commandLineResult;
}
};
return AZStd::visit(CommandLineParametersVisitor{}, m_commandlineParameters);
}
} //namespace AzFramework
@@ -11,13 +11,12 @@
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <iostream>
#include <errno.h>
@@ -210,46 +209,51 @@ namespace AzFramework
// this is so that the callers (which could be numerous) do not have to worry about this and sprinkle ifdefs
// all over their code.
// We'll convert this to UNIX style command line parameters by counting and eliminating quotes:
// Struct uses overloaded operator() to quote command line arguments based
// on whether a string or a vector<string> was supplied
struct EscapeCommandArguments
{
void operator()(const AZStd::string& commandParameterString)
{
AZStd::string outputString;
bool inQuotes = false;
for (size_t pos = 0; pos < commandParameterString.size(); ++pos)
{
char currentChar = commandParameterString[pos];
if (currentChar == '"')
{
inQuotes = !inQuotes;
}
else if ((currentChar == ' ') && (!inQuotes))
{
// its a space outside of quotes, so it ends the current parameter
commandArray.push_back(outputString);
outputString.clear();
}
else
{
// Its a normal character, or its a space inside quotes
outputString.push_back(currentChar);
}
}
if (!outputString.empty())
{
commandArray.push_back(outputString);
outputString.clear();
}
}
void operator()(const AZStd::vector<AZStd::string>& commandParameterArray)
{
commandArray = commandParameterArray;
}
AZStd::vector<AZStd::string>& commandArray;
};
AZStd::vector<AZStd::string> commandTokens;
AZStd::string outputString;
bool inQuotes = false;
for (size_t pos = 0; pos < processLaunchInfo.m_commandlineParameters.size(); ++pos)
{
char currentChar = processLaunchInfo.m_commandlineParameters[pos];
if (currentChar == '"')
{
// Allow quote literals to go through as quotes which do NOT alter our "in quotes" bool below
// This is to conform with our PC parameter strings which will sometimes include path parameters which
// Can have spaces and commas and need to be output as paramname="\"Some pa,ram\"" in order to capture both correctly
if (outputString.length() && outputString.back() == '\\')
{
outputString.back() = currentChar;
}
else
{
inQuotes = !inQuotes;
}
}
else if ((currentChar == ' ') && (!inQuotes))
{
// its a space outside of quotes, so it ends the current parameter
commandTokens.push_back(outputString);
outputString.clear();
}
else
{
// Its a normal character, or its a space inside quotes
outputString.push_back(currentChar);
}
}
if (!outputString.empty())
{
commandTokens.push_back(outputString);
outputString.clear();
}
AZStd::visit(EscapeCommandArguments{ commandTokens }, processLaunchInfo.m_commandlineParameters);
if (!processLaunchInfo.m_processExecutableString.empty())
{
@@ -417,5 +421,24 @@ namespace AzFramework
kill(m_pWatcherData->m_childProcessId, SIGKILL);
waitpid(m_pWatcherData->m_childProcessId, NULL, 0);
}
AZStd::string ProcessLauncher::ProcessLaunchInfo::GetCommandLineParametersAsString() const
{
struct CommandLineParametersVisitor
{
AZStd::string operator()(const AZStd::string& commandLine) const
{
return commandLine;
}
AZStd::string operator()(const AZStd::vector<AZStd::string>& commandLineArray) const
{
AZStd::string commandLineResult;
AZ::StringFunc::Join(commandLineResult, commandLineArray.begin(), commandLineArray.end(), " ");
return commandLineResult;
}
};
return AZStd::visit(CommandLineParametersVisitor{}, m_commandlineParameters);
}
} //namespace AzFramework
@@ -10,6 +10,7 @@
#include <AzCore/std/string/conversions.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
@@ -99,7 +100,7 @@ namespace AzFramework
AZStd::wstring editableCommandLine;
AZStd::wstring processExecutableString;
AZStd::wstring workingDirectory;
AZStd::to_wstring(editableCommandLine, processLaunchInfo.m_commandlineParameters);
AZStd::to_wstring(editableCommandLine, processLaunchInfo.GetCommandLineParametersAsString());
AZStd::to_wstring(processExecutableString, processLaunchInfo.m_processExecutableString);
AZStd::to_wstring(workingDirectory, processLaunchInfo.m_workingDirectory);
@@ -355,4 +356,41 @@ namespace AzFramework
::TerminateProcess(m_pWatcherData->processInformation.hProcess, exitCode);
}
}
AZStd::string ProcessLauncher::ProcessLaunchInfo::GetCommandLineParametersAsString() const
{
struct CommandLineParametersVisitor
{
AZStd::string operator()(const AZStd::string& commandLine) const
{
return commandLine;
}
AZStd::string operator()(const AZStd::vector<AZStd::string>& commandLineArray) const
{
AZStd::string commandLineResult;
// When re-constructing a command line from an argument list (on windows), if an argument
// is double-quoted, then the double-quotes must be escaped properly otherwise
// it will be absorbed by the native argument parser and possibly evaluated as
// multiple values for arguments
AZStd::string_view escapedDoubleQuote = R"("\")";
AZStd::vector<AZStd::string> preprocessedCommandArray;
for (const auto& commandArg : commandLineArray)
{
AZStd::string replacedArg = commandArg;
AZ::StringFunc::Replace(replacedArg, R"(")", R"("\")", false, true, true);
preprocessedCommandArray.emplace_back(replacedArg);
}
AZ::StringFunc::Join(commandLineResult, preprocessedCommandArray.begin(), preprocessedCommandArray.end(), " ");
return commandLineResult;
}
};
return AZStd::visit(CommandLineParametersVisitor{}, m_commandlineParameters);
}
} // namespace AzFramework
@@ -6,10 +6,10 @@
*
*/
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
namespace AzFramework
{
@@ -83,4 +83,23 @@ namespace AzFramework
{
}
AZStd::string ProcessLauncher::ProcessLaunchInfo::GetCommandLineParametersAsString() const
{
struct CommandLineParametersVisitor
{
AZStd::string operator()(const AZStd::string& commandLine) const
{
return commandLine;
}
AZStd::string operator()(const AZStd::vector<AZStd::string>& commandLineArray) const
{
AZStd::string commandLineResult;
Az::StringFunc::Join(commandLineResult, commandLineArray.begin(), commandLineArray.end(), " ");
return commandLineResult;
}
};
return AZStd::visit(CommandLineParametersVisitor{}, m_commandlineParameters);
}
} //namespace AzFramework
@@ -322,6 +322,17 @@ namespace UnitTest
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateZero()));
}
TEST(CameraInput, CameraPitchIsClampedWithExpectedTolerance)
{
const auto [expectedMinPitch, expectedMaxPitch] = AzFramework::CameraPitchMinMaxRadiansWithTolerance();
const float minPitch = AzFramework::ClampPitchRotation(-AZ::Constants::HalfPi);
const float maxPitch = AzFramework::ClampPitchRotation(AZ::Constants::HalfPi);
using ::testing::FloatNear;
EXPECT_THAT(minPitch, FloatNear(expectedMinPitch, AzFramework::CameraPitchTolerance));
EXPECT_THAT(maxPitch, FloatNear(expectedMaxPitch, AzFramework::CameraPitchTolerance));
}
TEST_F(CameraInputFixture, OrbitRotateCameraInputRotatesPitchOffsetByNinetyDegreesWithRequiredPixelDelta)
{
const auto cameraStartingPosition = AZ::Vector3::CreateAxisY(-20.0f);
@@ -75,7 +75,8 @@ namespace UnitTest
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest";
processLaunchInfo.m_commandlineParameters.emplace<AZStd::string>(AZStd::string(AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest"));
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
@@ -90,7 +91,9 @@ namespace UnitTest
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest -param1 param1val -param2=param2val";
processLaunchInfo.m_commandlineParameters.emplace<AZStd::vector<AZStd::string>>(
AZStd::vector<AZStd::string>{AZStd::string(AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest"), "-param1", "param1val","-param2", "param2val"});
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
@@ -117,14 +120,16 @@ namespace UnitTest
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithCommas_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_StringsWithCommas_Success)
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithCommas_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER R"(ProcessLaunchTest -param1 "\"param,1val\"" -param2="\"param2v,al\"")";
processLaunchInfo.m_commandlineParameters.emplace<AZStd::vector<AZStd::string>>(
AZStd::vector<AZStd::string>{AZStd::string(AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest"), "-param1", "param,1val","-param2", "param2v,al"});
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
@@ -137,28 +142,32 @@ namespace UnitTest
EXPECT_NE(param1itr, argMap.end());
AZStd::vector<AZStd::string> param1{ param1itr->second };
EXPECT_EQ(param1.size(), 1);
EXPECT_EQ(param1[0], "param,1val");
EXPECT_EQ(param1.size(), 2);
EXPECT_EQ(param1[0], "param");
EXPECT_EQ(param1[1], "1val");
auto param2itr = argMap.find("param2");
EXPECT_NE(param2itr, argMap.end());
AZStd::vector<AZStd::string> param2{ param2itr->second };
EXPECT_EQ(param2.size(), 1);
EXPECT_EQ(param2[0], "param2v,al");
EXPECT_EQ(param2.size(), 2);
EXPECT_EQ(param2[0], "param2v");
EXPECT_EQ(param2[1], "al");
}
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithSpaces_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_StringsWithSpaces_Success)
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithSpaces_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER R"(ProcessLaunchTest -param1 "\"param 1val\"" -param2="\"param2v al\"")";
processLaunchInfo.m_commandlineParameters.emplace<AZStd::vector<AZStd::string>>(AZStd::vector<AZStd::string>{
AZStd::string(AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest"), "-param1", R"("param 1val")", R"(-param2="param2v al")" });
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
@@ -185,14 +194,16 @@ namespace UnitTest
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithSpacesAndComma_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_StringsWithSpacesAndComma_Success)
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithSpacesAndComma_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER R"(ProcessLaunchTest -param1 "\"par,am 1val\"" -param2="\"param,2v al\"")";
processLaunchInfo.m_commandlineParameters.emplace<AZStd::vector<AZStd::string>>(AZStd::vector<AZStd::string>{
AZStd::string(AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest"), "-param1", R"("param, 1val")", R"(-param2="param,2v al")" });
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
@@ -206,7 +217,7 @@ namespace UnitTest
AZStd::vector<AZStd::string> param1{ param1itr->second };
EXPECT_EQ(param1.size(), 1);
EXPECT_EQ(param1[0], "par,am 1val");
EXPECT_EQ(param1[0], "param, 1val");
auto param2itr = argMap.find("param2");
EXPECT_NE(param2itr, argMap.end());
@@ -216,35 +227,4 @@ namespace UnitTest
EXPECT_EQ(param2[0], "param,2v al");
}
TEST_F(ProcessLaunchParseTests, ProcessLauncher_CommaStringNoQuotes_Success)
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZ_TRAIT_TEST_ROOT_FOLDER "ProcessLaunchTest -param1 param,1val -param2=param2v,al";
processLaunchInfo.m_workingDirectory = AZ::Test::GetCurrentExecutablePath();
processLaunchInfo.m_showWindow = false;
bool launchReturn = AzFramework::ProcessWatcher::LaunchProcessAndRetrieveOutput(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT, processOutput);
EXPECT_EQ(launchReturn, true);
argMap = ProcessLaunchParseTests::ParseParameters(processOutput.outputResult);
auto param1itr = argMap.find("param1");
EXPECT_NE(param1itr, argMap.end());
AZStd::vector<AZStd::string> param1{ param1itr->second };
EXPECT_EQ(param1.size(), 2);
EXPECT_EQ(param1[0], "param");
EXPECT_EQ(param1[1], "1val");
auto param2itr = argMap.find("param2");
EXPECT_NE(param2itr, argMap.end());
AZStd::vector<AZStd::string> param2{ param2itr->second };
EXPECT_EQ(param2.size(), 2);
EXPECT_EQ(param2[0], "param2v");
EXPECT_EQ(param2[1], "al");
}
} // namespace UnitTest
@@ -13,8 +13,6 @@
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_DISABLE_FAILED_AP_CONNECTION_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ATOM_RPI_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS true
@@ -23,7 +21,6 @@
#define AZ_TRAIT_DISABLE_FAILED_GRADIENT_SIGNAL_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MULTIPLAYER_GRIDMATE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_NATIVE_WINDOWS_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_DLL_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MODULE_TESTS true
@@ -64,7 +64,8 @@ namespace AzToolsFramework
}
}
if (clickOutcome == AzFramework::ClickDetector::ClickOutcome::Release)
if (clickOutcome == AzFramework::ClickDetector::ClickOutcome::Release ||
clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click)
{
if (m_leftMouseUp)
{
@@ -155,7 +155,7 @@ namespace AssetProcessor
return false;
}
const AZStd::string params = BuildParams("resident", buildersFolder.c_str(), UuidString(), "", "");
const AZStd::vector<AZStd::string> params = BuildParams("resident", buildersFolder.c_str(), UuidString(), "", "");
m_processWatcher = LaunchProcess(fullExePathString.c_str(), params);
@@ -179,7 +179,7 @@ namespace AssetProcessor
return !m_processWatcher || (m_processWatcher && m_processWatcher->IsProcessRunning(exitCode));
}
AZStd::string Builder::BuildParams(const char* task, const char* moduleFilePath, const AZStd::string& builderGuid, const AZStd::string& jobDescriptionFile, const AZStd::string& jobResponseFile) const
AZStd::vector<AZStd::string> Builder::BuildParams(const char* task, const char* moduleFilePath, const AZStd::string& builderGuid, const AZStd::string& jobDescriptionFile, const AZStd::string& jobResponseFile) const
{
QDir projectCacheRoot;
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
@@ -191,35 +191,24 @@ namespace AssetProcessor
int portNumber = 0;
ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort);
AZStd::string params;
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params = AZStd::string::format(
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)",
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.c_str(), enginePath.c_str(), portNumber);
#else
params = AZStd::string::format(
R"(-task=%s -id="%s" -project-name="\"%s\"" -project-cache-path="\"%s\"" -project-path="\"%s\"" -engine-path="\"%s\"" -port %d)",
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.c_str(), enginePath.c_str(), portNumber);
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
AZStd::vector<AZStd::string> params;
params.emplace_back(AZStd::string::format(R"(-task="%s")", task));
params.emplace_back(AZStd::string::format(R"(-id="%s")", builderGuid.c_str()));
params.emplace_back(AZStd::string::format(R"(-project-name="%s")", projectName.c_str()));
params.emplace_back(AZStd::string::format(R"(-project-cache-path="%s")", projectCacheRoot.absolutePath().toUtf8().constData()));
params.emplace_back(AZStd::string::format(R"(-project-path="%s")", projectPath.c_str()));
params.emplace_back(AZStd::string::format(R"(-engine-path="%s")", enginePath.c_str()));
params.emplace_back(AZStd::string::format("-port=%d", portNumber));
if (moduleFilePath && moduleFilePath[0])
{
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params.append(AZStd::string::format(R"( -module="%s")", moduleFilePath).c_str());
#else
params.append(AZStd::string::format(R"( -module="\"%s\"")", moduleFilePath).c_str());
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params.emplace_back(AZStd::string::format(R"(-module="%s")", moduleFilePath));
}
if (!jobDescriptionFile.empty() && !jobResponseFile.empty())
{
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params = AZStd::string::format(R"(%s -input="%s" -output="%s")", params.c_str(), jobDescriptionFile.c_str(), jobResponseFile.c_str());
#else
params = AZStd::string::format(R"(%s -input="\"%s\"" -output="\"%s\"")", params.c_str(), jobDescriptionFile.c_str(), jobResponseFile.c_str());
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params.emplace_back(AZStd::string::format(R"(-input="%s")", jobDescriptionFile.c_str()));
params.emplace_back(AZStd::string::format(R"(-output="%s")", jobResponseFile.c_str()));
}
auto settingsRegistry = AZ::SettingsRegistry::Get();
@@ -232,28 +221,25 @@ namespace AssetProcessor
for (size_t optionIndex = 0; optionIndex < commandOptionCount; ++optionIndex)
{
const AZStd::string& optionValue = commandLine.GetSwitchValue(optionKey, optionIndex);
params.append(AZStd::string::format(
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
R"( --%s="%s")",
#else
R"( --%s="\"%s\"")",
#endif
optionKey, optionValue.c_str()));
params.emplace_back(AZStd::string::format(R"(--%s="%s")", optionKey, optionValue.c_str()));
}
}
return params;
}
AZStd::unique_ptr<AzFramework::ProcessWatcher> Builder::LaunchProcess(const char* fullExePath, const AZStd::string& params) const
AZStd::unique_ptr<AzFramework::ProcessWatcher> Builder::LaunchProcess(const char* fullExePath, const AZStd::vector<AZStd::string>& params) const
{
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_processExecutableString = fullExePath;
processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" %s", fullExePath, params.c_str());
AZStd::vector<AZStd::string> commandLineArray{ fullExePath };
commandLineArray.insert(commandLineArray.end(), params.begin(), params.end());
processLaunchInfo.m_commandlineParameters = AZStd::move(commandLineArray);
processLaunchInfo.m_showWindow = false;
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_IDLE;
AZ_TracePrintf(AssetProcessor::DebugChannel, "Executing AssetBuilder with parameters: %s\n", processLaunchInfo.m_commandlineParameters.c_str());
AZ_TracePrintf(AssetProcessor::DebugChannel, "Executing AssetBuilder with parameters: %s\n", processLaunchInfo.GetCommandLineParametersAsString().c_str());
auto processWatcher = AZStd::unique_ptr<AzFramework::ProcessWatcher>(AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT));
@@ -103,8 +103,8 @@ namespace AssetProcessor
//! Sets the connection id and signals that the builder has connected
void SetConnection(AZ::u32 connId);
AZStd::string BuildParams(const char* task, const char* moduleFilePath, const AZStd::string& builderGuid, const AZStd::string& jobDescriptionFile, const AZStd::string& jobResponseFile) const;
AZStd::unique_ptr<AzFramework::ProcessWatcher> LaunchProcess(const char* fullExePath, const AZStd::string& params) const;
AZStd::vector<AZStd::string> BuildParams(const char* task, const char* moduleFilePath, const AZStd::string& builderGuid, const AZStd::string& jobDescriptionFile, const AZStd::string& jobResponseFile) const;
AZStd::unique_ptr<AzFramework::ProcessWatcher> LaunchProcess(const char* fullExePath, const AZStd::vector<AZStd::string>& params) const;
//! Waits for the builder exe to send the job response and pumps stdout/err
BuilderRunJobOutcome WaitForBuilderResponse(AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds, AZStd::binary_semaphore* waitEvent) const;
@@ -7,6 +7,8 @@
*/
#pragma once
#include <AzCore/StringFunc/StringFunc.h>
namespace AssetProcessor
{
//! Sends the job over to the builder and blocks until the response is received or the builder crashes/times out
@@ -82,10 +84,12 @@ namespace AssetProcessor
}
auto params = BuildParams(task.c_str(), modulePath.c_str(), "", jobRequestFile, jobResponseFile);
AZStd::string paramString;
AZ::StringFunc::Join(paramString, params.begin(), params.end(), " ");
AZ_TracePrintf(AssetProcessor::DebugChannel, "Job request written to %s\n", jobRequestFile.c_str());
AZ_TracePrintf(AssetProcessor::DebugChannel, "To re-run this request manually, run AssetBuilder with the following parameters:\n");
AZ_TracePrintf(AssetProcessor::DebugChannel, "%s\n", params.c_str());
AZ_TracePrintf(AssetProcessor::DebugChannel, "%s\n", paramString.c_str());
return true;
}
@@ -424,12 +424,12 @@ namespace O3DE::ProjectManager
return;
}
auto cmdPath = AZ::IO::FixedMaxPathString::format(
"%s --regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(),
fixedProjectPath.c_str());
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = cmdPath;
processLaunchInfo.m_commandlineParameters = AZStd::vector<AZStd::string>{
editorExecutablePath.String(),
AZStd::string::format(R"(--regset="/Amazon/AzCore/Bootstrap/project_path=%s")", fixedProjectPath.c_str())
};
;
bool launchSucceeded = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
if (!launchSucceeded)
{