Merge branch 'development' of https://github.com/o3de/o3de into daimini/settings-registry-origin-tracking

# Conflicts:
#	Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp
This commit is contained in:
Danilo Aimini
2021-08-13 15:04:47 -07:00
234 changed files with 2293 additions and 4711 deletions
+8 -11
View File
@@ -891,8 +891,7 @@ CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(const char
/////////////////////////////////////////////////////////////////////////////
namespace
{
CryMutex g_splashScreenStateLock;
CryConditionVariable g_splashScreenStateChange;
AZStd::mutex g_splashScreenStateLock;
enum ESplashScreenState
{
eSplashScreenState_Init, eSplashScreenState_Started, eSplashScreenState_Destroy
@@ -923,7 +922,7 @@ QString FormatRichTextCopyrightNotice()
/////////////////////////////////////////////////////////////////////////////
void CCryEditApp::ShowSplashScreen(CCryEditApp* app)
{
g_splashScreenStateLock.Lock();
g_splashScreenStateLock.lock();
CStartupLogoDialog* splashScreen = new CStartupLogoDialog(FormatVersion(app->m_pEditor->GetFileVersion()), FormatRichTextCopyrightNotice());
@@ -931,8 +930,7 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app)
g_splashScreen = splashScreen;
g_splashScreenState = eSplashScreenState_Started;
g_splashScreenStateLock.Unlock();
g_splashScreenStateChange.Notify();
g_splashScreenStateLock.unlock();
splashScreen->show();
// Make sure the initial paint of the splash screen occurs so we dont get stuck with a blank window
@@ -940,10 +938,9 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app)
QObject::connect(splashScreen, &QObject::destroyed, splashScreen, [=]
{
g_splashScreenStateLock.Lock();
AZStd::scoped_lock lock(g_splashScreenStateLock);
g_pInitializeUIInfo = nullptr;
g_splashScreen = nullptr;
g_splashScreenStateLock.Unlock();
});
}
@@ -973,9 +970,9 @@ void CCryEditApp::CloseSplashScreen()
if (CStartupLogoDialog::instance())
{
delete CStartupLogoDialog::instance();
g_splashScreenStateLock.Lock();
g_splashScreenStateLock.lock();
g_splashScreenState = eSplashScreenState_Destroy;
g_splashScreenStateLock.Unlock();
g_splashScreenStateLock.unlock();
}
GetIEditor()->Notify(eNotify_OnSplashScreenDestroyed);
@@ -984,12 +981,12 @@ void CCryEditApp::CloseSplashScreen()
/////////////////////////////////////////////////////////////////////////////
void CCryEditApp::OutputStartupMessage(QString str)
{
g_splashScreenStateLock.Lock();
g_splashScreenStateLock.lock();
if (g_pInitializeUIInfo)
{
g_pInitializeUIInfo->SetInfoText(str.toUtf8().data());
}
g_splashScreenStateLock.Unlock();
g_splashScreenStateLock.unlock();
}
//////////////////////////////////////////////////////////////////////////
@@ -68,45 +68,21 @@ QIcon& CEditorPreferencesPage_ViewportMovement::GetIcon()
void CEditorPreferencesPage_ViewportMovement::OnApply()
{
if (SandboxEditor::UsingNewCameraSystem())
{
SandboxEditor::SetCameraTranslateSpeed(m_cameraMovementSettings.m_moveSpeed);
SandboxEditor::SetCameraRotateSpeed(m_cameraMovementSettings.m_rotateSpeed);
SandboxEditor::SetCameraBoostMultiplier(m_cameraMovementSettings.m_fastMoveSpeed);
SandboxEditor::SetCameraScrollSpeed(m_cameraMovementSettings.m_wheelZoomSpeed);
SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_invertYRotation);
SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_invertPan);
SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_invertPan);
}
else
{
gSettings.cameraMoveSpeed = m_cameraMovementSettings.m_moveSpeed;
gSettings.cameraRotateSpeed = m_cameraMovementSettings.m_rotateSpeed;
gSettings.cameraFastMoveSpeed = m_cameraMovementSettings.m_fastMoveSpeed;
gSettings.wheelZoomSpeed = m_cameraMovementSettings.m_wheelZoomSpeed;
gSettings.invertYRotation = m_cameraMovementSettings.m_invertYRotation;
gSettings.invertPan = m_cameraMovementSettings.m_invertPan;
}
SandboxEditor::SetCameraTranslateSpeed(m_cameraMovementSettings.m_moveSpeed);
SandboxEditor::SetCameraRotateSpeed(m_cameraMovementSettings.m_rotateSpeed);
SandboxEditor::SetCameraBoostMultiplier(m_cameraMovementSettings.m_fastMoveSpeed);
SandboxEditor::SetCameraScrollSpeed(m_cameraMovementSettings.m_wheelZoomSpeed);
SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_invertYRotation);
SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_invertPan);
SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_invertPan);
}
void CEditorPreferencesPage_ViewportMovement::InitializeSettings()
{
if (SandboxEditor::UsingNewCameraSystem())
{
m_cameraMovementSettings.m_moveSpeed = SandboxEditor::CameraTranslateSpeed();
m_cameraMovementSettings.m_rotateSpeed = SandboxEditor::CameraRotateSpeed();
m_cameraMovementSettings.m_fastMoveSpeed = SandboxEditor::CameraBoostMultiplier();
m_cameraMovementSettings.m_wheelZoomSpeed = SandboxEditor::CameraScrollSpeed();
m_cameraMovementSettings.m_invertYRotation = SandboxEditor::CameraOrbitYawRotationInverted();
m_cameraMovementSettings.m_invertPan = SandboxEditor::CameraPanInvertedX() && SandboxEditor::CameraPanInvertedY();
}
else
{
m_cameraMovementSettings.m_moveSpeed = gSettings.cameraMoveSpeed;
m_cameraMovementSettings.m_rotateSpeed = gSettings.cameraRotateSpeed;
m_cameraMovementSettings.m_fastMoveSpeed = gSettings.cameraFastMoveSpeed;
m_cameraMovementSettings.m_wheelZoomSpeed = gSettings.wheelZoomSpeed;
m_cameraMovementSettings.m_invertYRotation = gSettings.invertYRotation;
m_cameraMovementSettings.m_invertPan = gSettings.invertPan;
}
m_cameraMovementSettings.m_moveSpeed = SandboxEditor::CameraTranslateSpeed();
m_cameraMovementSettings.m_rotateSpeed = SandboxEditor::CameraRotateSpeed();
m_cameraMovementSettings.m_fastMoveSpeed = SandboxEditor::CameraBoostMultiplier();
m_cameraMovementSettings.m_wheelZoomSpeed = SandboxEditor::CameraScrollSpeed();
m_cameraMovementSettings.m_invertYRotation = SandboxEditor::CameraOrbitYawRotationInverted();
m_cameraMovementSettings.m_invertPan = SandboxEditor::CameraPanInvertedX() && SandboxEditor::CameraPanInvertedY();
}
-4
View File
@@ -118,8 +118,4 @@ namespace SandboxEditor
SANDBOX_API AzFramework::InputChannelId CameraOrbitPanChannelId();
SANDBOX_API void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId);
//! Return if the new editor camera system is enabled or not.
//! @note This is implemented in EditorViewportWidget.cpp
SANDBOX_API bool UsingNewCameraSystem();
} // namespace SandboxEditor
+4 -23
View File
@@ -72,7 +72,6 @@
#include "IPostEffectGroup.h"
#include "EditorPreferencesPageGeneral.h"
#include "ViewportManipulatorController.h"
#include "LegacyViewportCameraController.h"
#include "EditorViewportSettings.h"
#include "ViewPane.h"
@@ -105,17 +104,8 @@
AZ_CVAR(
bool, ed_visibility_logTiming, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Output the timing of the new IVisibilitySystem query");
AZ_CVAR(bool, ed_useNewCameraSystem, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Editor camera system");
AZ_CVAR(bool, ed_showCursorCameraLook, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Show the cursor when using free look with the new camera system");
namespace SandboxEditor
{
bool UsingNewCameraSystem()
{
return ed_useNewCameraSystem;
}
} // namespace SandboxEditor
EditorViewportWidget* EditorViewportWidget::m_pPrimaryViewport = nullptr;
#if AZ_TRAIT_OS_PLATFORM_APPLE
@@ -640,7 +630,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
if (m_renderViewport)
{
m_renderViewport->GetControllerList()->SetEnabled(true);
m_renderViewport->SetInputProcessingEnabled(true);
}
break;
@@ -1274,15 +1264,8 @@ void EditorViewportWidget::SetViewportId(int id)
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::ViewportManipulatorController>());
if (ed_useNewCameraSystem)
{
m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id)));
}
else
{
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::LegacyViewportCameraController>());
}
m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id)));
m_renderViewport->SetViewportSettings(&g_EditorViewportSettings);
UpdateScene();
@@ -2239,7 +2222,6 @@ void EditorViewportWidget::CenterOnAABB(const AABB& aabb)
orbitDistance = fabs(orbitDistance);
SetViewTM(newTM);
SandboxEditor::OrbitCameraControlsBus::Event(GetViewportId(), &SandboxEditor::OrbitCameraControlsBus::Events::SetOrbitDistance, orbitDistance);
}
void EditorViewportWidget::CenterOnSliceInstance()
@@ -2715,8 +2697,7 @@ void EditorViewportWidget::RestoreViewportAfterGameMode()
QString(
tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you "
"had entered Game mode.<br/><br/><small>If you dislike this setting you can always change this anytime in the global "
"preferences.</small><br/><br/>"))
.arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
"preferences.</small><br/><br/>"));
QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode");
// Read the popup disabled registry value
+2 -3
View File
@@ -20,7 +20,6 @@
#include "LogFile.h"
#include "CryListenerSet.h"
#include "Util/ModalWindowDismisser.h"
#include <CryCommon/CryThread.h>
#endif
class CStartupLogoDialog;
@@ -117,11 +116,11 @@ public:
//! mutex used by other threads to lock up the PAK modification,
//! so only one thread can modify the PAK at once
static CryMutex& GetPakModifyMutex()
static AZStd::recursive_mutex& GetPakModifyMutex()
{
//! mutex used to halt copy process while the export to game
//! or other pak operation is done in the main thread
static CryMutex s_pakModifyMutex;
static AZStd::recursive_mutex s_pakModifyMutex;
return s_pakModifyMutex;
}
+1 -1
View File
@@ -136,7 +136,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE
m_settings.SetHiQuality();
}
CryAutoLock<CryMutex> autoLock(CGameEngine::GetPakModifyMutex());
AZStd::scoped_lock autoLock(CGameEngine::GetPakModifyMutex());
// Close this pak file.
if (!CloseLevelPack(m_levelPak, true))
+5 -17
View File
@@ -108,24 +108,12 @@ void GotoPositionDialog::OnUpdateNumbers()
void GotoPositionDialog::accept()
{
if (SandboxEditor::UsingNewCameraSystem())
{
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())));
}
else
{
SandboxEditor::SetDefaultViewportCameraPosition(AZ::Vector3(
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())));
SandboxEditor::SetDefaultViewportCameraRotation(
AZ::DegToRad(aznumeric_cast<float>(m_ui->m_dymAnglePitch->value())),
AZ::DegToRad(aznumeric_cast<float>(m_ui->m_dymAngleYaw->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())));
QDialog::accept();
}
+3 -3
View File
@@ -252,7 +252,7 @@ void CEditorImpl::Uninitialize()
void CEditorImpl::UnloadPlugins()
{
CryAutoLock<CryMutex> lock(m_pluginMutex);
AZStd::scoped_lock lock(m_pluginMutex);
// Flush core buses. We're about to unload DLLs and need to ensure we don't have module-owned functions left behind.
AZ::Data::AssetBus::ExecuteQueuedEvents();
@@ -273,7 +273,7 @@ void CEditorImpl::UnloadPlugins()
void CEditorImpl::LoadPlugins()
{
CryAutoLock<CryMutex> lock(m_pluginMutex);
AZStd::scoped_lock lock(m_pluginMutex);
static const QString editor_plugins_folder("EditorPlugins");
@@ -1460,7 +1460,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener)
ISourceControl* CEditorImpl::GetSourceControl()
{
CryAutoLock<CryMutex> lock(m_pluginMutex);
AZStd::scoped_lock lock(m_pluginMutex);
if (m_pSourceControl)
{
+1 -1
View File
@@ -401,7 +401,7 @@ protected:
IImageUtil* m_pImageUtil; // Vladimir@conffx
ILogFile* m_pLogFile; // Vladimir@conffx
CryMutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer.
AZStd::mutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer.
static const char* m_crashLogFileName;
};
@@ -1,537 +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 "LegacyViewportCameraController.h"
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <Atom/RPI.Public/ViewportContext.h>
#include <IViewSystem.h>
#include <ISystem.h>
#include "CryCommon/MathConversion.h"
#include "SandboxAPI.h"
#include "Settings.h"
namespace SandboxEditor
{
LegacyViewportCameraControllerInstance::LegacyViewportCameraControllerInstance(AzFramework::ViewportId viewportId, LegacyViewportCameraController* controller)
: AzFramework::MultiViewportControllerInstanceInterface<LegacyViewportCameraController>(viewportId, controller)
{
OrbitCameraControlsBus::Handler::BusConnect(viewportId);
}
LegacyViewportCameraControllerInstance::~LegacyViewportCameraControllerInstance()
{
OrbitCameraControlsBus::Handler::BusDisconnect();
}
bool LegacyViewportCameraControllerInstance::JustAltHeld() const
{
return (m_modifiers ^ Qt::AltModifier) == 0;
}
bool LegacyViewportCameraControllerInstance::NoModifierHeld() const
{
return !m_modifiers;
}
bool LegacyViewportCameraControllerInstance::AllowDolly() const
{
return JustAltHeld();
}
bool LegacyViewportCameraControllerInstance::AllowOrbit() const
{
return JustAltHeld();
}
bool LegacyViewportCameraControllerInstance::AllowPan() const
{
// begin pan with alt (inverted movement) or no modifiers
return JustAltHeld() || NoModifierHeld();
}
bool LegacyViewportCameraControllerInstance::InvertPan() const
{
return JustAltHeld();
}
void LegacyViewportCameraControllerInstance::SetOrbitDistance(float orbitDistance)
{
m_orbitDistance = orbitDistance;
}
AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportContext()
{
// This could be cached, if needed
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
if (!viewportContextManager)
{
return {};
}
return viewportContextManager->GetViewportContextById(GetViewportId());
}
bool LegacyViewportCameraControllerInstance::HandleMouseMove(
int dx, int dy)
{
if (dx == 0 && dy == 0)
{
return false;
}
auto viewportContext = GetViewportContext();
if (!viewportContext)
{
return false;
}
float speedScale = gSettings.cameraMoveSpeed;
if (m_modifiers & Qt::Key_Control)
{
speedScale *= gSettings.cameraFastMoveSpeed;
}
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
{
m_totalMouseMoveDelta += AZStd::abs(dx) + AZStd::abs(dy);
}
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
{
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
Vec3 ydir = m.GetColumn1().GetNormalized();
Vec3 pos = m.GetTranslation();
const float posDelta = 0.2f * dy * speedScale;
pos = pos - ydir * posDelta;
m_orbitDistance = m_orbitDistance + posDelta;
m_orbitDistance = fabs(m_orbitDistance);
m.SetTranslation(pos);
viewportContext->SetCameraTransform(LYTransformToAZTransform(m));
return true;
}
else if (m_inRotateMode)
{
Ang3 angles(dy, 0, dx);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertYRotation)
{
angles.x = -angles.x;
}
Matrix34 camtm = AZTransformToLYTransform(viewportContext->GetCameraTransform());
Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(camtm));
ypr.x += angles.z;
ypr.y += angles.x;
ypr.y = AZStd::clamp(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range
ypr.z = 0; // to have camera always upward
camtm = Matrix34(CCamera::CreateOrientationYPR(ypr), camtm.GetTranslation());
viewportContext->SetCameraTransform(LYTransformToAZTransform(camtm));
return true;
}
else if (m_inMoveMode)
{
// Slide.
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
Vec3 xdir = m.GetColumn0().GetNormalized();
Vec3 zdir = m.GetColumn2().GetNormalized();
if (InvertPan())
{
xdir = -xdir;
zdir = -zdir;
}
Vec3 pos = m.GetTranslation();
pos += 0.1f * xdir * dx * speedScale + 0.1f * zdir * dy * speedScale;
m.SetTranslation(pos);
AZ::Transform transform = viewportContext->GetCameraTransform();
transform.SetTranslation(LYVec3ToAZVec3(pos));
viewportContext->SetCameraTransform(transform);
return true;
}
else if (m_inOrbitMode)
{
Ang3 angles(dy, 0, dx);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertPan)
{
angles.z = -angles.z;
}
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(m));
ypr.x += angles.z;
ypr.y = AZStd::clamp(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range
ypr.y += angles.x;
Matrix33 rotateTM = CCamera::CreateOrientationYPR(ypr);
Vec3 src = m.GetTranslation();
Vec3 trg(m_orbitTarget.GetX(), m_orbitTarget.GetY(), m_orbitTarget.GetZ());
float fCameraRadius = (trg - src).GetLength();
// Calc new source.
src = trg - rotateTM * Vec3(0, 1, 0) * fCameraRadius;
Matrix34 camTM = rotateTM;
camTM.SetTranslation(src);
viewportContext->SetCameraTransform(LYTransformToAZTransform(camTM));
return true;
}
return false;
}
bool LegacyViewportCameraControllerInstance::HandleMouseWheel(float zDelta)
{
auto viewportContext = GetViewportContext();
if (!viewportContext)
{
return false;
}
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
const Vec3 ydir = m.GetColumn1().GetNormalized();
Vec3 pos = m.GetTranslation();
const float posDelta = 0.01f * zDelta * gSettings.wheelZoomSpeed;
pos += ydir * posDelta;
m_orbitDistance = m_orbitDistance - posDelta;
m_orbitDistance = fabs(m_orbitDistance);
m.SetTranslation(pos);
viewportContext->SetCameraTransform(LYTransformToAZTransform(m));
return true;
}
bool LegacyViewportCameraControllerInstance::IsKeyDown(Qt::Key key) const
{
return m_pressedKeys.contains(key);
}
Qt::Key LegacyViewportCameraControllerInstance::GetKeyboardKey(const AzFramework::InputChannel& inputChannel)
{
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::AlphanumericW)
{
return Qt::Key_W;
}
else if (id == Key::AlphanumericA)
{
return Qt::Key_A;
}
else if (id == Key::AlphanumericS)
{
return Qt::Key_S;
}
else if (id == Key::AlphanumericD)
{
return Qt::Key_D;
}
else if (id == Key::AlphanumericQ)
{
return Qt::Key_Q;
}
else if (id == Key::AlphanumericE)
{
return Qt::Key_E;
}
else if (id == Key::NavigationArrowUp)
{
return Qt::Key_Up;
}
else if (id == Key::NavigationArrowUp)
{
return Qt::Key_Down;
}
else if (id == Key::NavigationArrowUp)
{
return Qt::Key_Left;
}
else if (id == Key::NavigationArrowUp)
{
return Qt::Key_Right;
}
return Qt::Key_unknown;
}
Qt::KeyboardModifier LegacyViewportCameraControllerInstance::GetKeyboardModifier(const AzFramework::InputChannel& inputChannel)
{
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
{
return Qt::KeyboardModifier::AltModifier;
}
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
{
return Qt::KeyboardModifier::ControlModifier;
}
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
{
return Qt::KeyboardModifier::ShiftModifier;
}
return Qt::KeyboardModifier::NoModifier;
}
bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
using AzFramework::InputChannel;
using MouseButton = AzFramework::InputDeviceMouse::Button;
const auto& id = event.m_inputChannel.GetInputChannelId();
const auto& state = event.m_inputChannel.GetState();
bool shouldCaptureCursor = m_capturingCursor;
bool shouldConsumeEvent = false;
if (id == AzFramework::InputDeviceMouse::Movement::X || id == AzFramework::InputDeviceMouse::Movement::Y)
{
int dx = 0;
int dy = 0;
if (id == AzFramework::InputDeviceMouse::Movement::X)
{
dx = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
}
else
{
dy = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
}
return HandleMouseMove(dx, dy);
}
else if (id == MouseButton::Left)
{
if (state == InputChannel::State::Began)
{
if (AllowOrbit())
{
AzFramework::CameraState cameraState;
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
cameraState, event.m_viewportId,
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState);
m_inOrbitMode = true;
m_orbitTarget = cameraState.m_position + cameraState.m_forward * m_orbitDistance;
shouldConsumeEvent = true;
shouldCaptureCursor = true;
}
}
else if (state == InputChannel::State::Ended)
{
m_inOrbitMode = false;
shouldCaptureCursor = false;
}
}
else if (id == MouseButton::Right)
{
if (state == InputChannel::State::Began)
{
if (AllowDolly())
{
m_inZoomMode = true;
}
else
{
m_inRotateMode = true;
}
shouldCaptureCursor = true;
// Record how much the cursor has been moved to see if we should own the mouse up event.
m_totalMouseMoveDelta = 0;
}
else if (state == InputChannel::State::Ended)
{
m_inZoomMode = false;
m_inRotateMode = false;
// If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it.
shouldConsumeEvent = m_totalMouseMoveDelta > 2;
shouldCaptureCursor = false;
}
}
else if (id == MouseButton::Middle)
{
if (state == InputChannel::State::Began)
{
if (AllowPan())
{
m_inMoveMode = true;
shouldConsumeEvent = true;
shouldCaptureCursor = true;
}
}
else if (state == InputChannel::State::Ended)
{
m_inMoveMode = false;
shouldCaptureCursor = false;
}
}
else if (auto modifier = GetKeyboardModifier(event.m_inputChannel); modifier != Qt::KeyboardModifier::NoModifier)
{
if (state == InputChannel::State::Ended)
{
m_modifiers &= ~modifier;
}
else
{
m_modifiers |= modifier;
}
}
else if (id == AzFramework::InputDeviceMouse::Movement::Z)
{
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
{
shouldConsumeEvent = HandleMouseWheel(event.m_inputChannel.GetValue());
}
}
else if (auto key = GetKeyboardKey(event.m_inputChannel); key != Qt::Key_unknown)
{
if (!event.m_inputChannel.IsActive())
{
m_pressedKeys.erase(key);
}
else
{
m_pressedKeys.insert(key);
shouldConsumeEvent = true;
}
}
UpdateCursorCapture(shouldCaptureCursor);
return shouldConsumeEvent;
}
void LegacyViewportCameraControllerInstance::UpdateCursorCapture(bool shouldCaptureCursor)
{
if (m_capturingCursor != shouldCaptureCursor)
{
if (shouldCaptureCursor)
{
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture
);
}
else
{
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::EndCursorCapture
);
}
m_capturingCursor = shouldCaptureCursor;
}
}
void LegacyViewportCameraControllerInstance::ResetInputChannels()
{
m_modifiers = 0;
m_pressedKeys.clear();
UpdateCursorCapture(false);
m_inRotateMode = m_inMoveMode = m_inOrbitMode = m_inZoomMode = false;
}
void LegacyViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
auto viewportContext = GetViewportContext();
if (!viewportContext)
{
return;
}
AZ::Transform transform = viewportContext->GetCameraTransform();
AZ::Vector3 xdir = transform.GetBasisX();
AZ::Vector3 ydir = transform.GetBasisY();
AZ::Vector3 zdir = transform.GetBasisZ();
AZ::Vector3 pos = transform.GetTranslation();
float speedScale = AZStd::GetMin(30.0f * event.m_deltaTime.count(), 20.0f);
// Use the global modifier keys instead of our keymap. It's more reliable.
const bool shiftPressed = m_modifiers & Qt::ShiftModifier;
const bool controlPressed = m_modifiers & Qt::ControlModifier;
speedScale *= gSettings.cameraMoveSpeed;
if (controlPressed)
{
return;
}
if (shiftPressed)
{
speedScale *= gSettings.cameraFastMoveSpeed;
}
bool cameraMoved = false;
if (IsKeyDown(Qt::Key_Up) || IsKeyDown(Qt::Key_W))
{
// move forward
cameraMoved = true;
pos = pos + (speedScale * m_moveSpeed * ydir);
}
if (IsKeyDown(Qt::Key_Down) || IsKeyDown(Qt::Key_S))
{
// move backward
cameraMoved = true;
pos = pos - (speedScale * m_moveSpeed * ydir);
}
if (IsKeyDown(Qt::Key_Left) || IsKeyDown(Qt::Key_A))
{
// move left
cameraMoved = true;
pos = pos - (speedScale * m_moveSpeed * xdir);
}
if (IsKeyDown(Qt::Key_Right) || IsKeyDown(Qt::Key_D))
{
// move right
cameraMoved = true;
pos = pos + (speedScale * m_moveSpeed * xdir);
}
if (IsKeyDown(Qt::Key_E))
{
// move Up
cameraMoved = true;
pos = pos + (speedScale * m_moveSpeed * zdir);
}
if (IsKeyDown(Qt::Key_Q))
{
// move down
cameraMoved = true;
pos = pos - (speedScale * m_moveSpeed * zdir);
}
if (cameraMoved)
{
transform.SetTranslation(pos);
viewportContext->SetCameraTransform(transform);
}
}
} //namespace SandboxEditor
@@ -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
#include <AzCore/EBus/EBus.h>
#include <AzFramework/Viewport/ViewportId.h>
#include <AzFramework/Viewport/MultiViewportController.h>
#include <AzCore/Math/Vector3.h>
#include <Atom/RPI.Public/Base.h>
#include <QtCore/qnamespace.h>
#include <QPoint>
namespace AzFramework
{
struct ScreenPoint;
}
namespace SandboxEditor
{
class OrbitCameraControls
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AzFramework::ViewportId;
//////////////////////////////////////////////////////////////////////////
virtual void SetOrbitDistance(float orbitDistance [[maybe_unused]]) {;}
};
using OrbitCameraControlsBus = AZ::EBus<OrbitCameraControls>;
class LegacyViewportCameraControllerInstance;
using LegacyViewportCameraController = AzFramework::MultiViewportController<LegacyViewportCameraControllerInstance>;
class LegacyViewportCameraControllerInstance final
: public AzFramework::MultiViewportControllerInstanceInterface<LegacyViewportCameraController>
, public OrbitCameraControlsBus::Handler
{
public:
LegacyViewportCameraControllerInstance(AzFramework::ViewportId viewport, LegacyViewportCameraController* controller);
~LegacyViewportCameraControllerInstance();
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void ResetInputChannels() override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
void SetOrbitDistance(float orbitDistance) override;
private:
bool JustAltHeld() const;
bool NoModifierHeld() const;
bool AllowDolly() const;
bool AllowOrbit() const;
bool AllowPan() const;
bool InvertPan() const;
static Qt::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
static Qt::Key GetKeyboardKey(const AzFramework::InputChannel& inputChannel);
AZ::RPI::ViewportContextPtr GetViewportContext();
bool HandleMouseMove(int dx, int dy);
bool HandleMouseWheel(float zDelta);
bool IsKeyDown(Qt::Key key) const;
void UpdateCursorCapture(bool shouldCaptureCursor);
bool m_inRotateMode = false;
bool m_inMoveMode = false;
bool m_inOrbitMode = false;
bool m_inZoomMode = false;
int m_totalMouseMoveDelta = 0;
float m_orbitDistance = 10.f;
float m_moveSpeed = 1.f;
AZ::Vector3 m_orbitTarget = {};
unsigned int m_modifiers = {};
AZStd::unordered_set<Qt::Key> m_pressedKeys;
bool m_capturingCursor = false;
};
} //namespace SandboxEditor
@@ -1452,7 +1452,7 @@ void SandboxIntegrationManager::ContextMenu_NewEntity()
if (view)
{
const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY());
worldPosition = LYVec3ToAZVec3(view->SnapToGrid(view->ViewToWorld(viewPoint)));
worldPosition = view->GetHitLocation(viewPoint);
}
CreateNewEntityAtPosition(worldPosition);
@@ -1704,74 +1704,44 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
return;
}
if (SandboxEditor::UsingNewCameraSystem())
const AZ::Aabb aabb = AZStd::accumulate(
AZStd::begin(entityIds), AZStd::end(entityIds), AZ::Aabb::CreateNull(), [](AZ::Aabb acc, const AZ::EntityId entityId) {
const AZ::Aabb aabb = AzFramework::CalculateEntityWorldBoundsUnion(AzToolsFramework::GetEntityById(entityId));
acc.AddAabb(aabb);
return acc;
});
float radius;
AZ::Vector3 center;
aabb.GetAsSphere(center, radius);
// minimum center size is 40cm
const float minSelectionRadius = 0.4f;
const float selectionSize = AZ::GetMax(minSelectionRadius, radius);
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
const int viewCount = GetIEditor()->GetViewManager()->GetViewCount(); // legacy call
for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
{
const AZ::Aabb aabb = AZStd::accumulate(
AZStd::begin(entityIds), AZStd::end(entityIds), AZ::Aabb::CreateNull(), [](AZ::Aabb acc, const AZ::EntityId entityId) {
const AZ::Aabb aabb = AzFramework::CalculateEntityWorldBoundsUnion(AzToolsFramework::GetEntityById(entityId));
acc.AddAabb(aabb);
return acc;
});
float radius;
AZ::Vector3 center;
aabb.GetAsSphere(center, radius);
// minimum center size is 40cm
const float minSelectionRadius = 0.4f;
const float selectionSize = AZ::GetMax(minSelectionRadius, radius);
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
const int viewCount = GetIEditor()->GetViewManager()->GetViewCount(); // legacy call
for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
if (auto viewportContext = viewportContextManager->GetViewportContextById(viewIndex))
{
if (auto viewportContext = viewportContextManager->GetViewportContextById(viewIndex))
{
const AZ::Transform cameraTransform = viewportContext->GetCameraTransform();
const AZ::Vector3 forward = (center - cameraTransform.GetTranslation()).GetNormalized();
const AZ::Transform cameraTransform = viewportContext->GetCameraTransform();
const AZ::Vector3 forward = (center - cameraTransform.GetTranslation()).GetNormalized();
// move camera 25% further back than required
const float centerScale = 1.25f;
// compute new camera transform
const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix());
const float fovScale = (1.0f / AZStd::tan(fov * 0.5f));
const float distanceToLookAt = selectionSize * fovScale * centerScale;
const AZ::Transform nextCameraTransform =
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter());
// move camera 25% further back than required
const float centerScale = 1.25f;
// compute new camera transform
const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix());
const float fovScale = (1.0f / AZStd::tan(fov * 0.5f));
const float distanceToLookAt = selectionSize * fovScale * centerScale;
const AZ::Transform nextCameraTransform =
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter());
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
viewportContext->GetId(),
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform,
distanceToLookAt);
}
}
}
else
{
AABB selectionBounds;
selectionBounds.Reset();
bool entitiesAvailableForGoTo = false;
for (const AZ::EntityId& entityId : entityIds)
{
if (CollectEntityBoundingBoxesForZoom(entityId, selectionBounds))
{
entitiesAvailableForGoTo = true;
}
}
if (entitiesAvailableForGoTo)
{
int numViews = GetIEditor()->GetViewManager()->GetViewCount();
for (int viewIndex = 0; viewIndex < numViews; ++viewIndex)
{
CViewport* viewport = GetIEditor()->GetViewManager()->GetView(viewIndex);
if (viewport)
{
viewport->CenterOnAABB(selectionBounds);
}
}
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
viewportContext->GetId(),
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform,
distanceToLookAt);
}
}
}
@@ -20,7 +20,7 @@
#include <QMouseEvent>
OutlinerTreeView::OutlinerTreeView(QWidget* pParent)
: QTreeView(pParent)
: AzQtComponents::StyledTreeView(pParent)
, m_queuedMouseEvent(nullptr)
, m_draggingUnselectedItem(false)
{
@@ -135,16 +135,12 @@ void OutlinerTreeView::startDrag(Qt::DropActions supportedActions)
if (!selectionModel()->isSelected(index))
{
startCustomDrag({ index }, supportedActions);
StartCustomDrag({ index }, supportedActions);
return;
}
}
if (!selectionModel()->selectedIndexes().empty())
{
startCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
return;
}
StyledTreeView::startDrag(supportedActions);
}
void OutlinerTreeView::dragMoveEvent(QDragMoveEvent* event)
@@ -336,14 +332,14 @@ void OutlinerTreeView::processQueuedMousePressedEvent(QMouseEvent* event)
QTreeView::mousePressEvent(&mousePressedEvent);
}
void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
void OutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
{
m_draggingUnselectedItem = true;
//sort by container entity depth and order in hierarchy for proper drag image and drop order
QModelIndexList indexListSorted = indexList;
AZStd::unordered_map<AZ::EntityId, AZStd::list<AZ::u64>> locations;
for (auto index : indexListSorted)
for (const auto& index : indexListSorted)
{
AZ::EntityId entityId(index.data(OutlinerListModel::EntityIdRole).value<AZ::u64>());
AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]);
@@ -356,74 +352,7 @@ void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::Dro
return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end());
});
//get the data for the unselected item(s)
QMimeData* mimeData = model()->mimeData(indexListSorted);
if (mimeData)
{
//initiate drag/drop for the item
QDrag* drag = new QDrag(this);
drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted)));
drag->setMimeData(mimeData);
Qt::DropAction defDropAction = Qt::IgnoreAction;
if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction()))
{
defDropAction = defaultDropAction();
}
else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
{
defDropAction = Qt::CopyAction;
}
drag->exec(supportedActions, defDropAction);
}
}
QImage OutlinerTreeView::createDragImage(const QModelIndexList& indexList)
{
//generate a drag image of the item icon and text, normally done internally, and inaccessible
QRect rect(0, 0, 0, 0);
for (auto index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = visualRect(index);
rect.setHeight(rect.height() + itemRect.height());
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
}
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
QPainter dragPainter(&dragImage);
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
dragPainter.setOpacity(0.35f);
dragPainter.fillRect(rect, QColor("#222222"));
dragPainter.setOpacity(1.0f);
int imageY = 0;
for (auto index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = visualRect(index);
dragPainter.drawPixmap(QPoint(0, imageY),
model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
dragPainter.setPen(
model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
dragPainter.setFont(
font());
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
model()->data(index, Qt::DisplayRole).value<QString>());
imageY += itemRect.height();
}
dragPainter.end();
return dragImage;
StyledTreeView::StartCustomDrag(indexListSorted, supportedActions);
}
#include <UI/Outliner/moc_OutlinerTreeView.cpp>
@@ -15,7 +15,8 @@
#include <QBasicTimer>
#include <QEvent>
#include <QTreeView>
#include <AzQtComponents/Components/Widgets/TreeView.h>
#endif
#pragma once
@@ -31,7 +32,7 @@ class OutlinerTreeViewModel;
//! allow for dragging and dropping of entities from the outliner into the property editor
//! of other entities. If the selection updates instantly, this would never be possible.
class OutlinerTreeView
: public QTreeView
: public AzQtComponents::StyledTreeView
{
Q_OBJECT;
public:
@@ -66,9 +67,7 @@ private:
void processQueuedMousePressedEvent(QMouseEvent* event);
void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
QImage createDragImage(const QModelIndexList& indexList);
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
void DrawLayerUI(QPainter* painter, const QRect& rect, const QModelIndex& index) const;
@@ -9,7 +9,6 @@
#include "CryFile.h"
#include "PerforceSourceControl.h"
#include "PasswordDlg.h"
#include <CryCommon/CryThread.h>
#include <QSettings>
#include <QDir>
@@ -23,7 +22,7 @@
namespace
{
CryCriticalSection g_cPerforceValues;
AZStd::mutex g_cPerforceValues;
}
////////////////////////////////////////////////////////////
@@ -31,9 +30,9 @@ ULONG STDMETHODCALLTYPE CPerforceSourceControl::Release()
{
if ((--m_ref) == 0)
{
g_cPerforceValues.Lock();
g_cPerforceValues.lock();
delete this;
g_cPerforceValues.Unlock();
g_cPerforceValues.unlock();
return 0;
}
else
@@ -57,7 +56,7 @@ void CPerforceSourceControl::ShowSettings()
void CPerforceSourceControl::SetSourceControlState(SourceControlState state)
{
CryAutoLock<CryCriticalSection> lock(g_cPerforceValues);
AZStd::scoped_lock lock(g_cPerforceValues);
switch (state)
{
-1
View File
@@ -9,7 +9,6 @@
#pragma once
#include "CryThread.h"
#include "../Include/SandboxAPI.h"
#include <QString>
#include <QFileInfo>
+2
View File
@@ -22,6 +22,8 @@ AZ_PUSH_DISABLE_WARNING(4458, "-Wunknown-warning-option")
AZ_POP_DISABLE_WARNING
#include <QVariant>
#include <StlUtils.h>
inline const char* to_c_str(const char* str) { return str; }
#define MAX_VAR_STRING_LENGTH 4096
+24 -18
View File
@@ -46,24 +46,7 @@ void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& conte
PreWidgetRendering(); // required so that the current render cam is set.
Vec3 pos = Vec3(ZERO);
HitContext hit;
if (HitTest(pt, hit))
{
pos = hit.raySrc + hit.rayDir * hit.dist;
pos = SnapToGrid(pos);
}
else
{
bool hitTerrain;
pos = ViewToWorld(pt, &hitTerrain);
if (hitTerrain)
{
pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y);
}
pos = SnapToGrid(pos);
}
context.m_hitLocation = AZ::Vector3(pos.x, pos.y, pos.z);
context.m_hitLocation = GetHitLocation(pt);
PostWidgetRendering();
}
@@ -1154,6 +1137,29 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
return false;
}
AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point)
{
Vec3 pos = Vec3(ZERO);
HitContext hit;
if (HitTest(point, hit))
{
pos = hit.raySrc + hit.rayDir * hit.dist;
pos = SnapToGrid(pos);
}
else
{
bool hitTerrain;
pos = ViewToWorld(point, &hitTerrain);
if (hitTerrain)
{
pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y);
}
pos = SnapToGrid(pos);
}
return AZ::Vector3(pos.x, pos.y, pos.z);
}
//////////////////////////////////////////////////////////////////////////
void QtViewport::SetZoomFactor(float fZoomFactor)
{
+2
View File
@@ -201,6 +201,7 @@ public:
//! Performs hit testing of 2d point in view to find which object hit.
virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0;
virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0;
virtual void MakeConstructionPlane(int axis) = 0;
@@ -436,6 +437,7 @@ public:
//! Performs hit testing of 2d point in view to find which object hit.
bool HitTest(const QPoint& point, HitContext& hitInfo) override;
AZ::Vector3 GetHitLocation(const QPoint& point) override;
//! Do 2D hit testing of line in world space.
// pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned.
+4 -13
View File
@@ -172,8 +172,7 @@ void CViewportTitleDlg::SetupCameraDropdownMenu()
cameraSpeedActionWidget->setDefaultWidget(cameraSpeedContainer);
// Save off the move speed here since setting up the combo box can cause it to update values in the background.
const float cameraMoveSpeed = SandboxEditor::UsingNewCameraSystem() ? SandboxEditor::CameraTranslateSpeed() : gSettings.cameraMoveSpeed;
const float cameraMoveSpeed = SandboxEditor::CameraTranslateSpeed();
// Populate the presets in the ComboBox
for (float presetValue : m_speedPresetValues)
{
@@ -947,21 +946,13 @@ void CViewportTitleDlg::OnSpeedComboBoxEnter()
void CViewportTitleDlg::OnUpdateMoveSpeedText(const QString& text)
{
if (SandboxEditor::UsingNewCameraSystem())
{
SandboxEditor::SetCameraTranslateSpeed(aznumeric_cast<float>(Round(text.toDouble(), m_speedStep)));
}
else
{
gSettings.cameraMoveSpeed = aznumeric_cast<float>(Round(text.toDouble(), m_speedStep));
}
SandboxEditor::SetCameraTranslateSpeed(aznumeric_cast<float>(Round(text.toDouble(), m_speedStep)));
}
void CViewportTitleDlg::CheckForCameraSpeedUpdate()
{
if (const float currentCameraMoveSpeed =
SandboxEditor::UsingNewCameraSystem() ? SandboxEditor::CameraTranslateSpeed() : gSettings.cameraMoveSpeed;
currentCameraMoveSpeed != m_prevMoveSpeed && !m_cameraSpeed->lineEdit()->hasFocus())
const float currentCameraMoveSpeed = SandboxEditor::CameraTranslateSpeed();
if (currentCameraMoveSpeed != m_prevMoveSpeed && !m_cameraSpeed->lineEdit()->hasFocus())
{
m_prevMoveSpeed = currentCameraMoveSpeed;
SetSpeedComboBox(currentCameraMoveSpeed);
-2
View File
@@ -799,8 +799,6 @@ set(FILES
EditorViewportCamera.h
ViewportManipulatorController.cpp
ViewportManipulatorController.h
LegacyViewportCameraController.cpp
LegacyViewportCameraController.h
TopRendererWnd.cpp
TopRendererWnd.h
ViewManager.cpp
@@ -58,6 +58,12 @@ namespace AZ
Event& operator=(Event&& rhs);
//! Take the handlers registered with the other event
//! and move them to this event. The other will event
//! will be cleared after call
//! @param other event to move handlers
Event& ClaimHandlers(Event&& other);
//! Returns true if at least one handler is connected to this event.
bool HasHandlerConnected() const;
@@ -207,6 +207,32 @@ namespace AZ
}
template <typename... Params>
auto Event<Params...>::ClaimHandlers(Event&& other) -> Event&
{
auto handlers = AZStd::move(other.m_handlers);
auto addList = AZStd::move(other.m_addList);
other.m_freeList = {};
other.m_updating = false;
AZStd::array handlerContainers{ &handlers, &addList };
for (AZStd::vector<Handler*>* handlerList : handlerContainers)
{
for (Handler* handler : *handlerList)
{
if (handler != nullptr)
{
handler->m_index = 0;
handler->m_event = this;
Connect(*handler);
}
}
}
return *this;
}
template <typename... Params>
bool Event<Params...>::HasHandlerConnected() const
{
@@ -20,7 +20,7 @@
namespace AZ
{
template<typename T>
bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type)
bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value)
{
if (path.empty())
{
@@ -56,7 +56,6 @@ namespace AZ
static_assert(!AZStd::is_same_v<T, T>, "SettingsRegistryImpl::SetValueInternal called with unsupported type.");
}
m_notifiers.Signal(path, type);
return true;
}
return false;
@@ -157,11 +156,11 @@ namespace AZ
// Setting to empty string to prevent assert
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointer(path.data(), path.length());
if (pointer.IsValid())
{
AZStd::scoped_lock lock(m_settingMutex);
const rapidjson::Value* value = pointer.Get(m_settings);
if (value)
{
@@ -207,7 +206,7 @@ namespace AZ
{
NotifyEventHandler notifyHandler{ callback };
{
AZStd::scoped_lock lock(m_settingMutex);
AZStd::scoped_lock lock(m_notifierMutex);
notifyHandler.Connect(m_notifiers);
}
return notifyHandler;
@@ -217,7 +216,7 @@ namespace AZ
{
NotifyEventHandler notifyHandler{ AZStd::move(callback) };
{
AZStd::scoped_lock lock(m_settingMutex);
AZStd::scoped_lock lock(m_notifierMutex);
notifyHandler.Connect(m_notifiers);
}
return notifyHandler;
@@ -225,7 +224,7 @@ namespace AZ
void SettingsRegistryImpl::ClearNotifiers()
{
AZStd::scoped_lock lock(m_settingMutex);
AZStd::scoped_lock lock(m_notifierMutex);
m_notifiers.DisconnectAllHandlers();
}
@@ -276,6 +275,31 @@ namespace AZ
m_postMergeEvent.DisconnectAllHandlers();
}
void SettingsRegistryImpl::SignalNotifier(AZStd::string_view jsonPath, Type type)
{
// Move the Notifier AZ::Event to a local AZ::Event in order to allow
// the notifier handlers to be signaled outside of the notifier mutex
// This allows other threads to register notifiers while this thread
// is invoking the handlers
decltype(m_notifiers) localNotifierEvent;
{
AZStd::scoped_lock lock(m_notifierMutex);
localNotifierEvent = AZStd::move(m_notifiers);
}
localNotifierEvent.Signal(jsonPath, type);
{
// Swap the local handlers with the current m_notifiers which
// will contain any handlers added during the signaling of the
// local event
AZStd::scoped_lock lock(m_notifierMutex);
AZStd::swap(m_notifiers, localNotifierEvent);
// Append any added handlers to the m_notifier structure
m_notifiers.ClaimHandlers(AZStd::move(localNotifierEvent));
}
}
SettingsRegistryInterface::Type SettingsRegistryImpl::GetType(AZStd::string_view path) const
{
if (path.empty())
@@ -286,11 +310,11 @@ namespace AZ
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointer(path.data(), path.length());
if (pointer.IsValid())
{
AZStd::scoped_lock lock(m_settingMutex);
const rapidjson::Value* value = pointer.Get(m_settings);
if (value)
{
@@ -363,11 +387,11 @@ namespace AZ
// Setting to empty string to prevent assert
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointer(path.data(), path.length());
if (pointer.IsValid())
{
AZStd::scoped_lock lock(m_settingMutex);
const rapidjson::Value* value = pointer.Get(m_settings);
if (value)
{
@@ -380,32 +404,52 @@ namespace AZ
bool SettingsRegistryImpl::Set(AZStd::string_view path, bool value)
{
AZStd::scoped_lock lock(m_settingMutex);
return SetValueInternal(path, value, Type::Boolean);
if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value))
{
return false;
}
SignalNotifier(path, Type::Boolean);
return true;
}
bool SettingsRegistryImpl::Set(AZStd::string_view path, s64 value)
{
AZStd::scoped_lock lock(m_settingMutex);
return SetValueInternal(path, value, Type::Integer);
if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value))
{
return false;
}
SignalNotifier(path, Type::Integer);
return true;
}
bool SettingsRegistryImpl::Set(AZStd::string_view path, u64 value)
{
AZStd::scoped_lock lock(m_settingMutex);
return SetValueInternal(path, value, Type::Integer);
if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value))
{
return false;
}
SignalNotifier(path, Type::Integer);
return true;
}
bool SettingsRegistryImpl::Set(AZStd::string_view path, double value)
{
AZStd::scoped_lock lock(m_settingMutex);
return SetValueInternal(path, value, Type::FloatingPoint);
if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value))
{
return false;
}
SignalNotifier(path, Type::FloatingPoint);
return true;
}
bool SettingsRegistryImpl::Set(AZStd::string_view path, AZStd::string_view value)
{
AZStd::scoped_lock lock(m_settingMutex);
return SetValueInternal(path, value, Type::String);
if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value))
{
return false;
}
SignalNotifier(path, Type::String);
return true;
}
bool SettingsRegistryImpl::Set(AZStd::string_view path, const char* value)
@@ -423,7 +467,6 @@ namespace AZ
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointer(path.data(), path.length());
if (pointer.IsValid())
@@ -433,9 +476,10 @@ namespace AZ
value, nullptr, valueTypeID, m_serializationSettings);
if (jsonResult.GetProcessing() != JsonSerializationResult::Processing::Halted)
{
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Value& setting = pointer.Create(m_settings, m_settings.GetAllocator());
setting = AZStd::move(store);
m_notifiers.Signal(path, Type::Object);
SignalNotifier(path, Type::Object);
return true;
}
}
@@ -451,13 +495,13 @@ namespace AZ
// Setting to empty string to prevent assert
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointerPath(path.data(), path.size());
if (!pointerPath.IsValid())
{
return false;
}
AZStd::scoped_lock lock(m_settingMutex);
return pointerPath.Erase(m_settings);
}
@@ -587,7 +631,7 @@ namespace AZ
return false;
}
m_notifiers.Signal("", Type::Object);
SignalNotifier("", Type::Object);
return true;
}
@@ -609,8 +653,6 @@ namespace AZ
scratchBuffer = &buffer;
}
AZStd::scoped_lock lock(m_settingMutex);
bool result = false;
if (path[path.length()] == 0)
{
@@ -624,6 +666,8 @@ namespace AZ
R"(Path "%.*s" is too long. Either make sure that the provided path is terminated or use a shorter path.)",
static_cast<int>(path.length()), path.data());
Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-");
AZStd::scoped_lock lock(m_settingMutex);
Value pathValue(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator());
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Unable to read registry file."), m_settings.GetAllocator())
@@ -669,6 +713,7 @@ namespace AZ
{
AZ_Error("Settings Registry", false, "Folder path for the Setting Registry is too long: %.*s",
static_cast<int>(path.size()), path.data());
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Folder path for the Setting Registry is too long."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator()), m_settings.GetAllocator());
@@ -706,6 +751,7 @@ namespace AZ
if (fileList.size() >= MaxRegistryFolderEntries)
{
AZ_Error("Settings Registry", false, "Too many files in registry folder.");
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator())
@@ -725,7 +771,6 @@ namespace AZ
SystemFile::FindFiles(folderPath.c_str(), callback);
AZStd::scoped_lock lock(m_settingMutex);
if (!platform.empty())
{
// Move the folderPath prefix back to the supplied path before the wildcard
@@ -743,6 +788,7 @@ namespace AZ
if (fileList.size() >= MaxRegistryFolderEntries)
{
AZ_Error("Settings Registry", false, "Too many files in registry folder.");
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator())
@@ -970,6 +1016,8 @@ namespace AZ
collisionFound = true;
AZ_Error("Settings Registry", false, R"(Two registry files in "%.*s" point to the same specialization: "%s" and "%s")",
AZ_STRING_ARG(folderPath), lhs.m_relativePath.c_str(), rhs.m_relativePath.c_str());
AZStd::scoped_lock lock(m_settingMutex);
historyPointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator())
.AddMember(StringRef("Path"),
@@ -1124,6 +1172,7 @@ namespace AZ
}
}
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Unable to parse registry file due to invalid json."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator())
@@ -1149,6 +1198,7 @@ namespace AZ
R"(To merge the supplied settings registry file, the settings within it must be placed within a JSON Object '{}')"
R"( in order to allow moving of its fields using the root-key as an anchor.)", path);
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Cannot merge registry file with a root which is not a JSON Object,"
" an empty root key and a merge approach of JsonMergePatch. Otherwise the Settings Registry would be overridden."
@@ -1167,6 +1217,7 @@ namespace AZ
JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge);
if (rootKey.empty())
{
AZStd::scoped_lock lock(m_settingMutex);
mergeResult = JsonSerialization::ApplyPatch(m_settings, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings);
}
else
@@ -1174,6 +1225,7 @@ namespace AZ
Pointer root(rootKey.data(), rootKey.length());
if (root.IsValid())
{
AZStd::scoped_lock lock(m_settingMutex);
Value& rootValue = root.Create(m_settings, m_settings.GetAllocator());
mergeResult = JsonSerialization::ApplyPatch(rootValue, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings);
}
@@ -1181,6 +1233,7 @@ namespace AZ
{
AZ_Error("Settings Registry", false, R"(Failed to root path "%.*s" is invalid.)",
aznumeric_cast<int>(rootKey.length()), rootKey.data());
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Invalid root key."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator());
@@ -1190,15 +1243,19 @@ namespace AZ
if (mergeResult.GetProcessing() != JsonSerializationResult::Processing::Completed)
{
AZ_Error("Settings Registry", false, R"(Failed to fully merge registry file "%s".)", path);
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
.AddMember(StringRef("Error"), StringRef("Failed to fully merge registry file."), m_settings.GetAllocator())
.AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator());
return false;
}
pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator());
{
AZStd::scoped_lock lock(m_settingMutex);
pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator());
}
m_notifiers.Signal("", Type::Object);
SignalNotifier("", Type::Object);
return true;
}
@@ -95,7 +95,7 @@ namespace AZ
using RegistryFileList = AZStd::fixed_vector<RegistryFile, MaxRegistryFolderEntries>;
template<typename T>
bool SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type);
bool SetValueInternal(AZStd::string_view path, T value);
template<typename T>
bool GetValueInternal(T& result, AZStd::string_view path) const;
VisitResponse Visit(Visitor& visitor, StackedString& path, AZStd::string_view valueName,
@@ -106,8 +106,11 @@ namespace AZ
const rapidjson::Pointer& historyPointer, AZStd::string_view folderPath);
bool ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations);
bool MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector<char>& scratchBuffer);
void SignalNotifier(AZStd::string_view jsonPath, Type type);
mutable AZStd::recursive_mutex m_settingMutex;
mutable AZStd::recursive_mutex m_notifierMutex;
NotifyEvent m_notifiers;
PreMergeEvent m_preMergeEvent;
PostMergeEvent m_postMergeEvent;
@@ -240,6 +240,37 @@ namespace UnitTest
static_assert(!AZStd::is_copy_assignable_v<AZ::Event<int32_t>>, "AZ Events should not be copy assignable");
}
TEST_F(EventTests, TestClaimHandlers_TakesAllSourceHandlers)
{
AZ::Event<> testEvent1;
AZ::Event<> testEvent2;
int32_t handlerInvokeCount{};
auto handlerCallback = [&handlerInvokeCount]()
{
++handlerInvokeCount;
};
AZ::Event<>::Handler testHandler1(handlerCallback);
AZ::Event<>::Handler testHandler2(handlerCallback);
testHandler1.Connect(testEvent1);
testHandler2.Connect(testEvent2);
EXPECT_TRUE(testEvent1.HasHandlerConnected());
EXPECT_TRUE(testEvent2.HasHandlerConnected());
testEvent1.ClaimHandlers(AZStd::move(testEvent2));
EXPECT_TRUE(testEvent1.HasHandlerConnected());
EXPECT_FALSE(testEvent2.HasHandlerConnected());
// testEvent1 should have both handlers
testEvent1.Signal();
EXPECT_EQ(2, handlerInvokeCount);
// testEvent2 should have neither of the handlers
testEvent2.Signal();
EXPECT_EQ(2, handlerInvokeCount);
}
TEST_F(EventTests, HandlerMoveAssignment_ProperlyDisconnectsFromOldEvent)
{
AZ::Event<> testEvent1;
@@ -10,6 +10,17 @@
#include <AzCore/Console/IConsole.h>
void OnVsyncIntervalChanged(uint32_t const& interval)
{
AzFramework::WindowNotificationBus::Broadcast(
&AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged, AZ::GetClamp(interval, 0u, 4u));
}
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
// The value of the vsync interval is constrained between 0 and 4
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
AZ_CVAR(uint32_t, vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
namespace AzFramework
{
//////////////////////////////////////////////////////////////////////////
@@ -122,6 +133,16 @@ namespace AzFramework
return m_pimpl->GetDpiScaleFactor();
}
uint32_t NativeWindow::GetDisplayRefreshRate() const
{
return m_pimpl->GetDisplayRefreshRate();
}
uint32_t NativeWindow::GetSyncInterval() const
{
return vsync_interval;
}
/*static*/ bool NativeWindow::GetFullScreenStateOfDefaultWindow()
{
NativeWindowHandle defaultWindowHandle = nullptr;
@@ -240,4 +261,10 @@ namespace AzFramework
return 1.0f;
}
uint32_t NativeWindow::Implementation::GetDisplayRefreshRate() const
{
// Default to 60
return 60;
}
} // namespace AzFramework
@@ -130,6 +130,8 @@ namespace AzFramework
bool CanToggleFullScreenState() const override;
void ToggleFullScreenState() override;
float GetDpiScaleFactor() const override;
uint32_t GetSyncInterval() const override;
uint32_t GetDisplayRefreshRate() const override;
//! Get the full screen state of the default window.
//! \return True if the default window is currently in full screen, false otherwise.
@@ -172,6 +174,7 @@ namespace AzFramework
virtual void SetFullScreenState(bool fullScreenState);
virtual bool CanToggleFullScreenState() const;
virtual float GetDpiScaleFactor() const;
virtual uint32_t GetDisplayRefreshRate() const;
protected:
uint32_t m_width = 0;
@@ -74,6 +74,12 @@ namespace AzFramework
//! to a "standard" value of 96, the default for Windows in a DPI unaware setting. This can
//! be used to scale user interface elements to ensure legibility on high density displays.
virtual float GetDpiScaleFactor() const = 0;
//! Returns the sync interval which tells the drivers the number of v-blanks to synchronize with
virtual uint32_t GetSyncInterval() const = 0;
//! Returns the refresh rate of the main display
virtual uint32_t GetDisplayRefreshRate() const = 0;
};
using WindowRequestBus = AZ::EBus<WindowRequests>;
@@ -101,6 +107,9 @@ namespace AzFramework
//! This is called when vsync interval is changed.
virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); };
//! This is called if the main display's refresh rate changes
virtual void OnRefreshRateChanged([[maybe_unused]] uint32_t refreshRate) {}
};
using WindowNotificationBus = AZ::EBus<WindowNotifications>;
@@ -25,7 +25,7 @@ namespace AzFramework
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
NativeWindowHandle GetWindowHandle() const override;
uint32_t GetDisplayRefreshRate() const override;
private:
ANativeWindow* m_nativeWindow = nullptr;
};
@@ -55,4 +55,9 @@ namespace AzFramework
return reinterpret_cast<NativeWindowHandle>(m_nativeWindow);
}
uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const
{
// Using 60 for now until proper support is added
return 60;
}
} // namespace AzFramework
@@ -23,6 +23,7 @@ namespace AzFramework
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
NativeWindowHandle GetWindowHandle() const override;
uint32_t GetDisplayRefreshRate() const override;
};
NativeWindow::Implementation* NativeWindow::Implementation::Create()
@@ -44,4 +45,9 @@ namespace AzFramework
return nullptr;
}
uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const
{
//Using 60 for now until proper support is added
return 60;
}
} // namespace AzFramework
@@ -34,12 +34,14 @@ namespace AzFramework
bool GetFullScreenState() const override;
void SetFullScreenState(bool fullScreenState) override;
bool CanToggleFullScreenState() const override { return true; }
uint32_t GetDisplayRefreshRate() const override;
private:
static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks);
NSWindow* m_nativeWindow;
NSString* m_windowTitle;
uint32_t m_mainDisplayRefreshRate = 0;
};
NativeWindow::Implementation* NativeWindow::Implementation::Create()
@@ -76,6 +78,17 @@ namespace AzFramework
// Make the window active
[m_nativeWindow makeKeyAndOrderFront:nil];
m_nativeWindow.title = m_windowTitle;
CGDirectDisplayID display = CGMainDisplayID();
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display);
m_mainDisplayRefreshRate = CGDisplayModeGetRefreshRate(currentMode);
// Assume 60hz if 0 is returned.
// This can happen on OSX. In future we can hopefully use maximumFramesPerSecond which wont have this issue
if (m_mainDisplayRefreshRate == 0)
{
m_mainDisplayRefreshRate = 60;
}
}
NativeWindowHandle NativeWindowImpl_Darwin::GetWindowHandle() const
@@ -128,4 +141,9 @@ namespace AzFramework
const NSWindowStyleMask defaultMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
return nativeMask ? nativeMask : defaultMask;
}
uint32_t NativeWindowImpl_Darwin::GetDisplayRefreshRate() const
{
return m_mainDisplayRefreshRate;
}
} // namespace AzFramework
@@ -117,9 +117,11 @@ namespace AzFramework
, m_hasFocus(false)
, m_hasTextEntryStarted(false)
{
static const char* s_keyboardCountEnvironmentVarName = "InputDeviceKeyboardInstanceCount";
s_instanceCount = AZ::Environment::FindVariable<int>(s_keyboardCountEnvironmentVarName);
if (!s_instanceCount)
{
s_instanceCount = AZ::Environment::CreateVariable<int>("InputDeviceKeyboardInstanceCount", 1);
s_instanceCount = AZ::Environment::CreateVariable<int>(s_keyboardCountEnvironmentVarName, 1);
// Register for raw keyboard input
RAWINPUTDEVICE rawInputDevice;
@@ -138,9 +138,11 @@ namespace AzFramework
{
memset(&m_lastClientRect, 0, sizeof(m_lastClientRect));
static const char* s_mouseCountEnvironmentVarName = "InputDeviceMouseInstanceCount";
s_instanceCount = AZ::Environment::FindVariable<int>(s_mouseCountEnvironmentVarName);
if (!s_instanceCount)
{
s_instanceCount = AZ::Environment::CreateVariable<int>("InputDeviceMouseInstanceCount", 1);
s_instanceCount = AZ::Environment::CreateVariable<int>(s_mouseCountEnvironmentVarName, 1);
// Register for raw mouse input
RAWINPUTDEVICE rawInputDevice;
@@ -37,6 +37,7 @@ namespace AzFramework
void SetFullScreenState(bool fullScreenState) override;
bool CanToggleFullScreenState() const override { return true; }
float GetDpiScaleFactor() const override;
uint32_t GetDisplayRefreshRate() const override;
private:
static DWORD ConvertToWin32WindowStyleMask(const WindowStyleMasks& styleMasks);
@@ -56,6 +57,7 @@ namespace AzFramework
using GetDpiForWindowType = UINT(HWND hwnd);
GetDpiForWindowType* m_getDpiFunction = nullptr;
uint32_t m_mainDisplayRefreshRate = 0;
};
const wchar_t* NativeWindowImpl_Win32::s_defaultClassName = L"O3DEWin32Class";
@@ -144,6 +146,10 @@ namespace AzFramework
{
SetWindowLongPtr(m_win32Handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
}
DEVMODE DisplayConfig;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig);
m_mainDisplayRefreshRate = DisplayConfig.dmDisplayFrequency;
}
void NativeWindowImpl_Win32::Activate()
@@ -263,6 +269,15 @@ namespace AzFramework
WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnDpiScaleFactorChanged, newScaleFactor);
break;
}
case WM_WINDOWPOSCHANGED:
{
DEVMODE DisplayConfig;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig);
uint32_t refreshRate = DisplayConfig.dmDisplayFrequency;
WindowNotificationBus::Event(
nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnRefreshRateChanged, refreshRate);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
@@ -367,6 +382,11 @@ namespace AzFramework
return aznumeric_cast<float>(dotsPerInch) / aznumeric_cast<float>(defaultDotsPerInch);
}
uint32_t NativeWindowImpl_Win32::GetDisplayRefreshRate() const
{
return m_mainDisplayRefreshRate;
}
void NativeWindowImpl_Win32::EnterBorderlessWindowFullScreen()
{
if (m_isInBorderlessWindowFullScreenState)
@@ -27,9 +27,11 @@ namespace AzFramework
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
NativeWindowHandle GetWindowHandle() const override;
uint32_t GetDisplayRefreshRate() const override;
private:
UIWindow* m_nativeWindow;
uint32_t m_mainDisplayRefreshRate = 0;
};
NativeWindow::Implementation* NativeWindow::Implementation::Create()
@@ -56,6 +58,7 @@ namespace AzFramework
m_width = geometry.m_width;
m_height = geometry.m_height;
m_mainDisplayRefreshRate = [[UIScreen mainScreen] maximumFramesPerSecond];
}
NativeWindowHandle NativeWindowImpl_Ios::GetWindowHandle() const
@@ -63,5 +66,9 @@ namespace AzFramework
return m_nativeWindow;
}
uint32_t NativeWindowImpl_Ios::GetDisplayRefreshRate() const
{
return m_mainDisplayRefreshRate;
}
} // namespace AzFramework
@@ -8,10 +8,13 @@
#include <AzQtComponents/Components/Widgets/TreeView.h>
#include <QDrag>
#include <QEvent>
#include <QSettings>
#include <QPainter>
#include <AzCore/std/algorithm.h>
#include <AzQtComponents/Components/Style.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/ConfigHelpers.h>
@@ -252,5 +255,109 @@ namespace AzQtComponents
return qobject_cast<QTreeView*>(widget) && !qobject_cast<TableView*>(widget);
}
StyledTreeView::StyledTreeView(QWidget* parent)
: QTreeView(parent)
{
}
void StyledTreeView::startDrag(Qt::DropActions supportedActions)
{
if (!selectionModel()->selectedIndexes().empty())
{
StartCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
}
}
void StyledTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
{
StartCustomDragInternal(this, indexList, supportedActions);
}
void StyledTreeView::StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions)
{
QMimeData* mimeData = itemView->model()->mimeData(indexList);
if (mimeData)
{
QDrag* drag = new QDrag(itemView);
drag->setPixmap(QPixmap::fromImage(CreateDragImage(itemView, indexList)));
drag->setMimeData(mimeData);
Qt::DropAction defDropAction = Qt::IgnoreAction;
if (itemView->defaultDropAction() != Qt::IgnoreAction && (supportedActions & itemView->defaultDropAction()))
{
defDropAction = itemView->defaultDropAction();
}
else if (supportedActions & Qt::CopyAction && itemView->dragDropMode() != QAbstractItemView::InternalMove)
{
defDropAction = Qt::CopyAction;
}
drag->exec(supportedActions, defDropAction);
}
}
QImage StyledTreeView::CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList)
{
// Generate a drag image of the item icon and text, normally done internally, and inaccessible
QRect rect(0, 0, 0, 0);
for (const auto& index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = itemView->visualRect(index);
rect.setHeight(rect.height() + itemRect.height());
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
}
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
QPainter dragPainter(&dragImage);
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
dragPainter.setOpacity(0.35f);
dragPainter.fillRect(rect, QColor("#222222"));
dragPainter.setOpacity(1.0f);
int imageY = 0;
for (const auto& index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = itemView->visualRect(index);
dragPainter.drawPixmap(QPoint(0, imageY),
itemView->model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
dragPainter.setPen(
itemView->model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
dragPainter.setFont(
itemView->font());
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
itemView->model()->data(index, Qt::DisplayRole).value<QString>());
imageY += itemRect.height();
}
dragPainter.end();
return dragImage;
}
StyledTreeWidget::StyledTreeWidget(QWidget* parent)
: QTreeWidget(parent)
{
}
void StyledTreeWidget::startDrag(Qt::DropActions supportedActions)
{
if (!selectionModel()->selectedIndexes().empty())
{
StyledTreeView::StartCustomDragInternal(this, selectionModel()->selectedIndexes(), supportedActions);
}
}
} // namespace AzQtComponents
#include <Components/Widgets/moc_TreeView.cpp>
@@ -9,8 +9,11 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/SystemAllocator.h>
#include <AzQtComponents/AzQtComponentsAPI.h>
#include <AzQtComponents/Components/Widgets/TableView.h>
#include <QTreeWidget>
#endif
namespace AzQtComponents
@@ -68,4 +71,46 @@ namespace AzQtComponents
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};
//! For most of the custom QTreeView styling, we override in AzQtComponents::Style class,
//! but there are some cases (e.g. drag/drop) that can only be overriden by an actual
//! subclass of the QTreeView
class AZ_QT_COMPONENTS_API StyledTreeView
: public QTreeView
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(StyledTreeView, AZ::SystemAllocator, 0);
explicit StyledTreeView(QWidget* parent = nullptr);
//! NOTE: QTreeWidget derives from QTreeView, but because we need a custom dervied class
//! of QTreeView, then we can't inherit our custom drag methods in our custom derived
//! class of QTreeWidget, so these functions are made static so they can be shared
static void StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions);
static QImage CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList);
protected:
void startDrag(Qt::DropActions supportedActions) override;
virtual void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
};
//! For most of the custom QTreeWidget styling, we override in AzQtComponents::Style class,
//! but there are some cases (e.g. drag/drop) that can only be overriden by an actual
//! subclass of the QTreeWidget.
class AZ_QT_COMPONENTS_API StyledTreeWidget
: public QTreeWidget
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(StyledTreeWidget, AZ::SystemAllocator, 0);
explicit StyledTreeWidget(QWidget* parent = nullptr);
protected:
void startDrag(Qt::DropActions supportedActions) override;
};
} // namespace AzQtComponents
@@ -27,7 +27,7 @@
namespace AzToolsFramework
{
EntityOutlinerTreeView::EntityOutlinerTreeView(QWidget* pParent)
: QTreeView(pParent)
: AzQtComponents::StyledTreeView(pParent)
, m_queuedMouseEvent(nullptr)
, m_draggingUnselectedItem(false)
{
@@ -144,16 +144,12 @@ namespace AzToolsFramework
if (!selectionModel()->isSelected(index))
{
startCustomDrag({ index }, supportedActions);
StartCustomDrag({ index }, supportedActions);
return;
}
}
if (!selectionModel()->selectedIndexes().empty())
{
startCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
return;
}
StyledTreeView::startDrag(supportedActions);
}
void EntityOutlinerTreeView::dragMoveEvent(QDragMoveEvent* event)
@@ -243,14 +239,14 @@ namespace AzToolsFramework
QTreeView::mousePressEvent(&mousePressedEvent);
}
void EntityOutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
void EntityOutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
{
m_draggingUnselectedItem = true;
//sort by container entity depth and order in hierarchy for proper drag image and drop order
QModelIndexList indexListSorted = indexList;
AZStd::unordered_map<AZ::EntityId, AZStd::list<AZ::u64>> locations;
for (auto index : indexListSorted)
for (const auto& index : indexListSorted)
{
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]);
@@ -263,76 +259,8 @@ namespace AzToolsFramework
return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end());
});
//get the data for the unselected item(s)
QMimeData* mimeData = model()->mimeData(indexListSorted);
if (mimeData)
{
//initiate drag/drop for the item
QDrag* drag = new QDrag(this);
drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted)));
drag->setMimeData(mimeData);
Qt::DropAction defDropAction = Qt::IgnoreAction;
if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction()))
{
defDropAction = defaultDropAction();
}
else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
{
defDropAction = Qt::CopyAction;
}
drag->exec(supportedActions, defDropAction);
}
StyledTreeView::StartCustomDrag(indexListSorted, supportedActions);
}
QImage EntityOutlinerTreeView::createDragImage(const QModelIndexList& indexList)
{
//generate a drag image of the item icon and text, normally done internally, and inaccessible
QRect rect(0, 0, 0, 0);
for (auto index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = visualRect(index);
rect.setHeight(rect.height() + itemRect.height());
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
}
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
QPainter dragPainter(&dragImage);
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
dragPainter.setOpacity(0.35f);
dragPainter.fillRect(rect, QColor("#222222"));
dragPainter.setOpacity(1.0f);
int imageY = 0;
for (auto index : indexList)
{
if (index.column() != 0)
{
continue;
}
QRect itemRect = visualRect(index);
dragPainter.drawPixmap(QPoint(0, imageY),
model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
dragPainter.setPen(
model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
dragPainter.setFont(
font());
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
model()->data(index, Qt::DisplayRole).value<QString>());
imageY += itemRect.height();
}
dragPainter.end();
return dragImage;
}
}
#include <UI/Outliner/moc_EntityOutlinerTreeView.cpp>
@@ -14,7 +14,8 @@
#include <QBasicTimer>
#include <QEvent>
#include <QTreeView>
#include <AzQtComponents/Components/Widgets/TreeView.h>
#endif
#pragma once
@@ -33,7 +34,7 @@ namespace AzToolsFramework
//! allow for dragging and dropping of entities from the outliner into the property editor
//! of other entities. If the selection updates instantly, this would never be possible.
class EntityOutlinerTreeView
: public QTreeView
: public AzQtComponents::StyledTreeView
{
Q_OBJECT;
public:
@@ -68,9 +69,7 @@ namespace AzToolsFramework
void processQueuedMousePressedEvent(QMouseEvent* event);
void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
QImage createDragImage(const QModelIndexList& indexList);
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
void PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const;
@@ -7,6 +7,7 @@
*/
#include <unistd.h>
#include <AzCore/std/string/string.h>
namespace GridMate
{
@@ -7,6 +7,7 @@
*/
#include <unistd.h>
#include <AzCore/std/string/string.h>
namespace GridMate
{
@@ -10,6 +10,7 @@
#include <O3DEApplication_Mac.h>
#include <../Common/Apple/Launcher_Apple.h>
#include <../Common/UnixLike/Launcher_UnixLike.h>
#include <AzCore/Math/Vector2.h>
#if AZ_TESTS_ENABLED
@@ -9,6 +9,7 @@
#include <CryCommon/CryLibrary.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Memory/SystemAllocator.h>
int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow)
{
+15
View File
@@ -226,6 +226,21 @@ typedef uint64 __uint64;
#define _PTRDIFF_T_DEFINED 1
typedef union _LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
};
struct
{
DWORD LowPart;
LONG HighPart;
} u;
long long QuadPart;
} LARGE_INTEGER;
#define _A_RDONLY (0x01) /* Read only file */
#define _A_HIDDEN (0x02) /* Hidden file */
#define _A_SUBDIR (0x10) /* Subdirectory */
+2 -2
View File
@@ -72,7 +72,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b
static const int max_len = 4096;
static char gs_command_str[4096];
static CryLockT<CRYLOCK_RECURSIVE> lock;
static AZStd::recursive_mutex lock;
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
@@ -80,7 +80,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
CryAutoLock< CryLockT<CRYLOCK_RECURSIVE> > lk (lock);
AZStd::scoped_lock lk(lock);
snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'",
szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage);
int ret = system(gs_command_str);
-2
View File
@@ -70,8 +70,6 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b
static const int max_len = 4096;
static char gs_command_str[4096];
static CryLockT<CRYLOCK_RECURSIVE> lock;
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
size_t file_len = strlen(szFile);
+1 -1
View File
@@ -49,7 +49,7 @@
*/
#include <stdio.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Module/Environment.h>
#define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment"
-186
View File
@@ -1,186 +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
*
*/
// Description : Public include file for the multi-threading API.
#pragma once
// Include basic multithread primitives.
#include "MultiThread.h"
#include "BitFiddling.h"
#include <AzCore/std/string/string.h>
//////////////////////////////////////////////////////////////////////////
// Lock types:
//
// CRYLOCK_FAST
// A fast potentially (non-recursive) mutex.
// CRYLOCK_RECURSIVE
// A recursive mutex.
//////////////////////////////////////////////////////////////////////////
enum CryLockType
{
CRYLOCK_FAST = 1,
CRYLOCK_RECURSIVE = 2,
};
#define CRYLOCK_HAVE_FASTLOCK 1
/////////////////////////////////////////////////////////////////////////////
//
// Primitive locks and conditions.
//
// Primitive locks are represented by instance of class CryLockT<Type>
//
//
template<CryLockType Type>
class CryLockT
{
/* Unsupported lock type. */
};
//////////////////////////////////////////////////////////////////////////
// Typedefs.
//////////////////////////////////////////////////////////////////////////
typedef CryLockT<CRYLOCK_RECURSIVE> CryCriticalSection;
typedef CryLockT<CRYLOCK_FAST> CryCriticalSectionNonRecursive;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// CryAutoCriticalSection implements a helper class to automatically
// lock critical section in constructor and release on destructor.
//
//////////////////////////////////////////////////////////////////////////
template<class LockClass>
class CryAutoLock
{
private:
LockClass* m_pLock;
CryAutoLock();
CryAutoLock(const CryAutoLock<LockClass>&);
CryAutoLock<LockClass>& operator = (const CryAutoLock<LockClass>&);
public:
CryAutoLock(LockClass& Lock)
: m_pLock(&Lock) { m_pLock->Lock(); }
CryAutoLock(const LockClass& Lock)
: m_pLock(const_cast<LockClass*>(&Lock)) { m_pLock->Lock(); }
~CryAutoLock() { m_pLock->Unlock(); }
};
//////////////////////////////////////////////////////////////////////////
//
// Auto critical section is the most commonly used type of auto lock.
//
//////////////////////////////////////////////////////////////////////////
typedef CryAutoLock<CryCriticalSection> CryAutoCriticalSection;
/////////////////////////////////////////////////////////////////////////////
//
// Threads.
// Base class for runnable objects.
//
// A runnable is an object with a Run() and a Cancel() method. The Run()
// method should perform the runnable's job. The Cancel() method may be
// called by another thread requesting early termination of the Run() method.
// The runnable may ignore the Cancel() call, the default implementation of
// Cancel() does nothing.
class CryRunnable
{
public:
virtual ~CryRunnable() { }
virtual void Run() = 0;
virtual void Cancel() { }
};
// Class holding information about a thread.
//
// A reference to the thread information can be obtained by calling GetInfo()
// on the CrySimpleThread (or derived class) instance.
//
// NOTE:
// If the code is compiled with NO_THREADINFO defined, then the GetInfo()
// method will return a reference to a static dummy instance of this
// structure. It is currently undecided if NO_THREADINFO will be defined for
// release builds!
struct CryThreadInfo
{
// The symbolic name of the thread.
//
// You may set this name directly or through the SetName() method of
// CrySimpleThread (or derived class).
AZStd::string m_Name;
// A thread identification number.
// The number is unique but architecture specific. Do not assume anything
// about that number except for being unique.
//
// This field is filled when the thread is started (i.e. before the Run()
// method or thread routine is called). It is advised that you do not
// change this number manually.
uint32 m_ID;
};
// Simple thread class.
//
// CrySimpleThread is a simple wrapper around a system thread providing
// nothing but system-level functionality of a thread. There are two typical
// ways to use a simple thread:
//
// 1. Derive from the CrySimpleThread class and provide an implementation of
// the Run() (and optionally Cancel()) methods.
// 2. Specify a runnable object when the thread is started. The default
// runnable type is CryRunnable.
//
// The Runnable class specfied as the template argument must provide Run()
// and Cancel() methods compatible with the following signatures:
//
// void Runnable::Run();
// void Runnable::Cancel();
//
// If the Runnable does not support cancellation, then the Cancel() method
// should do nothing.
//
// The same instance of CrySimpleThread may be used for multiple thread
// executions /in sequence/, i.e. it is valid to re-start the thread by
// calling Start() after the thread has been joined by calling WaitForThread().
template<class Runnable = CryRunnable>
class CrySimpleThread;
///////////////////////////////////////////////////////////////////////////////
// Include architecture specific code.
#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
#include <CryThread_pthreads.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(WIN64)
#include <CryThread_windows.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThread_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
// Put other platform specific includes here!
#include <CryThread_dummy.h>
#endif
#if !defined _CRYTHREAD_CONDLOCK_GLITCH
typedef CryLockT<CRYLOCK_RECURSIVE> CryMutex;
#endif // !_CRYTHREAD_CONDLOCK_GLITCH
// Include all multithreading containers.
#include "MultiThread_Containers.h"
-29
View File
@@ -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
*
*/
#pragma once
#include <CryThread.h>
// Include architecture specific code.
#if defined(LINUX) || defined(APPLE)
#include <CryThreadImpl_pthreads.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(WIN64)
#include <CryThreadImpl_windows.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThreadImpl_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
// Put other platform specific includes here!
#endif
@@ -1,104 +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 CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
#pragma once
#include "CryThread_pthreads.h"
AZ_THREAD_LOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL;
//////////////////////////////////////////////////////////////////////////
// CryEvent(Timed) implementation
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Reset()
{
m_lockNotify.Lock();
m_flag = false;
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Set()
{
m_lockNotify.Lock();
m_flag = true;
m_cond.Notify();
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Wait()
{
m_lockNotify.Lock();
if (!m_flag)
{
m_cond.Wait(m_lockNotify);
}
m_flag = false;
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
bool CryEventTimed::Wait(const uint32 timeoutMillis)
{
bool bResult = true;
m_lockNotify.Lock();
if (!m_flag)
{
bResult = m_cond.TimedWait(m_lockNotify, timeoutMillis);
}
m_flag = false;
m_lockNotify.Unlock();
return bResult;
}
///////////////////////////////////////////////////////////////////////////////
// CryCriticalSection implementation
///////////////////////////////////////////////////////////////////////////////
typedef CryLockT<CRYLOCK_RECURSIVE> TCritSecType;
void CryDeleteCriticalSection(void* cs)
{
delete ((TCritSecType*)cs);
}
void CryEnterCriticalSection(void* cs)
{
((TCritSecType*)cs)->Lock();
}
bool CryTryCriticalSection(void* cs)
{
return false;
}
void CryLeaveCriticalSection(void* cs)
{
((TCritSecType*)cs)->Unlock();
}
void CryCreateCriticalSectionInplace(void* pCS)
{
new (pCS) TCritSecType;
}
void CryDeleteCriticalSectionInplace(void*)
{
}
void* CryCreateCriticalSection()
{
return (void*) new TCritSecType;
}
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
@@ -1,345 +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/PlatformIncl.h>
#include <AzCore/std/parallel/semaphore.h> // for CreateSemaphore
struct SThreadNameDesc
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
AZ_THREAD_LOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL;
//////////////////////////////////////////////////////////////////////////
CryEvent::CryEvent()
{
m_handle = (void*)CreateEvent(NULL, FALSE, FALSE, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryEvent::~CryEvent()
{
CloseHandle(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Reset()
{
ResetEvent(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Set()
{
SetEvent(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Wait() const
{
WaitForSingleObject(m_handle, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
bool CryEvent::Wait(const uint32 timeoutMillis) const
{
if (WaitForSingleObject(m_handle, timeoutMillis) == WAIT_TIMEOUT)
{
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// CryLock_WinMutex
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CryLock_WinMutex::CryLock_WinMutex()
: m_hdl(CreateMutex(NULL, FALSE, NULL)) {}
CryLock_WinMutex::~CryLock_WinMutex()
{
CloseHandle(m_hdl);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_WinMutex::Lock()
{
WaitForSingleObject(m_hdl, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_WinMutex::Unlock()
{
ReleaseMutex(m_hdl);
}
//////////////////////////////////////////////////////////////////////////
bool CryLock_WinMutex::TryLock()
{
return WaitForSingleObject(m_hdl, 0) != WAIT_TIMEOUT;
}
//////////////////////////////////////////////////////////////////////////
// CryLock_CritSection
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CryLock_CritSection::CryLock_CritSection()
{
InitializeCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
CryLock_CritSection::~CryLock_CritSection()
{
DeleteCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_CritSection::Lock()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_CritSection::Unlock()
{
LeaveCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
bool CryLock_CritSection::TryLock()
{
return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE;
}
//////////////////////////////////////////////////////////////////////////
// most of this is taken from http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
//////////////////////////////////////////////////////////////////////////
CryConditionVariable::CryConditionVariable()
{
m_waitersCount = 0;
m_wasBroadcast = 0;
m_sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
InitializeCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryConditionVariable::~CryConditionVariable()
{
CloseHandle(m_sema);
DeleteCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
CloseHandle(m_waitersDone);
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::Wait(LockType& lock)
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount++;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
SignalObjectAndWait(lock._get_win32_handle(), m_sema, INFINITE, FALSE);
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount--;
bool lastWaiter = m_wasBroadcast && m_waitersCount == 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (lastWaiter)
{
SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE);
}
else
{
WaitForSingleObject(lock._get_win32_handle(), INFINITE);
}
}
//////////////////////////////////////////////////////////////////////////
bool CryConditionVariable::TimedWait(LockType& lock, uint32 millis)
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount++;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool ok = true;
if (WAIT_TIMEOUT == SignalObjectAndWait(lock._get_win32_handle(), m_sema, millis, FALSE))
{
ok = false;
}
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount--;
bool lastWaiter = m_wasBroadcast && m_waitersCount == 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (lastWaiter)
{
SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE);
}
else
{
WaitForSingleObject(lock._get_win32_handle(), INFINITE);
}
return ok;
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::NotifySingle()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool haveWaiters = m_waitersCount > 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (haveWaiters)
{
ReleaseSemaphore(m_sema, 1, 0);
}
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::Notify()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool haveWaiters = false;
if (m_waitersCount > 0)
{
m_wasBroadcast = 1;
haveWaiters = true;
}
if (haveWaiters)
{
ReleaseSemaphore(m_sema, m_waitersCount, 0);
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
WaitForSingleObject(m_waitersDone, INFINITE);
m_wasBroadcast = 0;
}
else
{
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
}
}
//////////////////////////////////////////////////////////////////////////
CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount)
{
m_Semaphore = (void*)CreateSemaphore(NULL, nInitialCount, nMaximumCount, NULL);
}
//////////////////////////////////////////////////////////////////////////
CrySemaphore::~CrySemaphore()
{
CloseHandle((HANDLE)m_Semaphore);
}
//////////////////////////////////////////////////////////////////////////
void CrySemaphore::Acquire()
{
WaitForSingleObject((HANDLE)m_Semaphore, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
void CrySemaphore::Release()
{
ReleaseSemaphore((HANDLE)m_Semaphore, 1, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount)
: m_Semaphore(nMaximumCount)
, m_nCounter(nInitialCount)
{
}
//////////////////////////////////////////////////////////////////////////
CryFastSemaphore::~CryFastSemaphore()
{
}
//////////////////////////////////////////////////////////////////////////
void CryFastSemaphore::Acquire()
{
int nCount = ~0;
do
{
nCount = *const_cast<volatile int*>(&m_nCounter);
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nCounter), nCount - 1, nCount) != nCount);
// if the count would have been 0 or below, go to kernel semaphore
if ((nCount - 1) < 0)
{
m_Semaphore.Acquire();
}
}
//////////////////////////////////////////////////////////////////////////
void CryFastSemaphore::Release()
{
int nCount = ~0;
do
{
nCount = *const_cast<volatile int*>(&m_nCounter);
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nCounter), nCount + 1, nCount) != nCount);
// wake up kernel semaphore if we have waiter
if (nCount < 0)
{
m_Semaphore.Release();
}
}
//////////////////////////////////////////////////////////////////////////
CrySimpleThreadSelf::CrySimpleThreadSelf()
: m_thread(NULL)
, m_threadId(0)
{
}
//////////////////////////////////////////////////////////////////////////
void CrySimpleThreadSelf::WaitForThread()
{
assert(m_thread);
PREFAST_ASSUME(m_thread);
if (GetCurrentThreadId() != m_threadId)
{
WaitForSingleObject((HANDLE)m_thread, INFINITE);
}
}
CrySimpleThreadSelf::~CrySimpleThreadSelf()
{
if (m_thread)
{
CloseHandle(m_thread);
}
}
void CrySimpleThreadSelf::StartThread(unsigned (__stdcall * func)(void*), void* argList)
{
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThreadImpl_windows_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
m_thread = (void*)_beginthreadex(NULL, 0, func, argList, CREATE_SUSPENDED, &m_threadId);
#endif
assert(m_thread);
PREFAST_ASSUME(m_thread);
ResumeThread((HANDLE)m_thread);
}
-152
View File
@@ -1,152 +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 CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
#pragma once
#include <AzCore/base.h>
//////////////////////////////////////////////////////////////////////////
CryEvent::CryEvent() {}
CryEvent::~CryEvent() {}
void CryEvent::Reset() {}
void CryEvent::Set() {}
void CryEvent::Wait() const {}
bool CryEvent::Wait(const uint32 timeoutMillis) const {}
typedef CryEvent CryEventTimed;
//////////////////////////////////////////////////////////////////////////
class _DummyLock
{
public:
_DummyLock();
void Lock();
bool TryLock();
void Unlock();
#if defined(AZ_DEBUG_BUILD)
bool IsLocked();
#endif
};
template<>
class CryLock<CRYLOCK_FAST>
: public _DummyLock
{
CryLock(const CryLock<CRYLOCK_FAST>&);
void operator = (const CryLock<CRYLOCK_FAST>&);
public:
CryLock();
};
template<>
class CryLock<CRYLOCK_RECURSIVE>
: public _DummyLock
{
CryLock(const CryLock<CRYLOCK_RECURSIVE>&);
void operator = (const CryLock<CRYLOCK_RECURSIVE>&);
public:
CryLock();
};
template<>
class CryCondLock<CRYLOCK_FAST>
: public CryLock<CRYLOCK_FAST>
{
};
template<>
class CryCondLock<CRYLOCK_RECURSIVE>
: public CryLock<CRYLOCK_FAST>
{
};
template<>
class CryCond< CryLock<CRYLOCK_FAST> >
{
typedef CryLock<CRYLOCK_FAST> LockT;
CryCond(const CryCond<LockT>&);
void operator = (const CryCond<LockT>&);
public:
CryCond();
void Notify();
void NotifySingle();
void Wait(LockT&);
bool TimedWait(LockT &, uint32);
};
template<>
class CryCond< CryLock<CRYLOCK_RECURSIVE> >
{
typedef CryLock<CRYLOCK_RECURSIVE> LockT;
CryCond(const CryCond<LockT>&);
void operator = (const CryCond<LockT>&);
public:
CryCond();
void Notify();
void NotifySingle();
void Wait(LockT&);
bool TimedWait(LockT &, uint32);
};
class _DummyRWLock
{
public:
_DummyRWLock() { }
void RLock();
bool TryRLock();
void WLock();
bool TryWLock();
void Lock() { WLock(); }
bool TryLock() { return TryWLock(); }
void Unlock();
};
template<class Runnable>
class CrySimpleThread
: public CryRunnable
{
public:
typedef void (* ThreadFunction)(void*);
CrySimpleThread();
virtual ~CrySimpleThread();
#if !defined(NO_THREADINFO)
CryThreadInfo& GetInfo();
#endif
const char* GetName();
void SetName(const char*);
virtual void Run();
virtual void Cancel();
virtual void Start(Runnable&, unsigned = 0, const char* = NULL);
virtual void Start(unsigned = 0, const char* = NULL);
void StartFunction(ThreadFunction, void* = NULL, unsigned = 0);
void Exit();
void Join();
unsigned SetCpuMask(unsigned);
unsigned GetCpuMask();
void Stop();
bool IsStarted() const;
bool IsRunning() const;
};
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
File diff suppressed because it is too large Load Diff
-387
View File
@@ -1,387 +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 <process.h>
#if defined(AZ_RESTRICTED_PLATFORM)
#undef AZ_RESTRICTED_SECTION
#define CRYTHREAD_WINDOWS_H_SECTION_1 1
#define CRYTHREAD_WINDOWS_H_SECTION_2 2
#endif
//////////////////////////////////////////////////////////////////////////
// CryEvent represent a synchronization event
//////////////////////////////////////////////////////////////////////////
class CryEvent
{
public:
CryEvent();
~CryEvent();
// Reset the event to the unsignalled state.
void Reset();
// Set the event to the signalled state.
void Set();
// Access a HANDLE to wait on.
void* GetHandle() const { return m_handle; };
// Wait indefinitely for the object to become signalled.
void Wait() const;
// Wait, with a time limit, for the object to become signalled.
bool Wait(const uint32 timeoutMillis) const;
private:
CryEvent(const CryEvent&);
CryEvent& operator = (const CryEvent&);
private:
void* m_handle;
};
typedef CryEvent CryEventTimed;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// from winnt.h
struct CRY_CRITICAL_SECTION
{
void* DebugInfo;
long LockCount;
long RecursionCount;
threadID OwningThread;
void* LockSemaphore;
unsigned long* SpinCount; // force size on 64-bit systems when packed
};
//////////////////////////////////////////////////////////////////////////
// kernel mutex - don't use... use CryMutex instead
class CryLock_WinMutex
{
public:
CryLock_WinMutex();
~CryLock_WinMutex();
void Lock();
void Unlock();
bool TryLock();
void* _get_win32_handle() { return m_hdl; }
private:
CryLock_WinMutex(const CryLock_WinMutex&);
CryLock_WinMutex& operator = (const CryLock_WinMutex&);
private:
void* m_hdl;
};
// critical section... don't use... use CryCriticalSection instead
class CryLock_CritSection
{
public:
CryLock_CritSection();
~CryLock_CritSection();
void Lock();
void Unlock();
bool TryLock();
bool IsLocked()
{
return m_cs.RecursionCount > 0 && m_cs.OwningThread == CryGetCurrentThreadId();
}
private:
CryLock_CritSection(const CryLock_CritSection&);
CryLock_CritSection& operator = (const CryLock_CritSection&);
private:
CRY_CRITICAL_SECTION m_cs;
};
template <>
class CryLockT<CRYLOCK_RECURSIVE>
: public CryLock_CritSection
{
};
template <>
class CryLockT<CRYLOCK_FAST>
: public CryLock_CritSection
{
};
class CryMutex
: public CryLock_WinMutex
{
};
#define _CRYTHREAD_CONDLOCK_GLITCH 1
//////////////////////////////////////////////////////////////////////////
class CryConditionVariable
{
public:
typedef CryMutex LockType;
CryConditionVariable();
~CryConditionVariable();
void Wait(LockType& lock);
bool TimedWait(LockType& lock, uint32 millis);
void NotifySingle();
void Notify();
private:
CryConditionVariable(const CryConditionVariable&);
CryConditionVariable& operator = (const CryConditionVariable&);
private:
int m_waitersCount;
CRY_CRITICAL_SECTION m_waitersCountLock;
void* m_sema;
void* m_waitersDone;
size_t m_wasBroadcast;
};
//////////////////////////////////////////////////////////////////////////
// Platform independet wrapper for a counting semaphore
class CrySemaphore
{
public:
CrySemaphore(int nMaximumCount, int nInitialCount = 0);
~CrySemaphore();
void Acquire();
void Release();
private:
void* m_Semaphore;
};
//////////////////////////////////////////////////////////////////////////
// Platform independet wrapper for a counting semaphore
// except that this version uses C-A-S only until a blocking call is needed
// -> No kernel call if there are object in the semaphore
class CryFastSemaphore
{
public:
CryFastSemaphore(int nMaximumCount, int nInitialCount = 0);
~CryFastSemaphore();
void Acquire();
void Release();
private:
CrySemaphore m_Semaphore;
volatile int32 m_nCounter;
};
//////////////////////////////////////////////////////////////////////////
class CrySimpleThreadSelf
{
public:
CrySimpleThreadSelf();
void WaitForThread();
virtual ~CrySimpleThreadSelf();
protected:
void StartThread(unsigned (__stdcall * func)(void*), void* argList);
static AZ_THREAD_LOCAL CrySimpleThreadSelf* m_Self;
private:
CrySimpleThreadSelf(const CrySimpleThreadSelf&);
CrySimpleThreadSelf& operator = (const CrySimpleThreadSelf&);
protected:
void* m_thread;
uint32 m_threadId;
};
template<class Runnable>
class CrySimpleThread
: public CryRunnable
, public CrySimpleThreadSelf
{
public:
typedef void (* ThreadFunction)(void*);
typedef CryRunnable RunnableT;
void SetName(const char* Name)
{
m_name = Name;
}
const char* GetName() { return m_name; }
const volatile bool& GetStartedState() const { return m_bIsStarted; }
private:
Runnable* m_Runnable;
struct
{
ThreadFunction m_ThreadFunction;
void* m_ThreadParameter;
} m_ThreadFunction;
volatile bool m_bIsStarted;
volatile bool m_bIsRunning;
volatile bool m_bCreatedThread;
AZStd::string m_name;
protected:
virtual void Terminate()
{
// This method must be empty.
// Derived classes overriding Terminate() are not required to call this
// method.
}
private:
static unsigned __stdcall RunRunnable(void* thisPtr)
{
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_1
#include AZ_RESTRICTED_FILE(CryThread_windows_h)
#endif
CrySimpleThread<Runnable>* const self = (CrySimpleThread<Runnable>*)thisPtr;
self->m_bIsStarted = true;
self->m_bIsRunning = true;
self->m_Runnable->Run();
self->m_bIsRunning = false;
self->m_bCreatedThread = false;
self->Terminate();
return 0;
}
static unsigned __stdcall RunThis(void* thisPtr)
{
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_2
#include AZ_RESTRICTED_FILE(CryThread_windows_h)
#endif
CrySimpleThread<Runnable>* const self = (CrySimpleThread<Runnable>*)thisPtr;
self->m_bIsStarted = true;
self->m_bIsRunning = true;
self->Run();
self->m_bIsRunning = false;
self->m_bCreatedThread = false;
self->Terminate();
return 0;
}
CrySimpleThread(const CrySimpleThread<Runnable>&);
void operator = (const CrySimpleThread<Runnable>&);
public:
CrySimpleThread()
: m_bIsStarted(false)
, m_bIsRunning(false)
, m_bCreatedThread(false)
{
m_thread = NULL;
m_Runnable = NULL;
}
void* GetHandle() { return m_thread; }
virtual ~CrySimpleThread()
{
if (IsStarted())
{
if (gEnv && gEnv->pLog)
{
gEnv->pLog->LogError("Runaway thread %p '%s'", m_thread, m_name.c_str());
}
}
if (m_bCreatedThread)
{
Cancel();
WaitForThread();
}
}
virtual void Run()
{
// This Run() implementation supports the void StartFunction() method.
// However, code using this class (or derived classes) should eventually
// be refactored to use one of the other Start() methods. This code will
// be removed some day and the default implementation of Run() will be
// empty.
if (m_ThreadFunction.m_ThreadFunction != NULL)
{
m_ThreadFunction.m_ThreadFunction(m_ThreadFunction.m_ThreadParameter);
}
}
// Cancel the running thread.
//
// If the thread class is implemented as a derived class of CrySimpleThread,
// then the derived class should provide an appropriate implementation for
// this method. Calling the base class implementation is _not_ required.
//
// If the thread was started by specifying a Runnable (template argument),
// then the Cancel() call is passed on to the specified runnable.
//
// If the thread was started using the StartFunction() method, then the
// caller must find other means to inform the thread about the cancellation
// request.
virtual void Cancel()
{
if (IsStarted() && m_Runnable != NULL)
{
m_Runnable->Cancel();
}
}
virtual void Start(Runnable& runnable, [[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0)
{
if (m_bCreatedThread)
{
// Don't start thread more than once!
return;
}
m_Runnable = &runnable;
m_bCreatedThread = true;
StartThread(RunRunnable, this);
}
virtual void Start([[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0, int32 = 0)
{
if (m_bCreatedThread)
{
// Don't start thread more than once!
return;
}
m_bCreatedThread = true;
StartThread(RunThis, this);
}
void StartFunction(
ThreadFunction threadFunction,
void* threadParameter = NULL
)
{
m_ThreadFunction.m_ThreadFunction = threadFunction;
m_ThreadFunction.m_ThreadParameter = threadParameter;
Start();
}
static CrySimpleThread<Runnable>* Self()
{
return reinterpret_cast<CrySimpleThread<Runnable>*>(m_Self);
}
void Exit()
{
assert(!"implemented");
}
void Stop()
{
m_bIsStarted = false;
}
bool IsStarted() const { return m_bIsStarted; }
bool IsRunning() const { return m_bIsRunning; }
};
+4 -4
View File
@@ -14,7 +14,7 @@
#define CRYINCLUDE_CRYCOMMON_IFUNCTORBASE_H
#pragma once
#include <CryCommon/CryThread.h>
#include <AzCore/std/parallel/atomic.h>
// Base class for functor storage.
// Not intended for direct usage.
@@ -28,19 +28,19 @@ public:
void AddRef()
{
CryInterlockedIncrement(&m_nReferences);
m_nReferences.fetch_add(1, AZStd::memory_order_acq_rel);
}
void Release()
{
if (CryInterlockedDecrement(&m_nReferences) <= 0)
if (m_nReferences.fetch_sub(1, AZStd::memory_order_acq_rel) == 1)
{
delete this;
}
}
protected:
volatile int m_nReferences;
AZStd::atomic_int m_nReferences;
};
// Base Template for specialization.
-7
View File
@@ -6,13 +6,6 @@
*
*/
// In Mac, including ILog without including platform.h first fails because platform.h
// includes CryThread.h which includes CryThread_pthreads.h which uses ILog.
// So plaform.h needs the contents of ILog.h.
// By including platform.h outside of the guard, we give platform.h the right include order
#include <platform.h>
#ifndef CRYINCLUDE_CRYCOMMON_ILOG_H
#define CRYINCLUDE_CRYCOMMON_ILOG_H
#pragma once
-3
View File
@@ -37,7 +37,6 @@ struct IRenderMesh;
#include <IXml.h>
#include <smartptr.h>
#include <AzCore/EBus/EBus.h>
#include <CryThread.h>
#ifdef MAX_SUB_MATERIALS
// This checks that the values are in sync in the different files.
@@ -433,8 +432,6 @@ struct IMaterial
virtual uint32 GetDccMaterialHash() const = 0;
virtual void SetDccMaterialHash(uint32 hash) = 0;
virtual CryCriticalSection& GetSubMaterialResizeLock() = 0;
virtual void UpdateShaderItems() = 0;
// </interfuscator:shuffle>
-7
View File
@@ -6,13 +6,6 @@
*
*/
// In Mac, including ISystem without including platform.h first fails because platform.h
// includes CryThread.h which includes CryThread_pthreads.h which uses ISystem (gEnv).
// So plaform.h needs the contents of ISystem.h.
// By including platform.h outside of the guard, we give platform.h the right include order
#include <platform.h> // Needed for LARGE_INTEGER (for consoles).
#ifndef CRYINCLUDE_CRYCOMMON_ISYSTEM_H
#define CRYINCLUDE_CRYCOMMON_ISYSTEM_H
#pragma once
@@ -413,67 +413,12 @@ inline void SetLastError(DWORD dwErrCode) { errno = dwErrCode; }
//////////////////////////////////////////////////////////////////////////
extern threadID GetCurrentThreadId();
//////////////////////////////////////////////////////////////////////////
extern HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
);
//////////////////////////////////////////////////////////////////////////
extern DWORD Sleep(DWORD dwMilliseconds);
//////////////////////////////////////////////////////////////////////////
extern DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable);
//////////////////////////////////////////////////////////////////////////
extern DWORD WaitForSingleObjectEx(
HANDLE hHandle,
DWORD dwMilliseconds,
BOOL bAlertable);
//////////////////////////////////////////////////////////////////////////
extern DWORD WaitForMultipleObjectsEx(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds,
BOOL bAlertable);
//////////////////////////////////////////////////////////////////////////
extern DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
//////////////////////////////////////////////////////////////////////////
extern BOOL SetEvent(HANDLE hEvent);
//////////////////////////////////////////////////////////////////////////
extern BOOL ResetEvent(HANDLE hEvent);
//////////////////////////////////////////////////////////////////////////
extern HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCSTR lpName
);
//////////////////////////////////////////////////////////////////////////
extern BOOL ReleaseMutex(HANDLE hMutex);
//////////////////////////////////////////////////////////////////////////
typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
//////////////////////////////////////////////////////////////////////////
extern HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
extern BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize); //required for CryOnline
extern DWORD GetCurrentProcessId(void);
+2
View File
@@ -26,4 +26,6 @@
typedef uint64_t threadID;
#define VK_CONTROL 0
#endif // CRYINCLUDE_CRYCOMMON_MACSPECIFIC_H
-285
View File
@@ -1,285 +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(APPLE) || defined(LINUX)
#include <sched.h>
#endif
#include <AzCore/std/parallel/mutex.h>
#include "CryAssert.h"
// Section dictionary
#if defined(AZ_RESTRICTED_PLATFORM)
#define MULTITHREAD_H_SECTION_TRAITS 1
#define MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE 2
#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK 3
#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD 4
#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE 5
#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT1 6
#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT2 7
#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64 8
#endif
#define WRITE_LOCK_VAL (1 << 16)
// Traits
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_TRAITS
#include AZ_RESTRICTED_FILE(MultiThread_h)
#endif
void CrySpinLock(volatile int* pLock, int checkVal, int setVal);
void CryReleaseSpinLock (volatile int*, int);
LONG CryInterlockedIncrement(int volatile* lpAddend);
LONG CryInterlockedDecrement(int volatile* lpAddend);
LONG CryInterlockedOr(LONG volatile* Destination, LONG Value);
LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value);
LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand);
void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand);
void* CryInterlockedExchangePointer (void* volatile* dst, void* exchange);
void* CryCreateCriticalSection();
void CryCreateCriticalSectionInplace(void*);
void CryDeleteCriticalSection(void* cs);
void CryDeleteCriticalSectionInplace(void* cs);
void CryEnterCriticalSection(void* cs);
bool CryTryCriticalSection(void* cs);
void CryLeaveCriticalSection(void* cs);
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE
#include AZ_RESTRICTED_FILE(MultiThread_h)
#endif
ILINE void CrySpinLock(volatile int* pLock, int checkVal, int setVal)
{
#ifdef _CPU_X86
# ifdef __GNUC__
int val;
__asm__ __volatile__ (
"0: mov %[checkVal], %%eax\n"
" lock cmpxchg %[setVal], (%[pLock])\n"
" jnz 0b"
: "=m" (*pLock)
: [pLock] "r" (pLock), "m" (*pLock),
[checkVal] "m" (checkVal),
[setVal] "r" (setVal)
: "eax", "cc", "memory"
);
# else //!__GNUC__
__asm
{
mov edx, setVal
mov ecx, pLock
Spin:
// Trick from Intel Optimizations guide
#ifdef _CPU_SSE
pause
#endif
mov eax, checkVal
lock cmpxchg [ecx], edx
jnz Spin
}
# endif //!__GNUC__
#else // !_CPU_X86
# if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK
#include AZ_RESTRICTED_FILE(MultiThread_h)
# endif
# if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
# undef AZ_RESTRICTED_SECTION_IMPLEMENTED
# elif defined(APPLE) || defined(LINUX)
// register int val;
// __asm__ __volatile__ (
// "0: mov %[checkVal], %%eax\n"
// " lock cmpxchg %[setVal], (%[pLock])\n"
// " jnz 0b"
// : "=m" (*pLock)
// : [pLock] "r" (pLock), "m" (*pLock),
// [checkVal] "m" (checkVal),
// [setVal] "r" (setVal)
// : "eax", "cc", "memory"
// );
//while(CryInterlockedCompareExchange((volatile long*)pLock,setVal,checkVal)!=checkVal) ;
uint loops = 0;
while (__sync_val_compare_and_swap((volatile int32_t*)pLock, (int32_t)checkVal, (int32_t)setVal) != checkVal)
{
# if !defined (ANDROID) && !defined(IOS)
_mm_pause();
# endif
if (!(++loops & 0x7F))
{
usleep(1); // give threads with other prio chance to run
}
else if (!(loops & 0x3F))
{
sched_yield(); // give threads with same prio chance to run
}
}
# else
// NOTE: The code below will fail on 64bit architectures!
while (_InterlockedCompareExchange((volatile LONG*)pLock, setVal, checkVal) != checkVal)
{
_mm_pause();
}
# endif
#endif
}
ILINE void CryReleaseSpinLock(volatile int* pLock, int setVal)
{
*pLock = setVal;
}
//////////////////////////////////////////////////////////////////////////
ILINE void CryInterlockedAdd(volatile int* pVal, int iAdd)
{
#ifdef _CPU_X86
# ifdef __GNUC__
__asm__ __volatile__ (
" lock add %[iAdd], (%[pVal])\n"
: "=m" (*pVal)
: [pVal] "r" (pVal), "m" (*pVal), [iAdd] "r" (iAdd)
);
# else
__asm
{
mov edx, pVal
mov eax, iAdd
lock add [edx], eax
}
# endif
#else
// NOTE: The code below will fail on 64bit architectures!
#if defined(_WIN64)
_InterlockedExchangeAdd((volatile LONG*)pVal, iAdd);
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD
#include AZ_RESTRICTED_FILE(MultiThread_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(APPLE) || defined(LINUX)
CryInterlockedExchangeAdd((volatile LONG*)pVal, iAdd);
#elif defined(APPLE)
OSAtomicAdd32(iAdd, (volatile LONG*)pVal);
#else
InterlockedExchangeAdd((volatile LONG*)pVal, iAdd);
#endif
#endif
}
ILINE void CryInterlockedAddSize(volatile size_t* pVal, ptrdiff_t iAdd)
{
#if defined(PLATFORM_64BIT)
#if defined(_WIN64)
_InterlockedExchangeAdd64((volatile __int64*)pVal, iAdd);
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE
#include AZ_RESTRICTED_FILE(MultiThread_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32)
InterlockedExchangeAdd64((volatile LONG64*)pVal, iAdd);
#elif defined(APPLE) || defined(LINUX)
(void)__sync_fetch_and_add((int64_t*)pVal, (int64_t)iAdd);
#else
int64 x, n;
do
{
x = (int64) * pVal;
n = x + iAdd;
}
while (CryInterlockedCompareExchange64((volatile int64*)pVal, n, x) != x);
#endif
#else
CryInterlockedAdd((volatile int*)pVal, (int)iAdd);
#endif
}
//////////////////////////////////////////////////////////////////////////
ILINE void CryWriteLock(volatile int* rw)
{
CrySpinLock(rw, 0, WRITE_LOCK_VAL);
}
ILINE void CryReleaseWriteLock(volatile int* rw)
{
CryInterlockedAdd(rw, -WRITE_LOCK_VAL);
}
//////////////////////////////////////////////////////////////////////////
struct WriteLock
{
ILINE WriteLock(volatile int& rw) { CryWriteLock(&rw); prw = &rw; }
~WriteLock() { CryReleaseWriteLock(prw); }
private:
volatile int* prw;
};
//////////////////////////////////////////////////////////////////////////
struct WriteLockCond
{
ILINE WriteLockCond(volatile int& rw, int bActive = 1)
{
if (bActive)
{
CrySpinLock(&rw, 0, iActive = WRITE_LOCK_VAL);
}
else
{
iActive = 0;
}
prw = &rw;
}
ILINE WriteLockCond() { prw = &(iActive = 0); }
~WriteLockCond()
{
CryInterlockedAdd(prw, -iActive);
}
void SetActive(int bActive = 1) { iActive = -bActive & WRITE_LOCK_VAL; }
void Release() { CryInterlockedAdd(prw, -iActive); }
volatile int* prw;
int iActive;
};
#if defined(LINUX) || defined(APPLE)
ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 comperand)
{
return __sync_val_compare_and_swap(addr, comperand, exchange);
// This is OK, because long is signed int64 on Linux x86_64
//return CryInterlockedCompareExchange((volatile long*)addr, (long)exchange, (long)comperand);
}
#else
ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 compare)
{
// forward to system call
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64
#include AZ_RESTRICTED_FILE(MultiThread_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
return _InterlockedCompareExchange64((volatile int64*)addr, exchange, compare);
#endif
}
#endif
@@ -34,7 +34,7 @@ namespace CryMT
public:
typedef T value_type;
typedef std::vector<T, Alloc> container_type;
typedef CryAutoCriticalSection AutoLock;
typedef AZStd::lock_guard<AZStd::recursive_mutex> AutoLock;
//////////////////////////////////////////////////////////////////////////
// std::queue interface
@@ -46,7 +46,7 @@ namespace CryMT
// classic pop function of queue should not be used for thread safety, use try_pop instead
//void pop() { AutoLock lock(m_cs); return v.erase(v.begin()); };
CryCriticalSection& get_lock() const { return m_cs; }
AZStd::recursive_mutex& get_lock() const { return m_cs; }
bool empty() const { AutoLock lock(m_cs); return v.empty(); }
int size() const { AutoLock lock(m_cs); return v.size(); }
@@ -92,7 +92,7 @@ namespace CryMT
}
private:
container_type v;
mutable CryCriticalSection m_cs;
mutable AZStd::recursive_mutex m_cs;
};
}; // namespace CryMT
+5 -29
View File
@@ -21,8 +21,7 @@
//
//---------------------------------------------------------------------------
#include "MultiThread.h"
#include "CryThread.h"
#include <AzCore/std/parallel/spin_mutex.h>
namespace stl
{
@@ -52,43 +51,20 @@ namespace stl
struct PSyncMultiThread
{
PSyncMultiThread()
: _Semaphore(0) {}
PSyncMultiThread() {}
void Lock()
{
CryWriteLock(&_Semaphore);
m_lock.lock();
}
void Unlock()
{
CryReleaseWriteLock(&_Semaphore);
}
int IsLocked() const volatile
{
return _Semaphore;
m_lock.unlock();
}
private:
volatile int _Semaphore;
AZStd::spin_mutex m_lock;
};
#ifdef _DEBUG
struct PSyncDebug
: public PSyncMultiThread
{
void Lock()
{
assert(!IsLocked());
PSyncMultiThread::Lock();
}
};
#else
typedef PSyncNone PSyncDebug;
#endif
};
#endif // CRYINCLUDE_CRYCOMMON_SYNCHRONIZATION_H
+1 -188
View File
@@ -923,21 +923,6 @@ threadID GetCurrentThreadId()
}
#endif
//////////////////////////////////////////////////////////////////////////
HANDLE CreateEvent
(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "CreateEvent not implemented yet");
return 0;
}
//////////////////////////////////////////////////////////////////////////
DWORD Sleep(DWORD dwMilliseconds)
{
@@ -1003,95 +988,6 @@ DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable)
return 0;
}
//////////////////////////////////////////////////////////////////////////
DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "WaitForSingleObjectEx not implemented yet");
return 0;
}
#if 0
//////////////////////////////////////////////////////////////////////////
DWORD WaitForMultipleObjectsEx(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds,
BOOL bAlertable)
{
//TODO: implement
return 0;
}
#endif
//////////////////////////////////////////////////////////////////////////
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "WaitForSingleObject not implemented yet");
return 0;
}
//////////////////////////////////////////////////////////////////////////
BOOL SetEvent(HANDLE hEvent)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "SetEvent not implemented yet");
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
BOOL ResetEvent(HANDLE hEvent)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "ResetEvent not implemented yet");
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
HANDLE CreateMutex
(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCSTR lpName
)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "CreateMutex not implemented yet");
return 0;
}
//////////////////////////////////////////////////////////////////////////
BOOL ReleaseMutex(HANDLE hMutex)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "ReleaseMutex not implemented yet");
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
//////////////////////////////////////////////////////////////////////////
HANDLE CreateThread
(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)
{
//TODO: implement
CRY_ASSERT_MESSAGE(0, "CreateThread not implemented yet");
return 0;
}
#if defined(LINUX) || defined(APPLE)
BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize)
{
@@ -1270,90 +1166,7 @@ int CryMessageBox(const char* lpText, const char* lpCaption, unsigned int uType)
#endif
}
#if defined(LINUX) || defined(APPLE) || defined(DEFINE_CRY_INTERLOCKED_INCREMENT)
//[K01]: http://www.memoryhole.net/kyle/2007/05/atomic_incrementing.html
//http://forums.devx.com/archive/index.php/t-160558.html
//////////////////////////////////////////////////////////////////////////
DLL_EXPORT LONG CryInterlockedIncrement(LONG volatile* lpAddend)
{
/*int r;
__asm__ __volatile__ (
"lock ; xaddl %0, (%1) \n\t"
: "=r" (r)
: "r" (lpAddend), "0" (1)
: "memory"
);
return (LONG) (r + 1); */// add, since we get the original value back.
return __sync_fetch_and_add(lpAddend, 1) + 1;
}
//////////////////////////////////////////////////////////////////////////
DLL_EXPORT LONG CryInterlockedDecrement(LONG volatile* lpAddend)
{
/*int r;
__asm__ __volatile__ (
"lock ; xaddl %0, (%1) \n\t"
: "=r" (r)
: "r" (lpAddend), "0" (-1)
: "memory"
);
return (LONG) (r - 1); */// subtract, since we get the original value back.
return __sync_fetch_and_sub(lpAddend, 1) - 1;
}
//////////////////////////////////////////////////////////////////////////
DLL_EXPORT LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value)
{
/* LONG r;
__asm__ __volatile__ (
#if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64.
"lock ; xaddq %0, (%1) \n\t"
#else
"lock ; xaddl %0, (%1) \n\t"
#endif
: "=r" (r)
: "r" (lpAddend), "0" (Value)
: "memory"
);
return r;*/
return __sync_fetch_and_add(lpAddend, Value);
}
DLL_EXPORT LONG CryInterlockedOr(LONG volatile* Destination, LONG Value)
{
return __sync_fetch_and_or(Destination, Value);
}
DLL_EXPORT LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand)
{
return __sync_val_compare_and_swap(dst, comperand, exchange);
/*LONG r;
__asm__ __volatile__ (
#if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64.
"lock ; cmpxchgq %2, (%1) \n\t"
#else
"lock ; cmpxchgl %2, (%1) \n\t"
#endif
: "=a" (r)
: "r" (dst), "r" (exchange), "0" (comperand)
: "memory"
);
return r;*/
}
DLL_EXPORT void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand)
{
return __sync_val_compare_and_swap(dst, comperand, exchange);
//return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand);
}
DLL_EXPORT void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange)
{
__sync_synchronize();
return __sync_lock_test_and_set(dst, exchange);
//return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand);
}
#if defined(LINUX) || defined(APPLE)
threadID CryGetCurrentThreadId()
{
@@ -86,8 +86,6 @@ set(FILES
CryPodArray.h
CrySizer.h
CrySystemBus.h
CryThread.h
CryThreadImpl.h
CryTypeInfo.h
CryVersion.h
FrameProfiler.h
@@ -95,7 +93,6 @@ set(FILES
LegacyAllocator.h
MetaUtils.h
MiniQueue.h
MultiThread.h
MultiThread_Containers.h
NullAudioSystem.h
PNoise3.h
@@ -152,11 +149,6 @@ set(FILES
CryAssert_Mac.h
CryLibrary.cpp
CryLibrary.h
CryThread_dummy.h
CryThread_pthreads.h
CryThread_windows.h
CryThreadImpl_pthreads.h
CryThreadImpl_windows.h
Linux32Specific.h
Linux64Specific.h
Linux_Win32Wrapper.h
+4 -2
View File
@@ -26,6 +26,8 @@
#include <ISystem.h>
#include <AzCore/std/parallel/spin_mutex.h>
//////////////////////////////////////////////////////////////////////////
// Physics defines.
//////////////////////////////////////////////////////////////////////////
@@ -2834,8 +2836,8 @@ struct IGeometry
virtual int PointInsideStatus(const Vec3& pt) = 0; // for meshes, will create an auxiliary hashgrid for acceleration
// IntersectLocked - the main function for geomtries. pdata1,pdata2,pparams can be 0 - defaults will be assumed.
// returns a pointer to an internal thread-specific contact buffer, locked with the lock argument
virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock) = 0;
virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock, int iCaller) = 0;
virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock) = 0;
virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock, int iCaller) = 0;
// Intersect - same as Intersect, but doesn't lock pcontacts
virtual int Intersect(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts) = 0;
// FindClosestPoint - for non-convex meshes only does local search, doesn't guarantee global minimum
+1 -10
View File
@@ -135,7 +135,6 @@
#define PRINTF_EMPTY_FORMAT ""
#endif
//default stack size for threads, currently only used on pthread platforms
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_8
@@ -143,14 +142,6 @@
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(LINUX) || defined(APPLE)
#if !defined(_DEBUG)
#define SIMPLE_THREAD_STACK_SIZE_KB (256)
#else
#define SIMPLE_THREAD_STACK_SIZE_KB (256 * 4)
#endif
#else
#define SIMPLE_THREAD_STACK_SIZE_KB (32)
#endif
#include <AzCore/PlatformDef.h>
@@ -199,7 +190,7 @@
#elif defined(ANDROID)
#include "AndroidSpecific.h"
#elif defined(IOS)
#include "iOSSpecific.h"
#include "iOSSpecific.h"
#endif
#endif
-109
View File
@@ -38,10 +38,6 @@ struct SSystemGlobalEnvironment* gEnv = nullptr;
#include AZ_RESTRICTED_FILE(platform_impl_h)
#endif
//////////////////////////////////////////////////////////////////////////
// If not in static library.
#include <CryThreadImpl.h>
#if defined(WIN32) || defined(WIN64)
void CryPureCallHandler()
{
@@ -278,111 +274,6 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], uint
}
}
//////////////////////////////////////////////////////////////////////////
LONG CryInterlockedIncrement(int volatile* lpAddend)
{
return InterlockedIncrement((volatile LONG*)lpAddend);
}
//////////////////////////////////////////////////////////////////////////
LONG CryInterlockedDecrement(int volatile* lpAddend)
{
return InterlockedDecrement((volatile LONG*)lpAddend);
}
//////////////////////////////////////////////////////////////////////////
LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value)
{
return InterlockedExchangeAdd(lpAddend, Value);
}
LONG CryInterlockedOr(LONG volatile* Destination, LONG Value)
{
return InterlockedOr(Destination, Value);
}
LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand)
{
return InterlockedCompareExchange(dst, exchange, comperand);
}
void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand)
{
return InterlockedCompareExchangePointer(dst, exchange, comperand);
}
void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange)
{
return InterlockedExchangePointer(dst, exchange);
}
void CryInterlockedAdd(volatile size_t* pVal, ptrdiff_t iAdd)
{
#if defined (PLATFORM_64BIT)
#if !defined(NDEBUG)
size_t v = (size_t)
#endif
InterlockedAdd64((volatile int64*)pVal, iAdd);
#else
size_t v = (size_t)CryInterlockedExchangeAdd((volatile long*)pVal, (long)iAdd);
v += iAdd;
#endif
assert((iAdd == 0) || (iAdd < 0 && v < v - (size_t)iAdd) || (iAdd > 0 && v > v - (size_t)iAdd));
}
//////////////////////////////////////////////////////////////////////////
void* CryCreateCriticalSection()
{
CRITICAL_SECTION* pCS = new CRITICAL_SECTION;
InitializeCriticalSection(pCS);
return pCS;
}
void CryCreateCriticalSectionInplace(void* pCS)
{
InitializeCriticalSection((CRITICAL_SECTION*)pCS);
}
//////////////////////////////////////////////////////////////////////////
void CryDeleteCriticalSection(void* cs)
{
CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs;
if (pCS->LockCount >= 0)
{
CryFatalError("Critical Section hanging lock");
}
DeleteCriticalSection(pCS);
delete pCS;
}
//////////////////////////////////////////////////////////////////////////
void CryDeleteCriticalSectionInplace(void* cs)
{
CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs;
if (pCS->LockCount >= 0)
{
CryFatalError("Critical Section hanging lock");
}
DeleteCriticalSection(pCS);
}
//////////////////////////////////////////////////////////////////////////
void CryEnterCriticalSection(void* cs)
{
EnterCriticalSection((CRITICAL_SECTION*)cs);
}
//////////////////////////////////////////////////////////////////////////
bool CryTryCriticalSection(void* cs)
{
return TryEnterCriticalSection((CRITICAL_SECTION*)cs) != 0;
}
//////////////////////////////////////////////////////////////////////////
void CryLeaveCriticalSection(void* cs)
{
LeaveCriticalSection((CRITICAL_SECTION*)cs);
}
//////////////////////////////////////////////////////////////////////////
bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes)
{
+14 -23
View File
@@ -13,12 +13,14 @@
#include <platform.h>
#include <type_traits>
#include <MultiThread.h>
void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2);
#if defined(APPLE)
#include <cstddef>
#endif
#include <AzCore/std/parallel/atomic.h>
//////////////////////////////////////////////////////////////////
// SMART POINTER
//////////////////////////////////////////////////////////////////
@@ -353,38 +355,32 @@ protected:
class CMultiThreadRefCount
{
public:
CMultiThreadRefCount()
: m_cnt(0) {}
CMultiThreadRefCount() {}
virtual ~CMultiThreadRefCount() {}
inline int AddRef()
{
return CryInterlockedIncrement(&m_cnt);
return m_count.fetch_add(1, AZStd::memory_order_acq_rel) + 1; // because we get the original value back
}
inline int Release()
{
const int nCount = CryInterlockedDecrement(&m_cnt);
assert(nCount >= 0);
const int nCount = m_count.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back
AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice");
if (nCount == 0)
{
delete this;
}
else if (nCount < 0)
{
assert(0);
CryFatalError("Deleting Reference Counted Object Twice");
}
return nCount;
}
inline int GetRefCount() const { return m_cnt; }
inline int GetRefCount() const { return m_count.load(AZStd::memory_order_acquire); }
protected:
// Allows the memory for the object to be deallocated in the dynamic module where it was originally constructed, as it may use different memory manager (Debug/Release configurations)
virtual void DeleteThis() { delete this; }
private:
volatile int m_cnt;
AZStd::atomic_int m_count{ 0 };
};
// base class for interfaces implementing reference counting that needs to be thread-safe
@@ -405,29 +401,24 @@ public:
virtual void AddRef()
{
CryInterlockedIncrement(&m_nRefCounter);
m_nRefCounter.fetch_add(1, AZStd::memory_order_acq_rel);
}
virtual void Release()
{
const int nCount = CryInterlockedDecrement(&m_nRefCounter);
assert(nCount >= 0);
const int nCount = m_nRefCounter.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back
AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice");
if (nCount == 0)
{
delete this;
}
else if (nCount < 0)
{
assert(0);
CryFatalError("Deleting Reference Counted Object Twice");
}
}
Counter NumRefs() const { return m_nRefCounter; }
Counter NumRefs() const { return m_nRefCounter.load(AZStd::memory_order_acquire); }
protected:
volatile Counter m_nRefCounter;
AZStd::atomic<Counter> m_nRefCounter{ 0 };
};
typedef _i_reference_target<int> _i_reference_target_t;
+4 -3
View File
@@ -18,6 +18,7 @@
#include <AzCore/Debug/StackTracer.h>
#include <AzCore/Debug/EventTraceDrillerBus.h>
#include <AzCore/std/parallel/spin_mutex.h>
#include <AzCore/Utils/Utils.h>
#define VS_VERSION_INFO 1
@@ -153,13 +154,13 @@ void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable)
DWORD g_idDebugThreads[10];
const char* g_nameDebugThreads[10];
int g_nDebugThreads = 0;
volatile int g_lockThreadDumpList = 0;
AZStd::spin_mutex g_lockThreadDumpList;
void MarkThisThreadForDebugging(const char* name)
{
EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name);
WriteLock lock(g_lockThreadDumpList);
AZStd::scoped_lock lock(g_lockThreadDumpList);
DWORD id = GetCurrentThreadId();
if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0]))
{
@@ -179,7 +180,7 @@ void MarkThisThreadForDebugging(const char* name)
void UnmarkThisThreadFromDebugging()
{
WriteLock lock(g_lockThreadDumpList);
AZStd::scoped_lock lock(g_lockThreadDumpList);
DWORD id = GetCurrentThreadId();
for (int i = g_nDebugThreads - 1; i >= 0; i--)
{
@@ -309,8 +309,8 @@ private:
TLocalizationBitfield m_availableLocalizations;
//Lock for
mutable CryCriticalSection m_cs;
typedef CryAutoCriticalSection AutoLock;
mutable AZStd::mutex m_cs;
typedef AZStd::lock_guard<AZStd::mutex> AutoLock;
};
+4 -15
View File
@@ -31,17 +31,6 @@
#include <syslog.h>
#endif
// Only accept logging from the main thread.
#ifdef WIN32
#define THREAD_SAFE_LOG
//#define THREAD_SAFE_LOG CryAutoCriticalSection scope_lock(m_logCriticalSection);
#else
#define THREAD_SAFE_LOG
#endif //WIN32
#define LOG_BACKUP_PATH "@log@/LogBackups"
#if defined(IOS)
@@ -821,13 +810,13 @@ void CLog::PushAssetScopeName(const char* sAssetType, const char* sName)
SAssetScopeInfo as;
as.sType = sAssetType;
as.sName = sName;
CryAutoCriticalSection scope_lock(m_assetScopeQueueLock);
AZStd::scoped_lock scope_lock(m_assetScopeQueueLock);
m_assetScopeQueue.push_back(as);
}
void CLog::PopAssetScopeName()
{
CryAutoCriticalSection scope_lock(m_assetScopeQueueLock);
AZStd::scoped_lock scope_lock(m_assetScopeQueueLock);
assert(!m_assetScopeQueue.empty());
if (!m_assetScopeQueue.empty())
{
@@ -838,7 +827,7 @@ void CLog::PopAssetScopeName()
//////////////////////////////////////////////////////////////////////////
const char* CLog::GetAssetScopeString()
{
CryAutoCriticalSection scope_lock(m_assetScopeQueueLock);
AZStd::scoped_lock scope_lock(m_assetScopeQueueLock);
m_assetScopeString.clear();
for (size_t i = 0; i < m_assetScopeQueue.size(); i++)
@@ -1461,7 +1450,7 @@ void CLog::Update()
{
if (!m_threadSafeMsgQueue.empty())
{
CryAutoCriticalSection lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it)
AZStd::scoped_lock lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it)
// Must be called from main thread
SLogMsg msg;
while (m_threadSafeMsgQueue.try_pop(msg))
+1 -5
View File
@@ -10,8 +10,6 @@
#pragma once
#include <ILog.h>
#include <CryThread.h>
#include <MultiThread.h>
#include <MultiThread_Containers.h>
//////////////////////////////////////////////////////////////////////
@@ -168,7 +166,7 @@ private: // -------------------------------------------------------------------
};
std::vector<SAssetScopeInfo> m_assetScopeQueue;
CryCriticalSection m_assetScopeQueueLock;
AZStd::mutex m_assetScopeQueueLock;
string m_assetScopeString;
#endif
@@ -176,8 +174,6 @@ private: // -------------------------------------------------------------------
IConsole* m_pConsole; //
CryCriticalSection m_logCriticalSection;
struct SLogHistoryItem
{
char str[MAX_WARNING_LENGTH];
@@ -17,17 +17,17 @@ CSystemEventDispatcher::CSystemEventDispatcher()
bool CSystemEventDispatcher::RegisterListener(ISystemEventListener* pListener)
{
m_listenerRegistrationLock.Lock();
m_listenerRegistrationLock.lock();
bool ret = m_listeners.Add(pListener);
m_listenerRegistrationLock.Unlock();
m_listenerRegistrationLock.unlock();
return ret;
}
bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener)
{
m_listenerRegistrationLock.Lock();
m_listenerRegistrationLock.lock();
m_listeners.Remove(pListener);
m_listenerRegistrationLock.Unlock();
m_listenerRegistrationLock.unlock();
return true;
}
@@ -35,12 +35,12 @@ bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener)
//////////////////////////////////////////////////////////////////////////
void CSystemEventDispatcher::OnSystemEventAnyThread(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
{
m_listenerRegistrationLock.Lock();
m_listenerRegistrationLock.lock();
for (TSystemEventListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
{
notifier->OnSystemEventAnyThread(event, wparam, lparam);
}
m_listenerRegistrationLock.Unlock();
m_listenerRegistrationLock.unlock();
}
@@ -14,6 +14,7 @@
#include <ISystem.h>
#include <CryListenerSet.h>
#include <MultiThread_Containers.h>
class CSystemEventDispatcher
: public ISystemEventDispatcher
@@ -46,7 +47,7 @@ private:
typedef CryMT::queue<SEventParams> TSystemEventQueue;
TSystemEventQueue m_systemEventQueue;
CryCriticalSection m_listenerRegistrationLock;
AZStd::recursive_mutex m_listenerRegistrationLock;
};
#endif // CRYINCLUDE_CRYSYSTEM_SYSTEMEVENTDISPATCHER_H
+6 -6
View File
@@ -121,12 +121,6 @@ namespace AzTestRunner
{
const char* cwd = AzTestRunner::get_current_working_directory();
std::cout << "cwd = " << cwd << std::endl;
for (int i = 0; i < argc; i++)
{
std::cout << "arg[" << i << "] " << argv[i] << std::endl;
}
std::cout << "LIB: " << lib << std::endl;
}
@@ -227,6 +221,12 @@ namespace AzTestRunner
testMainFunction.reset();
}
// Construct a retry command if the test fails
if (result != 0)
{
std::cout << "Retry command: " << std::endl << argv[0] << " " << lib << " " << symbol << std::endl;
}
// unload and reset the module here, because it needs to release resources that were used / activated in
// system allocator / etc.
module.reset();
@@ -168,9 +168,13 @@ namespace O3DE::ProjectManager
// the decoration wrapper is intended to remember window positioning and sizing
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
wrapper->setGuest(m_mainWindow.data());
// show the main window here to apply the stylesheet before restoring geometry or we
// can end up with empty white space at the bottom of the window until the frame is resized again
m_mainWindow->show();
wrapper->enableSaveRestoreGeometry("O3DE", "ProjectManager", "mainWindowGeometry");
wrapper->showFromSettings();
m_mainWindow->show();
qApp->setQuitOnLastWindowClosed(true);
@@ -39,7 +39,7 @@ namespace O3DE::ProjectManager
NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent)
: ProjectSettingsScreen(parent)
{
const QString defaultName{ "NewProject" };
const QString defaultName = GetDefaultProjectName();
const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + defaultName);
m_projectName->lineEdit()->setText(defaultName);
@@ -162,6 +162,17 @@ namespace O3DE::ProjectManager
return defaultPath;
}
QString NewProjectSettingsScreen::GetDefaultProjectName()
{
return "NewProject";
}
QString NewProjectSettingsScreen::GetProjectAutoPath()
{
const QString projectName = m_projectName->lineEdit()->text();
return QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + projectName);
}
ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum()
{
return ProjectManagerScreen::NewProjectSettings;
@@ -260,4 +271,22 @@ namespace O3DE::ProjectManager
m_projectTemplateButtonGroup->blockSignals(false);
}
}
void NewProjectSettingsScreen::OnProjectNameUpdated()
{
if (ValidateProjectName() && !m_userChangedProjectPath)
{
m_projectPath->setText(GetProjectAutoPath());
}
}
void NewProjectSettingsScreen::OnProjectPathUpdated()
{
const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + GetDefaultProjectName());
const QString autoPath = GetProjectAutoPath();
const QString path = m_projectPath->lineEdit()->text();
m_userChangedProjectPath = path != defaultPath && path != autoPath;
ValidateProjectPath();
}
} // namespace O3DE::ProjectManager
@@ -40,8 +40,14 @@ namespace O3DE::ProjectManager
signals:
void OnTemplateSelectionChanged(int oldIndex, int newIndex);
protected:
void OnProjectNameUpdated() override;
void OnProjectPathUpdated() override;
private:
QString GetDefaultProjectName();
QString GetDefaultProjectPath();
QString GetProjectAutoPath();
QFrame* CreateTemplateDetails(int margin);
void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo);
@@ -51,6 +57,7 @@ namespace O3DE::ProjectManager
TagContainerWidget* m_templateIncludedGems;
QVector<ProjectTemplateInfo> m_templates;
int m_selectedTemplateIndex = -1;
bool m_userChangedProjectPath = false;
inline constexpr static int s_spacerSize = 20;
inline constexpr static int s_templateDetailsContentMargin = 20;
@@ -40,12 +40,11 @@ namespace O3DE::ProjectManager
m_verticalLayout->setAlignment(Qt::AlignTop);
m_projectName = new FormLineEditWidget(tr("Project name"), "", this);
connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::ValidateProjectName);
connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectNameUpdated);
m_verticalLayout->addWidget(m_projectName);
m_projectPath = new FormFolderBrowseEditWidget(tr("Project Location"), "", this);
m_projectPath->lineEdit()->setReadOnly(true);
connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::Validate);
connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectPathUpdated);
m_verticalLayout->addWidget(m_projectPath);
projectSettingsFrame->setLayout(m_verticalLayout);
@@ -110,28 +109,36 @@ namespace O3DE::ProjectManager
m_projectName->setErrorLabelVisible(!projectNameIsValid);
return projectNameIsValid;
}
bool ProjectSettingsScreen::ValidateProjectPath()
{
bool projectPathIsValid = true;
if (m_projectPath->lineEdit()->text().isEmpty())
QDir path(m_projectPath->lineEdit()->text());
if (!path.isAbsolute())
{
projectPathIsValid = false;
m_projectPath->setErrorLabelText(tr("Please provide a valid location."));
m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location."));
}
else
else if (path.exists() && !path.isEmpty())
{
QDir path(m_projectPath->lineEdit()->text());
if (path.exists() && !path.isEmpty())
{
projectPathIsValid = false;
m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location."));
}
projectPathIsValid = false;
m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location."));
}
m_projectPath->setErrorLabelVisible(!projectPathIsValid);
return projectPathIsValid;
}
void ProjectSettingsScreen::OnProjectNameUpdated()
{
ValidateProjectName();
}
void ProjectSettingsScreen::OnProjectPathUpdated()
{
Validate();
}
bool ProjectSettingsScreen::Validate()
{
return ValidateProjectName() && ValidateProjectPath();
@@ -33,10 +33,13 @@ namespace O3DE::ProjectManager
virtual bool Validate();
protected slots:
virtual bool ValidateProjectName();
virtual bool ValidateProjectPath();
virtual void OnProjectNameUpdated();
virtual void OnProjectPathUpdated();
protected:
bool ValidateProjectName();
virtual bool ValidateProjectPath();
QString GetDefaultProjectPath();
QHBoxLayout* m_horizontalLayout;
@@ -189,7 +189,7 @@ namespace O3DE::ProjectManager
const QString copiedFileSizeString = locale.formattedDataSize(outCopiedFileSize);
const QString totalFileSizeString = locale.formattedDataSize(totalSizeToCopy);
progressDialog->setLabelText(QString("Coping file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles),
progressDialog->setLabelText(QString("Copying file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles),
QString::number(filesToCopyCount),
copiedFileSizeString,
totalFileSizeString));
@@ -108,10 +108,11 @@ namespace O3DE::ProjectManager
bool UpdateProjectSettingsScreen::ValidateProjectPath()
{
bool projectPathIsValid = true;
if (m_projectPath->lineEdit()->text().isEmpty())
QDir path(m_projectPath->lineEdit()->text());
if (!path.isAbsolute())
{
projectPathIsValid = false;
m_projectPath->setErrorLabelText(tr("Please provide a valid location."));
m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location."));
}
m_projectPath->setErrorLabelVisible(!projectPathIsValid);
@@ -93,40 +93,62 @@ bool RCON_IsRemoteAllowedToConnect(const AZ::AzSock::AzSocketAddress& connectee)
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteThreadedObject::Start(const char* name)
{
AZStd::thread_desc desc;
desc.m_name = name;
auto function = AZStd::bind(&SRemoteThreadedObject::ThreadFunction, this);
m_thread = AZStd::thread(function, &desc);
}
void SRemoteThreadedObject::WaitForThread()
{
if (m_thread.joinable())
{
m_thread.join();
}
}
void SRemoteThreadedObject::ThreadFunction()
{
Run();
Terminate();
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::StartServer()
{
StopServer();
m_bAcceptClients = true;
Start(0, kServerThreadName);
Start(kServerThreadName);
}
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::StopServer()
{
Stop();
m_bAcceptClients = false;
AZ::AzSock::CloseSocket(m_socket);
m_socket = SOCKET_ERROR;
m_lock.Lock();
AZStd::unique_lock<AZStd::recursive_mutex> lock(m_mutex);
for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
{
it->pClient->StopClient();
}
m_lock.Unlock();
m_stopEvent.Wait();
m_stopEvent.Set();
m_stopCondition.wait(lock, [this] { return m_clients.empty(); });
}
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::ClientDone(SRemoteClient* pClient)
{
m_lock.Lock();
AZStd::scoped_lock lock(m_mutex);
for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
{
if (it->pClient == pClient)
{
it->pClient->Stop();
delete it->pClient;
delete it->pEvents;
m_clients.erase(it);
@@ -136,9 +158,8 @@ void SRemoteServer::ClientDone(SRemoteClient* pClient)
if (m_clients.empty())
{
m_stopEvent.Set();
m_stopCondition.notify_all();
}
m_lock.Unlock();
}
/////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,7 +170,6 @@ void SRemoteServer::Terminate()
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::Run()
{
SetName(kServerThreadName);
AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY
AZSOCKET sClient;
@@ -232,12 +252,10 @@ void SRemoteServer::Run()
continue;
}
m_lock.Lock();
m_stopEvent.Reset();
AZStd::scoped_lock lock(m_mutex);
SRemoteClient* pClient = new SRemoteClient(this);
m_clients.push_back(SRemoteClientInfo(pClient));
pClient->StartClient(sClient);
m_lock.Unlock();
}
AZ::AzSock::CloseSocket(m_socket);
CryLog("Remote console terminating.\n");
@@ -247,43 +265,42 @@ void SRemoteServer::Run()
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::AddEvent(IRemoteEvent* pEvent)
{
m_lock.Lock();
AZStd::scoped_lock lock(m_mutex);
for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
{
it->pEvents->push_back(pEvent->Clone());
}
m_lock.Unlock();
delete pEvent;
}
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteServer::GetEvents(TEventBuffer& buffer)
{
m_lock.Lock();
AZStd::scoped_lock lock(m_mutex);
buffer = m_eventBuffer;
m_eventBuffer.clear();
m_lock.Unlock();
}
/////////////////////////////////////////////////////////////////////////////////////////////
bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size)
{
m_lock.Lock();
IRemoteEvent* pEvent = nullptr;
for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
{
if (it->pClient == pClient)
AZStd::scoped_lock lock(m_mutex);
for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
{
TEventBuffer* pEvents = it->pEvents;
if (!pEvents->empty())
if (it->pClient == pClient)
{
pEvent = pEvents->front();
pEvents->pop_front();
TEventBuffer* pEvents = it->pEvents;
if (!pEvents->empty())
{
pEvent = pEvents->front();
pEvents->pop_front();
}
break;
}
break;
}
}
m_lock.Unlock();
const bool res = (pEvent != nullptr);
if (pEvent)
{
@@ -297,7 +314,7 @@ bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size
bool SRemoteServer::ReadBuffer(const char* buffer, int data)
{
bool result = true;
// Sometimes multiple events can come in a single buffer, so make sure we look
// at the entire thing.
int bytesRemaining = data;
@@ -306,15 +323,14 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data)
{
// Create the event from the current sub string in the buffer.
IRemoteEvent* event = SRemoteEventFactory::GetInst()->CreateEventFromBuffer(curBuffer, bytesRemaining);
result &= (event != nullptr);
if (event)
{
if (event->GetType() != eCET_Noop)
{
m_lock.Lock();
AZStd::scoped_lock lock(m_mutex);
m_eventBuffer.push_back(event);
m_lock.Unlock();
}
else
{
@@ -337,7 +353,7 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data)
void SRemoteClient::StartClient(AZSOCKET socket)
{
m_socket = socket;
Start(0, kClientThreadName);
Start(kClientThreadName);
}
/////////////////////////////////////////////////////////////////////////////////////////////
@@ -356,7 +372,6 @@ void SRemoteClient::Terminate()
/////////////////////////////////////////////////////////////////////////////////////////////
void SRemoteClient::Run()
{
SetName(kClientThreadName);
AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY
char szBuff[kDefaultBufferSize];
@@ -11,9 +11,11 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/list.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/parallel/condition_variable.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/string/string.h>
#include <CryThread.h>
extern const int defaultRemoteConsolePort;
@@ -146,6 +148,30 @@ private:
typedef AZStd::list<IRemoteEvent*> TEventBuffer;
/////////////////////////////////////////////////////////////////////////////////////////////
// SRemoteThreadedObject
//
// Simple runnable-like threaded object
//
/////////////////////////////////////////////////////////////////////////////////////////////
struct SRemoteThreadedObject
{
virtual ~SRemoteThreadedObject() = default;
void Start(const char* name);
void WaitForThread();
virtual void Run() = 0;
virtual void Terminate() = 0;
private:
void ThreadFunction();
AZStd::thread m_thread;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// SRemoteServer
//
@@ -154,10 +180,10 @@ typedef AZStd::list<IRemoteEvent*> TEventBuffer;
/////////////////////////////////////////////////////////////////////////////////////////////
struct SRemoteClient;
struct SRemoteServer
: public CrySimpleThread<>
: public SRemoteThreadedObject
{
SRemoteServer()
: m_socket(AZ_SOCKET_INVALID) { m_stopEvent.Set(); }
: m_socket(AZ_SOCKET_INVALID) {}
void StartServer();
void StopServer();
@@ -165,10 +191,8 @@ struct SRemoteServer
void AddEvent(IRemoteEvent* pEvent);
void GetEvents(TEventBuffer& buffer);
// CrySimpleThread
void Terminate() override;
void Run() override;
// ~CrySimpleThread
private:
bool WriteBuffer(SRemoteClient* pClient, char* buffer, int& size);
@@ -189,9 +213,9 @@ private:
typedef AZStd::vector<SRemoteClientInfo> TClients;
TClients m_clients;
AZSOCKET m_socket;
CryMutex m_lock;
AZStd::recursive_mutex m_mutex;
TEventBuffer m_eventBuffer;
CryEvent m_stopEvent;
AZStd::condition_variable_any m_stopCondition;
volatile bool m_bAcceptClients;
friend struct SRemoteClient;
};
@@ -204,7 +228,7 @@ private:
//
/////////////////////////////////////////////////////////////////////////////////////////////
struct SRemoteClient
: public CrySimpleThread<>
: public SRemoteThreadedObject
{
SRemoteClient(SRemoteServer* pServer)
: m_pServer(pServer)
@@ -213,10 +237,8 @@ struct SRemoteClient
void StartClient(AZSOCKET socket);
void StopClient();
// CrySimpleThread
void Terminate() override;
void Run() override;
// ~CrySimpleThread
private:
bool RecvPackage(char* buffer, int& size);
@@ -230,7 +230,7 @@ namespace TestImpact
processInFlight.m_process = LaunchProcess(AZStd::move(processInfo));
processInFlight.m_startTime = createTime;
}
catch (ProcessException& e)
catch ([[maybe_unused]] ProcessException& e)
{
AZ_Warning("ProcessScheduler", false, e.what());
createResult = LaunchResult::Failure;
@@ -169,7 +169,7 @@ namespace TestImpact
WriteFileContents<TestEngineException>(SerializeTestEnumeration(enumeration.value()), jobInfo->GetCache()->m_file);
}
}
catch (const Exception& e)
catch ([[maybe_unused]] const Exception& e)
{
AZ_Warning("Enumerate", false, e.what());
enumerations[jobId] = AZStd::nullopt;