Merge branch 'development' into Atom/guthadam/atomtools_refactor_document_system

This commit is contained in:
Guthrie Adams
2021-08-16 18:30:49 -05:00
186 changed files with 2992 additions and 4818 deletions
@@ -8,7 +8,7 @@ INTRODUCTION
------------
EditorPythonBindings is a Python project that contains a collection of editor testing tools
developed by the Lumberyard feature teams. The project contains tools for system level
developed by the O3DE feature teams. The project contains tools for system level
editor tests.
@@ -23,7 +23,7 @@ installed on your system.
INSTALL
-----------
It is recommended to set up these these tools with Lumberyard's CMake build commands.
It is recommended to set up these these tools with O3DE's CMake build commands.
Assuming CMake is already setup on your operating system, below are some sample build commands:
cd /path/to/od3e/
mkdir windows_vs2019
@@ -206,8 +206,8 @@ def run():
# PostFX Layer Component
ComponentTests("PostFX Layer")
# Radius Weight Modifier Component
ComponentTests("Radius Weight Modifier")
# PostFX Radius Weight Modifier Component
ComponentTests("PostFX Radius Weight Modifier")
# Light Component
ComponentTests("Light")
@@ -23,8 +23,7 @@ import azlmbr.legacy.general as general
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from atom_renderer.atom_utils import screenshot_utils
from atom_renderer.atom_utils import atom_component_helper
from atom_renderer.atom_utils import atom_component_helper, atom_constants, screenshot_utils
from editor_python_test_tools.editor_test_helper import EditorTestHelper
helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
@@ -92,7 +91,7 @@ def area_light_test():
'SetComponentProperty',
light_component_id_pair,
LIGHT_TYPE_PROPERTY,
atom_component_helper.LIGHT_TYPES['capsule']
atom_constants.LIGHT_TYPES['capsule']
)
# Update color and take screenshot in game mode
@@ -118,7 +117,7 @@ def area_light_test():
'SetComponentProperty',
light_component_id_pair,
LIGHT_TYPE_PROPERTY,
atom_component_helper.LIGHT_TYPES['spot_disk']
atom_constants.LIGHT_TYPES['spot_disk']
)
area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0)
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation)
@@ -131,7 +130,7 @@ def area_light_test():
'SetComponentProperty',
light_component_id_pair,
LIGHT_TYPE_PROPERTY,
atom_component_helper.LIGHT_TYPES['sphere']
atom_constants.LIGHT_TYPES['sphere']
)
general.idle_wait(1.0)
screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name)
@@ -210,7 +209,7 @@ def spot_light_test():
'SetComponentProperty',
light_component_type,
LIGHT_TYPE_PROPERTY,
atom_component_helper.LIGHT_TYPES['spot_disk']
atom_constants.LIGHT_TYPES['spot_disk']
)
general.idle_wait(1.0)
@@ -32,7 +32,7 @@ class TestAtomEditorComponentsMain(object):
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
1. Display Mapper
2. Light
3. Radius Weight Modifier
3. PostFX Radius Weight Modifier
4. PostFX Layer
5. Physical Sky
6. Global Skylight (IBL)
@@ -126,18 +126,18 @@ class TestAtomEditorComponentsMain(object):
"PostFX Layer_test: Entity deleted: True",
"PostFX Layer_test: UNDO entity deletion works: True",
"PostFX Layer_test: REDO entity deletion works: True",
# Radius Weight Modifier Component
"Radius Weight Modifier Entity successfully created",
"Radius Weight Modifier_test: Component added to the entity: True",
"Radius Weight Modifier_test: Component removed after UNDO: True",
"Radius Weight Modifier_test: Component added after REDO: True",
"Radius Weight Modifier_test: Entered game mode: True",
"Radius Weight Modifier_test: Exit game mode: True",
"Radius Weight Modifier_test: Entity is hidden: True",
"Radius Weight Modifier_test: Entity is shown: True",
"Radius Weight Modifier_test: Entity deleted: True",
"Radius Weight Modifier_test: UNDO entity deletion works: True",
"Radius Weight Modifier_test: REDO entity deletion works: True",
# PostFX Radius Weight Modifier Component
"PostFX Radius Weight Modifier Entity successfully created",
"PostFX Radius Weight Modifier_test: Component added to the entity: True",
"PostFX Radius Weight Modifier_test: Component removed after UNDO: True",
"PostFX Radius Weight Modifier_test: Component added after REDO: True",
"PostFX Radius Weight Modifier_test: Entered game mode: True",
"PostFX Radius Weight Modifier_test: Exit game mode: True",
"PostFX Radius Weight Modifier_test: Entity is hidden: True",
"PostFX Radius Weight Modifier_test: Entity is shown: True",
"PostFX Radius Weight Modifier_test: Entity deleted: True",
"PostFX Radius Weight Modifier_test: UNDO entity deletion works: True",
"PostFX Radius Weight Modifier_test: REDO entity deletion works: True",
# Light Component
"Light Entity successfully created",
"Light_test: Component added to the entity: True",
@@ -61,7 +61,7 @@ class AssetPickerUIUXTest(EditorTestHelper):
5) Verify if Mesh Asset is assigned via both OK/Enter options
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -37,7 +37,7 @@ class TestBasicEditorWorkflows(EditorTestHelper):
async def run_test(self):
"""
Summary:
Open Lumberyard editor and check if basic Editor workflows are completable.
Open O3DE editor and check if basic Editor workflows are completable.
Expected Behavior:
- A new level can be created
@@ -48,7 +48,7 @@ class TestBasicEditorWorkflows(EditorTestHelper):
- Level can be exported
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -36,7 +36,7 @@ class TestEditMenuOptions(EditorTestHelper):
2) Interact with Edit Menu options
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -32,7 +32,7 @@ class TestFileMenuOptions(EditorTestHelper):
2) Interact with File Menu options
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -36,7 +36,7 @@ class TestViewMenuOptions(EditorTestHelper):
2) Interact with View Menu options
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -52,7 +52,7 @@ def Pane_PropertiesChanged_RetainsOnRestart():
from utils import TestHelper as helper
import pyside_utils
# Lumberyard Imports
# O3DE Imports
import azlmbr.legacy.general as general
# Pyside imports
@@ -73,5 +73,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
)
ly_add_pytest(
NAME AutomatedTesting::LoadLevelCPU
TEST_SUITE sandbox
PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_CPULoadLevel_Works.py
TIMEOUT 100
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
AZ::PythonBindingsExample
Legacy::Editor
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
)
endif()
@@ -53,7 +53,7 @@ def Editor_NewExistingLevels_Works():
10) Save, Load and Export an existing level and close editor
Note:
- This test file must be called from the Lumberyard Editor command terminal
- This test file must be called from the O3DE Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
@@ -24,7 +24,7 @@ from ly_remote_console.remote_console_commands import (
@pytest.mark.parametrize("launcher_platform", ["windows"])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("level", ["Simple"])
@pytest.mark.SUITE_smoke
@pytest.mark.SUITE_sandbox
class TestRemoteConsoleLoadLevelWorks(object):
@pytest.fixture
def remote_console_instance(self, request):
@@ -1,17 +1,5 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "iPhoneNotificationIcon40x40.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "iPhoneNotificationIcon60x60.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
@@ -48,18 +36,6 @@
"filename" : "iPhoneAppIcon180x180.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "iPadNotificationIcon20x20.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "iPadNotificationIcon40x40.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
@@ -101,16 +77,10 @@
"idiom" : "ipad",
"filename" : "iPadProAppIcon167x167.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "iOSAppStoreIcon1024x1024.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
}
@@ -1,17 +1,5 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "iPhoneNotificationIcon40x40.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "iPhoneNotificationIcon60x60.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
@@ -48,18 +36,6 @@
"filename" : "iPhoneAppIcon180x180.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "iPadNotificationIcon20x20.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "iPadNotificationIcon40x40.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
@@ -101,16 +77,10 @@
"idiom" : "ipad",
"filename" : "iPadProAppIcon167x167.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "iOSAppStoreIcon1024x1024.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
}
@@ -1,50 +1,5 @@
{
"images" : [
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "2436h",
"filename" : "iPhoneLaunchImage1125x2436.png",
"minimum-system-version" : "11.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "2436h",
"filename" : "iPhoneLaunchImage2436x1125.png",
"minimum-system-version" : "11.0",
"orientation" : "landscape",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "iPhoneLaunchImage1242x2208.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "iPhoneLaunchImage2208x1242.png",
"minimum-system-version" : "8.0",
"orientation" : "landscape",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "667h",
"filename" : "iPhoneLaunchImage750x1334.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
@@ -166,4 +121,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
@@ -10,7 +10,6 @@
// Editor
#include "PropertyCtrl.h"
#include "PropertyAnimationCtrl.h"
#include "PropertyResourceCtrl.h"
#include "PropertyGenericCtrl.h"
#include "PropertyMiscCtrl.h"
@@ -22,9 +21,7 @@ void RegisterReflectedVarHandlers()
if (!registered)
{
registered = true;
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler());
@@ -73,16 +73,6 @@ void GenericPopupPropertyEditor::SetPropertyType(PropertyType type)
m_propertyType = type;
}
void ReverbPresetPropertyEditor::onEditClicked()
{
CSelectEAXPresetDlg PresetDlg(this);
PresetDlg.SetCurrPreset(GetValue());
if (PresetDlg.exec() == QDialog::Accepted)
{
SetValue(PresetDlg.GetCurrPreset());
}
}
void SequencePropertyEditor::onEditClicked()
{
CSelectSequenceDialog gtDlg(this);
@@ -96,15 +96,6 @@ public:
}
};
class ReverbPresetPropertyEditor
: public GenericPopupPropertyEditor
{
public:
ReverbPresetPropertyEditor(QWidget* pParent = nullptr)
: GenericPopupPropertyEditor(pParent){}
void onEditClicked() override;
};
class MissionObjPropertyEditor
: public GenericPopupPropertyEditor
{
@@ -155,7 +146,6 @@ public:
// So we use our own
#define CONST_AZ_CRC(name, value) AZ::u32(value)
using ReverbPresetPropertyHandler = GenericPopupWidgetHandler<ReverbPresetPropertyEditor, CONST_AZ_CRC("ePropertyReverbPreset", 0x51469f38)>;
using MissionObjPropertyHandler = GenericPopupWidgetHandler<MissionObjPropertyEditor, CONST_AZ_CRC("ePropertyMissionObj", 0x4a2d0dc8)>;
using SequencePropertyHandler = GenericPopupWidgetHandler<SequencePropertyEditor, CONST_AZ_CRC("ePropertySequence", 0xdd1c7d44)>;
using SequenceIdPropertyHandler = GenericPopupWidgetHandler<SequenceIdPropertyEditor, CONST_AZ_CRC("ePropertySequenceId", 0x05983dcc)>;
@@ -17,9 +17,9 @@
// AzToolsFramework
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h>
// Editor
#include "IResourceSelectorHost.h"
#include "Controls/QToolTipWidget.h"
#include "Controls/BitmapToolTip.h"
@@ -35,8 +35,8 @@ BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/)
void BrowseButton::SetPathAndEmit(const QString& path)
{
//only emit if path changes, except for ePropertyGeomCache. Old property control
if (path != m_path || m_propertyType == ePropertyGeomCache)
//only emit if path changes. Old property control
if (path != m_path)
{
m_path = path;
emit PathChanged(m_path);
@@ -78,21 +78,6 @@ private:
// Filters for texture.
selection = AssetSelectionModel::AssetGroupSelection("Texture");
}
else if (m_propertyType == ePropertyModel)
{
// Filters for models.
selection = AssetSelectionModel::AssetGroupSelection("Geometry");
}
else if (m_propertyType == ePropertyGeomCache)
{
// Filters for geom caches.
selection = AssetSelectionModel::AssetTypeSelection("Geom Cache");
}
else if (m_propertyType == ePropertyFile)
{
// Filters for files.
selection = AssetSelectionModel::AssetTypeSelection("File");
}
else
{
return;
@@ -106,14 +91,7 @@ private:
switch (m_propertyType)
{
case ePropertyTexture:
case ePropertyModel:
newPath.replace("\\\\", "/");
}
switch (m_propertyType)
{
case ePropertyTexture:
case ePropertyModel:
case ePropertyFile:
if (newPath.size() > MAX_PATH)
{
newPath.resize(MAX_PATH);
@@ -125,26 +103,51 @@ private:
}
};
class ResourceSelectorButton
class AudioControlSelectorButton
: public BrowseButton
{
public:
AZ_CLASS_ALLOCATOR(ResourceSelectorButton, AZ::SystemAllocator, 0);
AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0);
ResourceSelectorButton(PropertyType type, QWidget* pParent = nullptr)
AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr)
: BrowseButton(type, pParent)
{
setToolTip(tr("Select resource"));
setToolTip(tr("Select Audio Control"));
}
private:
void OnClicked() override
{
SResourceSelectorContext x;
x.parentWidget = this;
x.typeName = Prop::GetPropertyTypeToResourceType(m_propertyType);
QString newPath = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, m_path);
SetPathAndEmit(newPath);
AZStd::string resourceResult;
auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType
{
switch (type)
{
case ePropertyAudioTrigger:
return AzToolsFramework::AudioPropertyType::Trigger;
case ePropertyAudioRTPC:
return AzToolsFramework::AudioPropertyType::Rtpc;
case ePropertyAudioSwitch:
return AzToolsFramework::AudioPropertyType::Switch;
case ePropertyAudioSwitchState:
return AzToolsFramework::AudioPropertyType::SwitchState;
case ePropertyAudioEnvironment:
return AzToolsFramework::AudioPropertyType::Environment;
case ePropertyAudioPreloadRequest:
return AzToolsFramework::AudioPropertyType::Preload;
default:
return AzToolsFramework::AudioPropertyType::NumTypes;
}
};
auto propType = ConvertLegacyAudioPropertyType(m_propertyType);
if (propType != AzToolsFramework::AudioPropertyType::NumTypes)
{
AzToolsFramework::AudioControlSelectorRequestBus::EventResult(
resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource,
AZStd::string_view{ m_path.toUtf8().constData() });
SetPathAndEmit(QString{ resourceResult.c_str() });
}
}
};
@@ -235,18 +238,13 @@ void FileResourceSelectorWidget::SetPropertyType(PropertyType type)
AddButton(new TextureEditButton);
m_previewToolTip.reset(new CBitmapToolTip);
break;
case ePropertyModel:
case ePropertyGeomCache:
case ePropertyAudioTrigger:
case ePropertyAudioSwitch:
case ePropertyAudioSwitchState:
case ePropertyAudioRTPC:
case ePropertyAudioEnvironment:
case ePropertyAudioPreloadRequest:
AddButton(new ResourceSelectorButton(type));
break;
case ePropertyFile:
AddButton(new FileBrowseButton(type));
AddButton(new AudioControlSelectorButton(type));
break;
default:
break;
@@ -1,93 +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 : implementation file
#include "EditorDefs.h"
#include "ReflectedPropertiesPanel.h"
/////////////////////////////////////////////////////////////////////////////
// ReflectedPropertiesPanel dialog
ReflectedPropertiesPanel::ReflectedPropertiesPanel(QWidget* pParent)
: ReflectedPropertyControl(pParent)
{
}
//////////////////////////////////////////////////////////////////////////
void ReflectedPropertiesPanel::DeleteVars()
{
ClearVarBlock();
m_updateCallbacks.clear();
m_varBlock = nullptr;
}
//////////////////////////////////////////////////////////////////////////
void ReflectedPropertiesPanel::SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
{
assert(vb);
m_varBlock = vb;
RemoveAllItems();
m_varBlock = vb;
AddVarBlock(m_varBlock, category);
SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
// When new object set all previous callbacks freed.
m_updateCallbacks.clear();
if (updCallback)
{
stl::push_back_unique(m_updateCallbacks, updCallback);
}
}
//////////////////////////////////////////////////////////////////////////
void ReflectedPropertiesPanel::AddVars(CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
{
assert(vb);
bool bNewBlock = false;
// Make a clone of properties.
if (!m_varBlock)
{
RemoveAllItems();
m_varBlock = vb->Clone(true);
AddVarBlock(m_varBlock, category);
bNewBlock = true;
}
m_varBlock->Wire(vb);
if (bNewBlock)
{
SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
// When new object set all previous callbacks freed.
m_updateCallbacks.clear();
}
if (updCallback)
{
stl::push_back_unique(m_updateCallbacks, updCallback);
}
}
void ReflectedPropertiesPanel::OnPropertyChanged(IVariable* pVar)
{
std::list<ReflectedPropertyControl::UpdateVarCallback*>::iterator iter;
for (iter = m_updateCallbacks.begin(); iter != m_updateCallbacks.end(); ++iter)
{
(*iter)->operator()(pVar);
}
}
@@ -1,46 +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_EDITOR_REFLECTEDPROPERTIESPANEL_H
#define CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
#pragma once
#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h"
#include "Util/Variable.h"
/////////////////////////////////////////////////////////////////////////////
// ReflectedPropertiesPanel dialog
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
//This class is a port of ReflectedPropertiesPanel to use the ReflectedPropertyControl
class SANDBOX_API ReflectedPropertiesPanel
: public ReflectedPropertyControl
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
ReflectedPropertiesPanel(QWidget* pParent = nullptr); // standard constructor
void DeleteVars();
void AddVars(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
void SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
protected:
void OnPropertyChanged(IVariable* pVar);
protected:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
TSmartPtr<CVarBlock> m_varBlock;
std::list<ReflectedPropertyControl::UpdateVarCallback*> m_updateCallbacks;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
#endif // CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
@@ -255,9 +255,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
case ePropertySelection:
m_reflectedVarAdapter = new ReflectedVarEnumAdapter;
break;
case ePropertyAnimation:
m_reflectedVarAdapter = new ReflectedVarAnimationAdapter;
break;
case ePropertyColor:
m_reflectedVarAdapter = new ReflectedVarColorAdapter;
break;
@@ -265,7 +262,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
m_reflectedVarAdapter = new ReflectedVarUserAdapter;
break;
case ePropertyEquip:
case ePropertyReverbPreset:
case ePropertyGameToken:
case ePropertyMissionObj:
case ePropertySequence:
@@ -276,15 +272,12 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type);
break;
case ePropertyTexture:
case ePropertyModel:
case ePropertyGeomCache:
case ePropertyAudioTrigger:
case ePropertyAudioSwitch:
case ePropertyAudioSwitchState:
case ePropertyAudioRTPC:
case ePropertyAudioEnvironment:
case ePropertyAudioPreloadRequest:
case ePropertyFile:
m_reflectedVarAdapter = new ReflectedVarResourceAdapter;
break;
case ePropertyFloatCurve:
@@ -569,7 +562,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo
break;
case ePropertyTexture:
case ePropertyModel:
value.replace('\\', '/');
break;
}
@@ -578,8 +570,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo
switch (m_type)
{
case ePropertyTexture:
case ePropertyModel:
case ePropertyFile:
if (value.length() >= MAX_PATH)
{
value = value.left(MAX_PATH);
@@ -31,12 +31,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
->Field("description", &CReflectedVar::m_description)
->Field("varName", &CReflectedVar::m_varName);
serializeContext->Class <CReflectedVarAnimation, CReflectedVar >()
->Version(1)
->Field("animation", &CReflectedVarAnimation::m_animation)
->Field("entityID", &CReflectedVarAnimation::m_entityID)
;
serializeContext->Class <CReflectedVarResource, CReflectedVar >()
->Version(1)
->Field("path", &CReflectedVarResource::m_path)
@@ -76,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
AZ::EditContext* ec = serializeContext->GetEditContext();
if (ec)
{
ec->Class< CReflectedVarAnimation >("VarAnimation", "Animation")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAnimation::varName)
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAnimation::description)
;
ec->Class< CReflectedVarResource >("VarResource", "Resource")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName)
@@ -284,8 +272,6 @@ AZ::u32 CReflectedVarGenericProperty::handler()
return AZ_CRC("ePropertyShader", 0xc40932f1);
case ePropertyEquip:
return AZ_CRC("ePropertyEquip", 0x66ffd290);
case ePropertyReverbPreset:
return AZ_CRC("ePropertyReverbPreset", 0x51469f38);
case ePropertyDeprecated0:
return AZ_CRC("ePropertyCustomAction", 0x4ffa5ba5);
case ePropertyGameToken:
@@ -265,32 +265,8 @@ public:
AZ::Vector3 m_color;
};
//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
class CReflectedVarAnimation
: public CReflectedVar
{
public:
AZ_RTTI(CReflectedVarAnimation, "{635D982E-23EC-463F-8F33-4FC2C19D5673}", CReflectedVar)
CReflectedVarAnimation(const AZStd::string& name)
: CReflectedVar(name)
, m_entityID(0)
{}
CReflectedVarAnimation()
: m_entityID(0){}
AZStd::string varName() const { return m_varName; }
AZStd::string description() const { return m_description; }
AZStd::string m_animation;
AZ::EntityId m_entityID;
};
//Class to hold:
// ePropertyTexture (IVariable::DT_TEXTURE)
// ePropertyMaterial (IVariable::DT_MATERIAL)
// ePropertyModel (IVariable::DT_OBJECT)
// ePropertyGeomCache (IVariable::DT_GEOM_CACHE)
// ePropertyAudioTrigger (IVariable::DT_AUDIO_TRIGGER)
// ePropertyAudioSwitch (IVariable::DT_AUDIO_SWITCH )
// ePropertyAudioSwitchState (IVariable::DT_AUDIO_SWITCH_STATE)
@@ -344,7 +320,6 @@ public:
AZStd::vector<AZStd::string> m_itemDescriptions;
};
//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
class CReflectedVarSpline
: public CReflectedVar
{
@@ -392,25 +392,6 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
void ReflectedVarAnimationAdapter::SetVariable(IVariable *pVariable)
{
m_reflectedVar.reset(new CReflectedVarAnimation(pVariable->GetHumanName().toUtf8().data()));
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
}
void ReflectedVarAnimationAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
{
m_reflectedVar->m_entityID = static_cast<AZ::EntityId>(pVariable->GetUserData().value<AZ::u64>());
m_reflectedVar->m_animation = pVariable->GetDisplayValue().toUtf8().data();
}
void ReflectedVarAnimationAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
{
pVariable->SetUserData(static_cast<AZ::u64>(m_reflectedVar->m_entityID));
pVariable->SetDisplayValue(m_reflectedVar->m_animation.c_str());
}
void ReflectedVarResourceAdapter::SetVariable(IVariable *pVariable)
{
m_reflectedVar.reset(new CReflectedVarResource(pVariable->GetHumanName().toUtf8().data()));
@@ -429,7 +410,7 @@ void ReflectedVarResourceAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
void ReflectedVarResourceAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
{
const bool bForceModified = (m_reflectedVar->m_propertyType == ePropertyGeomCache);
const bool bForceModified = false;
pVariable->SetForceModified(bForceModified);
pVariable->SetDisplayValue(m_reflectedVar->m_path.c_str());
@@ -218,20 +218,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
class EDITOR_CORE_API ReflectedVarAnimationAdapter
: public ReflectedVarAdapter
{
public:
void SetVariable(IVariable* pVariable) override;
void SyncReflectedVarToIVar(IVariable* pVariable) override;
void SyncIVarToReflectedVar(IVariable* pVariable) override;
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
private:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
QScopedPointer<CReflectedVarAnimation > m_reflectedVar;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
class EDITOR_CORE_API ReflectedVarResourceAdapter
: public ReflectedVarAdapter
{
+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();
}
//////////////////////////////////////////////////////////////////////////
+2 -2
View File
@@ -130,7 +130,7 @@ public:
HotKey_BuildDefaults();
for (QPair<QString, QString> key : keys)
{
for (unsigned int j = 0; j < hotkeys.count(); j++)
for (int j = 0; j < hotkeys.count(); j++)
{
if (hotkeys[j].path.compare(key.first, Qt::CaseInsensitive) == 0)
{
@@ -256,7 +256,7 @@ public:
hotkey.second = settings.value("keySequence").toString();
if (!hotkey.first.isEmpty())
{
for (unsigned int j = 0; j < hotkeys.count(); j++)
for (int j = 0; j < hotkeys.count(); j++)
{
if (hotkeys[j].path.compare(hotkey.first, Qt::CaseInsensitive) == 0)
{
+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))
-2
View File
@@ -68,7 +68,6 @@ class CDisplaySettings;
struct SGizmoParameters;
class CLevelIndependentFileMan;
class CSelectionTreeManager;
struct IResourceSelectorHost;
struct SEditorSettings;
class CGameExporter;
class IAWSResourceManager;
@@ -714,7 +713,6 @@ struct IEditor
virtual ESystemConfigSpec GetEditorConfigSpec() const = 0;
virtual ESystemConfigPlatform GetEditorConfigPlatform() const = 0;
virtual void ReloadTemplates() = 0;
virtual IResourceSelectorHost* GetResourceSelectorHost() = 0;
virtual void ShowStatusText(bool bEnable) = 0;
// Provides a way to extend the context menu of an object. The function gets called every time the menu is opened.
+3 -5
View File
@@ -67,7 +67,6 @@ AZ_POP_DISABLE_WARNING
#include "EditorFileMonitor.h"
#include "MainStatusBar.h"
#include "ResourceSelectorHost.h"
#include "Util/FileUtil_impl.h"
#include "Util/ImageUtil_impl.h"
#include "LogFileImpl.h"
@@ -187,7 +186,6 @@ CEditorImpl::CEditorImpl()
m_pAnimationContext = new CAnimationContext;
m_pImageUtil = new CImageUtil_impl();
m_pResourceSelectorHost.reset(CreateResourceSelectorHost());
m_selectedRegion.min = Vec3(0, 0, 0);
m_selectedRegion.max = Vec3(0, 0, 0);
DetectVersion();
@@ -252,7 +250,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 +271,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 +1458,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener)
ISourceControl* CEditorImpl::GetSourceControl()
{
CryAutoLock<CryMutex> lock(m_pluginMutex);
AZStd::scoped_lock lock(m_pluginMutex);
if (m_pSourceControl)
{
+1 -3
View File
@@ -290,7 +290,6 @@ public:
ESystemConfigPlatform GetEditorConfigPlatform() const;
void ReloadTemplates();
void AddErrorMessage(const QString& text, const QString& caption);
IResourceSelectorHost* GetResourceSelectorHost() { return m_pResourceSelectorHost.get(); }
virtual void ShowStatusText(bool bEnable);
void OnObjectContextMenuOpened(QMenu* pMenu, const CBaseObject* pObject);
@@ -374,7 +373,6 @@ protected:
//! Export manager for exporting objects and a terrain from the game to DCC tools
CExportManager* m_pExportManager;
std::unique_ptr<CEditorFileMonitor> m_pEditorFileMonitor;
std::unique_ptr<IResourceSelectorHost> m_pResourceSelectorHost;
QString m_selectFileBuffer;
QString m_levelNameBuffer;
@@ -401,7 +399,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 -1
View File
@@ -65,7 +65,7 @@ struct HotKey
int size = (m_catSize < o_catSize) ? m_catSize : o_catSize;
//sort categories to keep them together
for (unsigned int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
if (m_categories[i] < o_categories[i])
{
-135
View File
@@ -1,135 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
// The aim of IResourceSelectorHost is to unify resource selection dialogs in a one
// API that can be reused with plugins. It also makes possible to register new
// resource selectors dynamically, e.g. inside plugins.
//
// Here is how new selectors are created. In your implementation file you add handler function:
//
// #include "IResourceSelectorHost.h"
//
// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue)
// {
// CMyModalDialog dialog(CWnd::FromHandle(x.parentWindow));
// ...
// return previousValue;
// }
// REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "Icons/sound_16x16.png")
//
// Here is how it can be invoked directly:
//
// SResourceSelectorContext x;
// x.parentWindow = parent.GetSafeHwnd();
// x.typeName = "Sound";
// string newValue = GetIEditor()->GetResourceSelector()->SelectResource(x, previousValue).c_str();
//
// If you have your own resource selectors in the plugin you will need to run
//
// RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelector())
//
// during plugin initialization.
//
// If you want to be able to pass some custom context to the selector (e.g. source of the information for the
// list of items or something similar) then you can add a poitner argument to your selector function, i.e.:
//
// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue,
// SoundFileList* list) // your context argument
#include <QString>
class QWidget;
struct SResourceSelectorContext
{
const char* typeName;
// use either parentWidget or parentWindow (not both) until everything porting to QWidget.
QWidget* parentWidget;
unsigned int entityId;
void* contextObject;
SResourceSelectorContext()
: parentWidget(0)
, typeName(0)
, entityId(0)
, contextObject()
{
}
};
// TResourceSelecitonFunction is used to declare handlers for specific types.
//
// For canceled dialogs previousValue should be returned.
typedef QString (* TResourceSelectionFunction)(const SResourceSelectorContext& selectorContext, const QString& previousValue);
typedef QString (* TResourceSelectionFunctionWithContext)(const SResourceSelectorContext& selectorContext, const QString& previousValue, void* contextObject);
struct SStaticResourceSelectorEntry;
// See note at the beginning of the file.
struct IResourceSelectorHost
{
virtual ~IResourceSelectorHost() = default;
virtual QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) = 0;
virtual const char* ResourceIconPath(const char* typeName) const = 0;
virtual void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) = 0;
// secondary responsibility of this class is to store global selections
virtual void SetGlobalSelection(const char* resourceType, const char* value) = 0;
virtual const char* GetGlobalSelection(const char* resourceType) const = 0;
};
// ---------------------------------------------------------------------------
#define INTERNAL_RSH_COMBINE_UTIL(A, B) A##B
#define INTERNAL_RSH_COMBINE(A, B) INTERNAL_RSH_COMBINE_UTIL(A, B)
#define REGISTER_RESOURCE_SELECTOR(name, function, icon) \
static SStaticResourceSelectorEntry INTERNAL_RSH_COMBINE(selector_##function, __LINE__)((name), (function), (icon));
struct SStaticResourceSelectorEntry
{
const char* typeName;
TResourceSelectionFunction function;
TResourceSelectionFunctionWithContext functionWithContext;
const char* iconPath;
static SStaticResourceSelectorEntry*& GetFirst() { static SStaticResourceSelectorEntry* first; return first; }
SStaticResourceSelectorEntry* next;
SStaticResourceSelectorEntry(const char* typeName, TResourceSelectionFunction function, const char* icon)
: typeName(typeName)
, function(function)
, functionWithContext()
, iconPath(icon)
{
next = GetFirst();
GetFirst() = this;
}
template<class T>
SStaticResourceSelectorEntry(const char* typeName, QString (*function)(const SResourceSelectorContext&, const QString& previousValue, T * context), const char* icon)
: typeName(typeName)
, function()
, functionWithContext(TResourceSelectionFunctionWithContext(function))
, iconPath(icon)
{
next = GetFirst();
GetFirst() = this;
}
};
inline void RegisterModuleResourceSelectors(IResourceSelectorHost* editorResourceSelector)
{
for (SStaticResourceSelectorEntry* current = SStaticResourceSelectorEntry::GetFirst(); current != 0; current = current->next)
{
editorResourceSelector->RegisterResourceSelector(current);
}
}
-1
View File
@@ -178,7 +178,6 @@ public:
MOCK_CONST_METHOD0(GetEditorConfigSpec, ESystemConfigSpec());
MOCK_CONST_METHOD0(GetEditorConfigPlatform, ESystemConfigPlatform());
MOCK_METHOD0(ReloadTemplates, void());
MOCK_METHOD0(GetResourceSelectorHost, IResourceSelectorHost* ());
MOCK_METHOD1(ShowStatusText, void(bool ));
MOCK_METHOD1(RegisterObjectContextMenuExtension, void(TContextMenuExtensionFunc ));
MOCK_METHOD0(GetEnv, SSystemGlobalEnvironment* ());
@@ -9,7 +9,6 @@
#include "ComponentEntityEditorPlugin.h"
#include <LyViewPaneNames.h>
#include "IResourceSelectorHost.h"
#include "UI/QComponentEntityEditorMainWindow.h"
#include "UI/QComponentEntityEditorOutlinerWindow.h"
@@ -180,8 +179,6 @@ ComponentEntityEditorPlugin::ComponentEntityEditorPlugin([[maybe_unused]] IEdito
RegisterViewPane<SliceRelationshipWidget>(LyViewPane::SliceRelationships, LyViewPane::CategoryTools, options);
}
RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelectorHost());
ComponentEntityEditorPluginInternal::RegisterSandboxObjects();
// Check for common mistakes in component declarations
@@ -82,7 +82,6 @@
#include <Editor/QtViewPaneManager.h>
#include <Editor/EditorViewportSettings.h>
#include <Editor/Util/PathUtil.h>
#include <IResourceSelectorHost.h>
#include "CryEdit.h"
#include "Undo/Undo.h"
@@ -1387,16 +1386,6 @@ AZStd::string SandboxIntegrationManager::GetLevelName()
return AZStd::string(GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().constData());
}
AZStd::string SandboxIntegrationManager::SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue)
{
SResourceSelectorContext context;
context.parentWidget = GetMainWindow();
context.typeName = resourceType.c_str();
QString resource = GetEditor()->GetResourceSelectorHost()->SelectResource(context, previousValue.c_str());
return AZStd::string(resource.toUtf8().constData());
}
void SandboxIntegrationManager::OnContextReset()
{
// Deselect everything.
@@ -158,7 +158,6 @@ private:
void LaunchLuaEditor(const char* files) override;
bool IsLevelDocumentOpen() override;
AZStd::string GetLevelName() override;
AZStd::string SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue) override;
void OpenPinnedInspector(const AzToolsFramework::EntityIdSet& entities) override;
void ClosePinnedInspector(AzToolsFramework::EntityPropertyEditor* editor) override;
void GoToSelectedOrHighlightedEntitiesInViewports() override;
@@ -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)
{
-163
View File
@@ -1,163 +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 "EditorDefs.h"
#include "ResourceSelectorHost.h"
// Qt
#include <QMessageBox>
#include <QString>
// AzToolsFramework
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
class CResourceSelectorHost
: public IResourceSelectorHost
{
public:
CResourceSelectorHost()
{
RegisterModuleResourceSelectors(this);
}
QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) override
{
if (!context.typeName)
{
assert(false && "SResourceSelectorContext::typeName is not specified");
return QString();
}
TTypeMap::iterator it = m_typeMap.find(context.typeName);
if (it == m_typeMap.end())
{
QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("No Resource Selector is registered for resource type \"%1\"").arg(context.typeName));
return previousValue;
}
QString result = previousValue;
if (it->second->function)
{
result = it->second->function(context, previousValue);
}
else if (it->second->functionWithContext)
{
result = it->second->functionWithContext(context, previousValue, context.contextObject);
}
return result;
}
const char* ResourceIconPath(const char* typeName) const override
{
TTypeMap::const_iterator it = m_typeMap.find(typeName);
if (it != m_typeMap.end())
{
return it->second->iconPath;
}
return "";
}
void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) override
{
m_typeMap[entry->typeName] = entry;
}
void SetGlobalSelection(const char* resourceType, const char* value) override
{
if (!resourceType || !value)
{
return;
}
m_globallySelectedResources[resourceType] = value;
}
const char* GetGlobalSelection(const char* resourceType) const override
{
if (!resourceType)
{
return "";
}
auto it = m_globallySelectedResources.find(resourceType);
if (it != m_globallySelectedResources.end())
{
return it->second.c_str();
}
return "";
}
private:
using TTypeMap = std::map<AZStd::string, const SStaticResourceSelectorEntry *, stl::less_stricmp<AZStd::string>>;
TTypeMap m_typeMap;
std::map<AZStd::string, AZStd::string> m_globallySelectedResources;
};
// ---------------------------------------------------------------------------
IResourceSelectorHost* CreateResourceSelectorHost()
{
return new CResourceSelectorHost();
}
// ---------------------------------------------------------------------------
QString SoundFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue)
{
AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Audio");
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
if (selection.IsValid())
{
return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str()));
}
else
{
return Path::FullPathToGamePath(previousValue);
}
}
REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "")
// ---------------------------------------------------------------------------
QString ModelFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue)
{
AssetSelectionModel selection = AssetSelectionModel::AssetGroupSelection("Geometry");
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
if (selection.IsValid())
{
return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str()));
}
else
{
return Path::FullPathToGamePath(previousValue);
}
}
REGISTER_RESOURCE_SELECTOR("Model", ModelFileSelector, "")
// ---------------------------------------------------------------------------
QString GeomCacheFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue)
{
AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Geom Cache");
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
if (selection.IsValid())
{
return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str()));
}
else
{
return Path::FullPathToGamePath(previousValue);
}
}
REGISTER_RESOURCE_SELECTOR("GeomCache", GeomCacheFileSelector, "")
-18
View File
@@ -1,18 +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_EDITOR_RESOURCESELECTORHOST_H
#define CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H
#pragma once
#include "IResourceSelectorHost.h"
IResourceSelectorHost* CreateResourceSelectorHost();
#endif // CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H
-1
View File
@@ -9,7 +9,6 @@
#pragma once
#include "CryThread.h"
#include "../Include/SandboxAPI.h"
#include <QString>
#include <QFileInfo>
-2
View File
@@ -10,8 +10,6 @@
#include "StringHelpers.h"
#include "Util.h"
#include <AzCore/std/string/string.h>
int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1)
{
const size_t minLength = Util::getMin(str0.length(), str1.length());
+1 -1
View File
@@ -12,7 +12,7 @@
#pragma once
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <vector>
namespace StringHelpers
{
+1 -1
View File
@@ -351,7 +351,7 @@ void CVarBlock::EnableUpdateCallbacks(bool boEnable)
void CVarBlock::GatherUsedResourcesInVar(IVariable* pVar, CUsedResources& resources)
{
int type = pVar->GetDataType();
if (type == IVariable::DT_FILE || type == IVariable::DT_OBJECT || type == IVariable::DT_TEXTURE)
if (type == IVariable::DT_TEXTURE)
{
// this is file.
QString filename;
+2 -6
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
@@ -140,15 +142,10 @@ struct IVariable
DT_PERCENT, //!< Percent data type, (Same as simple but value is from 0-1 and UI will be from 0-100).
DT_COLOR,
DT_ANGLE,
DT_FILE,
DT_TEXTURE,
DT_ANIMATION,
DT_OBJECT,
DT_SHADER,
DT_LOCAL_STRING,
DT_EQUIP,
DT_REVERBPRESET,
DT_DEPRECATED0, // formerly DT_MATERIAL
DT_MATERIALLOOKUP,
DT_EXTARRAY, // Extendable Array
DT_SEQUENCE, // Movie Sequence (DEPRECATED, use DT_SEQUENCE_ID, instead.)
@@ -158,7 +155,6 @@ struct IVariable
DT_SEQUENCE_ID, // Movie Sequence
DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set
DT_PARTICLE_EFFECT,
DT_GEOM_CACHE, // Geometry cache
DT_DEPRECATED, // formerly DT_FLARE
DT_AUDIO_TRIGGER,
DT_AUDIO_SWITCH,
-33
View File
@@ -37,17 +37,12 @@ namespace Prop
{ IVariable::DT_CURVE | IVariable::DT_PERCENT, "FloatCurve", ePropertyFloatCurve, 13 },
{ IVariable::DT_CURVE | IVariable::DT_COLOR, "ColorCurve", ePropertyColorCurve, 1 },
{ IVariable::DT_ANGLE, "Angle", ePropertyAngle, 0 },
{ IVariable::DT_FILE, "File", ePropertyFile, 7 },
{ IVariable::DT_TEXTURE, "Texture", ePropertyTexture, 4 },
{ IVariable::DT_ANIMATION, "Animation", ePropertyAnimation, -1 },
{ IVariable::DT_MOTION, "Motion", ePropertyMotion, -1 },
{ IVariable::DT_OBJECT, "Model", ePropertyModel, 5 },
{ IVariable::DT_SIMPLE, "Selection", ePropertySelection, -1 },
{ IVariable::DT_SIMPLE, "List", ePropertyList, -1 },
{ IVariable::DT_SHADER, "Shader", ePropertyShader, 9 },
{ IVariable::DT_DEPRECATED0, "DEPRECATED", ePropertyDeprecated2, -1 },
{ IVariable::DT_EQUIP, "Equip", ePropertyEquip, 11 },
{ IVariable::DT_REVERBPRESET, "ReverbPreset", ePropertyReverbPreset, 11 },
{ IVariable::DT_LOCAL_STRING, "LocalString", ePropertyLocalString, 3 },
{ IVariable::DT_SEQUENCE, "Sequence", ePropertySequence, -1 },
{ IVariable::DT_MISSIONOBJ, "Mission Objective", ePropertyMissionObj, -1 },
@@ -55,7 +50,6 @@ namespace Prop
{ IVariable::DT_SEQUENCE_ID, "SequenceId", ePropertySequenceId, -1 },
{ IVariable::DT_LIGHT_ANIMATION, "LightAnimation", ePropertyLightAnimation, -1 },
{ IVariable::DT_PARTICLE_EFFECT, "ParticleEffect", ePropertyParticleName, 3 },
{ IVariable::DT_GEOM_CACHE, "Geometry Cache", ePropertyGeomCache, 5 },
{ IVariable::DT_AUDIO_TRIGGER, "Audio Trigger", ePropertyAudioTrigger, 6 },
{ IVariable::DT_AUDIO_SWITCH, "Audio Switch", ePropertyAudioSwitch, 6 },
{ IVariable::DT_AUDIO_SWITCH_STATE, "Audio Switch", ePropertyAudioSwitchState, 6 },
@@ -301,31 +295,4 @@ namespace Prop
return -1;
}
const char* GetPropertyTypeToResourceType(PropertyType type)
{
// The strings below are names used together with
// REGISTER_RESOURCE_SELECTOR. See IResourceSelector.h.
switch (type)
{
case ePropertyModel:
return "Model";
case ePropertyGeomCache:
return "GeomCache";
case ePropertyAudioTrigger:
return "AudioTrigger";
case ePropertyAudioSwitch:
return "AudioSwitch";
case ePropertyAudioSwitchState:
return "AudioSwitchState";
case ePropertyAudioRTPC:
return "AudioRTPC";
case ePropertyAudioEnvironment:
return "AudioEnvironment";
case ePropertyAudioPreloadRequest:
return "AudioPreloadRequest";
default:
return nullptr;
}
}
}
-6
View File
@@ -28,16 +28,11 @@ enum PropertyType
ePropertyAngle,
ePropertyFloatCurve,
ePropertyColorCurve,
ePropertyFile,
ePropertyTexture,
ePropertyAnimation,
ePropertyModel,
ePropertySelection,
ePropertyList,
ePropertyShader,
ePropertyDeprecated2, // formerly ePropertyMaterial
ePropertyEquip,
ePropertyReverbPreset,
ePropertyLocalString,
ePropertyDeprecated0, // formerly ePropertyCustomAction
ePropertyGameToken,
@@ -48,7 +43,6 @@ enum PropertyType
ePropertyLightAnimation,
ePropertyDeprecated1, // formerly ePropertyFlare
ePropertyParticleName,
ePropertyGeomCache,
ePropertyAudioTrigger,
ePropertyAudioSwitch,
ePropertyAudioSwitchState,
-8
View File
@@ -289,7 +289,6 @@ set(FILES
Include/IPlugin.h
Include/IPreferencesPage.h
Include/IRenderListener.h
Include/IResourceSelectorHost.h
Include/ISourceControl.h
Include/ISubObjectSelectionReferenceFrameCalculator.h
Include/ITextureDatabaseUpdater.h
@@ -360,8 +359,6 @@ set(FILES
Controls/TimelineCtrl.cpp
Controls/TimelineCtrl.h
Controls/WndGridHelper.h
Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp
Controls/ReflectedPropertyControl/PropertyAnimationCtrl.h
Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
Controls/ReflectedPropertyControl/PropertyGenericCtrl.h
Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp
@@ -372,8 +369,6 @@ set(FILES
Controls/ReflectedPropertyControl/PropertyResourceCtrl.h
Controls/ReflectedPropertyControl/PropertyCtrl.cpp
Controls/ReflectedPropertyControl/PropertyCtrl.h
Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp
Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h
MainStatusBar.cpp
MainStatusBar.h
MainStatusBarItems.h
@@ -590,8 +585,6 @@ set(FILES
FBXExporterDialog.ui
FileTypeUtils.cpp
LightmapCompiler/SimpleTriangleRasterizer.cpp
ResourceSelectorHost.cpp
ResourceSelectorHost.h
ToolBox.cpp
TrackViewNewSequenceDialog.cpp
TrackViewNewSequenceDialog.ui
@@ -668,7 +661,6 @@ set(FILES
TrackView/2DBezierKeyUIControls.cpp
TrackView/AssetBlendKeyUIControls.cpp
TrackView/CaptureKeyUIControls.cpp
TrackView/CharacterKeyUIControls.cpp
TrackView/ConsoleKeyUIControls.cpp
TrackView/EventKeyUIControls.cpp
TrackView/GotoKeyUIControls.cpp
@@ -728,6 +728,7 @@ namespace AZ
DestroyReflectionManager();
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearNotifiers();
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearMergeEvents();
// Uninit and unload any dynamic modules.
m_moduleManager->UnloadModules();
@@ -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
{
@@ -123,6 +123,36 @@ namespace AZ
using NotifyEvent = AZ::Event<AZStd::string_view, Type>;
using NotifyEventHandler = typename NotifyEvent::Handler;
using PreMergeEventCallback = AZStd::function<void(AZStd::string_view path, AZStd::string_view rootKey)>;
using PostMergeEventCallback = AZStd::function<void(AZStd::string_view path, AZStd::string_view rootKey)>;
using PreMergeEvent = AZ::Event<AZStd::string_view, AZStd::string_view>;
using PostMergeEvent = AZ::Event<AZStd::string_view, AZStd::string_view>;
using PreMergeEventHandler = typename PreMergeEvent::Handler;
using PostMergeEventHandler = typename PostMergeEvent::Handler;
struct ScopedMergeEvent
{
ScopedMergeEvent(
PreMergeEvent& preMergeEvent, PostMergeEvent& postMergeEvent, AZStd::string_view filePath, AZStd::string_view rootKey)
: m_preMergeEvent{ preMergeEvent }
, m_postMergeEvent{ postMergeEvent }
, m_filePath{ filePath }
, m_rootKey{ rootKey }
{
preMergeEvent.Signal(m_filePath, m_rootKey);
}
~ScopedMergeEvent()
{
m_postMergeEvent.Signal(m_filePath, m_rootKey);
}
PreMergeEvent& m_preMergeEvent;
PostMergeEvent& m_postMergeEvent;
AZStd::string_view m_filePath;
AZStd::string_view m_rootKey;
};
using VisitorCallback =
AZStd::function<VisitResponse(AZStd::string_view path, AZStd::string_view valueName, VisitAction action, Type type)>;
//! Base class for the visitor class during traversal over the Settings Registry. The type-agnostic function is always
@@ -169,6 +199,20 @@ namespace AZ
//! @callback The function to call when an entry gets a new/updated value.
[[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0;
//! Register a function that will be called before a file is merged.
//! @callback The function to call before a file is merged.
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0;
//! Register a function that will be called before a file is merged.
//! @callback The function to call before a file is merged.
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0;
//! Register a function that will be called after a file is merged.
//! @callback The function to call after a file is merged.
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0;
//! Register a function that will be called after a file is merged.
//! @callback The function to call after a file is merged.
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0;
//! Gets the boolean value at the provided path.
//! @param result The target to write the result to.
//! @param path The path to the value.
@@ -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,10 +224,82 @@ namespace AZ
void SettingsRegistryImpl::ClearNotifiers()
{
AZStd::scoped_lock lock(m_settingMutex);
AZStd::scoped_lock lock(m_notifierMutex);
m_notifiers.DisconnectAllHandlers();
}
auto SettingsRegistryImpl::RegisterPreMergeEvent(const PreMergeEventCallback& callback) -> PreMergeEventHandler
{
PreMergeEventHandler preMergeHandler{ callback };
{
AZStd::scoped_lock lock(m_settingMutex);
preMergeHandler.Connect(m_preMergeEvent);
}
return preMergeHandler;
}
auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventCallback&& callback) -> PreMergeEventHandler
{
PreMergeEventHandler preMergeHandler{ AZStd::move(callback) };
{
AZStd::scoped_lock lock(m_settingMutex);
preMergeHandler.Connect(m_preMergeEvent);
}
return preMergeHandler;
}
auto SettingsRegistryImpl::RegisterPostMergeEvent(const PostMergeEventCallback& callback) -> PostMergeEventHandler
{
PostMergeEventHandler postMergeHandler{ callback };
{
AZStd::scoped_lock lock(m_settingMutex);
postMergeHandler.Connect(m_postMergeEvent);
}
return postMergeHandler;
}
auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventCallback&& callback) -> PostMergeEventHandler
{
PostMergeEventHandler postMergeHandler{ AZStd::move(callback) };
{
AZStd::scoped_lock lock(m_settingMutex);
postMergeHandler.Connect(m_postMergeEvent);
}
return postMergeHandler;
}
void SettingsRegistryImpl::ClearMergeEvents()
{
AZStd::scoped_lock lock(m_settingMutex);
m_preMergeEvent.DisconnectAllHandlers();
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())
@@ -239,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)
{
@@ -316,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)
{
@@ -333,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)
@@ -376,7 +467,6 @@ namespace AZ
path = "";
}
AZStd::scoped_lock lock(m_settingMutex);
rapidjson::Pointer pointer(path.data(), path.length());
if (pointer.IsValid())
@@ -386,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;
}
}
@@ -404,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);
}
@@ -540,7 +631,7 @@ namespace AZ
return false;
}
m_notifiers.Signal("", Type::Object);
SignalNotifier("", Type::Object);
return true;
}
@@ -562,8 +653,6 @@ namespace AZ
scratchBuffer = &buffer;
}
AZStd::scoped_lock lock(m_settingMutex);
bool result = false;
if (path[path.length()] == 0)
{
@@ -577,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())
@@ -622,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());
@@ -659,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())
@@ -678,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
@@ -696,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())
@@ -923,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"),
@@ -1077,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())
@@ -1102,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."
@@ -1115,9 +1212,12 @@ namespace AZ
return false;
}
ScopedMergeEvent scopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey);
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
@@ -1125,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);
}
@@ -1132,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());
@@ -1141,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;
}
@@ -48,6 +48,12 @@ namespace AZ
[[nodiscard]] NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) override;
void ClearNotifiers();
[[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) override;
[[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) override;
[[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) override;
[[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) override;
void ClearMergeEvents();
bool Get(bool& result, AZStd::string_view path) const override;
bool Get(s64& result, AZStd::string_view path) const override;
bool Get(u64& result, AZStd::string_view path) const override;
@@ -89,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,
@@ -100,9 +106,15 @@ 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;
rapidjson::Document m_settings;
JsonSerializerSettings m_serializationSettings;
JsonDeserializerSettings m_deserializationSettings;
@@ -25,6 +25,10 @@ namespace AZ
MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view));
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&));
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&));
MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&));
MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&));
MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(const PostMergeEventCallback&));
MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(PostMergeEventCallback&&));
MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view));
MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view));
@@ -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;
@@ -34,7 +34,7 @@ namespace AzFramework
bool GetFullScreenState() const override;
void SetFullScreenState(bool fullScreenState) override;
bool CanToggleFullScreenState() const override { return true; }
uint32_t GetMainDisplayRefreshRate() const;
uint32_t GetDisplayRefreshRate() const override;
private:
static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks);
@@ -142,7 +142,7 @@ namespace AzFramework
return nativeMask ? nativeMask : defaultMask;
}
uint32_t NativeWindowImpl_Darwin::GetMainDisplayRefreshRate() const
uint32_t NativeWindowImpl_Darwin::GetDisplayRefreshRate() const
{
return m_mainDisplayRefreshRate;
}
@@ -27,7 +27,7 @@ namespace AzFramework
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
NativeWindowHandle GetWindowHandle() const override;
uint32_t GetMainDisplayRefreshRate() const;
uint32_t GetDisplayRefreshRate() const override;
private:
UIWindow* m_nativeWindow;
@@ -66,7 +66,7 @@ namespace AzFramework
return m_nativeWindow;
}
uint32_t NativeWindowImpl_Ios::GetMainDisplayRefreshRate() const
uint32_t NativeWindowImpl_Ios::GetDisplayRefreshRate() const
{
return m_mainDisplayRefreshRate;
}
@@ -10,22 +10,9 @@
namespace AzNetworking
{
StringifySerializer::StringifySerializer(char delimeter, bool outputFieldNames, const AZStd::string& seperator)
: m_delimeter(delimeter)
, m_outputFieldNames(outputFieldNames)
, m_separator(seperator)
const StringifySerializer::ValueMap& StringifySerializer::GetValueMap() const
{
;
}
const AZStd::string& StringifySerializer::GetString() const
{
return m_string;
}
const StringifySerializer::StringMap& StringifySerializer::GetValueMap() const
{
return m_map;
return m_valueMap;
}
SerializerMode StringifySerializer::GetSerializerMode() const
@@ -137,22 +124,9 @@ namespace AzNetworking
template <typename T>
bool StringifySerializer::ProcessData(const char* name, const T& value)
{
// Only add delimeters after we have processed at least one element
if (!m_string.empty())
{
m_string += m_delimeter;
}
if (m_outputFieldNames)
{
m_string += m_prefix;
m_string += name;
m_string += m_separator;
}
AZ::CVarFixedString string = AZ::ConsoleTypeHelpers::ValueToString(value);
m_string += string.c_str();
m_map[m_prefix + name] = string.c_str();
const AZStd::string keyString = m_prefix + name;
AZ::CVarFixedString valueString = AZ::ConsoleTypeHelpers::ValueToString(value);
m_valueMap[keyString] = valueString.c_str();
return true;
}
}
@@ -20,17 +20,12 @@ namespace AzNetworking
{
public:
using StringMap = AZStd::map<AZStd::string, AZStd::string>;
using ValueMap = AZStd::map<AZStd::string, AZStd::string>;
StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "=");
StringifySerializer() = default;
// GetString
// After serializing objects, get the serialized values as a single string
const AZStd::string& GetString() const;
// GetValueMap
// After serializing objects, get the serialized values as key value pairs
const StringMap& GetValueMap() const;
//! After serializing objects, get the serialized values as a map of key/value pairs.
const ValueMap& GetValueMap() const;
// ISerializer interfaces
SerializerMode GetSerializerMode() const override;
@@ -62,15 +57,8 @@ namespace AzNetworking
template <typename T>
bool ProcessData(const char* name, const T& value);
private:
char m_delimeter;
bool m_outputFieldNames = true;
StringMap m_map;
AZStd::string m_string;
ValueMap m_valueMap;
AZStd::string m_prefix;
AZStd::string m_separator;
AZStd::deque<AZStd::size_t> m_prefixSizeStack;
};
}
@@ -1882,7 +1882,10 @@ namespace AzQtComponents
return;
}
QApplication::setOverrideCursor(m_dragCursor);
if (!QApplication::overrideCursor())
{
QApplication::setOverrideCursor(m_dragCursor);
}
QPoint relativePressPos = pressPos;
@@ -841,9 +841,6 @@ namespace AzToolsFramework
*/
virtual AZStd::string GetComponentIconPath(const AZ::Uuid& /*componentType*/, AZ::Crc32 /*componentIconAttrib*/, AZ::Component* /*component*/) { return AZStd::string(); }
/// Resource Selector hook, returns a path for a resource.
virtual AZStd::string SelectResource(const AZStd::string& /*resourceType*/, const AZStd::string& /*previousValue*/) { return AZStd::string(); }
/**
* Calculate the navigation 2D radius in units of an agent given its Navigation Type Name
* @param angentTypeName the name that identifies the agent navigation type
@@ -6,7 +6,6 @@
*
*/
// Description : For listing available script commands with their descriptions
#include "ScriptHelpDialog.h"
@@ -23,6 +22,7 @@
// AzToolsFramework
#include <AzToolsFramework/API/EditorPythonConsoleBus.h> // for EditorPythonConsoleInterface
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <AzToolsFramework/PythonTerminal/ui_ScriptHelpDialog.h>
@@ -313,6 +313,45 @@ namespace AzToolsFramework
connect(ui->tableView, &ScriptTableView::doubleClicked, this, &CScriptHelpDialog::OnDoubleClick);
}
CScriptHelpDialog* CScriptHelpDialog::GetInstance()
{
static CScriptHelpDialog* pInstance = nullptr;
if (!pInstance)
{
QMainWindow* mainWindow = GetMainWindowOfCurrentApplication();
if (!mainWindow)
{
AZ_Assert(false, "Failed to find MainWindow.");
return nullptr;
}
QWidget* parentWidget = mainWindow->window()
? mainWindow->window()
: mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS.
pInstance = new CScriptHelpDialog(parentWidget);
}
return pInstance;
}
QMainWindow* CScriptHelpDialog::GetMainWindowOfCurrentApplication()
{
QWidget* mainWindowWidget = nullptr;
EditorWindowRequestBus::BroadcastResult(mainWindowWidget, &EditorWindowRequests::GetAppMainWindow);
if (QMainWindow* mainWindow = qobject_cast<QMainWindow*>(mainWindowWidget))
{
return mainWindow;
}
for (QWidget* topLevelWidget : qApp->topLevelWidgets())
{
if (QMainWindow* mainWindow = qobject_cast<QMainWindow*>(topLevelWidget))
{
return mainWindow;
}
}
return nullptr;
}
void CScriptHelpDialog::OnDoubleClick(const QModelIndex& index)
{
if (!index.isValid())
@@ -132,43 +132,13 @@ namespace AzToolsFramework
{
Q_OBJECT
public:
static CScriptHelpDialog* GetInstance()
{
static CScriptHelpDialog* pInstance = nullptr;
if (!pInstance)
{
QMainWindow* mainWindow = GetMainWindowOfCurrentApplication();
if (!mainWindow)
{
AZ_Assert(false, "Failed to find MainWindow.");
return nullptr;
}
QWidget* parentWidget = mainWindow->window() ? mainWindow->window() : mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS.
pInstance = new CScriptHelpDialog(parentWidget);
}
return pInstance;
}
static CScriptHelpDialog* GetInstance();
private Q_SLOTS:
void OnDoubleClick(const QModelIndex&);
private:
static QMainWindow* GetMainWindowOfCurrentApplication()
{
QMainWindow* mainWindow = nullptr;
for (QWidget* w : qApp->topLevelWidgets())
{
mainWindow = qobject_cast<QMainWindow*>(w);
if (mainWindow)
{
return mainWindow;
}
}
return nullptr;
}
explicit CScriptHelpDialog(QWidget* parent = nullptr);
static QMainWindow* GetMainWindowOfCurrentApplication();
QScopedPointer<Ui::ScriptDialog> ui;
};
} // namespace AzToolsFramework
@@ -19,6 +19,7 @@
#include <AzCore/Component/Component.h>
#include <AzCore/Component/ComponentBus.h>
#include <AzCore/Component/EntityBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
#include <AzToolsFramework/Undo/UndoSystem.h>
@@ -110,6 +111,7 @@ namespace AzToolsFramework
, public EditorInspectorComponentNotificationBus::MultiHandler
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
, public AZ::EntitySystemBus::Handler
, public AZ::TickBus::Handler
, private EditorWindowUIRequestBus::Handler
{
Q_OBJECT;
@@ -117,6 +119,23 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR(EntityPropertyEditor, AZ::SystemAllocator, 0)
enum class ReorderState
{
Inactive, // No row widget reordering operation is in progress.
DraggingComponent, // User is dragging a component editor.
DraggingRowWidget, // User is dragging a row widget around.
UsingMenu, // User has the context menu open and may hover over a move up/down operation.
MenuOperationInProgress, // User has selected a move/up down menu item.
WaitForRedraw, // Wait for rebuild of RPE.
HighlightMovedRow // User has moved a row, highlight the new position.
};
enum class DropArea
{
Above,
Below
};
EntityPropertyEditor(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags(), bool isLevelEntityEditor = false);
virtual ~EntityPropertyEditor();
@@ -151,6 +170,16 @@ namespace AzToolsFramework
bool IsLockedToSpecificEntities() const { return !m_overrideSelectedEntityIds.empty(); }
static bool AreComponentsCopyable(const AZ::Entity::ComponentArrayType& components, const ComponentFilter& filter);
ReorderState GetReorderState() const;
ComponentEditor* GetEditorForCurrentReorderRowWidget() const;
PropertyRowWidget* GetReorderRowWidget() const;
PropertyRowWidget* GetReorderDropTarget() const;
DropArea GetReorderDropArea() const;
QPixmap GetReorderRowWidgetImage() const;
float GetMoveIndicatorAlpha() const;
PropertyRowWidget* GetRowToHighlight();
Q_SIGNALS:
void SelectedEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name);
@@ -211,6 +240,9 @@ namespace AzToolsFramework
void GetSelectedEntities(EntityIdList& selectedEntityIds) override;
void SetNewComponentId(AZ::ComponentId componentId) override;
// TickBus
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
// EditorWindowRequestBus overrides
void SetEditorUiEnabled(bool enable) override;
@@ -253,6 +285,10 @@ namespace AzToolsFramework
void ContextMenuActionPullFieldData(AZ::Component* parentComponent, InstanceDataNode* fieldNode);
void ContextMenuActionSetDataFlag(InstanceDataNode* node, AZ::DataPatch::Flag flag, bool additive);
void GenerateRowWidgetIndexMapToChildIndex(PropertyRowWidget* parent, int destIndex);
void ContextMenuActionMoveItemUp(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget);
void ContextMenuActionMoveItemDown(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget);
/// Given an InstanceDataNode, calculate a DataPatch address relative to the entity.
/// @return true if successful.
bool GetEntityDataPatchAddress(const InstanceDataNode* componentFieldNode, AZ::DataPatch::AddressType& dataPatchAddressOut, AZ::EntityId* entityIdOut = nullptr) const;
@@ -341,8 +377,6 @@ namespace AzToolsFramework
QAction* m_actionToMoveComponentsBottom = nullptr;
QAction* m_resetToSliceAction = nullptr;
bool m_isShowingContextMenu = false;
void CreateActions();
void UpdateActions();
@@ -390,6 +424,10 @@ namespace AzToolsFramework
void ResetToSlice();
bool DoesOwnFocus() const;
AZ::u32 GetHeightOfRowAndVisibleChildren(const PropertyRowWidget* row) const;
QRect GetWidgetAndVisibleChildrenGlobalRect(const PropertyRowWidget* widget) const;
PropertyRowWidget* GetRowWidgetAtSameLevelAfter(PropertyRowWidget* widget) const;
PropertyRowWidget* GetRowWidgetAtSameLevelBefore(PropertyRowWidget* widget) const;
QRect GetWidgetGlobalRect(const QWidget* widget) const;
bool DoesIntersectWidget(const QRect& globalRect, const QWidget* widget) const;
bool DoesIntersectSelectedComponentEditor(const QRect& globalRect) const;
@@ -445,6 +483,8 @@ namespace AzToolsFramework
bool HandleSelectionEvents(QObject* object, QEvent* event);
bool m_selectionEventAccepted;
bool HandleMenuEvent(QObject* object, QEvent* event);
// drag and drop events
QRect GetInflatedRectFromPoint(const QPoint& point, int radius) const;
bool GetComponentsAtDropEventPosition(QDropEvent* event, AZ::Entity::ComponentArrayType& targetComponents);
@@ -458,8 +498,12 @@ namespace AzToolsFramework
ComponentEditor* GetReorderDropTarget(const QRect& globalRect) const;
bool ResetDrag(QMouseEvent* event);
bool FindAllowedRowWidgetReorderDropTarget(const QPoint& globalPos);
bool UpdateRowWidgetDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData);
PropertyRowWidget* FindPropertyRowWidgetAt(QPoint globalPos);
bool UpdateDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData);
bool StartDrag(QMouseEvent* event);
void EndRowWidgetReorder();
bool HandleDrop(QDropEvent* event);
bool HandleDropForComponentTypes(QDropEvent* event);
bool HandleDropForComponentAssets(QDropEvent* event);
@@ -468,6 +512,8 @@ namespace AzToolsFramework
bool CanDropForComponentTypes(const QMimeData* mimeData) const;
bool CanDropForComponentAssets(const QMimeData* mimeData) const;
bool CanDropForAssetBrowserEntries(const QMimeData* mimeData) const;
void SetRowWidgetHighlighted(PropertyRowWidget* rowWidget);
AZStd::vector<AZ::s32> ExtractComponentEditorIndicesFromMimeData(const QMimeData* mimeData) const;
ComponentEditorVector GetComponentEditorsFromIndices(const AZStd::vector<AZ::s32>& indices) const;
ComponentEditor* GetComponentEditorsFromIndex(const AZ::s32 index) const;
@@ -559,6 +605,8 @@ namespace AzToolsFramework
QIcon m_emptyIcon;
QIcon m_clearIcon;
QIcon m_dragIcon;
QCursor m_dragCursor;
QStandardItem* m_comboItems[StatusItems];
EntityIdSet m_overrideSelectedEntityIds;
@@ -566,6 +614,19 @@ namespace AzToolsFramework
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
bool m_prefabsAreEnabled = false;
// Reordering row widgets within the RPE.
static constexpr float MoveFadeSeconds = 0.5f;
ReorderState m_currentReorderState = ReorderState::Inactive;
ComponentEditor* m_reorderRowWidgetEditor = nullptr;
InstanceDataNode* m_nodeToMove = nullptr;
PropertyRowWidget* m_reorderRowWidget = nullptr;
PropertyRowWidget* m_reorderDropTarget = nullptr;
DropArea m_reorderDropArea = DropArea::Above;
QPixmap m_reorderRowImage;
float m_moveFadeSecondsRemaining;
AZStd::vector<int> m_indexMapOfMovedRow;
// When m_initiatingPropertyChangeNotification is set to true, it means this EntityPropertyEditor is
// broadcasting a change to all listeners about a property change for a given entity. This is needed
// so that we don't update the values twice for this inspector
@@ -573,6 +634,9 @@ namespace AzToolsFramework
void ConnectToEntityBuses(const AZ::EntityId& entityId);
void DisconnectFromEntityBuses(const AZ::EntityId& entityId);
void BeginMoveRowWidgetFade();
void HighlightMovedRowWidget();
//! Stores a component id to be focused on next time the UI updates.
AZStd::optional<AZ::ComponentId> m_newComponentId;
@@ -594,6 +658,8 @@ namespace AzToolsFramework
bool SelectedEntitiesAreFromSameSourceSliceEntity() const;
void DragStopped();
AZ::Entity* GetSelectedEntityById(AZ::EntityId& entityId) const;
};
@@ -7,8 +7,8 @@
*/
#include "PropertyAudioCtrl.h"
#include "PropertyQTConstants.h"
#include <UI/PropertyEditor/PropertyAudioCtrl.h>
#include <UI/PropertyEditor/PropertyQTConstants.h>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
@@ -34,7 +34,7 @@ namespace AzToolsFramework
: QWidget(parent)
, m_browseEdit(nullptr)
, m_mainLayout(nullptr)
, m_propertyType(AudioPropertyType::Invalid)
, m_propertyType(AudioPropertyType::NumTypes)
{
// create the gui
m_mainLayout = new QHBoxLayout();
@@ -96,7 +96,7 @@ namespace AzToolsFramework
return;
}
if (type != AudioPropertyType::Invalid)
if (type != AudioPropertyType::NumTypes)
{
m_propertyType = type;
}
@@ -136,10 +136,11 @@ namespace AzToolsFramework
void AudioControlSelectorWidget::OnOpenAudioControlSelector()
{
AZStd::string resourceResult;
AZStd::string resourceType(GetResourceSelectorNameFromType(m_propertyType));
AZStd::string currentValue(m_controlName.toStdString().c_str());
EditorRequests::Bus::BroadcastResult(resourceResult, &EditorRequests::Bus::Events::SelectResource, resourceType, currentValue);
AZStd::string resourceResult;
AudioControlSelectorRequestBus::EventResult(
resourceResult, m_propertyType,
&AudioControlSelectorRequestBus::Events::SelectResource, currentValue);
SetControlName(QString(resourceResult.c_str()));
}
@@ -167,12 +168,12 @@ namespace AzToolsFramework
{
case AudioPropertyType::Trigger:
return { "AudioTrigger" };
case AudioPropertyType::Rtpc:
return { "AudioRTPC" };
case AudioPropertyType::Switch:
return { "AudioSwitch" };
case AudioPropertyType::SwitchState:
return { "AudioSwitchState" };
case AudioPropertyType::Rtpc:
return { "AudioRTPC" };
case AudioPropertyType::Environment:
return { "AudioEnvironment" };
case AudioPropertyType::Preload:
@@ -29,6 +29,27 @@ class QMimeData;
namespace AzToolsFramework
{
//=============================================================================
// Audio Control Selector Request Bus
// For connecting UI proper
//=============================================================================
class AudioControlSelectorRequests
: public AZ::EBusTraits
{
public:
// EBusTraits
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
using BusIdType = AudioPropertyType;
virtual AZStd::string SelectResource(AZStd::string_view previousValue)
{
return previousValue;
}
};
using AudioControlSelectorRequestBus = AZ::EBus<AudioControlSelectorRequests>;
//=============================================================================
// Audio Control Selector Widget
//=============================================================================
@@ -18,15 +18,15 @@
namespace AzToolsFramework
{
//=========================================================================
enum class AudioPropertyType
enum class AudioPropertyType : AZ::u32
{
Invalid = 0,
Trigger,
Trigger = 0,
Rtpc,
Switch,
SwitchState,
Rtpc,
Environment,
Preload,
NumTypes,
};
//=========================================================================
@@ -40,7 +40,7 @@ namespace AzToolsFramework
virtual ~CReflectedVarAudioControl() = default;
AZStd::string m_controlName;
AudioPropertyType m_propertyType = AudioPropertyType::Invalid;
AudioPropertyType m_propertyType = AudioPropertyType::NumTypes;
static void Reflect(AZ::ReflectContext* context)
{
@@ -368,10 +368,15 @@ namespace AzToolsFramework
delete m_containerAddButton;
}
this->unsetCursor();
if ((m_parentRow) && (m_parentRow->IsContainerEditable()))
{
if (!m_elementRemoveButton)
{
QIcon icon = QIcon(QStringLiteral(":/Cursors/Grab_release.svg"));
this->setCursor(QCursor(icon.pixmap(16), 5, 2));
static QIcon s_iconRemove(QStringLiteral(":/stylesheet/img/UI20/delete-16.svg"));
m_elementRemoveButton = new QToolButton(this);
m_elementRemoveButton->setAutoRaise(true);
@@ -570,7 +575,12 @@ namespace AzToolsFramework
AZ_Assert(m_selectionEnabled, "Property is not selectable");
m_isSelected = selected;
m_nameLabel->setProperty("selected", selected);
}
}
bool PropertyRowWidget::GetSelected()
{
return m_isSelected;
}
void PropertyRowWidget::SetSelectionEnabled(bool selectionEnabled)
{
@@ -1395,6 +1405,21 @@ namespace AzToolsFramework
return !m_childrenRows.empty();
}
AZ::u32 PropertyRowWidget::GetChildRowCount() const
{
return static_cast<AZ::u32>(m_childrenRows.size());
}
PropertyRowWidget* PropertyRowWidget::GetChildRowByIndex(AZ::u32 index) const
{
if (index >= m_childrenRows.size())
{
return nullptr;
}
return m_childrenRows[index];
}
bool PropertyRowWidget::ShouldPreValidatePropertyChange() const
{
return (m_changeValidators.size() > 0);
@@ -1722,6 +1747,162 @@ namespace AzToolsFramework
return m_parentRow->CanChildrenBeReordered();
}
int PropertyRowWidget::GetIndexInParent() const
{
if (!GetParentRow())
{
return -1;
}
for (AZ::u32 index = 0; index < GetParentRow()->GetChildRowCount(); index++)
{
if (GetParentRow()->GetChildrenRows()[index] == this)
{
return index;
}
}
return -1;
}
bool PropertyRowWidget::CanMoveUp() const
{
if (!CanBeReordered())
{
return false;
}
return this != m_parentRow->GetChildRowByIndex(0);
}
bool PropertyRowWidget::CanMoveDown() const
{
if (!CanBeReordered())
{
return false;
}
AZ::u32 numChildrenOfParent = m_parentRow->GetChildRowCount();
return this != m_parentRow->GetChildRowByIndex(numChildrenOfParent - 1);
}
int PropertyRowWidget::GetContainingEditorFrameWidth()
{
QWidget* parent = parentWidget();
// Find the first ancestor that can be cast to a QFrame, this will be the RPE.
while (!qobject_cast<QFrame*>(parent))
{
parent = parent->parentWidget();
}
if (!parent)
{
return 0;
}
// The parent of the RPE is the size we want.
parent = parent->parentWidget();
return parent->rect().width();
}
int PropertyRowWidget::GetHeightOfRowAndVisibleChildren()
{
int height = rect().height();
if (!GetChildRowCount() || !IsExpanded())
{
return height;
}
for (auto childRow : GetChildrenRows())
{
height += childRow->GetHeightOfRowAndVisibleChildren();
}
return height;
}
int PropertyRowWidget::DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos)
{
// Render our image into the given painter.
int ystart = ypos;
render(&painter, QPoint(xpos, ypos));
if (!GetChildRowCount() || !IsExpanded())
{
return rect().height();
}
ypos += rect().height();
// Recursively draw any children.
for (auto childRow : GetChildrenRows())
{
ypos += childRow->DrawDragImageAndVisibleChildrenInto(painter, xpos, ypos);
}
return ypos - ystart;
}
QPixmap PropertyRowWidget::createDragImage(
const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType)
{
// Make the drag box as wide as the containing editor minus a gap each side for the border.
static constexpr int ParentEditorBorderSize = 2;
int width = GetContainingEditorFrameWidth() - ParentEditorBorderSize * 2;
int height = 0;
if (imageType == DragImageType::IncludeVisibleChildren)
{
height = GetHeightOfRowAndVisibleChildren();
}
else
{
height = rect().height();
}
const auto dpr = devicePixelRatioF();
QPixmap dragImage(width * dpr, height * dpr);
dragImage.setDevicePixelRatio(dpr);
dragImage.fill(Qt::transparent);
QRect imageRect = QRect(0, 0, width, height);
QPainter dragPainter(&dragImage);
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
dragPainter.fillRect(imageRect, Qt::transparent);
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
dragPainter.setOpacity(alpha);
dragPainter.fillRect(imageRect, backgroundColor);
dragPainter.setOpacity(1.0f);
int marginWidth = (imageRect.width() - rect().width()) / 2 + ParentEditorBorderSize - 1;
if (imageType == DragImageType::IncludeVisibleChildren)
{
DrawDragImageAndVisibleChildrenInto(dragPainter, marginWidth, 0);
}
else
{
render(&dragPainter, QPoint(marginWidth, 0));
}
QPen pen;
pen.setColor(QColor(borderColor));
pen.setWidth(1);
dragPainter.setPen(pen);
dragPainter.drawRect(0, 0, imageRect.width() - 1, imageRect.height() - 1);
dragPainter.end();
return dragImage;
}
}
#include "UI/PropertyEditor/moc_PropertyRowWidget.cpp"
@@ -45,6 +45,13 @@ namespace AzToolsFramework
Q_PROPERTY(bool appendDefaultLabelToName READ GetAppendDefaultLabelToName WRITE AppendDefaultLabelToName)
public:
AZ_CLASS_ALLOCATOR(PropertyRowWidget, AZ::SystemAllocator, 0)
enum class DragImageType
{
SingleRow,
IncludeVisibleChildren
};
PropertyRowWidget(QWidget* pParent);
virtual ~PropertyRowWidget();
@@ -86,6 +93,9 @@ namespace AzToolsFramework
bool GetAppendDefaultLabelToName();
void AppendDefaultLabelToName(bool doAppend);
AZ::u32 GetChildRowCount() const;
PropertyRowWidget* GetChildRowByIndex(AZ::u32 index) const;
AZStd::vector<PropertyRowWidget*>& GetChildrenRows() { return m_childrenRows; }
bool HasChildRows() const;
@@ -124,6 +134,7 @@ namespace AzToolsFramework
void SetSelectionEnabled(bool selectionEnabled);
void SetSelected(bool selected);
bool GetSelected();
bool eventFilter(QObject *watched, QEvent *event) override;
void paintEvent(QPaintEvent*) override;
@@ -152,9 +163,18 @@ namespace AzToolsFramework
bool CanChildrenBeReordered() const;
bool CanBeReordered() const;
int GetIndexInParent() const;
bool CanMoveUp() const;
bool CanMoveDown() const;
int GetContainingEditorFrameWidth();
QPixmap createDragImage(const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType);
protected:
int CalculateLabelWidth() const;
int GetHeightOfRowAndVisibleChildren();
int DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos);
bool IsHidden(InstanceDataNode* node) const;
struct ChangeNotification;
@@ -216,6 +236,7 @@ namespace AzToolsFramework
bool m_isMultiSizeContainer = false;
bool m_isFixedSizeOrSmartPtrContainer = false;
bool m_custom = false;
bool m_canChildrenBeReordered = false;
bool m_isSelected = false;
bool m_selectionEnabled = false;
@@ -19,6 +19,7 @@
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QApplication>
#include <QPainter>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QTextFormat::d': class 'QSharedDataPointer<QTextFormatPrivate>' needs to have dll-interface to be used by clients of class 'QTextFormat'
#include <QtWidgets/QInputDialog>
AZ_POP_DISABLE_WARNING
@@ -1343,7 +1344,7 @@ namespace AzToolsFramework
// calculate the index/offset of the instance data node in the container
// (useful for notifying which element in a vector was modified/removed)
static size_t CalculateElementIndexInContainer(
static int CalculateElementIndexInContainer(
InstanceDataNode* node, void* parentInstanceNode,
AZ::SerializeContext::IDataContainer* container, AZStd::vector<void*>& nodeInstancesOut)
{
@@ -1358,7 +1359,7 @@ namespace AzToolsFramework
}
}
size_t elementIndex = 0;
int elementIndex = 0;
void* elementPtr = nodeInstancesOut.empty() ? nullptr : nodeInstancesOut.front();
// find the index of the element we are about to remove
@@ -1429,7 +1430,7 @@ namespace AzToolsFramework
// if the element being modified exists in a container, calculate
// the index to be passed through to PropertyNotify
const auto calculateElementIndex = [](InstanceDataNode* node) -> size_t {
const auto calculateElementIndex = [](InstanceDataNode* node) -> int {
if (InstanceDataNode* parent = node->GetParent())
{
if (AZ::SerializeContext::IDataContainer* container = parent->GetClassMetadata()->m_container)
@@ -1656,6 +1657,221 @@ namespace AzToolsFramework
AzToolsFramework::Refresh_EntireTree);
}
InstanceDataNode* ReflectedPropertyEditor::FindContainerNodeForNode(InstanceDataNode* node) const
{
// Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField.
InstanceDataNode* pContainerNode = node->GetParent();
if (!pContainerNode)
{
return nullptr;
}
while (pContainerNode && !pContainerNode->GetClassMetadata()->m_container)
{
pContainerNode = pContainerNode->GetParent();
node = node->GetParent();
}
// Check for pContainerNode again, can happen if a node is deleted during operation.
if (!pContainerNode)
{
return nullptr;
}
if (IsParentAssociativeContainer(pContainerNode) && IsPairContainer(pContainerNode))
{
// Go up one more level to the associative container, we'll remove the pair from that container
pContainerNode = pContainerNode->GetParent();
node = node->GetParent();
}
AZ_Assert(
pContainerNode, "Failed to locate parent container for element \"%s\" of type %s.",
node->GetElementMetadata() ? node->GetElementMetadata()->m_name : node->GetClassMetadata()->m_name,
node->GetClassMetadata()->m_typeId.ToString<AZStd::string>().c_str());
return pContainerNode;
}
InstanceDataNode* ReflectedPropertyEditor::GetNodeAtIndex(int index)
{
if (index >= m_impl->m_widgetsInDisplayOrder.size())
{
return nullptr;
}
return GetNodeFromWidget(m_impl->m_widgetsInDisplayOrder[index]);
}
QSet<PropertyRowWidget*> ReflectedPropertyEditor::GetTopLevelWidgets()
{
return m_impl->getTopLevelWidgets();
}
void ReflectedPropertyEditor::ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int fromIndex, int toIndex)
{
auto container = containerNode->GetElementMetadata()
? containerNode->GetElementMetadata()->m_genericClassInfo->GetClassData()->m_container
: nullptr;
if (fromIndex == toIndex)
{
return;
}
if (!container || container->GetAssociativeContainerInterface())
{
return;
}
AZ::Uuid typeId = node->GetClassMetadata()->m_typeId;
if (m_impl->m_ptrNotify)
{
m_impl->m_ptrNotify->BeforePropertyModified(containerNode);
}
const AZ::SerializeContext::ClassElement* containerClassElement = container->GetElement(container->GetDefaultElementNameCrc());
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
// Backup the item we're moving.
void* srcElement = nullptr;
void* destElement = nullptr;
int destIndex = -1;
int srcIndex = fromIndex;
srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex);
void* tmpBuffer = serializeContext->CloneObject(srcElement, typeId);
// Shuffle all intervening items up (or down).
int indexOffset = (toIndex < fromIndex) ? -1 : 1;
while (destIndex != toIndex - indexOffset)
{
destIndex = srcIndex;
srcIndex += indexOffset;
destElement = srcElement;
srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex);
serializeContext->CloneObjectInplace(destElement, srcElement, typeId);
}
// Now replace the final element with the one backed up previously.
destElement = srcElement;
serializeContext->CloneObjectInplace(destElement, tmpBuffer, typeId);
if (m_impl->m_ptrNotify)
{
m_impl->m_ptrNotify->AfterPropertyModified(containerNode);
m_impl->m_ptrNotify->SealUndoStack();
}
// Need to refresh any pinned inspectors as well to keep the container state in sync
QueueInvalidation(Refresh_Values);
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values);
}
void ReflectedPropertyEditor::MoveNodeToIndex(InstanceDataNode* node, int index)
{
InstanceDataNode* pContainerNode = FindContainerNodeForNode(node);
if (!pContainerNode)
{
return;
}
AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container;
AZStd::vector<void*> nodeInstancesOut;
const int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut);
ChangeNodeIndex(pContainerNode, node, elementIndex, index);
}
void ReflectedPropertyEditor::MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore)
{
InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove);
InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore);
if (nodeToMove == nodeToMoveBefore)
{
return;
}
// Can only move nodes within the same parent.
if (pContainerNode != pContainerNodeTarget)
{
return;
}
AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container;
AZStd::vector<void*> nodeInstancesOut;
int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut);
nodeInstancesOut.clear();
int elementIndexTarget =
CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut);
if (elementIndex < elementIndexTarget)
{
elementIndexTarget -= 1;
}
ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget);
}
void ReflectedPropertyEditor::MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore)
{
InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove);
InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore);
if (nodeToMove == nodeToMoveBefore)
{
return;
}
// Can only move nodes within the same parent.
if (pContainerNode != pContainerNodeTarget)
{
return;
}
AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container;
AZStd::vector<void*> nodeInstancesOut;
int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut);
nodeInstancesOut.clear();
int elementIndexTarget =
CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut);
if (elementIndex > elementIndexTarget)
{
elementIndexTarget += 1;
}
ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget);
}
int ReflectedPropertyEditor::GetNodeIndexInContainer(InstanceDataNode* node)
{
InstanceDataNode* pContainerNode = FindContainerNodeForNode(node);
AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container;
AZStd::vector<void*> nodeInstancesOut;
int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut);
return elementIndex;
}
void ReflectedPropertyEditor::OnPropertyRowRequestContainerRemoveItem(PropertyRowWidget* widget, InstanceDataNode* node)
{
// Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField.
@@ -1690,7 +1906,7 @@ namespace AzToolsFramework
// the index of the element being removed
AZStd::vector<void*> nodeInstancesOut;
const size_t elementIndex = CalculateElementIndexInContainer(
const int elementIndex = CalculateElementIndexInContainer(
node, pContainerNode->GetInstance(0), container, nodeInstancesOut);
// pass the context as the last parameter to actually delete the related data.
@@ -155,9 +155,19 @@ namespace AzToolsFramework
using VisibilityCallback = AZStd::function<void(InstanceDataNode* node, NodeDisplayVisibility& visibility, bool& checkChildVisibility)>;
void SetVisibilityCallback(VisibilityCallback callback);
void MoveNodeToIndex(InstanceDataNode* node, int index);
void MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore);
void MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore);
int GetNodeIndexInContainer(InstanceDataNode* node);
InstanceDataNode* GetNodeAtIndex(int index);
QSet<PropertyRowWidget*> GetTopLevelWidgets();
signals:
void OnExpansionContractionDone();
private:
InstanceDataNode* FindContainerNodeForNode(InstanceDataNode* node) const;
void ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int oldIndex, int newIndex);
class Impl;
std::unique_ptr<Impl> m_impl;
+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);
-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);
-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--)
{

Some files were not shown because too many files have changed in this diff Show More